From b02974209208ba545501865d9982a42e6b530e76 Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Sat, 28 Mar 2026 15:40:49 -0700 Subject: [PATCH] fix(cli): strengthen paste collapse fallback for terminals without bracketed paste (#3625) The _on_text_changed fallback only detected pastes when all characters arrived in a single event (chars_added > 1). Some terminals (notably VSCode integrated terminal in certain configs) may deliver paste data differently, causing the fallback to miss. Add a second heuristic: if the newline count jumps by 4+ in a single text-change event, treat it as a paste. Alt+Enter only adds 1 newline per event, so this never false-positives on manual multi-line input. Also fixes: the fallback path was missing _paste_just_collapsed flag set before replacing buffer text, which could cause a re-trigger loop. --- cli.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/cli.py b/cli.py index 8aaf1378bc..22594875f0 100644 --- a/cli.py +++ b/cli.py @@ -6656,6 +6656,7 @@ class HermesCLI: # Paste collapsing: detect large pastes and save to temp file _paste_counter = [0] _prev_text_len = [0] + _prev_newline_count = [0] _paste_just_collapsed = [False] def _on_text_changed(buf): @@ -6664,18 +6665,27 @@ class HermesCLI: When bracketed paste is available, handle_paste collapses large pastes directly. This handler is a fallback for terminals without bracketed paste support. + + Two heuristics (either triggers collapse): + 1. Many characters added at once (chars_added > 1) — works + when the terminal delivers the paste in one event-loop tick. + 2. Newline count jumped by 4+ in a single text-change event — + catches terminals that feed characters individually but + still batch newlines. Alt+Enter only adds 1 newline per + event so it never triggers this. """ text = buf.text chars_added = len(text) - _prev_text_len[0] _prev_text_len[0] = len(text) if _paste_just_collapsed[0]: _paste_just_collapsed[0] = False + _prev_newline_count[0] = text.count('\n') return line_count = text.count('\n') - # Heuristic: a real paste adds many characters at once (not just a - # single newline from Alt+Enter) AND the result has 5+ lines. - # Fallback for terminals without bracketed paste support. - if line_count >= 5 and chars_added > 1 and not text.startswith('/'): + newlines_added = line_count - _prev_newline_count[0] + _prev_newline_count[0] = line_count + is_paste = chars_added > 1 or newlines_added >= 4 + if line_count >= 5 and is_paste and not text.startswith('/'): _paste_counter[0] += 1 # Save to temp file paste_dir = _hermes_home / "pastes" @@ -6683,6 +6693,7 @@ class HermesCLI: paste_file = paste_dir / f"paste_{_paste_counter[0]}_{datetime.now().strftime('%H%M%S')}.txt" paste_file.write_text(text, encoding="utf-8") # Replace buffer with compact reference + _paste_just_collapsed[0] = True buf.text = f"[Pasted text #{_paste_counter[0]}: {line_count + 1} lines \u2192 {paste_file}]" buf.cursor_position = len(buf.text)