Skip to content

Commit c705fd1

Browse files
authored
bpo-39781: Do not jump when select in IDLE codecontext (GH-18683)
Previously, the button-up part of selecting with a mouse was treated as a click that meant 'jump' to this line, which modified the context and undid the selection
1 parent 4f17c5c commit c705fd1

File tree

4 files changed

+36
-19
lines changed

4 files changed

+36
-19
lines changed

Lib/idlelib/NEWS.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ Released on 2020-10-05?
33
======================================
44

55

6+
bpo-39781: Selecting code context lines no longer causes a jump.
7+
68
bpo-39663: Add tests for pyparse find_good_parse_start().
79

810
bpo-39600: Remove duplicate font names from configuration list.

Lib/idlelib/codecontext.py

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
enclosing block. The number of hint lines is determined by the maxlines
88
variable in the codecontext section of config-extensions.def. Lines which do
99
not open blocks are not shown in the context hints pane.
10-
1110
"""
1211
import re
1312
from sys import maxsize as INFINITY
@@ -17,8 +16,8 @@
1716

1817
from idlelib.config import idleConf
1918

20-
BLOCKOPENERS = {"class", "def", "elif", "else", "except", "finally", "for",
21-
"if", "try", "while", "with", "async"}
19+
BLOCKOPENERS = {'class', 'def', 'if', 'elif', 'else', 'while', 'for',
20+
'try', 'except', 'finally', 'with', 'async'}
2221

2322

2423
def get_spaces_firstword(codeline, c=re.compile(r"^(\s*)(\w*)")):
@@ -84,7 +83,7 @@ def __del__(self):
8483
if self.t1 is not None:
8584
try:
8685
self.text.after_cancel(self.t1)
87-
except tkinter.TclError:
86+
except tkinter.TclError: # pragma: no cover
8887
pass
8988
self.t1 = None
9089

@@ -112,19 +111,19 @@ def toggle_code_context_event(self, event=None):
112111
padx += widget.tk.getint(info['padx'])
113112
padx += widget.tk.getint(widget.cget('padx'))
114113
border += widget.tk.getint(widget.cget('border'))
115-
self.context = tkinter.Text(
114+
context = self.context = tkinter.Text(
116115
self.editwin.text_frame,
117116
height=1,
118117
width=1, # Don't request more than we get.
119118
highlightthickness=0,
120119
padx=padx, border=border, relief=SUNKEN, state='disabled')
121120
self.update_font()
122121
self.update_highlight_colors()
123-
self.context.bind('<ButtonRelease-1>', self.jumptoline)
122+
context.bind('<ButtonRelease-1>', self.jumptoline)
124123
# Get the current context and initiate the recurring update event.
125124
self.timer_event()
126125
# Grid the context widget above the text widget.
127-
self.context.grid(row=0, column=1, sticky=NSEW)
126+
context.grid(row=0, column=1, sticky=NSEW)
128127

129128
line_number_colors = idleConf.GetHighlight(idleConf.CurrentTheme(),
130129
'linenumber')
@@ -215,18 +214,25 @@ def update_code_context(self):
215214
self.context['state'] = 'disabled'
216215

217216
def jumptoline(self, event=None):
218-
"Show clicked context line at top of editor."
219-
lines = len(self.info)
220-
if lines == 1: # No context lines are showing.
221-
newtop = 1
222-
else:
223-
# Line number clicked.
224-
contextline = int(float(self.context.index('insert')))
225-
# Lines not displayed due to maxlines.
226-
offset = max(1, lines - self.context_depth) - 1
227-
newtop = self.info[offset + contextline][0]
228-
self.text.yview(f'{newtop}.0')
229-
self.update_code_context()
217+
""" Show clicked context line at top of editor.
218+
219+
If a selection was made, don't jump; allow copying.
220+
If no visible context, show the top line of the file.
221+
"""
222+
try:
223+
self.context.index("sel.first")
224+
except tkinter.TclError:
225+
lines = len(self.info)
226+
if lines == 1: # No context lines are showing.
227+
newtop = 1
228+
else:
229+
# Line number clicked.
230+
contextline = int(float(self.context.index('insert')))
231+
# Lines not displayed due to maxlines.
232+
offset = max(1, lines - self.context_depth) - 1
233+
newtop = self.info[offset + contextline][0]
234+
self.text.yview(f'{newtop}.0')
235+
self.update_code_context()
230236

231237
def timer_event(self):
232238
"Event on editor text widget triggered every UPDATEINTERVAL ms."

Lib/idlelib/idle_test/test_codecontext.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,14 @@ def test_jumptoline(self):
332332
jump()
333333
eq(cc.topvisible, 8)
334334

335+
# Context selection stops jump.
336+
cc.text.yview('5.0')
337+
cc.update_code_context()
338+
cc.context.tag_add('sel', '1.0', '2.0')
339+
cc.context.mark_set('insert', '1.0')
340+
jump() # Without selection, to line 2.
341+
eq(cc.topvisible, 5)
342+
335343
@mock.patch.object(codecontext.CodeContext, 'update_code_context')
336344
def test_timer_event(self, mock_update):
337345
# Ensure code context is not active.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Selecting code context lines no longer causes a jump.

0 commit comments

Comments
 (0)