diff --git a/cli.py b/cli.py index 28cc3269a6..d5deded931 100644 --- a/cli.py +++ b/cli.py @@ -1540,13 +1540,14 @@ def _strip_leaked_bracketed_paste_wrappers(text: str) -> str: # that appears when the ESC byte was stripped by a prior filter. _DSR_CPR_ESC_RE = re.compile(r"\x1b\[\d+;\d+R") _DSR_CPR_VISIBLE_RE = re.compile(r"\^\[\[\d+;\d+R") -_SGR_MOUSE_ESC_RE = re.compile(r"\x1b\[<\d{1,3};\d{1,4};\d{1,4}[Mm]") -_SGR_MOUSE_VISIBLE_RE = re.compile(r"\^\[\[<\d{1,3};\d{1,4};\d{1,4}[Mm]") +_SGR_MOUSE_ESC_RE = re.compile(r"\x1b\[<\d+;\d+;\d+[Mm]") +_SGR_MOUSE_VISIBLE_RE = re.compile(r"\^\[\[<\d+;\d+;\d+[Mm]") # Some terminals/filters can drop ESC and literal "^[[", leaving only # " tuple[str, bool]: """ if not text: return text, False - had_mouse_reports = bool( - _SGR_MOUSE_ESC_RE.search(text) - or _SGR_MOUSE_VISIBLE_RE.search(text) - or _SGR_MOUSE_BARE_RE.search(text) - ) - text = _DSR_CPR_ESC_RE.sub("", text) - text = _DSR_CPR_VISIBLE_RE.sub("", text) - text = _SGR_MOUSE_ESC_RE.sub("", text) - text = _SGR_MOUSE_VISIBLE_RE.sub("", text) - text = _SGR_MOUSE_BARE_RE.sub("", text) + if not any(marker in text for marker in _TERMINAL_RESPONSE_SENTINELS): + return text, False + + had_mouse_reports = False + + if "\x1b[" in text: + text = _DSR_CPR_ESC_RE.sub("", text) + text, count = _SGR_MOUSE_ESC_RE.subn("", text) + had_mouse_reports = had_mouse_reports or count > 0 + + if "^[" in text: + text = _DSR_CPR_VISIBLE_RE.sub("", text) + text, count = _SGR_MOUSE_VISIBLE_RE.subn("", text) + had_mouse_reports = had_mouse_reports or count > 0 + + if "<" in text: + text, count = _SGR_MOUSE_BARE_RE.subn("", text) + had_mouse_reports = had_mouse_reports or count > 0 + return text, had_mouse_reports diff --git a/tests/cli/test_cli_terminal_response_sanitizer.py b/tests/cli/test_cli_terminal_response_sanitizer.py index 11a0a9e351..1db16df90b 100644 --- a/tests/cli/test_cli_terminal_response_sanitizer.py +++ b/tests/cli/test_cli_terminal_response_sanitizer.py @@ -68,6 +68,10 @@ class TestStripLeakedTerminalResponses: text = "abc<65;1;49Mdef" assert _strip_leaked_terminal_responses(text) == "abcdef" + def test_strips_sgr_mouse_report_with_large_coordinates(self): + text = "abc\x1b[<10000;12345;98765Mdef" + assert _strip_leaked_terminal_responses(text) == "abcdef" + def test_strips_multiple_concatenated_sgr_mouse_reports(self): text = "<65;1;49M<35;1;42Mhello<64;1;40m" assert _strip_leaked_terminal_responses(text) == "hello"