You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 0933cdd
Browse filesBrowse the repository at this point in the historyBrowse files
fix(tui): reassemble fragmented escape sequences before Bubble Tea parses them (#107)
* fix(tui): reassemble fragmented escape sequences before Bubble Tea parses them
A terminal read can end in the middle of an escape sequence — most visibly
an SGR mouse report. Bubble Tea v1 parses each read independently, so the
pending ESC[ becomes an Alt+[ keypress and the printable tail is delivered
as ordinary text, typing garbage like 65;75;25M into the composer. #106
only stripped tails of reports split after a lone ESC; measured, 19 of 21
two-way split points still leaked.
AssembleInput (internal/tui) wraps the terminal input stream and holds an
undecidable head until the bytes that complete it arrive, so Bubble Tea
sees whole sequences: SGR and X10 mouse reports, SS3 keys, CSI, and OSC/
DCS-style string sequences. A mouse-shaped head whose tail never arrives
is dropped instead of echoed (keeping any bytes typed after it), a lone
ESC is released after 10ms so esc still closes popups, bracket-paste
bodies are never altered, and releases never cut a paste marker. The
wrapper presents itself as a term.File with the real descriptor — Bubble
Tea only puts a recognised file into raw mode, and cancelreader probes the
same shape — while Close stops the pump without closing stdin, which the
program does not own. Only a terminal file is wrapped; pipes and redirects
keep Bubble Tea's own handling.
Wired in buildProgramOptions, non-Windows. FilterShiftEnter's regex strip
stays as a backstop. Tests cover every two- and three-way split of every
report shape, bursts, typing around split reports, pastes (incl. 240KB),
stalled and slow reports, EOF, SS3/OSC joins, and end-to-end parsing
through a real tea.Program.
* fix(tui): consume input synchronously so kqueue never strands keystrokes
The reassembler's pump goroutine drained the terminal eagerly into a
channel. Bubble Tea's kqueue/epoll cancelreader waits on the file
descriptor, so bytes already drained were invisible to it: input that
arrived while the program was between reads (delivering the previous
message) was stranded until an unrelated later keystroke woke the
loop. Reads now consume the source synchronously one read at a time,
waiting via poll(2) for the settle/abandon windows, so bytes stay in
the kernel buffer until they are read and every wakeup stays coherent.
The test harness drives real tea.Program runs over an os.Pipe, which
Linux's epoll cancelreader requires; each script chunk is written as
its own read to keep split points real.
0 commit comments