/** * tmux send-keys input translation. * * Translates IC-1 key names (and literal text) into tmux send-keys arguments. * Used by the input route (T-1.5) to deliver keystrokes to a pane. * * Owner: T-1.1 */ import { execFile } from "node:child_process"; import { promisify } from "node:util"; const execFileAsync = promisify(execFile); /** Named keys from IC-1 ClientToServer `{ type: "key"; name: string }`. */ const KEY_MAP: Record = { escape: "Escape", tab: "Tab", up: "Up", down: "Down", left: "Left", right: "Right", enter: "Enter", "shift-enter": "S-Enter", backspace: "BSpace", "ctrl-c": "C-c", "ctrl-d": "C-d", "ctrl-z": "C-z", }; /** * Send a single named key to a tmux pane. * Pane defaults to the first pane of the session (session:0.0). */ export async function sendKey( session: string, name: string, pane = "0.0", ): Promise { const tmuxKey = KEY_MAP[name.toLowerCase()]; if (!tmuxKey) { throw new Error( `Unknown key name: "${name}". Supported: ${Object.keys(KEY_MAP).join(", ")}`, ); } await execFileAsync("tmux", [ "send-keys", "-t", `${session}:${pane}`, tmuxKey, ]); } /** * Send literal text to a tmux pane (IC-1 `{ type: "keys"; data: string }`). * Uses send-keys -l which sends each character literally. */ export async function sendKeys( session: string, data: string, pane = "0.0", ): Promise { await execFileAsync("tmux", [ "send-keys", "-t", `${session}:${pane}`, "-l", data, ]); } /** * Send bracketed-paste to a tmux pane (IC-1 `{ type: "paste"; data: string }`). * Wraps the data in bracketed-paste sequences then sends literally. */ export async function sendPaste( session: string, data: string, pane = "0.0", ): Promise { const wrapped = `\x1b[200~${data}\x1b[201~`; await execFileAsync("tmux", [ "send-keys", "-t", `${session}:${pane}`, "-l", wrapped, ]); }