mirror of
https://github.com/python/cpython.git
synced 2025-09-25 01:43:11 +00:00
[3.13] gh-123177: Fix prompt for wrapped lines in pyrepl (GH-123324) (#123327)
gh-123177: Fix prompt for wrapped lines in pyrepl (GH-123324)
When display lines above the cursor come from the cache, the first line
to not come from the cache may be a wrapped line, starting half way
through a logical line in the buffer. Detect and handle this case to
avoid accidentally drawing a stray prompt in the middle of a logical
line.
(cherry picked from commit 602fcf97df
)
Co-authored-by: Matt Wozniski <mwozniski@bloomberg.net>
This commit is contained in:
parent
4817365581
commit
865bfb1530
3 changed files with 42 additions and 1 deletions
|
@ -345,7 +345,10 @@ class Reader:
|
||||||
pos = self.pos
|
pos = self.pos
|
||||||
pos -= offset
|
pos -= offset
|
||||||
|
|
||||||
|
prompt_from_cache = (offset and self.buffer[offset - 1] != "\n")
|
||||||
|
|
||||||
lines = "".join(self.buffer[offset:]).split("\n")
|
lines = "".join(self.buffer[offset:]).split("\n")
|
||||||
|
|
||||||
cursor_found = False
|
cursor_found = False
|
||||||
lines_beyond_cursor = 0
|
lines_beyond_cursor = 0
|
||||||
for ln, line in enumerate(lines, num_common_lines):
|
for ln, line in enumerate(lines, num_common_lines):
|
||||||
|
@ -359,7 +362,12 @@ class Reader:
|
||||||
# No need to keep formatting lines.
|
# No need to keep formatting lines.
|
||||||
# The console can't show them.
|
# The console can't show them.
|
||||||
break
|
break
|
||||||
prompt = self.get_prompt(ln, ll >= pos >= 0)
|
if prompt_from_cache:
|
||||||
|
# Only the first line's prompt can come from the cache
|
||||||
|
prompt_from_cache = False
|
||||||
|
prompt = ""
|
||||||
|
else:
|
||||||
|
prompt = self.get_prompt(ln, ll >= pos >= 0)
|
||||||
while "\n" in prompt:
|
while "\n" in prompt:
|
||||||
pre_prompt, _, prompt = prompt.partition("\n")
|
pre_prompt, _, prompt = prompt.partition("\n")
|
||||||
last_refresh_line_end_offsets.append(offset)
|
last_refresh_line_end_offsets.append(offset)
|
||||||
|
|
|
@ -31,6 +31,37 @@ class TestReader(TestCase):
|
||||||
reader, _ = handle_events_narrow_console(events)
|
reader, _ = handle_events_narrow_console(events)
|
||||||
self.assert_screen_equals(reader, f"{9*"a"}\\\n{9*"a"}\\\naa")
|
self.assert_screen_equals(reader, f"{9*"a"}\\\n{9*"a"}\\\naa")
|
||||||
|
|
||||||
|
def test_calc_screen_prompt_handling(self):
|
||||||
|
def prepare_reader_keep_prompts(*args, **kwargs):
|
||||||
|
reader = prepare_reader(*args, **kwargs)
|
||||||
|
del reader.get_prompt
|
||||||
|
reader.ps1 = ">>> "
|
||||||
|
reader.ps2 = ">>> "
|
||||||
|
reader.ps3 = "... "
|
||||||
|
reader.ps4 = ""
|
||||||
|
reader.can_colorize = False
|
||||||
|
reader.paste_mode = False
|
||||||
|
return reader
|
||||||
|
|
||||||
|
events = code_to_events("if some_condition:\nsome_function()")
|
||||||
|
reader, _ = handle_events_narrow_console(
|
||||||
|
events,
|
||||||
|
prepare_reader=prepare_reader_keep_prompts,
|
||||||
|
)
|
||||||
|
# fmt: off
|
||||||
|
self.assert_screen_equals(
|
||||||
|
reader,
|
||||||
|
(
|
||||||
|
">>> if so\\\n"
|
||||||
|
"me_condit\\\n"
|
||||||
|
"ion:\n"
|
||||||
|
"... s\\\n"
|
||||||
|
"ome_funct\\\n"
|
||||||
|
"ion()"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
# fmt: on
|
||||||
|
|
||||||
def test_calc_screen_wrap_three_lines_mixed_character(self):
|
def test_calc_screen_wrap_three_lines_mixed_character(self):
|
||||||
# fmt: off
|
# fmt: off
|
||||||
code = (
|
code = (
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Fix a bug causing stray prompts to appear in the middle of wrapped lines in
|
||||||
|
the new REPL.
|
Loading…
Add table
Add a link
Reference in a new issue