# Clayterm Input Specification **Version:** 0.1 (draft) **Status:** Current-state specification. Descriptive for the input parsing surface. --- ## 1. Purpose This specification describes Clayterm's terminal input parsing surface: the API for decoding raw terminal byte sequences into structured events. Input parsing is architecturally independent from rendering (see [Renderer Specification](renderer-spec.md), INV-7). The two concerns share a compiled WASM binary for loading efficiency, but neither depends on the other's state, types, or API surface. Both consume the shared capability layer defined in the [Terminfo Specification](terminfo-spec.md); the input parser is additionally that layer's runtime write path (see Section 6). This specification is currently non-normative except where noted. The input API has clear design intent but has undergone more revision than the rendering core and faces known upcoming forces that will reshape it (Kitty progressive enhancement field surfacing). It is written to document the current surface and guide future stabilization. --- ## 2. Scope ### In scope (descriptive) - The input parser creation and lifecycle - The scan API and its return type - The `InputEvent` discriminated union and its variants - The ESC timeout resolution model - Terminfo integration: key sequence loading and capability query response recognition (Section 6, normative) ### Out of scope - Rendering (see [Renderer Specification](renderer-spec.md)) - Pointer hit detection (owned by the render loop; see Renderer Specification, Section 12.4) - Higher-level event routing, focus management, or keybinding systems --- ## 3. Terminology **Input parser.** A WASM-backed instance that accepts raw terminal bytes and produces structured events. Each parser maintains its own internal state for multi-byte sequence buffering and ESC timeout tracking. **Scan.** A single invocation of the parser. The caller provides raw bytes (or no bytes, for timeout resolution), and the parser returns any events it can produce along with pending-timeout information. **InputEvent.** A discriminated union representing a single parsed terminal event. Discriminated on a `type` field. --- ## 4. Input Parser API ### 4.1 Parser creation ``` createInput(options?): Promise ``` Creates an input parser instance. The returned promise resolves when the WASM module is ready. Options: - **`escLatency`** — Milliseconds to wait before resolving a lone ESC byte as the Escape key. Default: 25ms. This controls the tradeoff between responsiveness (lower values) and correct disambiguation of ESC-prefixed sequences (higher values). - **`terminfo`** — A `TerminalInfo` value from `detectTerminal()` (see [Terminfo Specification](terminfo-spec.md) §10.1). Terminal-specific key sequences from `terminfo.keys` are loaded into the parser's escape sequence trie at initialization (Section 6.1). When omitted, the parser uses built-in xterm default sequences. ### 4.2 Scan ``` input.scan(bytes?: Uint8Array): ScanResult ``` Feeds raw terminal bytes into the parser and returns parsed events. The `bytes` parameter is optional; calling without arguments triggers a rescan for ESC timeout resolution. The parser is synchronous: it processes all provided bytes in a single call and returns immediately. ### 4.3 ScanResult ``` { events: InputEvent[], pending?: { delay: number, deadline: number } } ``` - **`events`** — An array of parsed events produced from the provided bytes (and any previously buffered bytes that could now be resolved). - **`pending`** — When present, indicates that an ambiguous ESC byte is buffered and the parser cannot yet determine whether it begins an escape sequence or is a standalone Escape keypress. The caller SHOULD schedule a rescan (calling `scan()` with no arguments) after the indicated delay. The `delay` field is a relative duration in milliseconds. The `deadline` field is an absolute timestamp (milliseconds since epoch) for the same point in time. An ESC followed by exactly one introducer byte — `[`, `O`, `]`, `P`, or `_` — and nothing else is ambiguous in the same way: it is either an Alt-modified key or the start of an escape sequence or probe response. The parser MUST treat it as pending and report `pending`. If no further bytes arrive within `escLatency`, the rescan MUST resolve it as a key event for the introducer character with `alt: true`. --- ## 5. InputEvent Types The `InputEvent` discriminated union is discriminated on a `type` field. The current variants are: - **`KeyEvent`** (`type: "keydown" | "keyup" | "keyrepeat"`) — A keyboard event for special keys, control sequences, and modifier combinations. Fields include `key` (logical key name), `code` (physical key identifier), and modifier flags (`shift`, `ctrl`, `alt`, `meta`). - **`MouseEvent`** (`type: "mousedown" | "mouseup"`) — A mouse button press or release. Fields include `x`, `y` (cell coordinates), `button`, and modifier flags. - **`WheelEvent`** (`type: "wheel"`) — A scroll event. Fields include `x`, `y`, and scroll direction. - **`ResizeEvent`** (`type: "resize"`) — A terminal resize notification. Fields include `columns` and `rows`. The discriminant values and the type splits are deliberate design decisions. However, the field sets within each variant are expected to grow when Kitty progressive enhancement types are surfaced in the TypeScript layer (the C struct has already been extended with fields that are not yet mapped to the TS types). --- ## 6. Terminfo Integration _This section is normative. It defines the input parser's two roles in the capability layer specified by the [Terminfo Specification](terminfo-spec.md)._ ### 6.1 Key sequences from terminfo When given a `terminfo` value whose `keys` field is present, the parser MUST load the terminal's `key_*` string capabilities into its escape sequence trie at initialization, before any scan. Terminfo-supplied sequences take precedence over the built-in xterm defaults when they conflict; defaults remain registered for sequences the terminfo entry does not define. The key capabilities consumed are the `key_*` string range mapped to existing `KEY_*` codes: arrows (`kcuu1`, `kcud1`, `kcub1`, `kcuf1`), function keys (`kf1`–`kf12`), editing keys (`khome`, `kend`, `kich1`, `kdch1`, `kpp`, `knp`), and backtab (`kcbt`). Key capabilities with no corresponding `KEY_*` code are ignored. Terminfo key sequences longer than 16 bytes are ignored. ### 6.2 Query response recognition During a normal scan — with responses potentially interleaved with user input — the parser MUST recognize and consume the probe responses listed in Terminfo Specification §9.1: OSC 10/11/12 theme color reports, OSC 21 kitty color reports, OSC 22 pointer shape reports, XTGETTCAP DCS replies, DECRPM mode-2026 reports, kitty keyboard flag reports, kitty graphics APC replies, and the DA1 device attributes report. For each recognized response the parser MUST emit a `CapabilityEvent` in the `scan()` return value, per Terminfo Specification §6.3 and TINV-6. Responses are consumed silently: they MUST NOT surface as `InputEvent`s, and bytes belonging to a recognized response MUST NOT leak into adjacent events. When the parser is standalone (no `terminfo`), responses are still recognized and consumed so stray replies never corrupt the event stream. ### 6.3 Response termination OSC, DCS, and APC responses are terminated by BEL (`0x07`) or ST (`ESC \`). Once the parser has recognized a response header — `ESC ] Ps ;` with `Ps` one of 10, 11, 12, 21, or 22; `ESC P 0 + r` or `ESC P 1 + r`; or `ESC _ G` — the following bytes end the response early instead: - any other C0 control: `0x00`–`0x06`, `0x08`–`0x1A`, `0x1C`–`0x1F`; - DEL (`0x7F`); - ESC followed by any byte other than `\`. When a response ends early, the parser MUST discard the bytes received for it and MUST NOT emit a `CapabilityEvent` for it. Parsing resumes at the byte that ended the response, so the key or sequence it begins is delivered normally. --- ## 7. Deferred / Future Areas _These topics are explicitly excluded from this specification. Their omission is intentional, not an oversight._ **Full Kitty progressive enhancement event types.** The C-side input parser struct has been extended for progressive enhancement fields. The TypeScript event types have not been updated to surface them. **Whether input parsing should be a separate package.** Architecturally independent from the renderer but currently co-located. The distribution decision is open.