@@ -166,10 +166,94 @@ def pos2bytes(content, pos):
166166 return len (content [:pos ].encode ('utf-8' ))
167167
168168
169- def calltip (view , ltype , msg = None , timeout = None , delay = 0 , lid = 'CodeIntel' , logger = None ):
169+ class TooltipOutputCommand (sublime_plugin .TextCommand ):
170+ def run (self , edit , output = '' , clear = True ):
171+ if clear :
172+ region = sublime .Region (0 , self .view .size ())
173+ self .view .erase (edit , region )
174+ self .view .insert (edit , 0 , output )
175+
176+
177+ def tooltip_popup (view , snippets ):
178+ vid = view .id ()
179+ completions [vid ] = snippets
180+ view .run_command ('auto_complete' , {
181+ 'disable_auto_insert' : True ,
182+ 'api_completions_only' : True ,
183+ 'next_completion_if_showing' : False ,
184+ 'auto_complete_commit_on_tab' : True ,
185+ })
186+
187+
188+ def tooltip (view , calltips , original_pos ):
189+ view_settings = view .settings ()
190+ codeintel_snippets = view_settings .get ('codeintel_snippets' , True )
191+ codeintel_tooltips = view_settings .get ('codeintel_tooltips' , 'popup' )
192+
193+ snippets = []
194+ for calltip in calltips :
195+ tip_info = calltip .split ('\n ' )
196+ text = ' ' .join (tip_info [1 :])
197+ snippet = None
198+ # Insert parameters as snippet:
199+ m = re .search (r'([^\s]+)\(([^\[\(\)]*)' , tip_info [0 ])
200+ if m :
201+ params = [p .strip () for p in m .group (2 ).split (',' )]
202+ if params :
203+ snippet = []
204+ for i , p in enumerate (params ):
205+ if p :
206+ var , _ , _ = p .partition ('=' )
207+ if ' ' in var :
208+ var = var .split (' ' )[1 ]
209+ if var [0 ] == '$' :
210+ var = var [1 :]
211+ snippet .append ('${%s:%s}' % (i + 1 , var ))
212+ snippet = ', ' .join (snippet )
213+ text += ' - ' + tip_info [0 ] # Add function to the end
214+ else :
215+ text = tip_info [0 ] + ' ' + text # No function match, just add the first line
216+ if not codeintel_snippets :
217+ snippet = None
218+ snippets .extend (((' ' if i > 0 else '' ) + l , snippet or '${0}' ) for i , l in enumerate (tip_info ))
219+
220+ if codeintel_tooltips == 'popup' :
221+ tooltip_popup (view , snippets )
222+ elif codeintel_tooltips in ('status' , 'panel' ):
223+ if codeintel_tooltips == 'status' :
224+ set_status (view , 'tip' , text , timeout = 15000 )
225+ else :
226+ window = view .window ()
227+ output_panel = window .get_output_panel ('tooltips' )
228+ output_panel .set_read_only (False )
229+ text = '\n ' .join (list (zip (* snippets ))[0 ])
230+ output_panel .run_command ('tooltip_output' , {'output' : text })
231+ output_panel .set_read_only (True )
232+ window .run_command ('show_panel' , {'panel' : 'output.tooltips' })
233+ sublime .set_timeout (lambda : window .run_command ('hide_panel' , {'panel' : 'output.tooltips' }), 15000 )
234+
235+ if snippets and codeintel_snippets :
236+ # Insert function call snippets:
237+ # func = m.group(1)
238+ # scope = view.scope_name(pos)
239+ # view.run_command('new_snippet', {'contents': snippets[0][0], 'tab_trigger': func, 'scope': scope}) # FIXME: Doesn't add the new snippet... is it possible to do so?
240+ def _insert_snippet ():
241+ # Check to see we are still at a position where the snippet is wanted:
242+ view_sel = view .sel ()
243+ if not view_sel :
244+ return
245+ sel = view_sel [0 ]
246+ pos = sel .end ()
247+ if not pos or pos != original_pos :
248+ return
249+ view .run_command ('insert_snippet' , {'contents' : snippets [0 ][0 ]})
250+ sublime .set_timeout (_insert_snippet , 500 ) # Delay snippet insertion a bit... it's annoying some times
251+
252+
253+ def set_status (view , ltype , msg = None , timeout = None , delay = 0 , lid = 'CodeIntel' , logger = None ):
170254 if timeout is None :
171255 timeout = {'error' : 3000 , 'warning' : 5000 , 'info' : 10000 ,
172- 'event' : 10000 , 'tip' : 15000 }.get (ltype , 3000 )
256+ 'event' : 10000 }.get (ltype , 3000 )
173257
174258 if msg is None :
175259 msg , ltype = ltype , 'debug'
@@ -185,30 +269,24 @@ def calltip(view, ltype, msg=None, timeout=None, delay=0, lid='CodeIntel', logge
185269 finally :
186270 status_lock .release ()
187271
188- def _calltip_set ():
272+ def _set_status ():
189273 view_sel = view .sel ()
190274 lineno = view .rowcol (view_sel [0 ].end ())[0 ] if view_sel else 0
191275 status_lock .acquire ()
192276 try :
193277 current_type , current_msg , current_order = status_msg .get (lid , [None , None , 0 ])
194278 if msg != current_msg and order == current_order :
195- if msg :
196- print ("+" , "%s: %s" % (ltype .capitalize (), msg ), file = condeintel_log_file )
197- (logger or log .info )(msg )
198- if ltype != 'debug' :
199- view .set_status (lid , "%s: %s" % (ltype .capitalize (), msg ))
200- status_msg [lid ] = [ltype , msg , order ]
201- if 'warning' not in lid :
202- status_lineno [lid ] = lineno
203- else :
204- view .erase_status (lid )
205- status_msg [lid ][1 ] = None
206- if lid in status_lineno :
207- del status_lineno [lid ]
279+ print ("+" , "%s: %s" % (ltype .capitalize (), msg ), file = condeintel_log_file )
280+ (logger or log .info )(msg )
281+ if ltype != 'debug' :
282+ view .set_status (lid , "%s: %s" % (ltype .capitalize (), msg ))
283+ status_msg [lid ] = [ltype , msg , order ]
284+ if 'warning' not in lid :
285+ status_lineno [lid ] = lineno
208286 finally :
209287 status_lock .release ()
210288
211- def _calltip_erase ():
289+ def _erase_status ():
212290 status_lock .acquire ()
213291 try :
214292 if msg == status_msg .get (lid , [None , None , 0 ])[1 ]:
@@ -219,16 +297,17 @@ def _calltip_erase():
219297 finally :
220298 status_lock .release ()
221299
222- sublime .set_timeout (_calltip_set , delay or 0 )
223-
224300 if msg :
225- sublime .set_timeout (_calltip_erase , timeout )
301+ sublime .set_timeout (_set_status , delay or 0 )
302+ sublime .set_timeout (_erase_status , timeout )
303+ else :
304+ sublime .set_timeout (_erase_status , delay or 0 )
226305
227306
228307def logger (view , ltype , msg = None , timeout = None , delay = 0 , lid = 'CodeIntel' ):
229308 if msg is None :
230309 msg , ltype = ltype , 'info'
231- calltip (view , ltype , msg , timeout = timeout , delay = delay , lid = lid + '-' + ltype , logger = getattr (log , ltype , None ))
310+ set_status (view , ltype , msg , timeout = timeout , delay = delay , lid = lid + '-' + ltype , logger = getattr (log , ltype , None ))
232311
233312
234313def guess_lang (view = None , path = None ):
@@ -301,10 +380,8 @@ def _autocomplete_callback(view, path, original_pos, lang):
301380
302381 if not next or next != '_' and not next .isalnum ():
303382 vid = view .id ()
304- content = view .substr (sublime .Region (0 , view .size ()))
305383
306384 def _trigger (calltips , cplns = None ):
307- view_settings = view .settings ()
308385 if cplns is not None or calltips is not None :
309386 codeintel_log .info ("Autocomplete called (%s) [%s]" , lang , ',' .join (c for c in ['cplns' if cplns else None , 'calltips' if calltips else None ] if c ))
310387
@@ -323,49 +400,10 @@ def _trigger(calltips, cplns=None):
323400 'next_completion_if_showing' : False ,
324401 'auto_complete_commit_on_tab' : True ,
325402 })
403+ if calltips :
404+ tooltip (view , calltips , original_pos )
326405
327- if calltips is None :
328- return
329- tip_info = calltips [0 ].split ('\n ' )
330- tooltip = ' ' .join (tip_info [1 :])
331-
332- # Insert function call snippets:
333- if view_settings .get ('codeintel_snippets' , True ):
334- # Insert parameters as snippet:
335- if content [sel .begin () - 1 ] == '(' and content [sel .begin ()] == ')' :
336- m = re .search (r'([^\s]+)\(([^\[\(\)]*)' , tip_info [0 ])
337- if m :
338- params = [p .strip () for p in m .group (2 ).split (',' )]
339- if params :
340- snippet = []
341- for i , p in enumerate (params ):
342- if p :
343- var , _ , _ = p .partition ('=' )
344- if ' ' in var :
345- var = var .split (' ' )[1 ]
346- if var [0 ] == '$' :
347- var = var [1 :]
348- snippet .append ('${%s:%s}' % (i + 1 , var ))
349- contents = ', ' .join (snippet )
350- # func = m.group(1)
351- # scope = view.scope_name(pos)
352- # view.run_command('new_snippet', {'contents': contents, 'tab_trigger': func, 'scope': scope}) # FIXME: Doesn't add the new snippet... is it possible to do so?
353- def _insert_snippet ():
354- # Check to see we are still at a position where the snippet is wanted:
355- view_sel = view .sel ()
356- if not view_sel :
357- return
358- sel = view_sel [0 ]
359- pos = sel .end ()
360- if not pos or pos != original_pos :
361- return
362- view .run_command ('insert_snippet' , {'contents' : contents })
363- sublime .set_timeout (_insert_snippet , 500 ) # Delay snippet insertion a bit... it's annoying some times
364- tooltip += ' - ' + tip_info [0 ] # Add function to the end
365- else :
366- tooltip = tip_info [0 ] + ' ' + tooltip # No function match, just add the first line
367- # Trigger a tooltip
368- calltip (view , 'tip' , tooltip )
406+ content = view .substr (sublime .Region (0 , view .size ()))
369407 codeintel (view , path , content , lang , pos , forms , _trigger )
370408 # If it's a fill char, queue using lower values and preemptive behavior
371409 queue (view , _autocomplete_callback , timeout , busy_timeout , preemptive , args = args , kwargs = kwargs )
@@ -716,8 +754,8 @@ def _codeintel_scan():
716754 msgs = []
717755 if env ._valid :
718756 if forms :
719- calltip (view , 'tip' , "" )
720- calltip (view , 'event' , "" )
757+ set_status (view , 'tip' , "" )
758+ set_status (view , 'event' , "" )
721759 msg = "CodeIntel(%s) for %s@%s [%s]" % (', ' .join (forms ), path , pos , lang )
722760 msgs .append (('info' , "\n %s\n %s" % (msg , "-" * len (msg ))))
723761
@@ -817,7 +855,7 @@ def _codeintel(buf, msgs):
817855 continue
818856 merge = ''
819857 if not result and msg .startswith ('evaluating ' ):
820- calltip (view , 'warning' , msg )
858+ set_status (view , 'warning' , msg )
821859 result = True
822860
823861 ret = []
@@ -923,6 +961,7 @@ def get_revision(path=None):
923961ALL_SETTINGS = [
924962 'codeintel' ,
925963 'codeintel_snippets' ,
964+ 'codeintel_tooltips' ,
926965 'codeintel_enabled_languages' ,
927966 'codeintel_live' ,
928967 'codeintel_live_enabled_languages' ,
@@ -1035,7 +1074,7 @@ def on_selection_modified(self, view):
10351074 finally :
10361075 status_lock .release ()
10371076 for vid in slns :
1038- calltip (view , "" , lid = vid )
1077+ set_status (view , "" , lid = vid )
10391078
10401079 def on_query_completions (self , view , prefix , locations ):
10411080 vid = view .id ()
0 commit comments