Skip to content

feat(tui): keybinding framework, bottom hint bar, live-list picker#24

Closed
hi-lei wants to merge 1 commit into
mainfrom
feat/tui-prompts-hint-bindings-livelist
Closed

feat(tui): keybinding framework, bottom hint bar, live-list picker#24
hi-lei wants to merge 1 commit into
mainfrom
feat/tui-prompts-hint-bindings-livelist

Conversation

@hi-lei

@hi-lei hi-lei commented May 29, 2026

Copy link
Copy Markdown
Collaborator

Summary

Reworks the TUI prompt layer around a generic keybinding abstraction, adds a bottom hint bar to every prompt, and introduces a new live-updating list picker. Also bundles routine dependency/CI maintenance.

Keybinding framework (pkg/tui/bubbletea/keybinding.go, new)

Replaces ad-hoc switch msg.String() handling in each prompt with a declarative, data-driven model:

  • KeyBinding[M] — matcher + state-aware hint label + handler; empty label hides a binding from the hint bar without disabling the key.
  • Matchers: MatchKey, MatchRune (rune + modifiers), MatchText.
  • Dispatch (first stop=true wins, fall-through supported), HintsFor, ApplyBindingOverrides (non-mutating relabel/hide).
  • Each prompt exposes DefaultXBindings().

Bottom hint bar + relabel/hide options

All prompts (confirm, textinput, select, multiselect, password) refactored onto the binding system and gained a hint bar. New per-prompt config: WithXRelabel(id, label), WithXHide(ids...), WithShowHints, WithHints(...). Labels are dynamic (e.g. select esc flips esc backesc clear filter).

Live-list picker (pkg/tui/bubbletea/live_list.go, new)

New optional tui.LiveLister capability — a select-style picker whose rows update asynchronously over a <-chan LiveListUpdate while the user browses. Contract: unknown keys dropped, last-write-wins per key, cursor identity preserved by Key, type-to-filter on live labels, errored rows styled distinctly, clean pump-goroutine teardown on ctx-cancel / program-exit / channel-close.

Shared helpers & wizard

  • list_helpers.go: visibleWindow + refilter shared across select/multiselect/livelist.
  • Wizard composite merges wizard-level + prompt hints into one bottom bar; testing.Prompter gains AddLiveList/LiveList.

Maintenance

  • Go → 1.25.10; pgx and x/net bumped; .osv-scanner.toml ignores an unfixed kratos vuln with expiry.
  • CI: osv-scanner-action v2.1.0→v2.3.8; gitleaks pinned to v8.30.1.

Correctness fixes (from adversarial review)

  • Guard liveListModel.Update against a late pumped update after selection that could empty matched and panic View (index out of range).
  • compositeModel.Update re-reads prompt.Hints() each key so the wizard bottom bar reflects dynamic labels instead of a stale snapshot.
  • Both covered by new regression tests.

Test plan

  • go build ./..., go test ./..., make lint all green.
  • New regression tests: TestLiveList_NoPanicOnUpdateAfterChosen, TestComposite_HintBar_RefreshesOnFilter.

🤖 Generated with Claude Code

Two correctness fixes surfaced by an adversarial review of the
keybinding/live-list work on this branch:

- liveListModel.Update now early-returns on liveListUpdateMsg once a
  selection is chosen. bubbletea drains queued messages after tea.Quit,
  so a pumped update could refilter and empty matched, panicking View's
  chosen branch (index out of range). Added regression test.

- compositeModel.Update re-reads prompt.Hints() after forwarding a key,
  instead of relying on the one-time snapshot taken in setPrompt. Prompt
  hint labels are dynamic (e.g. esc flips to "clear filter" while
  filtering), so the wizard bottom bar went stale. Added regression test.

Also clarify the refilter allocation comment and document the
testing.Prompter.LiveList drain-goroutine lifecycle contract.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@hi-lei hi-lei force-pushed the feat/tui-prompts-hint-bindings-livelist branch from 1e534ed to d051ebe Compare May 29, 2026 11:37
@hi-lei

hi-lei commented May 29, 2026

Copy link
Copy Markdown
Collaborator Author

Superseded by #25 — this branch was already squash-merged via #22, so reusing it produced a conflicting/duplicated diff. Reopened the fix on a clean branch (fix/tui-livelist-panic-hint-bar) off main.

@hi-lei hi-lei closed this May 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant