### Setup fff.nvim with Configuration Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/configuration.md Use the `require('fff').setup(config)` function to initialize the plugin with your desired configuration. This example shows a comprehensive set of options. ```lua require('fff').setup({ base_path = vim.fn.getcwd(), -- Root for indexing prompt = '> ', -- Prompt text title = 'FFFiles', -- Picker title max_results = 100, -- Results per page max_threads = 4, -- Worker threads lazy_sync = true, -- Lazy scan initialization prompt_vim_mode = false, -- Vi keybinding in prompt follow_symlinks = false, -- Follow symlinks enable_home_dir_scanning = true, -- Index $HOME enable_fs_root_scanning = false, -- Index / layout = { height = 0.8, -- Window height (0-1) width = 0.8, -- Window width (0-1) prompt_position = 'bottom', -- or 'top' preview_position = 'right', -- 'left' | 'right' | 'top' | 'bottom' preview_size = 0.5, -- Preview width/height ratio border = nil, -- Border style or nil for global flex = { size = 130, wrap = 'top' }, -- Flex layout config min_list_height = 10, -- Min list height before hide show_scrollbar = true, -- Show scroll indicator path_shorten_strategy = 'middle_number', -- 'middle_number' | 'middle' | 'end' | 'start' anchor = 'center', -- Window anchor }, preview = { enabled = true, -- Show file preview max_size = 10 * 1024 * 1024, -- Max preview file size chunk_size = 8192, -- Read chunk for preview binary_file_threshold = 1024, -- Threshold for binary detection imagemagick_info_format_str = '%m: %wx%h, %[colorspace], %q-bit', line_numbers = false, -- Show line numbers cursorlineopt = 'both', -- Cursor line behavior wrap_lines = false, -- Wrap long lines filetypes = { -- Per-filetype overrides svg = { wrap_lines = true }, markdown = { wrap_lines = true }, text = { wrap_lines = true }, }, }, keymaps = { close = '', -- Close picker select = '', -- Select item select_split = '', -- Select in split select_vsplit = '', -- Select in vsplit select_tab = '', -- Select in tab move_up = { '', '' }, -- Move up move_down = { '', '' }, -- Move down preview_scroll_up = '', -- Scroll preview up preview_scroll_down = '', -- Scroll preview down toggle_debug = '', -- Toggle debug panel cycle_grep_modes = '', -- Cycle grep modes grep_jump_to_next_file = { '' }, -- Jump to next file (grep) grep_jump_to_prev_file = { '' }, -- Jump to prev file (grep) cycle_previous_query = '', -- Previous query toggle_select = '', -- Toggle selection send_to_quickfix = '', -- Send to quickfix focus_list = 'l', -- Focus list focus_preview = 'p>', -- Focus preview }, frecency = { enabled = true, -- Enable frecency ranking db_path = vim.fn.stdpath('cache') .. '/fff_nvim', -- DB path }, history = { enabled = true, -- Enable query history db_path = vim.fn.stdpath('data') .. '/fff_queries', min_combo_count = 3, -- Min for combo boost combo_boost_score_multiplier = 100, -- Combo boost amount }, git = { status_text_color = false, -- Color by git status }, select = { select_window = function(current_buf, action) -- Return winid to open file in, or nil for default end, }, grep = { max_file_size = 10 * 1024 * 1024, -- Max grep file size max_matches_per_file = 100, -- Max matches per file smart_case = true, -- Case-insensitive when lowercase time_budget_ms = 150, -- Wall-clock budget modes = { 'plain', 'regex', 'fuzzy' }, -- Available modes trim_whitespace = false, -- Strip whitespace enable_filename_constraint = false, -- Treat filenames as constraints location_format = ':%d:%d', -- Line:col format string }, debug = { enabled = false, -- Show debug panel show_scores = false, -- Show match scores }, }) ``` -------------------------------- ### Development Setup with uv Source: https://github.com/dmtrkovalenko/fff/blob/main/packages/fff-python/README.md Set up the development environment using uv for dependency management and installing the package in editable mode. ```bash cd packages/fff-python uv sync --all-extras uv run maturin develop --release ``` -------------------------------- ### Local development setup for pi-fff Source: https://github.com/dmtrkovalenko/fff/blob/main/packages/pi-fff/README.md Steps for cloning the repository, installing dependencies, and configuring pi for local development. ```bash git clone https://github.com/dmtrKovalenko/fff.nvim.git cd fff.nvim/packages/pi-fff npm install ``` -------------------------------- ### Bun FileFinder Quick Start Example Source: https://github.com/dmtrkovalenko/fff/blob/main/packages/fff-bun/README.md Demonstrates creating a FileFinder instance, performing initial scan, and executing various search operations including fuzzy file search, glob filtering, content search, and directory search. Remember to destroy the instance when done. ```typescript import { FileFinder } from "@ff-labs/fff-bun"; // Create an instance bound to a directory const created = FileFinder.create({ basePath: "/path/to/project" }); if (!created.ok) throw new Error(created.error); const finder = created.value; // Wait for the initial scan (non-blocking) await finder.waitForScan(5000); // 1. Fuzzy file search (typo resistant) const files = finder.fileSearch("typescropt.ts", { pageSize: 10 }); if (files.ok) { for (const item of files.value.items) { console.log(item.relativePath, item.gitStatus); } } // 2. Glob filter — no fuzzy matching, 100% compatible with npm `glob` const globbed = finder.glob("src/**/*.ts"); if (globbed.ok) console.log(`${globbed.value.totalMatched} TypeScript files`); // 3. Content search (live grep) with pagination const grep = finder.grep("TODO", { mode: "plain", pageSize: 20 }); if (grep.ok) { for (const m of grep.value.items) { console.log(`${m.relativePath}:${m.lineNumber}: ${m.lineContent}`); } } // 4. Directory search based on the query (typo resistant) const dirs = finder.directorySearch("components"); if (dirs.ok) console.log(dirs.value.items.map((d) => d.relativePath)); // Free the resources when you don't need a file picker anymore inder.destroy(); ``` -------------------------------- ### Install pi-fff via npm Source: https://github.com/dmtrkovalenko/fff/blob/main/packages/pi-fff/README.md Install the extension using npm as a pi package. This is the recommended installation method. ```bash pi install npm:@ff-labs/pi-fff ``` -------------------------------- ### FFF Configuration Example Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/configuration.md Example of FFF configuration settings for file info display and logging. ```lua show_file_info = { file_info = true, -- Show file info section score_breakdown = true, -- Show score details timings = true, -- Show timestamps full_path = true, -- Show absolute path }, logging = { log_file = vim.fn.stdpath('log') .. '/fff.log', log_level = 'info', -- 'trace', 'debug', 'info', 'warn', 'error' retain_runs = 20, -- Keep N log files }, }) ``` -------------------------------- ### C Library Usage Source: https://github.com/dmtrkovalenko/fff/blob/main/README.md Provides instructions and a minimal example for building and linking against the FFF C library. It covers build commands, installation, and a basic C program demonstrating FFF instance creation and search functionality. ```APIDOC ## C library ### Build ```bash # Builds only the C cdylib (fastest): make build-c-lib # or directly with cargo: cargo build --release -p fff-c --features zlob ``` > The `zlob` feature (requires the [Zig](https://ziglang.org) toolchain) switches both > glob matching **and** filesystem traversal to [zlob](https://github.com/dmtrKovalenko/zlob)'s > native parallel walker. Without it, the default build uses the pure-Rust > [`ignore`](https://crates.io/crates/ignore) (ripgrep) walker and `globset`. The output is a `cdylib` (`libfff_c.so` / `libfff_c.dylib` / `fff_c.dll`). The header lives at [`crates/fff-c/include/fff.h`](./crates/fff-c/include/fff.h). ### Install ```bash # System-wide (needs sudo): sudo make install # User-local, no sudo: make install PREFIX=$HOME/.local # Staged install for packagers: make install DESTDIR=/tmp/pkgroot PREFIX=/usr ``` Drops `libfff_c.{so,dylib,dll}` into `$(PREFIX)/lib` and the header into `$(PREFIX)/include/fff.h`. Remove with `make uninstall`, which honours the same `PREFIX` and `DESTDIR`. Link against it after install: ```bash cc my_app.c -lfff_c -o my_app ``` Ensure `$(PREFIX)/lib` is on your runtime library search path (`LD_LIBRARY_PATH` on Linux, `DYLD_LIBRARY_PATH` on macOS, or an entry in `/etc/ld.so.conf.d/`). ### Minimal example ```c #include #include int main(void) { FffResult *res = fff_create_instance( ".", // base_path "", // frecency_db_path (empty = default) "", // history_db_path false, // use_unsafe_no_lock true, // enable_mmap_cache true, // enable_content_indexing true, // watch false // ai_mode ); if (!res->success) { fprintf(stderr, "init failed: %s\n", res->error); fff_free_result(res); return 1; } void *handle = res->handle; fff_free_result(res); // Search FffResult *search = fff_search(handle, "main.rs", "", 0, 0, 20, 100, 3); // ... read FffSearchResult from search->handle, then fff_free_search_result() fff_destroy(handle); return 0; } ``` ``` -------------------------------- ### Standalone Example Execution Source: https://github.com/dmtrkovalenko/fff/blob/main/packages/fff-python/README.md Run a standalone Python example script using uv. ```bash cd packages/fff-python uv run python examples/basic.py . ``` -------------------------------- ### setup Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/api-reference/neovim-lua.md Initializes the fff plugin with a configuration table. This should be called once at startup. ```APIDOC ## setup ### Description Initializes the plugin with configuration. Call once at startup. ### Parameters #### config (table) - Optional: Configuration table with various fields. See `configuration.md` for all options. ### Example ```lua require('fff').setup({ base_path = vim.fn.getcwd(), max_results = 100, max_threads = 4, lazy_sync = true, layout = { height = 0.8, width = 0.8, prompt_position = 'bottom', }, frecency = { enabled = true, db_path = vim.fn.stdpath('cache') .. '/fff_nvim', }, }) ``` ``` -------------------------------- ### Minimal C Library Example Source: https://github.com/dmtrkovalenko/fff/blob/main/README.md A basic C example demonstrating how to initialize the FFF library, perform a search, and clean up resources. Error handling for initialization is included. ```c #include #include int main(void) { FffResult *res = fff_create_instance( ".", // base_path "", // frecency_db_path (empty = default) "", // history_db_path false, // use_unsafe_no_lock true, // enable_mmap_cache true, // enable_content_indexing true, // watch false // ai_mode ); if (!res->success) { fprintf(stderr, "init failed: %s\n", res->error); fff_free_result(res); return 1; } void *handle = res->handle; fff_free_result(res); // Search FffResult *search = fff_search(handle, "main.rs", "", 0, 0, 20, 100, 3); // ... read FffSearchResult from search->handle, then fff_free_search_result() fff_destroy(handle); return 0; } ``` -------------------------------- ### Complete FilePicker Usage Example Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/api-reference/rust-crate.md A comprehensive example demonstrating the initialization of shared handles, databases, the FilePicker, and performing a fuzzy search. This illustrates the typical workflow for using the fff_search crate. ```rust use fff_search::{ FilePicker, FilePickerOptions, FFFMode, QueryParser, SharedFilePicker, SharedFrecency, SharedQueryTracker, FuzzySearchOptions, PaginationArgs, GrepMode, FrecencyTracker, QueryTracker, }; use std::path::PathBuf; use std::time::Duration; fn main() -> Result<(), Box> { // 1. Create shared handles let shared_picker = SharedFilePicker::default(); let shared_frecency = SharedFrecency::default(); let shared_queries = SharedQueryTracker::default(); // 2. Initialize databases let frecency = FrecencyTracker::open(".cache/frecency")?; shared_frecency.init(frecency)?; let queries = QueryTracker::open(".cache/queries")?; shared_queries.init(queries)?; // 3. Initialize file picker FilePicker::new_with_shared_state( shared_picker.clone(), shared_frecency.clone(), FilePickerOptions { base_path: PathBuf::from("."), mode: FFFMode::Ai, ..Default::default() }, )?; // 4. Wait for scan shared_picker.wait_for_scan(Duration::from_secs(10)); // 5. Perform search let picker_guard = shared_picker.read()?; let picker = picker_guard.as_ref().unwrap(); let parser = QueryParser::new(); let query = parser.parse("lib.rs"); let results = picker.fuzzy_search( &query, None, FuzzySearchOptions { pagination: PaginationArgs { offset: 0, limit: 50 }, ..Default::default() }, ); for (item, score) in results.items.iter().zip(results.scores.iter()) { println!("{}: {}", item.relative_path(picker), score.total); } Ok(()) } ``` -------------------------------- ### Install pi-fff via git Source: https://github.com/dmtrkovalenko/fff/blob/main/packages/pi-fff/README.md Install the extension directly from a git repository. ```bash pi install git:github.com/dmtrKovalenko/fff.nvim ``` -------------------------------- ### Install Node & Bun SDK Source: https://github.com/dmtrkovalenko/fff/blob/main/README.md Install the FFF Node.js and Bun SDK using npm or bun. This package provides a TypeScript wrapper over the C library. ```bash npm install @ff-labs/fff-node # or bun add @ff-labs/fff-node ``` -------------------------------- ### Lazy.nvim Installation for fff.nvim Source: https://github.com/dmtrkovalenko/fff/blob/main/doc/fff.nvim.txt Install fff.nvim using Lazy.nvim, including downloading prebuilt binaries or building from source. Configure debug options and keymaps for file finding and grepping. ```lua { 'dmtrKovalenko/fff.nvim', build = function() -- downloads a prebuilt binary or falls back to cargo build require("fff.download").download_or_build_binary() end, -- for nixos: -- build = "nix run .#release", opts = { debug = { enabled = true, show_scores = true, }, }, lazy = false, -- the plugin lazy-initialises itself keys = { { "ff", function() require('fff').find_files() end, desc = 'FFFind files' }, { "fg", function() require('fff').live_grep() end, desc = 'LiFFFe grep' }, { "fz", function() require('fff').live_grep({ grep = { modes = { 'fuzzy', 'plain' } } }) end, desc = 'Live fffuzy grep', }, { "fw", function() require('fff').live_grep_under_cursor() end, mode = { 'n', 'x' }, desc = 'Search current word / selection', }, }, } ``` -------------------------------- ### Install fff-bun Package Source: https://github.com/dmtrkovalenko/fff/blob/main/packages/fff-bun/README.md Add the fff-bun package to your project using Bun. The correct native binary for your platform is installed automatically. ```bash bun add @ff-labs/fff-bun ``` -------------------------------- ### Install fff.nvim with lazy.nvim Source: https://github.com/dmtrkovalenko/fff/blob/main/README.md Configuration for installing the fff.nvim plugin using the lazy.nvim package manager. Includes a build step to download or build the binary and optional debug settings. ```lua { 'dmtrKovalenko/fff.nvim', build = function() -- downloads a prebuilt binary or falls back to cargo build require("fff.download").download_or_build_binary() end, -- for nixos: -- build = "nix run .#release", opts = { debug = { enabled = true, show_scores = true, }, }, lazy = false, -- the plugin lazy-initialises itself keys = { { "ff", function() require('fff').find_files() end, desc = 'FFFind files' }, { "fg", function() require('fff').live_grep() end, desc = 'LiFFFe grep' }, { "fz", function() require('fff').live_grep({ grep = { modes = { 'fuzzy', 'plain' } } }) end, desc = 'Live fffuzy grep', }, { "fw", function() require('fff').live_grep_under_cursor() end, mode = { 'n', 'x' }, desc = 'Search current word / selection', }, }, } ``` -------------------------------- ### Install pi-fff via git and pin to a release Source: https://github.com/dmtrkovalenko/fff/blob/main/packages/pi-fff/README.md Install a specific release version of the extension from a git repository. ```bash pi install git:github.com/dmtrKovalenko/fff.nvim@v0.3.0 ``` -------------------------------- ### Install pi-fff locally via npm Source: https://github.com/dmtrkovalenko/fff/blob/main/packages/pi-fff/README.md Install the extension locally within your project using npm. ```bash pi install -l npm:@ff-labs/pi-fff ``` -------------------------------- ### Install FFF MCP Server (Windows PowerShell) Source: https://github.com/dmtrkovalenko/fff/blob/main/README.md Installs the FFF MCP server on Windows using PowerShell. This command downloads and executes the installation script. ```powershell irm https://raw.githubusercontent.com/dmtrKovalenko/fff.nvim/main/install-mcp.ps1 | iex ``` -------------------------------- ### Install FFF MCP Server (Linux/macOS) Source: https://github.com/dmtrkovalenko/fff/blob/main/README.md Installs the FFF MCP server on Linux or macOS using a curl script. This script fetches and executes the installation commands. ```bash curl -L https://dmtrkovalenko.dev/install-fff-mcp.sh | bash ``` -------------------------------- ### Install C Library Source: https://github.com/dmtrkovalenko/fff/blob/main/README.md Install the C library system-wide, user-locally, or staged for packagers. This process copies the library and header files to the specified prefix. ```bash # System-wide (needs sudo): sudo make install # User-local, no sudo: make install PREFIX=$HOME/.local # Staged install for packagers: make install DESTDIR=/tmp/pkgroot PREFIX=/usr ``` -------------------------------- ### Install FFF Python Package Source: https://github.com/dmtrkovalenko/fff/blob/main/README.md Install the fff-search package using pip or build and install from source using uv and maturin. ```bash pip install fff-search ``` ```bash cd packages/fff-python uv sync --all-extras uv run maturin develop --release ``` -------------------------------- ### Create FFF Instance with Options (C) Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/configuration.md Example of creating an FFF instance using `FffCreateOptions`. This demonstrates setting essential options like `version`, `base_path`, `ai_mode`, `watch`, and `enable_mmap_cache`. ```c FffCreateOptions opts = { .version = FFF_CREATE_OPTIONS_VERSION, .base_path = "/path/to/repo", .ai_mode = true, .watch = true, .enable_mmap_cache = true, }; FffResult *res = fff_create_instance_with(&opts); ``` -------------------------------- ### FFF Query Syntax Examples Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/INDEX.md Illustrates various ways to construct queries in FFF, combining glob patterns, Git status, negation, and free text. These examples show how to perform targeted searches across files and content. ```plaintext src/**/*.rs # Glob patterns (standard glob syntax) git:modified # Git status: modified, staged, untracked, deleted, etc. !test/ # Negation prefix !*.min.js # Exclude pattern user controller # Free text (fuzzy match) *.ts git:modified # Combine glob + constraint ``` -------------------------------- ### Vim.pack Installation for fff.nvim Source: https://github.com/dmtrkovalenko/fff/blob/main/doc/fff.nvim.txt Install fff.nvim using vim.pack, including setting up autocommands for binary downloads and configuring global settings. Defines keymaps for file finding and grepping. ```lua vim.pack.add({ 'https://github.com/dmtrKovalenko/fff.nvim' }) vim.api.nvim_create_autocmd('PackChanged', { callback = function(ev) local name, kind = ev.data.spec.name, ev.data.kind if name == 'fff.nvim' and (kind == 'install' or kind == 'update') then if not ev.data.active then vim.cmd.packadd('fff.nvim') end require('fff.download').download_or_build_binary() end end, }) vim.g.fff = { lazy_sync = true, debug = { enabled = true, show_scores = true }, } vim.keymap.set('n', 'ff', function() require('fff').find_files() end, { desc = 'FFFind files' }) ``` -------------------------------- ### Install fff-node Package Source: https://github.com/dmtrkovalenko/fff/blob/main/packages/fff-node/README.md Install the fff-node package using npm. The correct native binary for your platform is installed automatically. ```bash npm install @ff-labs/fff-node ``` -------------------------------- ### Install FFF MCP via Homebrew (macOS/Linux) Source: https://github.com/dmtrkovalenko/fff/blob/main/README.md Installs the FFF MCP server using Homebrew on macOS or Linux. This command adds the FFF tap and installs the fff-mcp package. ```bash brew install dmtrKovalenko/fff/fff-mcp ``` -------------------------------- ### Quick Start with FileFinder Source: https://github.com/dmtrkovalenko/fff/blob/main/packages/fff-node/README.md Demonstrates creating a FileFinder instance, waiting for the initial scan, and performing various searches including fuzzy file search, glob filtering, content search, and directory search. Remember to destroy the finder instance when done. ```typescript import { FileFinder } from "@ff-labs/fff-node"; // Create an instance bound to a directory const created = FileFinder.create({ basePath: "/path/to/project" }); if (!created.ok) throw new Error(created.error); const finder = created.value; // Wait for the initial scan (async, non-blocking) await finder.waitForScan(5000); // 1. Fuzzy file search (typo resistant) const files = finder.fileSearch("typescropt.ts", { pageSize: 10 }); if (files.ok) { for (const item of files.value.items) { console.log(item.relativePath, item.gitStatus); } } // 2. Glob filter — no fuzzy matching, 100% compatible with npm `glob` const globbed = finder.glob("src/**/*.ts"); if (globbed.ok) console.log(`${globbed.value.totalMatched} TypeScript files`); // 3. Content search (live grep) with pagination const grep = finder.grep("TODO", { mode: "plain", pageSize: 20 }); if (grep.ok) { for (const m of grep.value.items) { console.log(`${m.relativePath}:${m.lineNumber}: ${m.lineContent}`); } } // 4. Directory search based on the query (typo resistant) const dirs = finder.directorySearch("components"); if (dirs.ok) console.log(dirs.value.items.map((d) => d.relativePath)); // Free the resources when you don't need a file picker anymore finder.destroy(); ``` -------------------------------- ### Install fff.nvim with vim.pack Source: https://github.com/dmtrkovalenko/fff/blob/main/README.md Configuration for installing the fff.nvim plugin using vim.pack. Includes an autocmd for handling plugin changes and setting global variables for debug mode. ```lua vim.pack.add({ 'https://github.com/dmtrKovalenko/fff.nvim' }) vim.api.nvim_create_autocmd('PackChanged', { callback = function(ev) local name, kind = ev.data.spec.name, ev.data.kind if name == 'fff.nvim' and (kind == 'install' or kind == 'update') then if not ev.data.active then vim.cmd.packadd('fff.nvim') end require('fff.download').download_or_build_binary() end end, }) vim.g.fff = { lazy_sync = true, debug = { enabled = true, show_scores = true }, } vim.keymap.set('n', 'ff', function() require('fff').find_files() end, { desc = 'FFFind files' }) ``` -------------------------------- ### Constraint Query Syntax Examples Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/README.md Provides examples of the supported constraint query syntax, including glob patterns, Git status filters, negation, and fuzzy text matching. ```plaintext src/**/*.rs # Glob patterns git:modified # Git status filters !test/ # Negation config main # Fuzzy text ``` -------------------------------- ### Example Query Syntax Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/api-reference/node-sdk.md Illustrates the query language for file search and grep, combining glob patterns, git status filters, and exclusions. ```plaintext src/**/*.rs !test/ *.ts git:modified config main !backup ``` -------------------------------- ### Example Usage of Grep Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/api-reference/rust-crate.md Demonstrates how to use the grep function to search for a query and iterate over the results. Includes fetching the next page if available. ```rust use fff_search::GrepMode; let results = picker.grep( "TODO", GrepMode::Plain, GrepOptions { max_matches_per_file: 100, page_limit: 50, before_context: 1, after_context: 1, ..Default::default() }, )?; for m in &results.items { println!("{}:{}: {}", m.relative_path, m.line_number, m.line_content); } if results.next_file_offset > 0 { // Fetch next page } ``` -------------------------------- ### Basic FileFinder Usage Source: https://github.com/dmtrkovalenko/fff/blob/main/packages/fff-python/README.md Demonstrates synchronous usage of FileFinder to search for files. Ensure the 'fff' library is installed. ```python from fff import FileFinder with FileFinder("/path/to/project", watch=False) as finder: finder.wait_for_scan_blocking(timeout_ms=5000) print(f"Indexed under {finder.base_path}") result = finder.search("main") if result: print(f"Showing {len(result)} of {result.total_matched} matches") for item, score in zip(result.items, result.scores): print(f"{item.relative_path}: {score.total}") ``` -------------------------------- ### Example: Async File Search Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/api-reference/python-bindings.md Demonstrates how to use the asynchronous `wait_for_scan` method to perform a file search and print results. Ensures proper cleanup of the FileFinder instance. ```python import asyncio from fff import FileFinder async def main(): finder = FileFinder("/path/to/project") if await finder.wait_for_scan(10_000): result = finder.search("main.py") for item in result.items: print(item.relative_path) finder.close() asyncio.run(main()) ``` -------------------------------- ### Example: Track Query Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/api-reference/python-bindings.md Illustrates how to track a user's selection for a search query. This involves performing a search, selecting an item, and then calling `track_query`. ```python result = finder.search("config") if result.items: selected = result.items[0].relative_path finder.track_query("config", selected) ``` -------------------------------- ### Pagination Example with Cursor Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/README.md Illustrates how to implement cursor-based pagination for search queries. Fetch the first page, then use the `nextCursor` from the result to retrieve subsequent pages. ```typescript // First page let result = finder.grep("query", { pageSize: 50 }); // Next page if (result.nextCursor) { result = finder.grep("query", { cursor: result.nextCursor }); } ``` -------------------------------- ### Node & Bun SDK Usage Source: https://github.com/dmtrkovalenko/fff/blob/main/README.md Demonstrates how to install and use the FFF Node.js SDK for file searching, grepping, and glob matching. It highlights the creation of a FileFinder instance, performing searches, and handling results. ```APIDOC ## Node & Bun SDK ### Installation ```bash npm install @ff-labs/fff-node # or bun add @ff-labs/fff-node ``` ### Usage Example ```ts import { FileFinder } from "@ff-labs/fff-node"; const finder = FileFinder.create({ basePath: process.cwd(), aiMode: true }); if (!finder.ok) throw new Error(finder.error); await finder.value.waitForScan(10_000); // Perform file search const files = finder.value.fileSearch("incognito profile", { pageSize: 20 }); // Perform grep operation const hits = finder.value.grep("GetOffTheRecordProfile", { mode: "plain", smartCase: true, beforeContext: 1, afterContext: 1, classifyDefinitions: true, }); // Perform fast glob matching const rustFiles = finder.value.glob("**/*.rs", { pageSize: 100 }); // Clean up the finder instance finder.value.destroy(); ``` ### Result Type Every method returns a `Result` which is either `{ ok: true, value }` or `{ ok: false, error }`. ``` -------------------------------- ### Grep Example Usage Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/api-reference/python-bindings.md Demonstrates how to use the grep function to find matches and handle pagination. It shows iterating through results and fetching subsequent pages. ```python matches = finder.grep( "TODO", mode="plain", before_context=1, after_context=1, max_results=100, ) for match in matches.items: print(f"{match.relative_path}:{match.line_number}") print(f" {match.line_content}") # Pagination: check if there are more results if matches.next_file_offset > 0: next_matches = finder.grep( "TODO", file_offset=matches.next_file_offset, ) ``` -------------------------------- ### Example Usage of SharedFilePicker Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/api-reference/rust-crate.md Demonstrates how to acquire a read lock on SharedFilePicker, access the underlying FilePicker, perform a fuzzy search, and release the lock. ```rust let guard = shared_picker.read()?; let picker = guard.as_ref().unwrap(); let results = picker.fuzzy_search(&query, None, options); drop(guard); // Release lock ``` -------------------------------- ### CLI: Download Binary Source: https://github.com/dmtrkovalenko/fff/blob/main/packages/fff-node/README.md Manually download the fff-node binary using npx. This serves as a fallback if the npm package installation fails to provide the necessary binary. ```bash npx @ff-labs/fff-node download [tag] ``` -------------------------------- ### Live Grep with Custom Modes Source: https://github.com/dmtrkovalenko/fff/blob/main/README.md Initiate a live grep search with specific grep modes. This example demonstrates how to override the default grep modes for a single call and pre-fill a search query. ```lua require('fff').live_grep({ grep = { modes = { 'fuzzy', 'plain' } } }) require('fff').live_grep({ query = 'search term' }) -- pre-fill ``` -------------------------------- ### Initialize FilePicker with Custom Options (Rust) Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/configuration.md Create a FilePicker instance in Rust using FilePickerOptions, setting a specific base path and AI mode, while inheriting other settings from the default configuration. This example assumes shared state objects are available. ```rust use fff_search::{FilePicker, FilePickerOptions, FFFMode}; let opts = FilePickerOptions { base_path: PathBuf::from("/path/to/project"), mode: FFFMode::Ai, watch: true, enable_mmap_cache: true, enable_content_indexing: true, ..Default::default() }; FilePicker::new_with_shared_state(shared_picker, shared_frecency, opts)?; ``` -------------------------------- ### Create FFF Instance with Options (C) Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/api-reference/c-library.md Use this function to create a new file finder instance with specified options. Ensure the options struct version is set correctly and base_path is valid. Handles errors by returning a FffResult struct. ```c struct FffResult *fff_create_instance_with(const struct FffCreateOptions *opts); ``` ```c #include FffCreateOptions opts = { .version = FFF_CREATE_OPTIONS_VERSION, .base_path = "/path/to/project", .ai_mode = true, .watch = true, .enable_content_indexing = true, }; FffResult *res = fff_create_instance_with(&opts); if (!res->success) { fprintf(stderr, "Failed to init: %s\n", res->error); fff_free_result(res); return 1; } void *handle = res->handle; fff_free_result(res); // Use handle... fff_destroy(handle); ``` -------------------------------- ### Display fff-bun Platform Info Source: https://github.com/dmtrkovalenko/fff/blob/main/packages/fff-bun/README.md Use the fff-bun CLI to show platform information and the location of the binary. ```bash # Show platform info and binary location bunx fff info ``` -------------------------------- ### Create FFF Instance with Versioned Options (C) Source: https://github.com/dmtrkovalenko/fff/blob/main/README.md Use FffCreateOptions for instance creation, leveraging C99 designated initializers for readability and proper initialization of fields. ```c FffResult *res = fff_create_instance_with(&(FffCreateOptions){ .version = FFF_CREATE_OPTIONS_VERSION, .base_path = "/path/to/repo", .ai_mode = true, .watch = true, .enable_fs_root_scanning = false, // off by default .enable_home_dir_scanning = false, // off by default }); ``` -------------------------------- ### Install fff-search Package Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/api-reference/python-bindings.md Install the FFF Python package using pip. This package provides ABI3 wheels compatible with Python 3.10+. ```bash pip install fff-search ``` -------------------------------- ### Build fff-c Library from Source Source: https://github.com/dmtrkovalenko/fff/blob/main/packages/fff-node/README.md Instructions for building the native C library from source if prebuilt binaries are not available for your platform. This involves cloning the repository and using Cargo to build the release version. ```bash # Clone the repository git clone https://github.com/dmtrKovalenko/fff.nvim cd fff.nvim # Build the C library cargo build --release -p fff-c # The binary will be at target/release/libfff_c.{so,dylib,dll} ``` -------------------------------- ### TypeScript glob Example Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/api-reference/node-sdk.md Example of using the glob function to filter for TypeScript files with a custom page size. Ensure the finder object is initialized. ```typescript // Filter to TypeScript files only, no fuzzy const result = finder.glob("**/*.ts", { pageSize: 200 }); ``` -------------------------------- ### Initialize FileFinder with Custom Options (Python) Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/configuration.md Instantiate the FileFinder class with specific paths for databases and logs, and enable AI mode for optimized searches. Ensure the finder is used within a 'with' statement for proper resource management. ```python from fff import FileFinder finder = FileFinder( "/path/to/project", watch=True, ai_mode=True, frecency_db_path=".cache/fff_frecency", history_db_path=".cache/fff_history", log_file_path=".cache/fff.log", ) with finder: result = finder.search("query") ``` -------------------------------- ### fff_create_instance_with Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/api-reference/c-library.md Creates a new file finder instance using a versioned options struct. It initializes the FFF search engine with specified configurations. ```APIDOC ## fff_create_instance_with ### Description Create a new file finder instance from a versioned options struct. ### Method ```c struct FffResult *fff_create_instance_with(const struct FffCreateOptions *opts); ``` ### Parameters #### Parameters - **opts** (const struct FffCreateOptions*) - Required - Pointer to options struct with version set to `FFF_CREATE_OPTIONS_VERSION` ### Returns `FffResult` with `handle` field set to opaque instance pointer on success. On failure, `success = false` and `error` contains the message. ### Notes - `opts->base_path` must be non-NULL and non-empty - All string pointers in opts must be valid UTF-8 or NULL - When all three `cache_budget_*` values are 0, budget auto-computes from repo size after scan - Zero budget fields fall back to `unlimited()` defaults ### Example ```c #include FffCreateOptions opts = { .version = FFF_CREATE_OPTIONS_VERSION, .base_path = "/path/to/project", .ai_mode = true, .watch = true, .enable_content_indexing = true, }; FffResult *res = fff_create_instance_with(&opts); if (!res->success) { fprintf(stderr, "Failed to init: %s\n", res->error); fff_free_result(res); return 1; } void *handle = res->handle; fff_free_result(res); // Use handle... fff_destroy(handle); ``` ``` -------------------------------- ### Initialize fff Plugin with Configuration Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/api-reference/neovim-lua.md Call this once at startup to initialize the plugin with your desired configuration. The config table is optional and all fields can be omitted. ```lua require('fff').setup(config) ``` ```lua require('fff').setup({ base_path = vim.fn.getcwd(), max_results = 100, max_threads = 4, lazy_sync = true, layout = { height = 0.8, width = 0.8, prompt_position = 'bottom', }, frecency = { enabled = true, db_path = vim.fn.stdpath('cache') .. '/fff_nvim', }, }) ``` -------------------------------- ### Custom Ignore File Example Source: https://github.com/dmtrkovalenko/fff/blob/main/README.md Define custom ignore patterns in a sibling `.ignore` file to exclude files from FFF.nvim searches without affecting git. This example ignores all `.md` files and `.md` files within the `docs/archive` directory. ```gitignore *.md docs/archive/**/*.md ``` -------------------------------- ### Get Base Path Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/api-reference/node-sdk.md Retrieves the root directory that is currently being indexed by the SDK. ```typescript getBasePath(): Result; ``` -------------------------------- ### Initialize and Use Node & Bun SDK Source: https://github.com/dmtrkovalenko/fff/blob/main/README.md Create a FileFinder instance, perform file searches, and grep operations. Ensure to destroy the instance when done. Methods return a Result type. ```typescript import { FileFinder } from "@ff-labs/fff-node"; const finder = FileFinder.create({ basePath: process.cwd(), aiMode: true }); if (!finder.ok) throw new Error(finder.error); await finder.value.waitForScan(10_000); const files = finder.value.fileSearch("incognito profile", { pageSize: 20 }); const hits = finder.value.grep("GetOffTheRecordProfile", { mode: "plain", smartCase: true, beforeContext: 1, afterContext: 1, classifyDefinitions: true, }); // Run extremely fast glob matching which is significantly (10-100 times) faster than Bun's and Node implementation const rustFiles = finder.value.glob("**/*.rs", { pageSize: 100 }); finder.value.destroy(); ``` -------------------------------- ### Get Base Path Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/api-reference/rust-crate.md Retrieves the root directory that is currently being indexed. Use this to confirm the indexing target. ```rust pub fn get_base_path(&self) -> &Path; ``` -------------------------------- ### MatchRange Interface Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/types.md Defines the start and end byte offsets for matches within a line. Used for highlighting. ```typescript interface MatchRange { start: number; // Start byte offset within line end: number; // End byte offset within line } ``` -------------------------------- ### Initialize FileFinder with Options Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/api-reference/python-bindings.md Instantiate FileFinder with various configuration options such as enabling AI mode, specifying a frecency database path, and enabling the file watcher. ```python from fff import FileFinder finder = FileFinder( "/path/to/project", watch=True, ai_mode=True, frecency_db_path=".cache/fff_frecency", ) ``` -------------------------------- ### Example: Health Check Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/api-reference/python-bindings.md Demonstrates how to retrieve and parse health/diagnostic information from the FileFinder instance. Useful for debugging and monitoring. ```python import json health = json.loads(finder.health_check()) print(f"Files: {health['filePicker']['indexedFiles']}") print(f"Git: {health['git']['available']}") ``` -------------------------------- ### Get Historical Query Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/api-reference/python-bindings.md Retrieves a previously executed search query based on its offset from the most recent query (0 being the latest). ```python def get_historical_query(self, offset: int = 0) -> Optional[str]: ``` -------------------------------- ### FileFinder Initialization and Exception Handling Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/api-reference/python-bindings.md Demonstrates how to initialize FileFinder and handle potential FFFException errors. ```APIDOC ## FileFinder Initialization and Exception Handling ### Description Operations may raise `FFFException` on errors. This snippet shows how to catch these exceptions during FileFinder initialization. ### Method ```python from fff import FFFException, FileFinder try: finder = FileFinder(path) except FFFException as e: print(f"Error: {e}") ``` ### Parameters #### Path Parameters - **path** (string) - Required - The path to initialize the FileFinder with. ### Response #### Error Response - **FFFException** - Raised when an error occurs during initialization or operation. ``` -------------------------------- ### MatchRange Data Structure Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/api-reference/python-bindings.md Defines the structure for MatchRange, indicating the start and end byte offsets within a line for a match. ```python class MatchRange: start: int # Start byte offset in line end: int # End byte offset in line ``` -------------------------------- ### Initialize FileFinder Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/api-reference/python-bindings.md Create an instance of FileFinder, the main entry point for searches. It's recommended to create one instance and reuse it. Set `watch=False` to disable the background file watcher. ```python finder = FileFinder("/path/to/project", watch=False) ``` -------------------------------- ### Highlight Groups Configuration Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/api-reference/neovim-lua.md Customize the appearance of the picker UI by defining highlight groups. This configuration is passed to the `setup()` function under the `hl` key. ```APIDOC ## hl Groups Customizable highlight groups for picker UI. Set in `setup()` under `hl`: ```lua require('fff').setup({ hl = { normal = 'NormalFloat', title = 'FloatTitle', border = 'FloatBorder', cursorline = 'PmenuSel', search_match = 'Search', git_modified = 'DiagnosticWarn', git_staged = 'DiagnosticOk', git_untracked = 'DiagnosticInfo', file_info_section = 'Title', file_info_separator = 'FloatBorder', file_info_label = 'Comment', file_info_value = 'Normal', file_info_value_dim = 'NonText', file_info_size = 'Number', file_info_type = 'Type', file_info_path = 'Directory', file_info_total_score = 'Number', file_info_match_type = 'Special', file_info_score_pos = 'DiagnosticOk', file_info_score_neg = 'DiagnosticError', }, hl.winhl = { prompt = 'Normal:NormalFloat', -- Per-window highlights list = 'Normal:NormalFloat', preview = 'Normal:NormalFloat', file_info = 'Normal:NormalFloat', }, }) ``` ``` -------------------------------- ### Get Historical Query Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/api-reference/node-sdk.md Retrieves a previously executed search query based on its position in the history. An offset of 0 corresponds to the most recent query. ```typescript getHistoricalQuery(offset: number): Result; ``` -------------------------------- ### Build FFF.nvim Source: https://github.com/dmtrkovalenko/fff/blob/main/CLAUDE.md Use this command to build the entire project. Prefer Makefile commands over other package managers. ```makefile make build ``` -------------------------------- ### Link C Library Source: https://github.com/dmtrkovalenko/fff/blob/main/README.md Link the installed FFF C library against your application. Ensure the library's directory is in the runtime library search path. ```bash cc my_app.c -lfff_c -o my_app ``` -------------------------------- ### Get Scan Progress Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/api-reference/node-sdk.md Retrieves the current progress of the file scanning operation. Includes counts of scanned files and status of various internal components. ```typescript getScanProgress(): Result; ``` ```typescript interface ScanProgress { scannedFilesCount: number; // Files scanned so far isScanning: boolean; // Currently scanning isWatcherReady: boolean; // Watcher initialized isWarmupComplete: boolean; // Content index/bigram phase done } ``` -------------------------------- ### Initialize FileFinder with Options Source: https://github.com/dmtrkovalenko/fff/blob/main/_autodocs/configuration.md Use this snippet to create a new FileFinder instance. Ensure `basePath` is set to the root directory you want to index. Other options like `aiMode`, database paths, and logging can be configured here. ```typescript import { FileFinder } from "@ff-labs/fff-node"; const finder = FileFinder.create({ basePath: process.cwd(), aiMode: true, frecencyDbPath: ".cache/fff-frecency", historyDbPath: ".cache/fff-history", logFilePath: ".cache/fff.log", logLevel: "info", }); if (!finder.ok) { console.error(finder.error); } ``` -------------------------------- ### Format All Code Source: https://github.com/dmtrkovalenko/fff/blob/main/CLAUDE.md Run this command to format all code files in the project. This ensures consistent code style. ```makefile make format ``` -------------------------------- ### Upgrade FFF MCP via Homebrew (macOS/Linux) Source: https://github.com/dmtrkovalenko/fff/blob/main/README.md Upgrades an existing FFF MCP installation managed by Homebrew on macOS or Linux to the latest stable release. ```bash brew upgrade fff-mcp ```