Skip to content
34 changes: 31 additions & 3 deletions Lib/idlelib/calltip.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,46 @@ def refresh_calltip_event(self, event):
self.open_calltip(False)

def open_calltip(self, evalfuncs):
self.remove_calltip_window()

hp = HyperParser(self.editwin, "insert")
sur_paren = hp.get_surrounding_brackets('(')
if not sur_paren:
# Not inside parentheses: Don't open a calltip, and close one if
# currently open.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if not sur_paren:
# Not inside parentheses: Don't open a calltip, and close one if
# currently open.
if not sur_paren: # Outer call just closed by releasing ).

See response to your response below.

Copy link
Contributor Author

@taleinat taleinat Nov 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typing ')' is not the only case where this branch will be reached: it can also happen in various other cases via force_open_calltip_event().

self.remove_calltip_window()
return

if self.active_calltip:
opener_line, opener_col = map(int, sur_paren[0].split('.'))
if (
(opener_line, opener_col) ==
(self.active_calltip.parenline, self.active_calltip.parencol)
):
# After the same opening parenthesis as for the currently open
# calltip: Do nothing.
return

hp.set_index(sur_paren[0])
expression = hp.get_expression()
try:
expression = hp.get_expression()
except ValueError:
expression = None
if not expression:
# No expression before the opening parenthesis, e.g. because it's
# in a string or the opener for a tuple: Do nothing.
return

# At this point, the current index is after an opening parenthesis, in
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might later think about rewording or condensing the added comments, but tests are a higher priority.

# a section of code, preceded by a valid expression. If there is an
# existing open calltip, it's not for the same index, and it should
# definitely be closed.
self.remove_calltip_window()

# If the preceding expression includes an opening parenthesis, it
# likely includes a function call. So if evalfuncs is false, a calltip
# should not be opened.
if not evalfuncs and (expression.find('(') != -1):
return

argspec = self.fetch_tip(expression)
if not argspec:
return
Expand Down
2 changes: 1 addition & 1 deletion Lib/idlelib/calltip_w.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def get_position(self):
return box[0] + 2, box[1] + box[3]

def position_window(self):
"Reposition the window if needed."
"""Reposition the window if needed."""
curline = int(self.anchor_widget.index("insert").split('.')[0])
if curline == self.lastline:
return
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Typing opening and closing parentheses inside the parentheses of a function
call will no longer cause unnecessary "flashing" off and on of an existing
open call-tip, e.g. when typed in a string literal.