8000 gh-133349: Enable auto-indent for pdb's multi-line mode (#133350) · python/cpython@9aa8261 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9aa8261

Browse files
gaogaotiantiannascheme
authored andcommitted
gh-133349: Enable auto-indent for pdb's multi-line mode (#133350)
1 parent 4ac916a commit 9aa8261

File tree

4 files changed

+66
-12
lines changed

4 files changed

+66
-12
lines changed

Doc/whatsnew/3.14.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1443,6 +1443,11 @@ pdb
14431443
fill in a 4-space indentation now, instead of inserting a ``\t`` character.
14441444
(Contributed by Tian Gao in :gh:`130471`.)
14451445

1446+
* Auto-indent is introduced in :mod:`pdb` multi-line input. It will either
1447+
keep the indentation of the last line or insert a 4-space indentation when
1448+
it detects a new code block.
1449+
(Contributed by Tian Gao in :gh:`133350`.)
1450+
14461451
* ``$_asynctask`` is added to access the current asyncio task if applicable.
14471452
(Contributed by Tian Gao in :gh:`124367`.)
14481453

Lib/pdb.py

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -745,12 +745,34 @@ def displayhook(self, obj):
745745
self.message(repr(obj))
746746

747747
@contextmanager
748-
def _enable_multiline_completion(self):
748+
def _enable_multiline_input(self):
749+
try:
750+
import readline
751+
except ImportError:
752+
yield
753+
return
754+
755+
def input_auto_indent():
756+
last_index = readline.get_current_history_length()
757+
last_line = readline.get_history_item(last_index)
758+
if last_line:
759+
if last_line.isspace():
760+
# If the last line is empty, we don't need to indent
761+
return
762+
763+
last_line = last_line.rstrip('\r\n')
764+
indent = len(last_line) - len(last_line.lstrip())
765+
if last_line.endswith(":"):
766+
indent += 4
767+
readline.insert_text(' ' * indent)
768+
749769
completenames = self.completenames
750770
try:
751771
self.completenames = self.complete_multiline_names
772+
readline.set_startup_hook(input_auto_indent)
752773
yield
753774
finally:
775+
readline.set_startup_hook()
754776
self.completenames = completenames
755777
return
756778

@@ -859,7 +881,7 @@ def _read_code(self, line):
859881
try:
860882
if (code := codeop.compile_command(line + '\n', '<stdin>', 'single')) is None:
861883
# Multi-line mode
862-
with self._enable_multiline_completion():
884+
with self._enable_multiline_input():
863885
buffer = line
864886
continue_prompt = "... "
865887
while (code := codeop.compile_command(buffer, '<stdin>', 'single')) is None:
@@ -881,7 +903,11 @@ def _read_code(self, line):
881903
return None, None, False
882904
else:
883905
line = line.rstrip('\r\n')
884-
buffer += '\n' + line
906+
if line.isspace():
907+
# empty line, just continue
908+
buffer += '\n'
909+
else:
910+
buffer += '\n' + line
885911
self.lastcmd = buffer
886912
except SyntaxError as e:
887913
# Maybe it's an await expression/statement

Lib/test/test_pdb.py

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4849,14 +4849,35 @@ def f():
48494849

48504850
self.assertIn(b'I love Python', output)
48514851

4852+
def test_multiline_auto_indent(self):
4853+
script = textwrap.dedent("""
4854+
import pdb; pdb.Pdb().set_trace()
4855+
""")
4856+
4857+
input = b"def f(x):\n"
4858+
input += b"if x > 0:\n"
4859+
input += b"x += 1\n"
4860+
input += b"return x\n"
4861+
# We need to do backspaces to remove the auto-indentation
4862+
input += b"\x08\x08\x08\x08else:\n"
4863+
input += b" 628C ;return -x\n"
4864+
input += b"\n"
4865+
input += b"f(-21-21)\n"
4866+
input += b"c\n"
4867+
4868+
output = run_pty(script, input)
4869+
4870+
self.assertIn(b'42', output)
4871+
48524872
def test_multiline_completion(self):
48534873
script = textwrap.dedent("""
48544874
import pdb; pdb.Pdb().set_trace()
48554875
""")
48564876

48574877
input = b"def func():\n"
4858-
# Complete: \treturn 40 + 2
4859-
input += b"\tret\t 40 + 2\n"
4878+
# Auto-indent
4879+
# Complete: return 40 + 2
4880+
input += b"ret\t 40 + 2\n"
48604881
input += b"\n"
48614882
# Complete: func()
48624883
input += b"fun\t()\n"
@@ -4876,20 +4897,21 @@ def test_multiline_indent_completion(self):
48764897
# if the completion is not working as expected
48774898
input = textwrap.dedent("""\
48784899
def func():
4879-
\ta = 1
4880-
\ta += 1
4881-
\ta += 1
4882-
\tif a > 0:
4883-
a += 1
4884-
\t\treturn a
4900+
a = 1
4901+
\x08\ta += 1
4902+
\x08\x08\ta += 1
4903+
\x08\x08\x08\ta += 1
4904+
\x08\x08\x08\x08\tif a > 0:
4905+
a += 1
4906+
\x08\x08\x08\x08return a
48854907
48864908
func()
48874909
c
48884910
""").encode()
48894911

48904912
output = run_pty(script, input)
48914913

4892-
self.assertIn(b'4', output)
4914+
self.assertIn(b'5', output)
48934915
self.assertNotIn(b'Error', output)
48944916

48954917
def test_interact_completion(self):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Introduced auto-indent in :mod:`pdb` multi-line input.

0 commit comments

Comments
 (0)
0