Public: anyone can read this; the crew can change it.

The terminal's loop, under test: a key and a state in, an intent out — without a pty #84

open not picked up yet opened this
opened this

Intent. Finish the split #57 started, so the half of the terminal a person actually presses is tested before #78 adds three more keys to it.

Measured on main today (63a4041): bun test --coverage reports src/tty.ts at 53.07% of lines, uncovered 208–291 — which is exactly run(): the keyboard in raw mode, the key-to-action dispatch, the typing buffer, the refusal printed on the status line, the redraw and the exit path. Every other module in the repository is at 88% or better and most are at 100%; screen() and keys() are fully covered because #57 made them pure. The loop was left, and #78 will add offer, accept and pass to it.

Done looks like

  • [ ] The loop's decision comes out as a pure function, the way screen did: a key and the current state in, an intent out — move the cursor, start typing, append or backspace, submit, call this action with these arguments, quit, or ignore. No database, no process.stdout, no process.env, no clock.
  • [ ] run() keeps only what genuinely touches the world: opening the database, whoAtTty(), raw mode, reading bytes, executing the intent, printing the frame, restoring the terminal on exit.
  • [ ] Tests in src/tty.test.ts that fail without it: j and k move and clamp at both ends; o starts typing and a name is typed, backspaced and submitted; enter on an empty name does not call the action; s and x call join and leave for the selected table and print the action's refusal verbatim when it refuses; q and ctrl-C both quit; a key nobody offered does nothing; a guest pressing a writing key is offered nothing and changes nothing.
  • [ ] The bytes a terminal really sends are covered where they decide something: an arrow key arrives as three bytes and must not be mistaken for escape then B, and a paste arrives as several keys in one read.
  • [ ] Coverage of src/tty.ts is in line with the rest of the repository, and the pull says the number.

Files I expect to change. src/tty.ts, src/tty.test.ts.

Risks. Do not mock the world to test it — the point of the split is that there is nothing left to mock. Restoring the terminal on exit is the one thing a test cannot prove; leave it in run() and say so. If #78 lands first, this covers its keys too and the two should not be written twice.

Who. @mason, reviewed by @juniper. Ready now.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs