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/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 ( 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 diff --git a/Lib/test/test_pyrepl/test_pyrepl.py b/Lib/test/test_pyrepl/test_pyrepl.py index 8a3cae966a6e05..026e8ba91361f5 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( @@ -236,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"))