Skip to main content

pty_reader_loop

Function pty_reader_loop 

Source
fn pty_reader_loop(
    reader: Box<dyn Read + Send>,
    tx: Sender<LineEvent>,
    idle_tx: Sender<()>,
    idle_timeout: Duration,
)
Expand description

PTY reader loop: drains bytes from the master, strips DSR / ANSI control sequences, and forwards line-split chunks to the publisher.

Uses a thread-bridge + recv_timeout to add a quiet-window flush identical to stream_reader’s tokio::time::timeout approach, but for the blocking sync I/O that the PTY master reader requires.

P1a — collapse_cr: called on the pending accumulator after each PTY read (after strip_ansi), collapsing mid-buffer lone-\r overwrites (trailing-\r convention, e.g. "frame\r") and embedded multi-frame chunks (e.g. printf 'f1\rf2\rfinal\n'). Previously the PTY path passed \r bytes intact and relied on spawn_publisher_loop’s pending_cr_line slot; that slot only fires per-LineEvent so embedded \rs in a single write survived uncollapsed.

P1b — leading-\r spinner collapse: throttled spinners (npm, cargo, ora, tqdm at ~80-100 ms/frame, above the 50 ms quiet window) arrive as separate reads. When the quiet window expires and pending starts with \r, the frame is stashed in a pending_cr_override slot rather than flushed. The next read prepends it so collapse_cr overwrites it with the new frame. The slot is flushed when a \n-terminated line arrives or at EOF.

P2a — FLUSH_BYTES guard: flushed unconditionally when accumulated size exceeds FLUSH_BYTES, preventing unbounded accumulation from a trailing-\r spinner that never emits \n.