diff options
author | Matt Wozniski <mwozniski@bloomberg.net> | 2024-08-25 22:54:06 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-25 22:54:06 (GMT) |
commit | 602fcf97df1665538d4e9841f9dc6bc33e38bece (patch) | |
tree | cc892e3ee534c2781c0ce5dbf97658d08175c9e6 | |
parent | 70bfef52b5734d6cd81c5e8ca9eaf85658916b04 (diff) | |
download | cpython-602fcf97df1665538d4e9841f9dc6bc33e38bece.zip cpython-602fcf97df1665538d4e9841f9dc6bc33e38bece.tar.gz cpython-602fcf97df1665538d4e9841f9dc6bc33e38bece.tar.bz2 |
gh-123177: Fix prompt for wrapped lines in pyrepl (#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.
-rw-r--r-- | Lib/_pyrepl/reader.py | 10 | ||||
-rw-r--r-- | Lib/test/test_pyrepl/test_reader.py | 31 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Core_and_Builtins/2024-08-25-18-27-49.gh-issue-123177.yLuyqE.rst | 2 |
3 files changed, 42 insertions, 1 deletions
diff --git a/Lib/_pyrepl/reader.py b/Lib/_pyrepl/reader.py index 13b1f3e..aa3f5fd 100644 --- a/Lib/_pyrepl/reader.py +++ b/Lib/_pyrepl/reader.py @@ -345,7 +345,10 @@ class Reader: pos = self.pos pos -= offset + prompt_from_cache = (offset and self.buffer[offset - 1] != "\n") + lines = "".join(self.buffer[offset:]).split("\n") + cursor_found = False lines_beyond_cursor = 0 for ln, line in enumerate(lines, num_common_lines): @@ -359,7 +362,12 @@ class Reader: # No need to keep formatting lines. # The console can't show them. 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: pre_prompt, _, prompt = prompt.partition("\n") last_refresh_line_end_offsets.append(offset) diff --git a/Lib/test/test_pyrepl/test_reader.py b/Lib/test/test_pyrepl/test_reader.py index e82c3ca..6c72a1d 100644 --- a/Lib/test/test_pyrepl/test_reader.py +++ b/Lib/test/test_pyrepl/test_reader.py @@ -30,6 +30,37 @@ class TestReader(TestCase): reader, _ = handle_events_narrow_console(events) 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): # fmt: off code = ( diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-08-25-18-27-49.gh-issue-123177.yLuyqE.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-08-25-18-27-49.gh-issue-123177.yLuyqE.rst new file mode 100644 index 0000000..1f1791d --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2024-08-25-18-27-49.gh-issue-123177.yLuyqE.rst @@ -0,0 +1,2 @@ +Fix a bug causing stray prompts to appear in the middle of wrapped lines in +the new REPL. |