]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-39781: Do not jump when select in IDLE codecontext (GH-18683)
authorTerry Jan Reedy <tjreedy@udel.edu>
Fri, 28 Feb 2020 18:22:55 +0000 (13:22 -0500)
committerGitHub <noreply@github.com>
Fri, 28 Feb 2020 18:22:55 +0000 (13:22 -0500)
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

Lib/idlelib/NEWS.txt
Lib/idlelib/codecontext.py
Lib/idlelib/idle_test/test_codecontext.py
Misc/NEWS.d/next/IDLE/2020-02-27-22-17-09.bpo-39781.bbYBeL.rst [new file with mode: 0644]

index 021e1f7710e0f8997a6dc18f858f741e0210b20e..0651b3d68dc8b17fdd227cb6f8682d4e0d174d84 100644 (file)
@@ -3,6 +3,8 @@ Released on 2020-10-05?
 ======================================
 
 
+bpo-39781: Selecting code context lines no longer causes a jump.
+
 bpo-39663: Add tests for pyparse find_good_parse_start().
 
 bpo-39600: Remove duplicate font names from configuration list.
index 4ce98136fe417592ba0e1aa05146ae12b6742007..989b30e5994650c745eccb302c0e24ef636a4522 100644 (file)
@@ -7,7 +7,6 @@ the lines which contain the block opening keywords, e.g. 'if', for the
 enclosing block.  The number of hint lines is determined by the maxlines
 variable in the codecontext section of config-extensions.def. Lines which do
 not open blocks are not shown in the context hints pane.
-
 """
 import re
 from sys import maxsize as INFINITY
@@ -17,8 +16,8 @@ from tkinter.constants import NSEW, SUNKEN
 
 from idlelib.config import idleConf
 
-BLOCKOPENERS = {"class", "def", "elif", "else", "except", "finally", "for",
-                "if", "try", "while", "with", "async"}
+BLOCKOPENERS = {'class', 'def', 'if', 'elif', 'else', 'while', 'for',
+                 'try', 'except', 'finally', 'with', 'async'}
 
 
 def get_spaces_firstword(codeline, c=re.compile(r"^(\s*)(\w*)")):
@@ -84,7 +83,7 @@ class CodeContext:
         if self.t1 is not None:
             try:
                 self.text.after_cancel(self.t1)
-            except tkinter.TclError:
+            except tkinter.TclError:  # pragma: no cover
                 pass
             self.t1 = None
 
@@ -112,7 +111,7 @@ class CodeContext:
                 padx += widget.tk.getint(info['padx'])
                 padx += widget.tk.getint(widget.cget('padx'))
                 border += widget.tk.getint(widget.cget('border'))
-            self.context = tkinter.Text(
+            context = self.context = tkinter.Text(
                 self.editwin.text_frame,
                 height=1,
                 width=1,  # Don't request more than we get.
@@ -120,11 +119,11 @@ class CodeContext:
                 padx=padx, border=border, relief=SUNKEN, state='disabled')
             self.update_font()
             self.update_highlight_colors()
-            self.context.bind('<ButtonRelease-1>', self.jumptoline)
+            context.bind('<ButtonRelease-1>', self.jumptoline)
             # Get the current context and initiate the recurring update event.
             self.timer_event()
             # Grid the context widget above the text widget.
-            self.context.grid(row=0, column=1, sticky=NSEW)
+            context.grid(row=0, column=1, sticky=NSEW)
 
             line_number_colors = idleConf.GetHighlight(idleConf.CurrentTheme(),
                                                        'linenumber')
@@ -215,18 +214,25 @@ class CodeContext:
         self.context['state'] = 'disabled'
 
     def jumptoline(self, event=None):
-        "Show clicked context line at top of editor."
-        lines = len(self.info)
-        if lines == 1:  # No context lines are showing.
-            newtop = 1
-        else:
-            # Line number clicked.
-            contextline = int(float(self.context.index('insert')))
-            # Lines not displayed due to maxlines.
-            offset = max(1, lines - self.context_depth) - 1
-            newtop = self.info[offset + contextline][0]
-        self.text.yview(f'{newtop}.0')
-        self.update_code_context()
+        """ Show clicked context line at top of editor.
+
+        If a selection was made, don't jump; allow copying.
+        If no visible context, show the top line of the file.
+        """
+        try:
+            self.context.index("sel.first")
+        except tkinter.TclError:
+            lines = len(self.info)
+            if lines == 1:  # No context lines are showing.
+                newtop = 1
+            else:
+                # Line number clicked.
+                contextline = int(float(self.context.index('insert')))
+                # Lines not displayed due to maxlines.
+                offset = max(1, lines - self.context_depth) - 1
+                newtop = self.info[offset + contextline][0]
+            self.text.yview(f'{newtop}.0')
+            self.update_code_context()
 
     def timer_event(self):
         "Event on editor text widget triggered every UPDATEINTERVAL ms."
index 3ec49e97af6f916c19111e09553ac096b65e306f..9578cc731a6f93aee4777e53c41e842818c04057 100644 (file)
@@ -332,6 +332,14 @@ class CodeContextTest(unittest.TestCase):
         jump()
         eq(cc.topvisible, 8)
 
+        # Context selection stops jump.
+        cc.text.yview('5.0')
+        cc.update_code_context()
+        cc.context.tag_add('sel', '1.0', '2.0')
+        cc.context.mark_set('insert', '1.0')
+        jump()  # Without selection, to line 2.
+        eq(cc.topvisible, 5)
+
     @mock.patch.object(codecontext.CodeContext, 'update_code_context')
     def test_timer_event(self, mock_update):
         # Ensure code context is not active.
diff --git a/Misc/NEWS.d/next/IDLE/2020-02-27-22-17-09.bpo-39781.bbYBeL.rst b/Misc/NEWS.d/next/IDLE/2020-02-27-22-17-09.bpo-39781.bbYBeL.rst
new file mode 100644 (file)
index 0000000..4ae0def
--- /dev/null
@@ -0,0 +1 @@
+Selecting code context lines no longer causes a jump.