Wait for rest of escape sequence before parsing - #4901
Conversation
Read loop dropped its escDelay retry budget after every successful byte, so a sequence split across reads reached the parser as a fragment, parsed as ALT-[ with the remainder left behind as query text. - fzf queries DECRQM at startup since dab626b, so a terminal answering late leaked "?2004;2$y" into the query - Same split leaked modified keys and mouse sequences: CTRL-UP left "5A", SGR mouse left "0;1;1M" - Bound unchanged, a stall longer than escDelay still falls back to ALT Fix #4899
There was a problem hiding this comment.
🟡 Changes recommended
incompleteEscape is invoked per-byte and currently scans the full buffer, creating O(n^2) behavior during large reads (e.g. paste), which is a likely performance regression.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR adjusts the TUI input read loop to avoid handing partial ANSI escape sequences to the parser by extending the escape-delay window while a CSI/SS3 sequence is still incomplete, addressing the regression reported in #4899.
Changes:
- Add CSI framing helpers and
incompleteEscapedetection to decide when to keep waiting for more bytes. - Update
getBytesInternalto refresh the escape-delay “budget” while an escape sequence is still arriving. - Add unit tests covering complete vs. incomplete escape-sequence buffering behavior.
File summaries
| File | Description |
|---|---|
| src/tui/light.go | Adds escape-sequence continuation detection and updates the read loop to wait for completion. |
| src/tui/light_escape_test.go | Adds tests for incompleteEscape to ensure correct waiting behavior. |
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
incompleteEscape runs once per byte read and scanned the whole buffer back to the last ESC, so a paste that accumulates in one read made input handling quadratic. 256KB paste took 15.3s against 3.8s before. - Scan only the last 256 bytes, well past any sequence fzf parses - Sequence longer than that is not waited for, same as before this branch - Window size does not affect throughput, 64 and 1024 measure the same Reported by Copilot on #4901
There was a problem hiding this comment.
🟢 Approval recommended
The change is narrowly scoped, includes targeted tests, and directly prevents partial escape-sequence parsing that can leak terminal replies into the prompt.
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 0 new
- Review effort level: Lite
Read loop dropped its escDelay retry budget after every successful byte, so a sequence split across reads reached the parser as a fragment, parsed as ALT-[ with the remainder left behind as query text. - fzf queries DECRQM at startup since dab626b, so a terminal answering late leaked "?2004;2$y" into the query - Same split leaked modified keys and mouse sequences: CTRL-UP left "5A", SGR mouse left "0;1;1M" - Bound unchanged, a stall longer than escDelay still falls back to ALT Fix junegunn#4899
Fix #4899
Contribution Policy
We do not accept pull requests generated primarily by AI without genuine understanding or real-world usage context.
All contributions are expected to demonstrate:
If these expectations are not met, we would prefer to implement the changes ourselves rather than spend time reviewing low-effort submissions.
Acknowledgement