# ADR-0049: Input-field readline keymap — Esc-clear + Ctrl-A/E/W/K/U (I1b) ## Status **Accepted + implemented 2026-06-12 (issue #29).** Closes Gitea **#29** ("Command input keystroke support") and the deferred **I1b** readline requirement in `requirements.md`. Every fork below was escalated to the user and user-chosen before any code was written; implemented test-first (22 new Tier-1 tests in `src/app.rs`, all green; clippy nursery clean). This ADR **amends ADR-0046**, which explicitly listed "readline shortcuts (I1b)" in its out-of-scope set: that item is now in scope and decided here. It is orthogonal to ADR-0003's input-*mode* model (simple vs advanced, the `:` sigil) — these are editing keys within the input field, not mode or sigil changes — and it extends the single-line cursor editing already shipped under requirement **I1a** (Left/Right/Home/End/ Backspace/Delete, `app.rs`). ## Context The input field already supported in-line cursor editing (I1a): Left/ Right by char (UTF-8 aware), Home/End to the extremes, Backspace/Delete. Two gaps remained, raised in issue #29: 1. No way to **clear a partly-typed command** in one keystroke — a user who started typing the wrong thing had to hold Backspace. 2. No **readline cursor/kill shortcuts** (Ctrl-A/Ctrl-E and friends) for keyboards without Home/End and for muscle-memory in a command-driven workflow. This is requirement I1b, deferred by ADR-0046. `Esc` was free in the input field except that a *live Tab-completion memo* consumes it first (to undo the completion in one keystroke, ADR-0022). Ctrl-A/E/W/K/U were unbound. The existing chords are Ctrl-C (quit), Ctrl-O (nav focus cycle, ADR-0046), and Ctrl-`]` (demo caption toggle, ADR-0047) — none collide with a/e/w/k/u. ## Decision Bind the following in the input field (non-modal, non-navigation, both input modes), in `App::handle_key`: | Key | Action | |-----------|---------------------------------------------------| | `Esc` | Clear the input (empty buffer, cursor→0, scroll→0)| | `Ctrl-A` | Cursor to line start (alias of Home) | | `Ctrl-E` | Cursor to line end (alias of End) | | `Ctrl-W` | Delete the word before the cursor | | `Ctrl-K` | Kill from the cursor to end of line | | `Ctrl-U` | Kill from start of line to the cursor | Behavioural rules: - **Esc precedence.** A live completion memo still wins: the first Esc undoes the completion (ADR-0022), and Esc only *clears* when no memo is alive. This is a natural progression — Esc once to back out the completion, Esc again to clear. - **Esc does not clear while navigating the sidebar.** When a sidebar panel is focused (Ctrl-O, ADR-0046 DC3), `handle_key` routes every key to the navigation handler *before* the input-field keymap, where Esc exits navigation mode (`nav_exit`). Entering nav mode never touched the input buffer, so Esc-to-close-the-panel returns focus to the input with the partly-typed command intact — it cannot reach the clear binding. Locked by a regression test. - **Single Esc clears** (user-chosen over double-Esc). Discoverable and fast; the trade-off (an accidental Esc wipes an unsubmitted line) was accepted. A submitted line is always recoverable from history; only *unsubmitted* draft text is lost. - **Cursor-only keys don't touch history navigation.** Ctrl-A/Ctrl-E, like Home/End, move the cursor without ending history recall. - **Buffer-mutating keys end history navigation.** Esc-clear and Ctrl-W/K/U call `cancel_history_navigation` (the cleared/edited line *is* the new draft), matching Backspace/Delete. - **Ctrl-W is readline-style and UTF-8 safe.** It eats any run of trailing whitespace, then the preceding run of non-whitespace; word boundaries are found on char boundaries so multi-byte words delete cleanly. It only ever deletes back to the cursor (a mid-line Ctrl-W leaves the suffix intact). Helpers added: `clear_input`, `delete_prev_word`, `kill_to_end`, `kill_to_start` (`src/app.rs`), mirroring the existing `cursor_left` / `delete_before_cursor` style. ## Forks (all user-chosen) - **Esc semantics:** single-Esc-clears, *not* double-Esc — discoverable over accident-proof. - **Scope:** the *full* I1b set (Esc-clear + Ctrl-A/E/W/K/U), not just the issue's literal Ctrl-A/E + Esc — closes the whole I1b requirement in one pass rather than leaving Ctrl-W/K/U for a follow-up. - **Documentation:** a new ADR (this one), recording the input-field keymap convention and amending ADR-0046's OOS list — over folding it into ADR-0046 or shipping it I1a-style with no ADR. ## Consequences - I1b is complete; `requirements.md` I1b moves to `[x]`. - The new keys are **not yet advertised on screen.** Surfacing per-focus keybindings in the bottom status line is issue #27's domain (a separate, in-design UX change); this ADR makes the keys *work*, #27 will make them *discoverable*. - **Demo-mode badges** (ADR-0047) are *not* extended to the new Ctrl- chords here. Esc already badges as `[ESC]`; Ctrl-A/E/W/K/U are glyph-less and would be invisible in an asciinema cast. Whether to add `[CTRL-A]`…`[CTRL-U]` badges is left to ADR-0047's scope and flagged as a follow-up — it is a cast-polish concern, not a #29 requirement. ## Out of scope - On-screen keybinding hints for the input field (issue #27). - Demo badges for the new chords (ADR-0047 follow-up; flagged above). - Multi-line input (I1) and its Ctrl-Enter submit — unrelated, still deferred. - Word-wise *cursor motion* (Alt-B/Alt-F) and transpose/yank — not requested; not part of I1b.