From 86977f93a5b5213c2c8477c033ca7640f64e10be Mon Sep 17 00:00:00 2001 From: johnslavik Date: Tue, 7 Apr 2026 19:13:48 +0200 Subject: [PATCH 1/4] Enable error overlays --- Lib/_colorize.py | 1 + Lib/_pyrepl/reader.py | 7 ++++++- Lib/_pyrepl/readline.py | 3 --- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Lib/_colorize.py b/Lib/_colorize.py index 8361ddbea89716..fd0ed2f93b2d6d 100644 --- a/Lib/_colorize.py +++ b/Lib/_colorize.py @@ -334,6 +334,7 @@ class LiveProfiler(ThemeSection): @dataclass(frozen=True, kw_only=True) class Syntax(ThemeSection): prompt: str = ANSIColors.BOLD_MAGENTA + error: str = ANSIColors.BOLD_RED keyword: str = ANSIColors.BOLD_BLUE keyword_constant: str = ANSIColors.BOLD_BLUE builtin: str = ANSIColors.CYAN diff --git a/Lib/_pyrepl/reader.py b/Lib/_pyrepl/reader.py index f35a99fb06a3f9..3c1ce72f834233 100644 --- a/Lib/_pyrepl/reader.py +++ b/Lib/_pyrepl/reader.py @@ -196,6 +196,7 @@ class Reader: ps3: str = "|.. " ps4: str = R"\__ " kill_ring: list[list[str]] = field(default_factory=list) + error_prefix: str = "! " msg: str = "" arg: int | None = None dirty: bool = False @@ -641,7 +642,11 @@ def finish(self) -> None: pass def error(self, msg: str = "none") -> None: - self.msg = "! " + msg + " " + error_prefix = self.error_prefix + if self.can_colorize: + t = THEME() + error_prefix = f"{t.error}{error_prefix}{t.reset}" + self.msg = error_prefix + msg self.dirty = True self.console.beep() diff --git a/Lib/_pyrepl/readline.py b/Lib/_pyrepl/readline.py index 8d3be37b4adeec..2cce542a73d28e 100644 --- a/Lib/_pyrepl/readline.py +++ b/Lib/_pyrepl/readline.py @@ -124,9 +124,6 @@ def __post_init__(self) -> None: self.commands["backspace_dedent"] = backspace_dedent self.commands["backspace-dedent"] = backspace_dedent - def error(self, msg: str = "none") -> None: - pass # don't show error messages by default - def get_stem(self) -> str: b = self.buffer p = self.pos - 1 From 9415f6b7ed96f6053ddd23b554dd0d9a1e91a632 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Tue, 7 Apr 2026 19:49:10 +0200 Subject: [PATCH 2/4] Fix `down` command error reporting bug --- Lib/_pyrepl/commands.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Lib/_pyrepl/commands.py b/Lib/_pyrepl/commands.py index 10127e58897a58..a52ac8889018be 100644 --- a/Lib/_pyrepl/commands.py +++ b/Lib/_pyrepl/commands.py @@ -289,8 +289,10 @@ def do(self) -> None: r.select_item(r.historyi + 1) r.pos = r.eol(0) return - r.pos = len(b) - r.error("end of buffer") + if r.pos == len(b): + r.error("end of buffer") + else: + r.pos = len(b) return if ( From 62b357797ba3e1c6a28cd25fd323d0baf0737150 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Tue, 7 Apr 2026 19:54:23 +0200 Subject: [PATCH 3/4] Fix `test_down_arrow_end_of_input` --- Lib/test/test_pyrepl/test_pyrepl.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_pyrepl/test_pyrepl.py b/Lib/test/test_pyrepl/test_pyrepl.py index 8a3cae966a6e05..ce98e7b8acdb88 100644 --- a/Lib/test/test_pyrepl/test_pyrepl.py +++ b/Lib/test/test_pyrepl/test_pyrepl.py @@ -212,13 +212,15 @@ def test_down_arrow_end_of_input(self): events = itertools.chain( code_to_events(code), [ + # Go left first to avoid end of buffer error. + Event(evt="key", data="left", raw=bytearray(b"\x1bOD")), Event(evt="key", data="down", raw=bytearray(b"\x1bOB")), ], ) reader, console = handle_all_events(events) self.assertEqual(reader.cxy, (0, 2)) - console.move_cursor.assert_called_once_with(0, 2) + console.move_cursor.assert_called_with(0, 2) def test_left_arrow_simple(self): events = itertools.chain( From 50188d301912e1ef08bc90106c7239a8242fd32f Mon Sep 17 00:00:00 2001 From: johnslavik Date: Tue, 7 Apr 2026 19:54:44 +0200 Subject: [PATCH 4/4] Fix `test_right_arrow_end_of_line` test --- Lib/test/test_pyrepl/test_pyrepl.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_pyrepl/test_pyrepl.py b/Lib/test/test_pyrepl/test_pyrepl.py index ce98e7b8acdb88..026e8ba91361f5 100644 --- a/Lib/test/test_pyrepl/test_pyrepl.py +++ b/Lib/test/test_pyrepl/test_pyrepl.py @@ -238,13 +238,15 @@ def test_right_arrow_end_of_line(self): events = itertools.chain( code_to_events("11+11"), [ + # Go left first to avoid end of buffer error. + Event(evt="key", data="left", raw=bytearray(b"\x1bOD")), Event(evt="key", data="right", raw=bytearray(b"\x1bOC")), ], ) reader, console = handle_all_events(events) self.assertEqual(reader.cxy, (5, 0)) - console.move_cursor.assert_called_once_with(5, 0) + console.move_cursor.assert_called_with(5, 0) def test_cursor_position_simple_character(self): events = itertools.chain(code_to_events("k"))