Skip to content

feat(fuzzy): interactive fuzzy-search TUI for password store#41

Merged
vollate merged 7 commits into
mainfrom
feat-fuzzy-support
May 31, 2026
Merged

feat(fuzzy): interactive fuzzy-search TUI for password store#41
vollate merged 7 commits into
mainfrom
feat-fuzzy-support

Conversation

@vollate

@vollate vollate commented May 31, 2026

Copy link
Copy Markdown
Owner

Summary

Add an interactive fuzzy-search TUI that opens when pars is invoked with no subcommand (replacing the old default ls behavior). The feature is gated by feature_config.fuzzy_search and falls back to cmd_ls when disabled.

Highlights

  • Live fuzzy filtering with fzf-style tiered ranking: exact match > contiguous substring > nucleo subsequence; matched character indices drive the highlight (no greedy local re-scan).
  • Action popup per entry — Copy, Display, QR, Edit, Regenerate — with lazy decryption (PGP only runs when an action that needs the plaintext is chosen).
  • New-entry creation (Generate / Insert) via a separate name-input popup (Ctrl-G / Ctrl-N), with overwrite confirmation when an entry already exists.
  • Vim mode (feature_config.vim_mode): Esc/i mode toggle, j/k, g/G, dd/D to clear input, Ctrl-U/D/F/B half/full page nav.
  • Mouse support: scroll, single-click to position cursor, double-click to open action popup, click-outside-popup to dismiss.
  • Display view is now a dedicated full-screen viewer (no popup over the list) so terminal-native multi-line text selection grabs only password text — no border glyphs, no neighboring entry names.
  • Clean editor handoff: cmd_edit, cmd_generate, cmd_insert run with the alt-screen torn down so vim/nano render correctly; full screen refresh on every mode transition.
  • Vim-like clean exit: terminal cleared, alt-screen left, mouse capture released, cursor restored.
  • Windows ConPTY fix: drop non-KeyEventKind::Press events at the top of the loop so the Enter that launched the binary doesn't get re-delivered as a release and auto-select the first entry.
  • Configurable: exit_on_copy (default off), vim_mode (default off), fuzzy_search (default on); env overrides PARS_VIM_MODE, PARS_NO_FUZZY.
  • Improved error message for the external-subcommand path so unknown command names produce a readable Failed to execute external command 'name': ....

Module layout (cli/src/fuzzy/)

  • mod.rs — public entry, terminal setup/teardown, AppMode enum
  • app.rsApp state, PendingAction, PopupRect hit-testing
  • entries.rs — store walk + tiered fuzzy filter
  • events.rs — main event loop and per-mode handlers
  • actions.rs — copy / display / qr / edit / regenerate / generate-new / insert-new + lazy-decrypt + y/N reader
  • ui.rs — all ratatui rendering (search bar, list with match highlights, action popup, name-input popup, full-screen display view, confirmation card)

Test plan

  • cargo build and cargo test clean
  • Run pars with an empty store → friendly message, no panic
  • Run pars with entries → live filter, arrow + j/k + scroll navigation
  • Enter / double-click a row → action popup opens; verify decryption happens only on Copy/Display/QR
  • Copy → clipboard populated; respects exit_on_copy
  • Display → full-screen viewer; multi-line mouse selection contains only password text (no /, no other entry names)
  • QR → renders; native text selection works on it as well
  • Edit → vim/nano launches and TUI restores cleanly
  • Regenerate → confirmation card visible, password updates, message shown
  • Ctrl-G / Ctrl-N → name-input popup; overwrite confirmation when entry exists
  • Vim mode: Esc → Normal, i → Insert; dd, D, Ctrl-U/D/F/B, g/G
  • Windows PowerShell: cargo run does NOT auto-open the action popup on launch
  • q / Ctrl-C exit cleanly with no leftover screen artifacts

🤖 Generated with Claude Code

vollate added 7 commits May 26, 2026 20:59
…eation

  Split the monolithic fuzzy/mod.rs (~900 lines) into focused modules:
  - app.rs       — App state, AppMode, PendingAction
  - entries.rs   — store walking + tiered fuzzy matcher (exact > substring > subseq)
  - events.rs    — main event loop and per-mode keyboard/mouse handlers
  - actions.rs   — copy/display/qr/edit/regenerate/generate-new/insert-new handlers
  - ui.rs        — ratatui rendering only
- Add double-click on result rows to act as Enter (open action popup)
- Anchor display popup near the selected row instead of always centering
- Strict key handling in display mode: only Esc/Enter/q/Ctrl-C respond
- Fix Ctrl+C in action popup being misread as the 'c' (copy) shortcut
- Restore terminal cleanly on exit (clear + leave alt screen, vim-like)
- Release mouse capture in display mode for native text selection
On Windows (ConPTY), crossterm reports both Press and Release for every
key, while Linux/macOS only report Press. The Enter pressed to launch
the binary delivered a Release event into the TUI's event loop right
after startup, which our handlers treated as a fresh Enter Press and
auto-opened the action popup on the first entry.
@vollate vollate self-assigned this May 31, 2026
@vollate vollate merged commit 4b415b4 into main May 31, 2026
0 of 3 checks passed
@vollate vollate deleted the feat-fuzzy-support branch May 31, 2026 07:58
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