[Python-checkins] bpo-39885: Make IDLE context menu cut and copy work again (GH-18951)

Miss Islington (bot) webhook-mailer at python.org
Fri May 29 19:11:36 EDT 2020


https://github.com/python/cpython/commit/80b6a05d38ce34ef543a2376b8132eef4ada67ce
commit: 80b6a05d38ce34ef543a2376b8132eef4ada67ce
branch: 3.7
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: GitHub <noreply at github.com>
date: 2020-05-29T16:11:28-07:00
summary:

bpo-39885: Make IDLE context menu cut and copy work again (GH-18951)


Leave selection when right click within.  This exception to clearing selections when right-clicking was omitted from the previous commit, 4ca060d.  I did not realize that this completely disabled the context menu entries, and  I should have merged a minimal fix immediately.  An automated test should follow.
(cherry picked from commit 97e4e0f53d6690db6b942678489716a30925b8af)

Co-authored-by: Terry Jan Reedy <tjreedy at udel.edu>

files:
A Misc/NEWS.d/next/IDLE/2020-05-29-18-21-58.bpo-39885.zB_-bN.rst
M Lib/idlelib/NEWS.txt
M Lib/idlelib/editor.py
M Lib/idlelib/idle_test/test_editor.py

diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt
index 8226af4a4de6c..c751dc3bb099a 100644
--- a/Lib/idlelib/NEWS.txt
+++ b/Lib/idlelib/NEWS.txt
@@ -17,8 +17,9 @@ Released on 2020-03-10
 bpo-27115: For 'Go to Line', use a Query entry box subclass with
 IDLE standard behavior and improved error checking.
 
-bpo-39885: Since clicking to get an IDLE context menu moves the
-cursor, any text selection should be and now is cleared.
+bpo-39885: When a context menu is invoked by right-clicking outside
+of a selection, clear the selection and move the cursor.  Cut and
+Copy require that the click be within the selection.
 
 bpo-39852: Edit "Go to line" now clears any selection, preventing
 accidental deletion.  It also updates Ln and Col on the status bar.
diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py
index b0f88b5463d1b..a178eaf93c013 100644
--- a/Lib/idlelib/editor.py
+++ b/Lib/idlelib/editor.py
@@ -499,15 +499,23 @@ def handle_yview(self, event, *args):
     rmenu = None
 
     def right_menu_event(self, event):
-        self.text.tag_remove("sel", "1.0", "end")
-        self.text.mark_set("insert", "@%d,%d" % (event.x, event.y))
+        text = self.text
+        newdex = text.index(f'@{event.x},{event.y}')
+        try:
+            in_selection = (text.compare('sel.first', '<=', newdex) and
+                           text.compare(newdex, '<=',  'sel.last'))
+        except TclError:
+            in_selection = False
+        if not in_selection:
+            text.tag_remove("sel", "1.0", "end")
+            text.mark_set("insert", newdex)
         if not self.rmenu:
             self.make_rmenu()
         rmenu = self.rmenu
         self.event = event
         iswin = sys.platform[:3] == 'win'
         if iswin:
-            self.text.config(cursor="arrow")
+            text.config(cursor="arrow")
 
         for item in self.rmenu_specs:
             try:
@@ -520,7 +528,6 @@ def right_menu_event(self, event):
             state = getattr(self, verify_state)()
             rmenu.entryconfigure(label, state=state)
 
-
         rmenu.tk_popup(event.x_root, event.y_root)
         if iswin:
             self.text.config(cursor="ibeam")
diff --git a/Lib/idlelib/idle_test/test_editor.py b/Lib/idlelib/idle_test/test_editor.py
index 91e8ef89d1d72..443dcf021679f 100644
--- a/Lib/idlelib/idle_test/test_editor.py
+++ b/Lib/idlelib/idle_test/test_editor.py
@@ -5,6 +5,7 @@
 from collections import namedtuple
 from test.support import requires
 from tkinter import Tk
+from idlelib.idle_test.mock_idle import Func
 
 Editor = editor.EditorWindow
 
@@ -92,6 +93,12 @@ def test_tabwidth_8(self):
                 )
 
 
+def insert(text, string):
+    text.delete('1.0', 'end')
+    text.insert('end', string)
+    text.update()  # Force update for colorizer to finish.
+
+
 class IndentAndNewlineTest(unittest.TestCase):
 
     @classmethod
@@ -113,13 +120,6 @@ def tearDownClass(cls):
         cls.root.destroy()
         del cls.root
 
-    def insert(self, text):
-        t = self.window.text
-        t.delete('1.0', 'end')
-        t.insert('end', text)
-        # Force update for colorizer to finish.
-        t.update()
-
     def test_indent_and_newline_event(self):
         eq = self.assertEqual
         w = self.window
@@ -170,13 +170,13 @@ def test_indent_and_newline_event(self):
         w.prompt_last_line = ''
         for test in tests:
             with self.subTest(label=test.label):
-                self.insert(test.text)
+                insert(text, test.text)
                 text.mark_set('insert', test.mark)
                 nl(event=None)
                 eq(get('1.0', 'end'), test.expected)
 
         # Selected text.
-        self.insert('  def f1(self, a, b):\n    return a + b')
+        insert(text, '  def f1(self, a, b):\n    return a + b')
         text.tag_add('sel', '1.17', '1.end')
         nl(None)
         # Deletes selected text before adding new line.
@@ -184,11 +184,37 @@ def test_indent_and_newline_event(self):
 
         # Preserves the whitespace in shell prompt.
         w.prompt_last_line = '>>> '
-        self.insert('>>> \t\ta =')
+        insert(text, '>>> \t\ta =')
         text.mark_set('insert', '1.5')
         nl(None)
         eq(get('1.0', 'end'), '>>> \na =\n')
 
 
+class RMenuTest(unittest.TestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        requires('gui')
+        cls.root = Tk()
+        cls.root.withdraw()
+        cls.window = Editor(root=cls.root)
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.window._close()
+        del cls.window
+        cls.root.update_idletasks()
+        for id in cls.root.tk.call('after', 'info'):
+            cls.root.after_cancel(id)
+        cls.root.destroy()
+        del cls.root
+
+    class DummyRMenu:
+        def tk_popup(x, y): pass
+
+    def test_rclick(self):
+        pass
+
+
 if __name__ == '__main__':
     unittest.main(verbosity=2)
diff --git a/Misc/NEWS.d/next/IDLE/2020-05-29-18-21-58.bpo-39885.zB_-bN.rst b/Misc/NEWS.d/next/IDLE/2020-05-29-18-21-58.bpo-39885.zB_-bN.rst
new file mode 100644
index 0000000000000..a847b75997117
--- /dev/null
+++ b/Misc/NEWS.d/next/IDLE/2020-05-29-18-21-58.bpo-39885.zB_-bN.rst
@@ -0,0 +1,2 @@
+Make context menu Cut and Copy work again when right-clicking within a
+selection.



More information about the Python-checkins mailing list