Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Lib/_pyrepl/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,11 @@ def disp_str(
if colors and colors[0].span.start == i: # new color starts now
pre_color = theme[colors[0].tag]

if c == "\x1a": # CTRL-Z on Windows
if c == "\t": # gh-140502: handle tabs
width = 8 - (sum(char_widths) % 8)
chars.append(" " * width)
char_widths.append(width)
elif c == "\x1a": # CTRL-Z on Windows
chars.append(c)
char_widths.append(2)
elif ord(c) < 128:
Expand Down
17 changes: 17 additions & 0 deletions Lib/test/test_pyrepl/test_pyrepl.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
ReadlineConfig,
_ReadlineWrapper,
)
from _pyrepl.utils import disp_str
from _pyrepl.readline import multiline_input as readline_multiline_input

try:
Expand Down Expand Up @@ -1911,3 +1912,19 @@ def test_ctrl_d_single_line_end_no_newline(self):
)
reader, _ = handle_all_events(events)
self.assertEqual("hello", "".join(reader.buffer))


class TestDispStr(TestCase):
def test_disp_str_width_calculation(self):
test_cases = [
("\tX", [8, 1]), # column 0 -> 8 spaces
("X\t", [1, 7]), # column 1 -> 7 spaces to column 8
("ABC\tX", [1, 1, 1, 5, 1]), # column 3 -> 5 spaces to column 8
("XXXXXXX\t", [1, 1, 1, 1, 1, 1, 1, 1]), # column 7 -> 1 space
("XXXXXXXX\t", [1, 1, 1, 1, 1, 1, 1, 1, 8]), # column 8 -> 8 spaces
("中\tX", [2, 6, 1]), # wide char + tab
]
for buffer, expected_widths in test_cases:
with self.subTest(buffer=repr(buffer)):
_, widths = disp_str(buffer, 0)
self.assertEqual(widths, expected_widths)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix: default REPL ``disp_str`` does not handle tab right.
Loading