Skip to content

feat(tui): palette book-name suggestions with fuzzy match#12

Merged
ivanmaierg merged 6 commits into
mainfrom
feat/palette-suggestions
May 12, 2026
Merged

feat(tui): palette book-name suggestions with fuzzy match#12
ivanmaierg merged 6 commits into
mainfrom
feat/palette-suggestions

Conversation

@ivanmaierg

Copy link
Copy Markdown
Owner

Summary

Live book-name suggestions in the reader's palette.

  • Fuzzy match: subsequence + light scoring (exact 100, prefix 50, density bonus). joh matches John, 1 John, 2 John, 3 John; 1sa matches 1 Samuel.
  • Display names derived from longest alias per USFM code at module load; numbered books get a regex transform ("1samuel""1 Samuel").
  • State machine extension: awaiting gains suggestions: BookSuggestion[] and selectedIndex: number. New actions SuggestionMovedUp/Down/Accepted; existing handlers updated to maintain the new fields.
  • View: list renders under the input when non-empty (hidden when empty). Selected row uses fg={ACCENT_HEX} matching the verse-cursor pattern; canonical USFM code in DIM on the right.
  • Driver gate split: //Tab flow through to suggestion actions while in awaiting; other reader keys stay suppressed. q/Q quit still works above the gate.
  • Key separation: Tab accepts the selected suggestion (rewrites input to {DisplayName} ready for chapter typing). Enter always submits the query as-typed. No ambiguity.

What does NOT change

  • Domain types untouched apart from one new pure module (book-suggestions.ts) and the export of BOOK_ALIASES.
  • Application use cases (getPassage, getChapter) unchanged.
  • API adapter unchanged.
  • ADR 0010 TS-native dialect retained.

Verify

SDD verify: PASS WITH WARNINGS (0 critical / 2 warning / 2 suggestion). All 16 REQs satisfied. One post-verify fix from manual PTY smoke:

9d5b4dfonChangeonInput. OpenTUI's <input> uses DOM semantics: onChange fires on commit/blur, onInput fires per keystroke. The reader was wired to onChange, so state.query lagged and suggestBooks always received an empty string during typing. One-line fix. This bug was latent in PRs #10 and #11 too (those still worked because onChange fires just before onSubmit on Enter), but this is the first PR that depends on per-keystroke updates.

bun test: 178/178 pass. bun run tsc --noEmit: exits 0.

Test plan

  • bun test 178/178
  • Manual PTY smoke confirmed by user (suggestions appear live, Tab rewrites input, Enter submits)

Out of scope

  • Chapter picker after book pick — surfaced during smoke. Filed as backlog (not on v1 roadmap). v1 still owes translations, favorites, last-position, --format, mouse input — those should land before more palette UX polish.
  • USFM code column alignment (cosmetic).
  • Recent references / history.

Full SDD trail in `openspec/changes/archive/palette-suggestions/`.

PASS WITH WARNINGS (0 critical / 2 warning / 2 suggestion).
All 16 REQs satisfied, 178 tests green, tsc clean.

Tab key works as designed — OpenTUI doesn't consume keys with
charCode < 32, so Tab (9) reaches useKeyboard cleanly. No fallback
key needed.

Pending: manual PTY smoke of the actual fuzzy-finder UX.
OpenTUI's <input> fires onChange on commit/blur, not per keystroke
(matching DOM semantics, not React's onChange override). The reader
was wired to onChange, so state.query only updated when Enter fired
onSubmit — meaning suggestBooks always saw an empty string and the
suggestion list never appeared while typing.

onInput is the per-keystroke event in OpenTUI. Switching to it makes
QueryTyped dispatch on every character, suggestions populate live,
and the list renders as the user types.

This bug was latent in PRs #10 and #11 too — the reader still worked
because onChange fires before onSubmit on Enter, so the final value
landed in state.query just in time for QuerySubmitted. But during
typing, state.query was perpetually one step behind.
SDD cycle closed. PASS WITH WARNINGS verify + 1 user-sanctioned
post-verify fix (onChange→onInput so suggestions update on every
keystroke). 178/178 tests pass. Manual PTY smoke confirmed by user.

Out-of-scope follow-ups: chapter picker after book pick (backlog,
not on v1 roadmap); USFM code column alignment (cosmetic); recent
references / history; chapter-level suggestions within a book.
@ivanmaierg ivanmaierg merged commit a174cf0 into main May 12, 2026
1 check passed
@ivanmaierg ivanmaierg deleted the feat/palette-suggestions branch May 12, 2026 13:26
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