Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion os/v3/puppy/console-tui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,26 @@ remains arithmetic (one escape plus 4.5 KiB) - a person at the monitor or a 60 f

This is insurance, not the fix for a noisy writer: a writer that paints this screen is still a defect in the writer.

**Text from outside is cleaned before it becomes a cell.** Two of the pane's inputs are not ours - the tail of Lemonade's
log and the catalogue's names - and a cell's symbol is written to the terminal unchanged, so a control byte that arrives
as *data* is a control byte on the appliance's screen. It is reachable without malice: at `log_level: debug` that log
carries the demo pages' prompts, and the engine's progress-bar lines carry `ESC[K` (erase to end of line) and a bare CR.
Measured against the take's own log, the shipped c26 candidate (`5b21a0a8…`, which has the heal and not this) leaves
**4 escape bytes in one frame**, and on a 240x67 pty its progress row is cut at the first `ESC[K` with the wrapped
remainder gone; this build is **0 bytes**. On the appliance's own 160x50 text console the same line came back whole on
both binaries - the once-a-second full paint rewrites the cells the erase cleared - so this is defence in depth, not a
visible repair: a cell is simply not the place to execute what a log file says.
`facts::screen_text()` removes CSI and OSC whole (the bytes after an escape are control, not text), turns TAB into a
space and drops the other C0/DEL; everything else is untouched (`SoC 78°C`, `café`, `┌─┐`), and it is applied where
external text enters, so no draw site can forget it (`a_log_line_or_a_model_name_cannot_carry_an_escape_into_the_screen`).

**An interrupted paint repaints; a terminal that cannot be written still ends the console.** A paint that fails with
`ErrorKind::Interrupted` drew nothing - a signal arrived before the write reached the terminal - so the next pass simply
paints again instead of ending the screen. That is reachable in normal use: crossterm's event source installs a SIGWINCH
handler, so an ssh user dragging a window edge is the realistic trigger. Every other error kind still exits, which is
what hands tty1 to the `dialog` menu (`paint_failed()`;
`an_interrupted_paint_is_repainted_but_a_dead_terminal_ends_the_console`).

## Keys

| key | what it does |
Expand Down Expand Up @@ -212,7 +232,7 @@ dynamic one (`readelf` PT_INTERP, `ldd`).
## Tests

```sh
cargo test # 52 tests: the probe parsers, the QR drawing (incl. a literal known answer), the links, the short-window degradation, the two renders, the engine row's model choice
cargo test # 55 tests: the probe parsers, the QR drawing (incl. a literal known answer), the links, the short-window degradation, the two renders, the engine row's model choice, the escape sanitiser, the interrupted paint
cargo run -- --snapshot 240x67 --fixture # the frame tests/snapshots/240x67.txt holds
cargo run -- --snapshot 80x25 --fixture
cargo run -- --status # the same facts as plain text (what a shell or a gate row can read)
Expand Down
Loading