Skip to content

Commit 111a2f8

Browse files
committed
fixup! Merge pull request #123 from johnslavik/pablo-pyrepl-docstrings
1 parent 2c750c3 commit 111a2f8

File tree

4 files changed

+59
-15
lines changed

4 files changed

+59
-15
lines changed

Lib/_pyrepl/commands.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -464,8 +464,8 @@ def do(self) -> None:
464464

465465
with self.reader.suspend():
466466
self.reader.msg = _sitebuiltins._Helper()() # type: ignore[assignment]
467-
self.reader.invalidate_prompt()
468-
467+
self.reader.invalidate_prompt()
468+
469469

470470
class invalid_key(Command):
471471
def do(self) -> None:
@@ -491,13 +491,11 @@ def do(self) -> None:
491491
pager(history, gethistoryfile())
492492
self.reader.console.prepare()
493493

494-
# We need to copy over the state so that it's consistent between
495-
# console and reader, and console does not overwrite/append stuff
496-
trace("command.show_history sync_rendered_screen")
497-
self.reader.console.sync_rendered_screen(
498-
self.reader.rendered_screen,
499-
self.reader.cxy,
500-
)
494+
# After the pager exits, the screen state is unknown (Unix may
495+
# restore via alternate screen, Windows shows pager output).
496+
# Clear and force a full redraw for consistency.
497+
self.reader.console.clear()
498+
self.reader.invalidate_full()
501499

502500

503501
class paste_mode(Command):

Lib/_pyrepl/reader.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -357,15 +357,21 @@ def get_cached_location(
357357
return 0, 0
358358
if buffer_from_pos is None:
359359
buffer_from_pos = min(reader.pos, self.pos)
360-
offset = 0
361360
num_common_lines = len(self.line_end_offsets)
362361
while num_common_lines > 0:
363-
offset = self.line_end_offsets[num_common_lines - 1]
364-
if buffer_from_pos > offset:
362+
candidate = self.line_end_offsets[num_common_lines - 1]
363+
if buffer_from_pos > candidate:
365364
break
366365
num_common_lines -= 1
367-
else:
368-
offset = 0
366+
# Prompt-only leading rows consume no buffer content. Reusing them
367+
# in isolation causes the next incremental rebuild to emit them a
368+
# second time.
369+
while (
370+
num_common_lines > 0
371+
and self.layout_rows[num_common_lines - 1].buffer_advance == 0
372+
):
373+
num_common_lines -= 1
374+
offset = self.line_end_offsets[num_common_lines - 1] if num_common_lines else 0
369375
return offset, num_common_lines
370376

371377
last_refresh_cache: RefreshCache = field(default_factory=RefreshCache)

Lib/_pyrepl/windows_console.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -686,7 +686,7 @@ def getpending(self) -> Event:
686686
# ignore SHIFT_PRESSED and special keys
687687
continue
688688
if ch == "\r":
689-
ch += "\n"
689+
ch = "\n"
690690
e.data += ch
691691
return e
692692

Lib/test/test_pyrepl/test_reader.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,48 @@
2020
colors = {overrides.get(k, k[0].lower()): v for k, v in default_theme.syntax.items()}
2121

2222

23+
def prepare_reader_multiline_prompt(*args, **kwargs):
24+
reader = prepare_reader(*args, **kwargs)
25+
del reader.get_prompt
26+
reader.ps1 = "Python 3.15\n>>> "
27+
reader.ps2 = "Python 3.15\n>>> "
28+
reader.ps3 = "Python 3.15\n... "
29+
reader.ps4 = "Python 3.15\n... "
30+
reader.can_colorize = False
31+
reader.paste_mode = False
32+
return reader
33+
34+
2335
@force_not_colorized_test_class
2436
class TestReader(ScreenEqualMixin, TestCase):
37+
def assert_multiline_prompt_screen(self, code, expected_screen, expected_cxy):
38+
reader, _ = handle_all_events(
39+
code_to_events(code),
40+
prepare_reader=prepare_reader_multiline_prompt,
41+
)
42+
43+
self.assertEqual(reader.screen, expected_screen)
44+
self.assertEqual(reader.cxy, expected_cxy)
45+
46+
def test_multiline_prompt_does_not_duplicate_leading_lines(self):
47+
self.assert_multiline_prompt_screen(
48+
"abc",
49+
["Python 3.15", ">>> abc"],
50+
(7, 1),
51+
)
52+
53+
def test_multiline_prompt_does_not_duplicate_leading_lines_across_buffer_lines(self):
54+
self.assert_multiline_prompt_screen(
55+
"if x:\n y",
56+
[
57+
"Python 3.15",
58+
">>> if x:",
59+
"Python 3.15",
60+
"... y",
61+
],
62+
(13, 3),
63+
)
64+
2565
def test_calc_screen_wrap_simple(self):
2666
events = code_to_events(10 * "a")
2767
reader, _ = handle_events_narrow_console(events)

0 commit comments

Comments
 (0)