-
Notifications
You must be signed in to change notification settings - Fork 58
feat: Query parsing (HUGE THING READ CHANGELOG) #224
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
a7d3129 to
81e4574
Compare
47b3bad to
e57cefc
Compare
4c845f9 to
43acae2
Compare
Build Artifacts for your PRNeovim PluginTest with lazy.nvim: {
"dmtrKovalenko/fff.nvim",
tag: "4f47a6b",
}Bun/TypeScript PackageThe Built from 4f47a6b |
243beb7 to
60120c4
Compare
7c78719 to
a862602
Compare
06a44f9 to
9ff4fcd
Compare
7fd2704 to
52cf13c
Compare
eb027c8 to
300bc4d
Compare
300bc4d to
6efa978
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Adds multi-token query parsing with constraints (glob/ext/path/exclude) and propagates parsed query info through the Rust core, while also introducing a Bun/TypeScript package + C FFI surface and updating CI/release/test infrastructure.
Changes:
- Introduces
fff-query-parserand integrates parsed constraints/location into scoring/search. - Refactors Rust into a workspace (
fff-core,fff-nvim,fff-c) and adds a Bun/TS client package with binary download/FFI bindings. - Adds Lua E2E tests + updates GitHub Actions workflows and release artifact generation.
Reviewed changes
Copilot reviewed 59 out of 73 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/minimal_init.lua | Minimal Neovim runtime bootstrap for Plenary-based Lua tests |
| tests/fff_core_spec.lua | Adds core Lua integration tests (scan/search/git/health) |
| plugin/fff.lua | Keeps debug flags in sync (show_scores ↔ show_file_info) |
| packages/fff/tsconfig.json | Adds TS config for the Bun package build/typecheck |
| packages/fff/test.ts | Adds a manual Bun test script for local verification |
| packages/fff/src/types.ts | Defines public TS types + Result helpers + option mappers |
| packages/fff/src/platform.ts | Adds platform triple + library naming helpers |
| packages/fff/src/index.ts | Public entrypoint exports for the Bun package |
| packages/fff/src/index.test.ts | Adds Bun tests for platform/binary detection + FileFinder lifecycle |
| packages/fff/src/finder.ts | Implements FileFinder high-level API wrapping FFI functions |
| packages/fff/src/ffi.ts | Implements Bun FFI bindings + result parsing/camelCase transform |
| packages/fff/src/download.ts | Adds GitHub release binary download + checksum verification |
| packages/fff/scripts/postinstall.ts | Auto-downloads native binary during package install |
| packages/fff/scripts/cli.ts | Adds bunx fff CLI for download/info/check/version/help |
| packages/fff/package.json | Defines Bun package metadata, scripts, bins, and dependencies |
| packages/fff/examples/search.ts | Adds interactive TTY demo for searching/indexing output |
| packages/fff/README.md | Documents Bun package usage, API, and query syntax |
| packages/fff/.gitignore | Ignores downloaded native binaries and build output |
| lua/fff/rust/types.rs | Removes old Lua-facing Rust type conversion module (moved/refactored) |
| lua/fff/rust/score.rs | Removes old scoring implementation (moved into fff-core) |
| lua/fff/rust/init.lua | Improves cross-platform backend library path resolution (Windows) |
| lua/fff/rust/db_healthcheck.rs | Removes old Lua-only DB healthcheck trait (moved to core) |
| lua/fff/main.lua | Uses backend git-root API + updates fuzzy_search_files argument order |
| lua/fff/fuzzy.lua | Exposes additional backend APIs (get_git_root, health_check, etc.) |
| lua/fff/conf.lua | Keeps toggled debug flags synced (show_scores ↔ show_file_info) |
| flake.nix | Adds Zig + libclang inputs for builds depending on zlob/bindgen |
| doc/fff.nvim.txt | Updates help doc “Last change” timestamp |
| crates/fff-query-parser/src/parser.rs | New query parser: constraints + fuzzy parts + location extraction |
| crates/fff-query-parser/src/location.rs | Adds module docs and cleans up tests import |
| crates/fff-query-parser/src/lib.rs | New crate root + exports + tests for parser behavior |
| crates/fff-query-parser/src/constraints.rs | Defines query constraint types + buffer aliases |
| crates/fff-query-parser/src/config.rs | Adds configurable parsing behavior via ParserConfig |
| crates/fff-query-parser/benches/parse_bench.rs | Adds Criterion benches for parser performance |
| crates/fff-query-parser/Cargo.toml | New crate manifest |
| crates/fff-nvim/src/path_shortening.rs | Refactors path shortening API and error types |
| crates/fff-nvim/src/lua_types.rs | New Lua conversion layer for fff-core result types |
| crates/fff-nvim/src/log.rs | Changes tracing init signature to return io::Error |
| crates/fff-nvim/src/lib.rs | Refactors nvim module to use fff-core, parser integration, git root export |
| crates/fff-nvim/src/error.rs | Adds explicit error conversion helpers for mlua (orphan rule workaround) |
| crates/fff-nvim/Cargo.toml | New manifest for fff-nvim crate in workspace |
| crates/fff-core/src/types.rs | Introduces shared core types + parsed query propagation |
| crates/fff-core/src/score.rs | New scoring implementation supporting parsed constraints + multi-part fuzzy |
| crates/fff-core/src/path_utils.rs | Moves distance penalty util into core with tests |
| crates/fff-core/src/lib.rs | New core crate root + global state + re-exports |
| crates/fff-core/src/file_picker.rs | Updates fuzzy search to accept parsed query + location handling |
| crates/fff-core/src/error.rs | Removes mlua conversion from core error type |
| crates/fff-core/src/db_healthcheck.rs | Moves db healthcheck logic into core crate |
| crates/fff-core/build.rs | Adds Windows MSVC CRT link directives for Zig-built objects |
| crates/fff-core/Cargo.toml | New manifest for fff-core crate |
| crates/fff-c/src/lib.rs | Adds C ABI exports wrapping fff-core (init/search/scan/health/etc.) |
| crates/fff-c/src/ffi_types.rs | Defines FFI result structs + JSON serialization types |
| crates/fff-c/Cargo.toml | New manifest for fff-c crate |
| Makefile | Adds build/test/format helpers incl. Plenary setup for Lua tests |
| Cross.toml | Removes cross-rs configuration (migrated to zigbuild in workflows) |
| Cargo.toml | Converts repo into a workspace with shared dependency versions |
| .github/workflows/rust.yml | Updates CI: Zig install + workspace tests excluding fff-nvim |
| .github/workflows/release.yaml | Splits builds for fff-nvim and fff-c, uses zigbuild, reshapes artifacts |
| .github/workflows/lua-tests.yml | Adds Lua E2E workflow (build + headless Neovim + Plenary) |
| .cargo/config.toml | Simplifies macOS rustflags config using cfg target selector |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| release: | ||
| name: Release | ||
| needs: build | ||
| needs: [build-nvim, build-c] |
Copilot
AI
Feb 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The release job no longer has an event guard, but the workflow runs on both push and pull_request. This can trigger release creation attempts on PRs. Add back an if: github.event_name == 'push' (or similar) gating on the release job to prevent accidental releases during PR validation.
| needs: [build-nvim, build-c] | |
| needs: [build-nvim, build-c] | |
| if: github.event_name == 'push' |
| { | ||
| "dmtrKovalenko/fff.nvim", | ||
| tag = "${{ steps.vars.outputs.short_sha }}", | ||
| tag: "${{ steps.vars.outputs.short_sha }}", |
Copilot
AI
Feb 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This snippet is Lua, but it uses tag: which is invalid Lua table syntax (Lua uses = for key assignment). Change it to tag = \"...\" so the example is copy/pasteable.
| tag: "${{ steps.vars.outputs.short_sha }}", | |
| tag = "${{ steps.vars.outputs.short_sha }}", |
| Constraint::Text(text) => { | ||
| // Case-insensitive contains without allocation | ||
| file.relative_path_lower | ||
| .contains(&text.to_ascii_lowercase()) | ||
| } |
Copilot
AI
Feb 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
text.to_ascii_lowercase() allocates a new String for every file checked, which can become very expensive when constraints include Text. Since relative_path_lower is already cached, consider lowercasing the query token once (e.g., during parsing or when building the constraint set) and then doing relative_path_lower.contains(text_lower) without per-file allocation.
| // Only collect paths if we have glob constraints (expensive) | ||
| let has_globs = other_constraints | ||
| .iter() | ||
| .any(|c| matches!(c, Constraint::Glob(_) | Constraint::Not(_))); | ||
|
|
||
| let glob_results = if has_globs { | ||
| let paths: Vec<&str> = files.iter().map(|f| f.relative_path.as_str()).collect(); | ||
| precompute_glob_matches_refs(&other_constraints, &paths) | ||
| } else { | ||
| Vec::new() | ||
| }; |
Copilot
AI
Feb 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
has_globs treats any Constraint::Not(_) as requiring glob precomputation, but many negations (e.g., !status:modified, !*.rs via Not(Extension), !text) don't need glob matching. This causes the paths vector allocation and precompute pass unnecessarily. Consider detecting globs by walking the constraint tree and returning true only if a Glob exists (including inside Not).
| - **Type-safe** - Full TypeScript support with Result types | ||
|
|
||
| ## Installation | ||
|
|
Copilot
AI
Feb 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The install command (bun add fff) implies the published package name is fff, but packages/fff/package.json currently sets name to @ff-labs/bun. Either update the README (and import examples) to use the actual published name, or change package.json to match the documented install/import path so consumers don’t get a broken setup.
| describe("FileFinder - Availability", () => { | ||
| test("isAvailable returns true when binary exists", () => { | ||
| const available = FileFinder.isAvailable(); | ||
| expect(available).toBe(true); | ||
| }); | ||
| }); |
Copilot
AI
Feb 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These tests hard-fail if the native library isn’t present on the machine running the test suite (e.g., clean CI without a prior download/build). To reduce brittleness, consider either (a) ensuring the binary is present in a test setup step (download/build) or (b) conditionally skipping these tests when FileFinder.isAvailable() is false with a clear message.
closes #225
closes #160
This allows you to write more words to the query like "some thing www" and fff now correctly parse all those tokens and will show only the results that matching all of the constraints. In addition to that you can use specific tokens:
www/- include only the subdirectoriies of child (no matter how deep they are)*.rs,*.ts- include files with certain extension (either of one that is used)**/tests/**/*.spec.??- any valid glob expression including support of **, braces, ? and any valid glob expressions!<token>- values that are not qualifying any token