Skip to content

Terminal: consume non-CSI/OSC escapes (SS3 ESC O, charset ESC(, keypad) so stray 'B' stops leaking in tmux #40

Description

@bedro96

What to build

Escape sequences other than CSI (ESC [) and OSC (ESC ]) are not consumed by the terminal parser, so their trailing bytes leak as visible text. Confirmed on the Android emulator against a live SSH shell running tmux:

  • The prompt/status render stray Bs: sshtest@kukovmB:~B$, tmux status ... 03-Jul-2B.
  • Controlled probe results:
    • printf 'ss3_down:[\033OBx]\n' -> renders ss3_down:[Bx] (the SS3 ESC O B leaked its B; no cursor move)
    • The persistent prompt Bs match ESC ( B (designate ASCII/G0), which tmux and many apps emit constantly.

Root cause: the parser handles ESC [ and ESC ] but treats other escape introducers as text. It must recognize and consume the standard escape families:

  • SS3: ESC O <final> (e.g. ESC O B) — consume introducer + one final byte.
  • Charset designation: ESC ( <x>, ESC ) <x>, ESC * <x>, ESC + <x> — consume intermediate + one final.
  • Two-char escapes: ESC =, ESC > (keypad), ESC 7, ESC 8, ESC D, ESC M, ESC E, ESC c, etc. — consume without leaking.
  • Anything unrecognized after ESC should be consumed conservatively (not printed).

Verified GOOD and must NOT regress (all correct on the emulator): CSI cursor motion — ESC[B (down), ESC[3C (forward), ESC[1A (up) with overwrite (up_over -> upOVERr:L1); ls -al, du -sh .; 256-color/bold; in-place spinner; OSC title/color already swallowed; no 0; leak.

Acceptance criteria

  • ESC O B (and other SS3 finals) produce NO visible text and are treated as the corresponding control (or no-op), not printed.
  • ESC ( B / ESC ) 0 and other charset-designation sequences are fully consumed (no stray B/0).
  • ESC =, ESC >, ESC 7/8, ESC D/M/E/c are consumed without leaking.
  • In tmux over SSH, the prompt and status bar render with NO stray B characters.
  • Handling is correct across chunk-split boundaries.
  • Existing CSI cursor motion, SGR colors, OSC handling, ls -al/du output remain correct (regression-covered).
  • Unit tests cover each escape family above using the exact probe fragments; ./run-tests.sh green.

Blocked by

None - can start immediately.

Agent workflow

Work test-first (/tdd): add failing tests for ESC O B, ESC ( B, and the two-char escapes leaking text, then implement consumption in the parser, and iterate (/fleet) until tmux shows no stray characters and ./run-tests.sh is green. Do not release/build the APK from untested code. Note: final on-device sign-off is done on the Android emulator running tmux.

Metadata

Metadata

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions