* fix(nvim): Correctly handle different cwds
* fix(ci): suppress missing-fields diagnostic in test file
* fix(test): clear DirChanged autocmd to prevent race in e2e suite
* fix(test): normalize paths for cross-platform comparison in e2e
* fix(test): robust path normalization for Windows 8.3 names and case
* fix(test): use fs_realpath for Windows 8.3 name expansion
* fix(test): constrain grep test to .rs files to avoid flaky ordering
* fix(constraints): double-negation bug in Not(Glob(...)) filtering
* chore: Upgarde zlob and biome
* chore: Update docs for - chore: Upgarde zlob and biome
* fix(nix): redirect Zig cache dirs out of /homeless-shelter
Zig 0.16 writes to $HOME/.cache/zig even when --global-cache-dir is
passed, which fails in the nix sandbox where $HOME is /homeless-shelter.
Point ZIG_*_CACHE_DIR and XDG_CACHE_HOME at $TMPDIR instead.
* chore: Update docs for - fix(nix): redirect Zig cache dirs out of /homeless-shelter
* chore: lock zlob at 1.3.3
Cargo.toml was bumped to 1.3.3 but Cargo.lock still pinned the
1.3.3-dev.5 prerelease, which made cargo's vendored dir fail resolution
under crane's nix build.
* fix(grep): avoid duplicate results from bitset overflow overlap
Restrict the bigram candidate bitset iteration to indexed files only,
since overflow files are appended unconditionally by the overflow loop.
The bitset is sized to ceil(base_file_count / 64) * 64 bits, so when
base_file_count is not a multiple of 64 trailing bits can map to file
indices in the overflow range. If any of those bits are set (e.g. via
overlay modified-file merging), the same file was previously pushed
twice — once by the bitset loop and once by the overflow loop —
producing duplicate grep results.
Closes#407
* chore: Update docs for - fix(grep): avoid duplicate results from bitset overflow overlap
* fix fmt
* fix(file_picker): index only base files in bigram filter
Root cause of #407: when watcher events landed between the initial
scan completing and the background bigram-index build snapshotting
`sync_data.files()`, the snapshot included overflow files. The filter
was built with `file_count = base + overflow`, but the overlay was
created with only `base_file_count`. At grep time, the candidate
bitset legitimately carried bits for overflow file indices (from the
filter), and the overflow-append loop pushed those same files again
producing duplicates.
Snapshot `base_count` alongside `files` and pass `&files[..base_count]`
to `build_bigram_index` so the filter and overlay agree on which
files are indexed. The grep-side `file_idx < overflow_start` guard
stays in place as a defensive check.
* fix: avoid unicode filepath suffix panic
* fix: prevent unicode char boundary panics in all constraint functions
The previous fix (a09292e) only guarded path_ends_with_suffix with
path.get(start..), but three problems remained:
1. path_ends_with_suffix: path_bytes[start - 1] reads inside a
multi-byte char when start is a valid boundary but start-1 is not.
Fixed by scanning backward to find the preceding ASCII byte.
2. path_contains_segment: path[..segment_len] and path[start..end]
slice at non-char-boundary offsets when segment is ASCII but the
path contains multi-byte UTF-8 (Korean, etc).
Fixed with is_char_boundary() checks before each slice.
3. file_has_extension: same byte-offset issue for dot_pos.
Fixed with is_char_boundary() check.
Adds regression tests with the exact Korean filenames that caused
panics (커리큘럼, 세부_커리큘럼_최종, 설치-및-기본-사용, etc).
Merges upstream unicode tests (apostrophe, narrow-space mismatches).
---------
Co-authored-by: Dmitriy Kovalenko <dmtr.kovalenko@outlook.com>
* fix(windows): normalize path separators for directorySearch
* fix: all the usage of literal path separator
* fix: macos tests
* feat: Official pi fff extension (#374)
* feat: add pi extension for FFF file search
Add @ff-labs/pi-fff package providing pi coding agent integration:
- Overrides built-in find/grep tools with FFF-powered versions
- Adds multi_grep tool for SIMD-accelerated multi-pattern search
- Replaces @-mention autocomplete with FFF frecency-ranked suggestions
- Commands: /fff-health, /fff-rescan, /fff-mode (with immediate switch)
- Streamlined implementation: 26% code reduction (800→590 lines)
Published as pi package: npm:@ff-labs/pi-fff
* docs: fix install instructions
- Remove git install option (doesn't work for monorepo subfolders)
- Remove config file from mode precedence (no longer used)
- Keep npm as only recommended install method
* feat: add root pi manifest for git installs
Add pi configuration to root package.json pointing to packages/pi-fff.
This enables:
pi install git:github.com/dmtrKovalenko/fff.nvim
The root stays private (not published to npm), but pi can now discover
the extension from the git repo structure.
* docs: add git install instructions
Now that root package.json has pi manifest, git installs work:
pi install git:github.com/dmtrKovalenko/fff.nvim
* fix: address PR review feedback
- Add config file persistence for /fff-mode (fixes 'persist' claim)
- Add readConfigMode() and writeConfigMode() helpers
- Use applyEditorMode() in /fff-mode command (DRY)
- Add publishConfig.access: 'public' for npm publishing
- Fix @types/node to ^22.0.0 (align with repo)
- Remove ignoreCase parameter (FFF doesn't support force case-insensitive)
- Run Biome formatter (fix tab indentation)
* update toolnames and add to release pipeline
* do not override default tools
* Make an option to override the default tools
* fix: macos tests
* better toolnames mangement
---------
Co-authored-by: Dmitriy Kovalenko <dmtr.kovalenko@outlook.com>
* chore: release 0.6.1
* chore: fix versioning of pi package
* add tests
* get rid of all rfinds
---------
Co-authored-by: Dmitriy Kovalenko <dmtr.kovalenko@outlook.com>
Co-authored-by: Samuel Huber <40248495+SamuelLHuber@users.noreply.github.com>
* feat: add pi extension for FFF file search
Add @ff-labs/pi-fff package providing pi coding agent integration:
- Overrides built-in find/grep tools with FFF-powered versions
- Adds multi_grep tool for SIMD-accelerated multi-pattern search
- Replaces @-mention autocomplete with FFF frecency-ranked suggestions
- Commands: /fff-health, /fff-rescan, /fff-mode (with immediate switch)
- Streamlined implementation: 26% code reduction (800→590 lines)
Published as pi package: npm:@ff-labs/pi-fff
* docs: fix install instructions
- Remove git install option (doesn't work for monorepo subfolders)
- Remove config file from mode precedence (no longer used)
- Keep npm as only recommended install method
* feat: add root pi manifest for git installs
Add pi configuration to root package.json pointing to packages/pi-fff.
This enables:
pi install git:github.com/dmtrKovalenko/fff.nvim
The root stays private (not published to npm), but pi can now discover
the extension from the git repo structure.
* docs: add git install instructions
Now that root package.json has pi manifest, git installs work:
pi install git:github.com/dmtrKovalenko/fff.nvim
* fix: address PR review feedback
- Add config file persistence for /fff-mode (fixes 'persist' claim)
- Add readConfigMode() and writeConfigMode() helpers
- Use applyEditorMode() in /fff-mode command (DRY)
- Add publishConfig.access: 'public' for npm publishing
- Fix @types/node to ^22.0.0 (align with repo)
- Remove ignoreCase parameter (FFF doesn't support force case-insensitive)
- Run Biome formatter (fix tab indentation)
* update toolnames and add to release pipeline
* do not override default tools
* Make an option to override the default tools
* fix: macos tests
* better toolnames mangement
---------
Co-authored-by: Dmitriy Kovalenko <dmtr.kovalenko@outlook.com>
* breaking(sdk): Rename several options & add more flags to control
* chore: Update docs for - breaking(sdk): Rename several options & add more flags to control
There are 2 problems:
1. There is a fixed limit of how many fsevents streams macos can spawn per process
2. New created directories are not getting watched
This fixes both
* wip: Paths and dirs
* feat: att 2
* final changes
* feat!: Revamp & optimize the way paths are stored
This is a very crucial redesign that actually required a lot of
consideration to move forward but now it allows us to save a lot of RAM,
acutally improves query time and gives an ability to query directories
for free
* fix: Wrong pointer
* chore: Update docs for - fix: Wrong pointer
* fix: notify debouncer on macos
* get rid of flienma_ptrs juggling
* consolidate arena/picker via pub trait
* fix: close picker immediately on <C-c> in vim mode
When prompt_vim_mode is enabled, <C-c> in insert mode was just leaving
insert (Neovim default) instead of closing the picker. Map it explicitly
to close.
* chore: Update docs for - fix: close picker immediately on <C-c> in vim mode
* feat: enable vim-mode
* feat: handle cursor move to move up until prefix
* feat: make it configurable
* docs: vim_mode
* docs: update to prompt_vim_mode
Co-authored-by: Dmitriy Kovalenko <dmitriy@iusevimbtw.com>
* refactor: rename vim_mode to prompt_vim_mode
Matches the maintainer's preferred naming from PR review: since this is a
neovim plugin, the flag scope is clarified by the prompt_ prefix.
* style: collapse single-statement if for stylua
---------
Co-authored-by: Dmitriy Kovalenko <dmitriy@iusevimbtw.com>
* feat: Correct bonuses for actual path prefix
The issue is related to the fact that long prefix similarity the suffix
difference got neglected as a small typo which is wrong
* chore: Update docs for - feat: Correct bonuses for actual path prefix
* fix(grep): align preview highlight stripping with Rust query parser
The Lua heuristic in highlight_grep_matches used a simple prefix check
(^[*!/] or ^.) to strip constraints. This diverged from the Rust
GrepConfig parser in several ways:
- Multi-word queries like 'foo bar *.rs' only highlighted 'foo'
- Constraint prefixes like type:rust were not stripped
- Tokens starting with '.' were incorrectly treated as constraints
- Escaped constraint tokens (e.g. \*.config) were not handled
Replace the heuristic with _is_grep_constraint() that matches the
Rust parser's actual GrepConfig rules: extensions (*.rs), path segments
(/src/), exclusions (!test), type filters (type:rust), and path-oriented
globs. Use all text parts joined with space for highlighting, matching
grep_text() on the Rust side.
Fixes#331
* refactor(grep): expose parsed query to lua via Rust function
Replace the Lua-side constraint detection (_is_grep_constraint) with a
new parse_grep_query() function that delegates to the Rust GrepConfig
parser. This keeps the Rust parser as the single source of truth for
query parsing, avoiding drift when new token types are added.
The new function is exposed to Lua as fff.parse_grep_query(query) and
returns a table with the grep_text field (the search text with all
constraints stripped).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
vim.json.decode returns Blobs instead of strings when the decoded
value contains NUL bytes. Passing a Blob to strdisplaywidth triggers
E976. Guard item.name and item.directory the same way
grep_renderer.lua already guards line_content.
Fixes#310
* feat: add serialization accessors to BigramFilter
Add read-only accessors and a from_raw_parts constructor to
BigramFilter, enabling external tools to serialize/deserialize
the bigram index to/from disk without reaching into private fields.
New public methods:
- lookup(), dense_data(), words(), dense_count(), populated()
- skip_index() -> Option<&BigramFilter>
- from_raw_parts(lookup, dense_data, ...) -> Self
* Remove section header, rename from_raw_parts to reconstruct
* fix lint and rename
* fix ci
---------
Co-authored-by: Dmitriy Kovalenko <dmtr.kovalenko@outlook.com>
* fix(mcp): accept whole-number float maxResults from MCP clients
Some MCP clients serialize integer values as floats (e.g., 30.0 instead of 30).
This change allows the MCP server to accept both usize and whole-number f64
values for the maxResults parameter, while rejecting fractional values.
* fix it properly
* fix ci
* fix spellcheck
---------
Co-authored-by: RoomWithOutRoof <taizi@sparklab.io>
Co-authored-by: Dmitriy Kovalenko <dmtr.kovalenko@outlook.com>