feat: term.update() folds CapabilityEvents into runtime capabilities - #133
natemoo-re wants to merge 3 commits into
Conversation
Changeset suggestionThe current changeset no longer matches this PR. This review contains a corrected replacement. Why: Changeset package scope does not match the affected packages confidently. Changeset bump does not match the consumer-visible impact. Changeset contains implementation or roadmap noise. Changeset contains unsupported consumer-facing claims. View the proposed changeset---
'@bomb.sh/tty': minor
---
Adds `detectTerminal`, `Capabilities`, `Detection`, `CapabilityEvent`, and `KeyTable` to the public API.
`detectTerminal()` reads a compiled terminfo binary (from disk or injected bytes), applies environment evidence (`COLORTERM`), and returns a frozen `Detection` carrying static `Capabilities`, a `probe` query batch to write to stdout, and opaque `keys` bytes for the input parser.
Pass `detection` to `createInput` to seed its escape-sequence trie with terminal-specific `key_*` sequences. Pass capability events from `scan()` to `term.update()` to keep the renderer's runtime capability snapshot current.
`scan()` now recognizes probe responses — OSC 10/11/12/21/22, XTGETTCAP, DECRPM mode 2026, kitty keyboard, kitty graphics APC, and the DA1 fence — and surfaces them as `CapabilityEvent` values interleaved with key and mouse events. Route these to `term.update()`, which returns a `Uint8Array` of bytes to write immediately (empty when no output is needed).
`InputOptions.terminfo` is replaced by `InputOptions.detection`. Both parsers remain usable without a `Detection`; the 256-color baseline and xterm default key sequences apply when it is omitted.
#### Migration
```diff
-const input = await createInput({ terminfo: await Deno.readFile(terminfoPath) });
+const detection = await detectTerminal({ env: process.env });
+const input = await createInput({ detection });
+process.stdout.write(detection.probe);
```
```diff
-term.update({ events: resizeEvents });
+for (const event of input.scan(bytes).events) {
+ if (event.type === "resize" || event.type === "capability") {
+ const out = term.update(event);
+ if (out.length) process.stdout.write(out);
+ }
+}
```Review this changeset manually If this draft is correct, react with 🚀 and Cooper will commit it to this branch. |
| @@ -0,0 +1,32 @@ | |||
| --- | |||
There was a problem hiding this comment.
Changeset needs revision.
Changeset package scope does not match the affected packages confidently. Changeset bump does not match the consumer-visible impact. Changeset contains implementation or roadmap noise. Changeset contains unsupported consumer-facing claims.
View the proposed replacement
---
'@bomb.sh/tty': minor
---
Adds `detectTerminal`, `Capabilities`, `Detection`, `CapabilityEvent`, and `KeyTable` to the public API.
`detectTerminal()` reads a compiled terminfo binary (from disk or injected bytes), applies environment evidence (`COLORTERM`), and returns a frozen `Detection` carrying static `Capabilities`, a `probe` query batch to write to stdout, and opaque `keys` bytes for the input parser.
Pass `detection` to `createInput` to seed its escape-sequence trie with terminal-specific `key_*` sequences. Pass capability events from `scan()` to `term.update()` to keep the renderer's runtime capability snapshot current.
`scan()` now recognizes probe responses — OSC 10/11/12/21/22, XTGETTCAP, DECRPM mode 2026, kitty keyboard, kitty graphics APC, and the DA1 fence — and surfaces them as `CapabilityEvent` values interleaved with key and mouse events. Route these to `term.update()`, which returns a `Uint8Array` of bytes to write immediately (empty when no output is needed).
`InputOptions.terminfo` is replaced by `InputOptions.detection`. Both parsers remain usable without a `Detection`; the 256-color baseline and xterm default key sequences apply when it is omitted.
#### Migration
```diff
-const input = await createInput({ terminfo: await Deno.readFile(terminfoPath) });
+const detection = await detectTerminal({ env: process.env });
+const input = await createInput({ detection });
+process.stdout.write(detection.probe);
```
```diff
-term.update({ events: resizeEvents });
+for (const event of input.scan(bytes).events) {
+ if (event.type === "resize" || event.type === "capability") {
+ const out = term.update(event);
+ if (out.length) process.stdout.write(out);
+ }
+}
```|
Size Increased — +18.3 KB 121.1 KB unpacked |
commit: |
c64972d to
d5be56e
Compare
Widen Update from { width, height } | CapabilityEvent to
{ width, height } | InputEvent. Events other than resize and capability
are no-op steps, so hosts can pass the full scan() events array without
filtering. Only ResizeEvent carries width/height, so the shapes stay
unambiguous. Matches the implementation in #133.
42fa5a4 to
f124b5d
Compare
…(renderer-spec §7.7, §8.6)
The terminfo spec no longer lists applyUpdate as public API; update() is the only entry point, and tests already exercise it through term.update().
The renderer spec now accepts any InputEvent as an Update and requires non-resize, non-capability events to change no state and emit no bytes.
f124b5d to
5be02ae
Compare
Part 4/4 (final) of the terminfo foundation stack. Requires #132; draft until the spec (#130) is approved.
What this adds
term.ts:update()becomes the universal sink for resize and capability changes (renderer-spec §7.7, §8.6) —Update = { width, height } | CapabilityEvent, folded in order; returns bytes to write immediately (empty when none). Newterm.capabilitiesexposes the frozenRuntimeCapabilitiessnapshot (staticCapabilities+ folded event values);createTerm({ detection })seeds the static baseline (256-color/xterm defaults when omitted).validate.ts:validated()forwards the newcapabilitiesgetter.test/term.test.ts: batch folding, capability events, resize no-op semantics..changeset/terminfo-capability-layer.md: minor bump; documents the cumulative API surface and migration for the whole stack (InputOptions.terminfo→detection,update({ events })→ per-eventupdate()).Explicitly out of scope
No renderer byte output changes (renderer-spec §7.8 defers all gated emission). First focused consumer: color encoding modes (#60). Other protocol follow-ups: #129.
Split from #106 for reviewability; #106 will be closed when this stack lands.