原始内容
pi-fzfp
Fuzzy file picker for pi. Replaces the built-in @ file autocomplete with fzf-powered fuzzy matching.
The Problem
Pi's built-in @file autocomplete uses fd with a regex pattern and substring scoring. Typing @inxts won't find index.ts because the characters aren't contiguous.
The Fix
pi-fzfp pipes fd output through fzf --filter for true subsequence fuzzy matching, scored and sorted by fzf's battle-tested algorithm.
Requirements
Install
pi install npm:pi-fzfp
pi-fzfp stacks an fzf-powered autocomplete provider on top of the built-in
provider via ctx.ui.addAutocompleteProvider(). It does not install an editor
component, so it works alongside any custom editor (pi-vim, etc.) with no extra
configuration or coordination — just install both packages.
How It Works
Autocomplete
- Intercepts
@queries in the autocomplete provider - Runs
fdto list project files (respects.gitignore, excludes.git) - Pipes the file list through
fzf --filter=<query>for fuzzy matching and scoring - Returns all matches sorted by fzf's score (no artificial limit)
- Builds autocomplete suggestions with proper
@prefix and quoting - Non-
@queries delegate to the underlying provider unchanged
Scanning and caching
The fd filesystem walk is the expensive part, so pi-fzfp is careful about it:
- Full-depth scan with a time budget. Directories are scanned full-depth so
deeply nested files are always found, with no result cap. A 5s wall-clock
timeout bounds the walk for pathological trees (e.g. accidentally scanning
$HOMEor a network mount); fd is fast enough that this never trips on a normal repo (tens of ms even for 100k files). - Browse without recursing. When the file query is empty (e.g. navigating
into
@~/or@/mnt/e/), only the directory's immediate children are listed (readdirSync), not a full recursive scan. The recursivefdscan runs only once you start typing a name. This keeps browsing into huge directories instant. - Per-directory cache. Each directory's listing (both recursive scans and
child listings) is cached in memory with a 30s TTL and reused across
keystrokes — repeated typing only re-runs the cheap in-memory
fzf --filter, notfd.
Binary lookup (fd/fzf) uses a pure-filesystem PATH walk (accessSync), with
no which subprocess.
Integration
pi-fzfp registers its provider with ctx.ui.addAutocompleteProvider((current) => ...)
at session_start. pi passes the currently-active provider as current, and
pi-fzfp wraps it: @ queries are matched with fzf, everything else delegates to
current. Because this stacks on top of whatever provider is active (built-in or
from a custom editor), no editor detection or event handshake is needed.
API
wrapWithFuzzyFiles(provider, basePath?)
Wraps any AutocompleteProvider with fzf-powered fuzzy file matching for @ queries. Returns the provider unchanged if fd or fzf is not available.
FzfFileAutocompleteProvider
The wrapper class, if you need more control.