@@ -14,6 +14,12 @@ class PopupManager():
1414
1515 It uses the WorkScheduler class to handle sending requests to the server to
1616 ensure good performance.
17+
18+ The main challenge is that certain activities, such as cursor movement, can
19+ automatically dismiss the popup - even though the cursor may still be in the
20+ argument list. Therefore the class listens to the on_hidden event, and will
21+ redisplay if necessary (i.e. if the cursor is still in the argument list).
22+ If the popup is explicitly dismissed, on_close_popup is called.
1723 """
1824
1925 html_template = ''
@@ -30,6 +36,9 @@ def __init__(self, proxy):
3036 self .signature_index = 0
3137 self .current_parameter = 0
3238
39+ # Track current popup location to see if we only need to update the text
40+ self .current_location = None
41+
3342 def queue_signature_popup (self , view ):
3443 cursor = view .rowcol (view .sel ()[0 ].begin ())
3544 point = Location (cursor [0 ] + 1 , cursor [1 ] + 1 )
@@ -58,14 +67,15 @@ def on_response(self, responseJson, view):
5867 self .current_parameter = responseJson ["body" ]["argumentIndex" ]
5968
6069 # Add a region to track the arg list as the user types
61- # Needs to be ajusted to 0-based indexing
70+ # Needs to be adjusted to 0-based indexing
6271 arg_span = self .signature_help ["applicableSpan" ]
6372 span_start = view .text_point (
6473 arg_span ["start" ]["line" ] - 1 ,
6574 arg_span ["start" ]["offset" ] - 2 )
6675 span_end = view .text_point (
6776 arg_span ["end" ]["line" ] - 1 ,
68- arg_span ["end" ]["offset" ] - 1 )
77+ arg_span ["end" ]["offset" ])
78+
6979 arg_region = sublime .Region (span_start , span_end )
7080 view .add_regions ('argSpan' , [arg_region ],
7181 flags = sublime .HIDDEN )
@@ -78,15 +88,36 @@ def display(self):
7888 popup_text = PopupManager .html_template .substitute (popup_parts )
7989
8090 log .debug ('Displaying signature popup' )
81- if not self .current_view .is_popup_visible ():
91+
92+ arg_region = self .current_view .get_regions ('argSpan' )[0 ]
93+ location = arg_region .begin () # Default to start of arg list
94+
95+ # If the cursor is not in the first line of the arg list, set the popup
96+ # location to first non-whitespace, or EOL, of the current line
97+ cursor_point = self .current_view .sel ()[0 ].begin ()
98+ opening_line = self .current_view .line (arg_region .begin ())
99+ if (not opening_line .contains (cursor_point )):
100+ cursor_line_start = self .current_view .line (cursor_point ).begin ()
101+ location = self .current_view .find (
102+ r'\s*?(?=[\S\n\r]|$)' ,
103+ cursor_line_start
104+ ).end ()
105+
106+ # If the popup is currently visible and at the right location, then
107+ # call 'update' instead of 'show', else this can get in a loop when show
108+ # causes the old popup to be hidden (and on_hidden is called), as well
109+ # as causing some unnecessary UI flickering.
110+ if self .current_view .is_popup_visible () and self .current_location == location :
111+ self .current_view .update_popup (popup_text )
112+ else :
113+ self .current_location = location
82114 self .current_view .show_popup (
83115 popup_text ,
84116 sublime .COOPERATE_WITH_AUTO_COMPLETE ,
85117 on_navigate = self .on_navigate ,
86118 on_hide = self .on_hidden ,
119+ location = location ,
87120 max_width = 800 )
88- else :
89- self .current_view .update_popup (popup_text )
90121
91122 def move_next (self ):
92123 if not self .signature_help :
@@ -113,15 +144,17 @@ def on_navigate(self, loc):
113144 def on_hidden (self ):
114145 log .debug ('In popup on_hidden handler' )
115146 if not self .current_view :
147+ log .debug ('No current view for popup session. Hiding popup' )
116148 return
117149
150+ # If we're still in the arg list, then redisplay
118151 cursor_region = self .current_view .sel ()[0 ]
119152 arg_regions = self .current_view .get_regions ('argSpan' )
120153 if len (arg_regions ):
121154 argSpan = self .current_view .get_regions ('argSpan' )[0 ]
122155 if argSpan .contains (cursor_region ):
123156 log .debug ('Was hidden while in region. Redisplaying' )
124- # Occurs on left/right movement. Rerun to redisplay popup.
157+ # Occurs on cursor movement. Rerun to redisplay popup.
125158 self .display ()
126159 else :
127160 # Cleanup
@@ -202,7 +235,8 @@ def get_current_signature_parts(self):
202235 param = item ["parameters" ][self .current_parameter ]
203236 activeParam = '<span class="param">{0}:</span> <i>{1}</i>' .format (
204237 param ["name" ],
205- param ["documentation" ][0 ]["text" ] if param ["documentation" ] else "" )
238+ param ["documentation" ][0 ]["text" ]
239+ if param ["documentation" ] else "" )
206240 else :
207241 activeParam = ''
208242
0 commit comments