export type ReadlineKeymapName = "vi-command" | "vi-insert"; /** A resolved inputrc key sequence binding. */ export type ReadlineBinding = | { kind: "command"; command: string; } | { kind: "macro"; expansion: string; } | { kind: "unbound"; }; /** * Immutable map of canonical inputrc key-sequence strings to bindings. * Key-sequence decoding deliberately belongs to the trie layer added later. */ export class ReadlineKeymap { readonly #bindings: ReadonlyMap; private constructor( readonly name: ReadlineKeymapName, bindings: ReadonlyMap, ) { this.#bindings = bindings; } static empty(name: ReadlineKeymapName): ReadlineKeymap { return new ReadlineKeymap(name, new Map()); } get size(): number { return this.#bindings.size; } resolve(sequence: string): ReadlineBinding | undefined { return this.#bindings.get(sequence); } withBinding(sequence: string, binding: ReadlineBinding): ReadlineKeymap { if (sequence.length === 0) { throw new RangeError("A Readline key sequence must not be empty"); } const bindings = new Map(this.#bindings); bindings.set(sequence, binding); return new ReadlineKeymap(this.name, bindings); } entries(): ReadonlyArray { return [...this.#bindings.entries()]; } }