Skip to content

feat(diff): telescope-style global fuzzy search (ctrl+f)#160

Merged
jnsahaj merged 1 commit into
mainfrom
feat/global-fuzzy-search
Jun 3, 2026
Merged

feat(diff): telescope-style global fuzzy search (ctrl+f)#160
jnsahaj merged 1 commit into
mainfrom
feat/global-fuzzy-search

Conversation

@jnsahaj

@jnsahaj jnsahaj commented Jun 3, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds a full-screen telescope-style fuzzy search across every line of every file in the diff, opened with ctrl+f. Existing in-file / search is left untouched.
  • Two-pane layout (50/50): results list on the left, real stacked-diff preview on the right with tree-sitter syntax highlighting.
  • Powered by nucleo-matcher (same fuzzy engine as Helix / Zellij) for fzf-quality scoring.

What's in scope

Indexing (built once per modal open):

  • Equal rows → new side only (no duplicates)
  • Delete / Insert → only the side with content
  • Modified → both sides (genuinely different text)
  • Blank/whitespace-only lines skipped
  • Smart case + smart unicode normalization

Results list:

  • selector, change-symbol prefix, project-relative path:line, body with fzf-matched chars bolded
  • Horizontal + vertical mouse scroll; list scroll separate from selection (mouse can scroll past cursor)
  • Click a row to select; ↑↓ / ctrl+n / ctrl+p / ctrl+j / ctrl+k also select

Preview pane:

  • Real stacked (unified) mini-diff around the matched line, full file scrollable
  • Tree-sitter syntax highlighting, cached per (file, panel)
  • Tab expansion matches main diff view
  • Cursor row centered vertically; brightened in-palette so green-on-green / red-on-red are preserved, with selection_bg fallback on themes that defer to terminal bg
  • Background colors match the main diff view (page bg for equal/empty, added_bg/deleted_bg for changes)
  • Mouse wheel scrolls; shift+wheel flips to horizontal

Key bindings:

key action
ctrl+f open
esc / ctrl+c close
enter jump to match (seeds / search with the query)
↑↓ / ctrl+n / ctrl+p / ctrl+j / ctrl+k move selection
pgup / pgdn / ctrl+d page
home / end jump top/bottom
ctrl+u / cmd+backspace clear query
ctrl+w / opt+backspace erase word

Performance

The render path is on the hot frame loop, so every layer is optimized:

  • Two-pass preview render — pass 1 walks the full SBS building cheap (sbs_idx, side, is_cursor) metas; pass 2 materializes only the visible window through the expensive highlighter + tab-expand + scroll path. On a 1000-line file with a 30-row preview, that's ~33× fewer highlighter calls per frame.
  • Run-coalesced spans in result rows — was one Span::styled(ch.to_string(), …) per haystack char (~4000 single-char allocs per frame for a typical visible list); now ~10× fewer spans by grouping consecutive same-style chars.
  • Reusable Matcher — taken-and-restored across refilter calls so we don't pay nucleo's scratch-slab allocation per keystroke.
  • Top-K via select_nth_unstable_by instead of full sort + truncate — ~10× faster sort phase on large match sets.
  • SBS pre-seeded into cache during build — first preview render is cache-hot since we already compute SBS at index time.

Test plan

  • cargo build and cargo build --release both clean
  • ctrl+f opens; modal is full-screen with empty list + preview
  • Typing a query updates results in real time; matched chars are bolded
  • Preview pane renders a stacked mini-diff around the cursor row, syntax-highlighted
  • Cursor row visibly highlighted on equal/added/deleted rows across themes
  • enter jumps to the matched file + line and seeds / search
  • Mouse wheel scrolls list and preview independently; shift+wheel horizontal
  • Click a result row to select it
  • cmd+backspace / ctrl+u clear query; opt+backspace / ctrl+w erase word
  • esc / ctrl+c close without jumping
  • Preview bg matches main diff view bg (no sticky-header tint)
  • Smooth on a large diff (many files / many lines) — no visible lag on keystroke

🤖 Generated with Claude Code

Add a full-screen fuzzy search modal across every line of every file in
the diff, triggered by ctrl+f. Leaves the existing in-file `/` search
untouched. Uses nucleo-matcher (same fuzzy engine as helix/zellij/nucleo)
for scoring and a two-pane telescope layout: results list on the left,
mini stacked-diff preview on the right.

Search behavior:
- Equal lines indexed on the new side only (avoids dupes)
- Delete/Insert on the affected side; Modified on both
- Blank/whitespace-only lines skipped
- Smart case + smart unicode normalization
- Top 500 matches by score; sort stable by entry index

Preview pane:
- Real stacked (unified) mini-diff around the matched line, full file
  scrollable
- Tree-sitter syntax highlighting (cached per file × panel)
- Tab expansion matches the main diff view
- Cursor row centered vertically, brightened in-palette so green-on-green
  and red-on-red are preserved; falls back to selection_bg on themes
  that defer to the terminal bg
- Horizontal + vertical mouse scroll; shift+wheel = horizontal
- Bg matches main diff view (page bg for equal/empty, added/deleted_bg
  for changes)

Results list:
- Selector ❯, change-symbol prefix, full project-relative path:line,
  body with fzf-matched chars bolded
- Horizontal + vertical mouse scroll; selection-driven auto-scroll
  separate from mouse-wheel scroll
- Click a row to select it; enter to jump

Key bindings:
- ctrl+f open · esc/ctrl+c close · enter jump
- ↑↓ / ctrl+n / ctrl+p / ctrl+j / ctrl+k select
- pgup/pgdn / ctrl+d page
- home/end top/bottom
- ctrl+u and cmd+backspace clear · ctrl+w and opt+backspace word-erase

Performance:
- Two-pass preview render: cheap meta walk over full SBS, then materialize
  only the visible window (~33× fewer highlighter calls per frame on
  large files)
- Run-coalesced spans in result rows (~10× fewer per-char allocations)
- Matcher reused across keystrokes via take-and-restore
- Top-K via select_nth_unstable_by instead of full sort + truncate
- SBS pre-seeded into cache during build so first preview is hot
@jnsahaj jnsahaj merged commit 76f8ac3 into main Jun 3, 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