// Terminal key encoding: control characters, meta prefixes, and cursor escape // sequences. Table-driven and easy to get subtly wrong, so it lives apart from // the DOM and is tested directly. export function toCtrl(ch: string): string { if (ch.length !== 1) return ch; const upper = ch.toUpperCase().codePointAt(0) ?? 0; if (upper >= 0x40 && upper <= 0x5f) return String.fromCodePoint(upper & 0x1f); if (ch === " ") return "\x00"; if (ch === "?") return "\x7f"; return ch; } /** Apply pending modifiers to a single typed character: Ctrl → control code, * Alt → ESC prefix (xterm meta). Both compose (Ctrl+Alt = ESC + control). */ export function applyModsToChar(ch: string, ctrl: boolean, alt: boolean): string { let out = ctrl ? toCtrl(ch) : ch; if (alt) out = "\x1b" + out; return out; } /** Cursor/nav-key sequence, promoted to the modified CSI form when Ctrl/Alt are * pending — `\x1b[1;`, n = 1 + alt(2) + ctrl(4) (xterm convention). */ export function cursorSeq(final: string, ctrl: boolean, alt: boolean): string { if (!ctrl && !alt) return `\x1b[${final}`; const n = 1 + (alt ? 2 : 0) + (ctrl ? 4 : 0); return `\x1b[1;${n}${final}`; }