]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-125377: Improve tab indentation for pdb multi-line input (#130471)
authorTian Gao <gaogaotiantian@hotmail.com>
Tue, 4 Mar 2025 20:45:38 +0000 (15:45 -0500)
committerGitHub <noreply@github.com>
Tue, 4 Mar 2025 20:45:38 +0000 (15:45 -0500)
Doc/whatsnew/3.14.rst
Lib/pdb.py
Lib/test/test_pdb.py
Misc/NEWS.d/next/Library/2025-02-22-19-44-00.gh-issue-125377.LFTK0H.rst [new file with mode: 0644]

index 8dfe25ad99abe38f46987e9e4b6128ba7fa6ec7f..b457ccf66571b0332c55b5d268f62ad839fc24d8 100644 (file)
@@ -785,6 +785,10 @@ pdb
   (if any).
   (Contributed by Tian Gao in :gh:`130493`.)
 
+* ``<tab>`` at the beginning of the line in :mod:`pdb` multi-line input will
+  fill in a 4-space indentation now, instead of inserting a ``\t`` character.
+  (Contributed by Tian Gao in :gh:`130471`.)
+
 
 pickle
 ------
index ea6a7890f8c2bc68854a08b4d86d239510ba84c9..75fc29068fa843908b7f3c93eac7b6ca28c0499d 100644 (file)
@@ -652,10 +652,10 @@ class Pdb(bdb.Bdb, cmd.Cmd):
             self.message(repr(obj))
 
     @contextmanager
-    def _disable_command_completion(self):
+    def _enable_multiline_completion(self):
         completenames = self.completenames
         try:
-            self.completenames = self.completedefault
+            self.completenames = self.complete_multiline_names
             yield
         finally:
             self.completenames = completenames
@@ -753,7 +753,7 @@ class Pdb(bdb.Bdb, cmd.Cmd):
             buffer = line
             if (code := codeop.compile_command(line + '\n', '<stdin>', 'single')) is None:
                 # Multi-line mode
-                with self._disable_command_completion():
+                with self._enable_multiline_completion():
                     buffer = line
                     continue_prompt = "...   "
                     while (code := codeop.compile_command(buffer, '<stdin>', 'single')) is None:
@@ -996,6 +996,21 @@ class Pdb(bdb.Bdb, cmd.Cmd):
             # Complete a simple name.
             return [n for n in ns.keys() if n.startswith(text)]
 
+    def _complete_indentation(self, text, line, begidx, endidx):
+        try:
+            import readline
+        except ImportError:
+            return []
+        # Fill in spaces to form a 4-space indent
+        return [' ' * (4 - readline.get_begidx() % 4)]
+
+    def complete_multiline_names(self, text, line, begidx, endidx):
+        # If text is space-only, the user entered <tab> before any text.
+        # That normally means they want to indent the current line.
+        if not text.strip():
+            return self._complete_indentation(text, line, begidx, endidx)
+        return self.completedefault(text, line, begidx, endidx)
+
     def completedefault(self, text, line, begidx, endidx):
         if text.startswith("$"):
             # Complete convenience variables
index a3246e4ec76b5061d4e690e3b8a4928f28e67ee6..94332f1daee47960a6e95df9249c621f67a659ed 100644 (file)
@@ -4513,6 +4513,32 @@ class PdbTestReadline(unittest.TestCase):
 
         self.assertIn(b'42', output)
 
+    def test_multiline_indent_completion(self):
+        script = textwrap.dedent("""
+            import pdb; pdb.Pdb().set_trace()
+        """)
+
+        # \t should always complete a 4-space indent
+        # This piece of code will raise an IndentationError or a SyntaxError
+        # if the completion is not working as expected
+        input = textwrap.dedent("""\
+            def func():
+            \ta = 1
+             \ta += 1
+              \ta += 1
+               \tif a > 0:
+                    a += 1
+            \t\treturn a
+
+            func()
+            c
+        """).encode()
+
+        output = run_pty(script, input)
+
+        self.assertIn(b'4', output)
+        self.assertNotIn(b'Error', output)
+
 
 def load_tests(loader, tests, pattern):
     from test import test_pdb
diff --git a/Misc/NEWS.d/next/Library/2025-02-22-19-44-00.gh-issue-125377.LFTK0H.rst b/Misc/NEWS.d/next/Library/2025-02-22-19-44-00.gh-issue-125377.LFTK0H.rst
new file mode 100644 (file)
index 0000000..b3b5275
--- /dev/null
@@ -0,0 +1 @@
+``<tab>`` at the beginning of the line in :mod:`pdb` multi-line input will fill in a 4-space indentation now, instead of inserting a ``\t`` character.