]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-60436: fix curses textbox backspace/del (#103783)
authorAidan Melen <aidan-melen@protonmail.com>
Wed, 26 Apr 2023 20:54:07 +0000 (14:54 -0600)
committerGitHub <noreply@github.com>
Wed, 26 Apr 2023 20:54:07 +0000 (22:54 +0200)
Co-authored-by: Ɓukasz Langa <lukasz@langa.pl>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Co-authored-by: Michael Blahay <mblahay@gmail.com>
Lib/curses/textpad.py
Lib/test/test_curses.py
Misc/NEWS.d/next/macOS/2023-04-24-18-37-48.gh-issue-60436.in-IyF.rst [new file with mode: 0644]

index 2079953a06614ba7ffc8f669ed9849f9b4d2ceb4..aa87061b8d749e97245676ef3d78c2b4cb034193 100644 (file)
@@ -102,7 +102,10 @@ class Textbox:
                 self._insert_printable_char(ch)
         elif ch == curses.ascii.SOH:                           # ^a
             self.win.move(y, 0)
-        elif ch in (curses.ascii.STX,curses.KEY_LEFT, curses.ascii.BS,curses.KEY_BACKSPACE):
+        elif ch in (curses.ascii.STX,curses.KEY_LEFT,
+                    curses.ascii.BS,
+                    curses.KEY_BACKSPACE,
+                    curses.ascii.DEL):
             if x > 0:
                 self.win.move(y, x-1)
             elif y == 0:
@@ -111,7 +114,7 @@ class Textbox:
                 self.win.move(y-1, self._end_of_line(y-1))
             else:
                 self.win.move(y-1, self.maxx)
-            if ch in (curses.ascii.BS, curses.KEY_BACKSPACE):
+            if ch in (curses.ascii.BS, curses.KEY_BACKSPACE, curses.ascii.DEL):
                 self.win.delch()
         elif ch == curses.ascii.EOT:                           # ^d
             self.win.delch()
index b550f4af555ce4e96bf9ad6aff23ff798bf5dc79..3ab837e4f95681aff64d151538ce9b01521cbada 100644 (file)
@@ -5,6 +5,7 @@ import string
 import sys
 import tempfile
 import unittest
+from unittest.mock import MagicMock
 
 from test.support import (requires, verbose, SaveSignals, cpython_only,
                           check_disallow_instantiation)
@@ -1319,5 +1320,75 @@ def lorem_ipsum(win):
     for y, line in enumerate(text[:maxy]):
         win.addstr(y, 0, line[:maxx - (y == maxy - 1)])
 
+
+class TextboxTest(unittest.TestCase):
+    def setUp(self):
+        self.mock_win = MagicMock(spec=curses.window)
+        self.mock_win.getyx.return_value = (1, 1)
+        self.mock_win.getmaxyx.return_value = (10, 20)
+        self.textbox = curses.textpad.Textbox(self.mock_win)
+
+    def test_init(self):
+        """Test textbox initialization."""
+        self.mock_win.reset_mock()
+        tb = curses.textpad.Textbox(self.mock_win)
+        self.mock_win.getmaxyx.assert_called_once_with()
+        self.mock_win.keypad.assert_called_once_with(1)
+        self.assertEqual(tb.insert_mode, False)
+        self.assertEqual(tb.stripspaces, 1)
+        self.assertIsNone(tb.lastcmd)
+        self.mock_win.reset_mock()
+
+    def test_insert(self):
+        """Test inserting a printable character."""
+        self.mock_win.reset_mock()
+        self.textbox.do_command(ord('a'))
+        self.mock_win.addch.assert_called_with(ord('a'))
+        self.textbox.do_command(ord('b'))
+        self.mock_win.addch.assert_called_with(ord('b'))
+        self.textbox.do_command(ord('c'))
+        self.mock_win.addch.assert_called_with(ord('c'))
+        self.mock_win.reset_mock()
+
+    def test_delete(self):
+        """Test deleting a character."""
+        self.mock_win.reset_mock()
+        self.textbox.do_command(curses.ascii.BS)
+        self.textbox.do_command(curses.KEY_BACKSPACE)
+        self.textbox.do_command(curses.ascii.DEL)
+        assert self.mock_win.delch.call_count == 3
+        self.mock_win.reset_mock()
+
+    def test_move_left(self):
+        """Test moving the cursor left."""
+        self.mock_win.reset_mock()
+        self.textbox.do_command(curses.KEY_LEFT)
+        self.mock_win.move.assert_called_with(1, 0)
+        self.textbox.do_command(curses.KEY_RIGHT)
+        self.mock_win.move.assert_called_with(1, 2)
+        self.mock_win.reset_mock()
+
+    def test_move_left(self):
+        """Test moving the cursor left."""
+        self.mock_win.reset_mock()
+        self.textbox.do_command(curses.KEY_RIGHT)
+        self.mock_win.move.assert_called_with(1, 2)
+        self.mock_win.reset_mock()
+
+    def test_move_up(self):
+        """Test moving the cursor left."""
+        self.mock_win.reset_mock()
+        self.textbox.do_command(curses.KEY_UP)
+        self.mock_win.move.assert_called_with(0, 1)
+        self.mock_win.reset_mock()
+
+    def test_move_down(self):
+        """Test moving the cursor left."""
+        self.mock_win.reset_mock()
+        self.textbox.do_command(curses.KEY_DOWN)
+        self.mock_win.move.assert_called_with(2, 1)
+        self.mock_win.reset_mock()
+
+
 if __name__ == '__main__':
     unittest.main()
diff --git a/Misc/NEWS.d/next/macOS/2023-04-24-18-37-48.gh-issue-60436.in-IyF.rst b/Misc/NEWS.d/next/macOS/2023-04-24-18-37-48.gh-issue-60436.in-IyF.rst
new file mode 100644 (file)
index 0000000..f274d3b
--- /dev/null
@@ -0,0 +1 @@
+update curses textbox to additionally handle backspace using the ``curses.ascii.DEL`` key press.