feat(diff): telescope-style global fuzzy search (ctrl+f)#160
Merged
Conversation
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
ctrl+f. Existing in-file/search is left untouched.nucleo-matcher(same fuzzy engine as Helix / Zellij) for fzf-quality scoring.What's in scope
Indexing (built once per modal open):
Results list:
❯selector, change-symbol prefix, project-relativepath:line, body with fzf-matched chars boldedctrl+n/ctrl+p/ctrl+j/ctrl+kalso selectPreview pane:
(file, panel)selection_bgfallback on themes that defer to terminal bgadded_bg/deleted_bgfor changes)shift+wheelflips to horizontalKey bindings:
ctrl+fesc/ctrl+center/search with the query)↑↓/ctrl+n/ctrl+p/ctrl+j/ctrl+kpgup/pgdn/ctrl+dhome/endctrl+u/cmd+backspacectrl+w/opt+backspacePerformance
The render path is on the hot frame loop, so every layer is optimized:
(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.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.Matcher— taken-and-restored acrossrefiltercalls so we don't pay nucleo's scratch-slab allocation per keystroke.select_nth_unstable_byinstead of full sort + truncate — ~10× faster sort phase on large match sets.Test plan
cargo buildandcargo build --releaseboth cleanctrl+fopens; modal is full-screen with empty list + previewenterjumps to the matched file + line and seeds/searchshift+wheelhorizontalcmd+backspace/ctrl+uclear query;opt+backspace/ctrl+werase wordesc/ctrl+cclose without jumping🤖 Generated with Claude Code