feat(tui): number-key quick-select in choice dialogs - #136
Conversation
Pressing 1-9 in a choice dialog selects and confirms the option at that position in one keystroke. Dialogs with <=9 options get '1. '-'9. ' label hints and an updated help line so the shortcut is discoverable; callers can opt out with numberShortcuts: false. - Disabled while a filter is active (digits remain filter input) and while content is expanded. - Digits past the option count are a no-op (setSelectedIndex clamps, so the guard is explicit). - Existing Up/Down + Enter flow unchanged. Closes kingsword09#135
There was a problem hiding this comment.
🟡 Changes recommended
The default help text loses scroll discoverability when shortcuts are enabled, and the new “number hints” test does not currently assert the intended UI output/opt-out behavior.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adds single-keystroke 1–9 quick-select (select + confirm) to the zcode TUI choice dialog, aimed at speeding up frequent approval prompts while preserving the existing Up/Down + Enter flow.
Changes:
- Implement digit quick-select in
ChoiceDialog.handleInput()with an opt-outnumberShortcuts: false. - Prefix labels with
1.… hints (when applicable) and update the default help text to advertise “number selects”. - Add a new targeted test file for number shortcut behavior and adjust an existing help-text assertion.
File summaries
| File | Description |
|---|---|
| packages/zcode-tui/src/choice-dialog.ts | Implements digit quick-select, label numbering hints, and help-text updates for choice dialogs. |
| test/choice-dialog-number-shortcuts.test.ts | Adds tests intended to validate digit confirm, out-of-range digits, filter interaction, and numbering hints. |
| test/choice-dialog.test.ts | Updates an assertion to accommodate the updated help text formatting/content. |
Review details
- Files reviewed: 3/3 changed files
- Comments generated: 5
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| : "Type to filter · Up/Down choose · Enter confirm · Esc cancel · Ctrl+U clear"), | ||
| ? (options.numberShortcuts === false | ||
| ? "Type to filter · Up/Down choose · Ctrl+O details · ←/→ or PgUp/PgDn scroll · Enter confirm · Esc cancel" | ||
| : "Type to filter · number selects · Up/Down choose · Ctrl+O details · Enter confirm · Esc cancel") |
There was a problem hiding this comment.
Fixed in 74d0132 — both default help variants (with details and without) now keep "←/→ or PgUp/PgDn scroll" when number shortcuts are enabled.
| test("labels carry number hints by default and omit them with numberShortcuts: false", async () => { | ||
| const { ui, host, focused } = makeFakeUi(); | ||
| let seen = ""; | ||
| const promise = choose(ui, host, theme, { | ||
| title: "T", | ||
| prompt: "P", | ||
| items: items(4), | ||
| signal: (() => { | ||
| const controller = new AbortController(); | ||
| queueMicrotask(() => { | ||
| // capture rendered help before aborting | ||
| seen = JSON.stringify((host as unknown as { children: Component[] }).children.length); | ||
| controller.abort(); | ||
| }); | ||
| return controller.signal; | ||
| })() | ||
| }); | ||
| await promise; | ||
| expect(typeof seen).toBe("string"); | ||
| }); |
There was a problem hiding this comment.
Fixed in 74d0132 — the test now renders the dialog and asserts the "N. label" prefixes, the number-selects help fragment, and the numberShortcuts: false opt-out; added regression tests for >9-item and custom-help dialogs as well.
| expect(output).not.toContain("plan line 30"); | ||
| expect(output).toContain("Plan 1–6 of 30"); | ||
| expect(output).toContain("Ctrl+O details"); | ||
| expect(output.replace(/\n/g, " ")).toContain("Ctrl+O"); |
There was a problem hiding this comment.
Fixed in 74d0132 — assertion restored to "Ctrl+O details" (with newline-wrapping normalization kept, since the longer help line wraps at width 60).
| // Number shortcut: pressing 1-9 selects and confirms the visible option at | ||
| // that position (1 = first item) in a single keystroke. Disabled while a | ||
| // filter is active so typing digits keeps working as filter input. |
There was a problem hiding this comment.
Fixed in 74d0132 — comment updated to state the absolute-index semantics explicitly.
| /** Prefix labels with 1-9 hints and enable digit quick-select. Default: true when no custom help. */ | ||
| numberShortcuts?: boolean; |
There was a problem hiding this comment.
Fixed in 74d0132 — went further than a comment fix: availability now mirrors the rendered hints (≤9 items, no custom help) via one shared flag covering hints, the default help line, and the shortcut, so they can no longer disagree; numberShortcuts: true force-enables. Docstring updated to match.
…rage Review-pass fixes from Copilot review + independent depth review: - Digit quick-select availability now mirrors the rendered number hints (<=9 items, no custom help) via one shared flag: hints, the default help line, and the shortcut in handleInput can no longer disagree. On >9-item or custom-help dialogs digits stay filter input instead of instantly confirming a wrong item on the first keystroke of a digit-leading filter. numberShortcuts: true force-enables the shortcut regardless of hints. - Default help lines with details keep the scroll hint so scrolling stays discoverable when number shortcuts are on. - Rewrite the vacuous hints test: render the dialog and assert the "N. label" prefixes, the number-selects help fragment, the numberShortcuts: false opt-out, and force-enable via true; add regression tests for >9-item and custom-help dialogs (no hints, no shortcut, nothing confirms on a digit press). - Restore the stronger "Ctrl+O details" help-text assertion. - Fix numberShortcuts/numberShortcutCount doc comments to match actual behavior; return unconditionally inside the shortcut block.
|
Thanks for the contribution! I added a small follow-up commit to scope number shortcuts to permission prompts and preserve numeric filtering in other choice dialogs. |
Closes #135.
What
Choice dialogs (tool approvals, plan approval, questions) now support single-keystroke selection: pressing
1–9selects and confirms the option at that position.1.–9.number hints prefixed to labels plus an updated help line ("number selects"), so the shortcut is discoverable.numberShortcuts: false.setSelectedIndexclamps to the last item, so the guard is explicit).Why
Approval prompts interrupt flow constantly in tmux fleet workflows (multiple zcode sessions side by side). Up-Up-Enter per approval adds up; a single digit cuts the most common interaction ("Allow once") to one keystroke. Claude Code's permission prompts do the same thing — the interaction is proven.
Tests
New
test/choice-dialog-number-shortcuts.test.ts(5 tests) driving the publicchoose()with a fake TUI:1confirms the first option;3confirms the thirdbun run typecheckclean;bun test test/choice-dialog*.test.ts15/15 green. Remaining full-suite failures are pre-existing on cleanmainin this environment (launcher/runtime integration + SSE recovery tests — verified identical failure set with and without the change).