Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c9e94c716f |
+164
-40
@@ -1,4 +1,4 @@
|
||||
*fff.nvim.txt* For Neovim >= 0.8.0 Last change: 2025 August 05
|
||||
*fff.nvim.txt* For Neovim >= 0.8.0 Last change: 2025 August 10
|
||||
|
||||
==============================================================================
|
||||
Table of Contents *fff.nvim-table-of-contents*
|
||||
@@ -23,8 +23,8 @@ FEATURES *fff.nvim-features*
|
||||
|
||||
- Works out of the box with no additional configuration
|
||||
- Typo resistant fuzzy search <https://github.com/saghen/frizbee>
|
||||
- Git status integration allowing to take adavantage of last modified times within a worktree
|
||||
- Separate file index maintained by a dedicaged backend allows <10 milliseconds search time for 50k files codebase
|
||||
- Git status integration allowing to take advantage of last modified times within a worktree
|
||||
- Separate file index maintained by a dedicated backend allows <10 milliseconds search time for 50k files codebase
|
||||
- Display images in previews (for now requires snacks.nvim)
|
||||
- Smart in a plenty of different ways hopefully helpful for your workflow
|
||||
|
||||
@@ -32,7 +32,7 @@ FEATURES *fff.nvim-features*
|
||||
INSTALLATION *fff.nvim-installation*
|
||||
|
||||
|
||||
[!NOTE] Although we’ll try to make sure to keep 100% backward compatibiility,
|
||||
[!NOTE] Although we’ll try to make sure to keep 100% backward compatibility,
|
||||
by using you should understand that silly bugs and breaking changes may happen.
|
||||
And also we hope for your contributions and feedback to make this plugin ideal
|
||||
for everyone.
|
||||
@@ -72,38 +72,65 @@ LAZY.NVIM
|
||||
<
|
||||
|
||||
|
||||
DEFAULT CONFIGURATION ~
|
||||
CONFIGURATION ~
|
||||
|
||||
FFF.nvim comes with sensible defaults. Here’s the complete default
|
||||
configuration:
|
||||
FFF.nvim comes with sensible defaults. Here’s the complete configuration with
|
||||
all available options:
|
||||
|
||||
>lua
|
||||
require("fff").setup({
|
||||
-- UI dimensions and appearance
|
||||
width = 0.8, -- Window width as fraction of screen
|
||||
height = 0.8, -- Window height as fraction of screen
|
||||
prompt = '🪿 ', -- Input prompt symbol
|
||||
preview = {
|
||||
enabled = true,
|
||||
width = 0.5,
|
||||
max_lines = 100,
|
||||
max_size = 1024 * 1024, -- 1MB
|
||||
},
|
||||
title = 'FFF Files', -- Window title
|
||||
max_results = 60, -- Maximum search results to display
|
||||
max_threads = 4, -- Maximum threads for fuzzy search
|
||||
require('fff').setup({
|
||||
-- Core settings
|
||||
base_path = vim.fn.getcwd(), -- Base directory for file indexing
|
||||
max_results = 100, -- Maximum search results to display
|
||||
max_threads = 4, -- Maximum threads for fuzzy search
|
||||
prompt = '🪿 ', -- Input prompt symbol
|
||||
title = 'FFF Files', -- Window title
|
||||
ui_enabled = true, -- Enable UI (default: true)
|
||||
|
||||
-- Window dimensions
|
||||
width = 0.8, -- Window width as fraction of screen
|
||||
height = 0.8, -- Window height as fraction of screen
|
||||
|
||||
-- Preview configuration
|
||||
preview = {
|
||||
enabled = true, -- Enable preview pane
|
||||
width = 0.5, -- Preview width as fraction of window
|
||||
max_lines = 5000, -- Maximum lines to load
|
||||
max_size = 10 * 1024 * 1024, -- Maximum file size (10MB)
|
||||
imagemagick_info_format_str = '%m: %wx%h, %[colorspace], %q-bit', -- ImageMagick info format
|
||||
line_numbers = false, -- Show line numbers in preview
|
||||
wrap_lines = false, -- Wrap long lines
|
||||
show_file_info = true, -- Show file info header
|
||||
binary_file_threshold = 1024, -- Bytes to check for binary detection
|
||||
filetypes = { -- Per-filetype settings
|
||||
svg = { wrap_lines = true },
|
||||
markdown = { wrap_lines = true },
|
||||
text = { wrap_lines = true },
|
||||
log = { tail_lines = 100 },
|
||||
},
|
||||
},
|
||||
|
||||
-- Layout configuration (alternative to width/height)
|
||||
layout = {
|
||||
prompt_position = 'top', -- Position of prompt ('top' or 'bottom')
|
||||
preview_position = 'right', -- Position of preview ('right' or 'left')
|
||||
preview_width = 0.4, -- Width of preview pane
|
||||
height = 0.8, -- Window height
|
||||
width = 0.8, -- Window width
|
||||
},
|
||||
|
||||
-- Keymaps
|
||||
keymaps = {
|
||||
close = '<Esc>',
|
||||
select = '<CR>',
|
||||
select_split = '<C-s>',
|
||||
select_vsplit = '<C-v>',
|
||||
select_tab = '<C-t>',
|
||||
-- Multiple bindings supported
|
||||
move_up = { '<Up>', '<C-p>' },
|
||||
move_up = { '<Up>', '<C-p>' }, -- Multiple bindings supported
|
||||
move_down = { '<Down>', '<C-n>' },
|
||||
preview_scroll_up = '<C-u>',
|
||||
preview_scroll_down = '<C-d>',
|
||||
toggle_debug = '<F2>', -- Toggle debug scores display
|
||||
},
|
||||
|
||||
-- Highlight groups
|
||||
@@ -119,9 +146,42 @@ configuration:
|
||||
debug = 'Comment',
|
||||
},
|
||||
|
||||
-- Frecency tracking (track file access patterns)
|
||||
frecency = {
|
||||
enabled = true, -- Enable frecency tracking
|
||||
db_path = vim.fn.stdpath('cache') .. '/fff_nvim', -- Database location
|
||||
},
|
||||
|
||||
-- Logging configuration
|
||||
logging = {
|
||||
enabled = true, -- Enable logging
|
||||
log_file = vim.fn.stdpath('log') .. '/fff.log', -- Log file location
|
||||
log_level = 'info', -- Log level (debug, info, warn, error)
|
||||
},
|
||||
|
||||
-- UI appearance
|
||||
ui = {
|
||||
wrap_paths = true, -- Wrap long file paths in list
|
||||
wrap_indent = 2, -- Indentation for wrapped paths
|
||||
max_path_width = 80, -- Maximum path width before wrapping
|
||||
},
|
||||
|
||||
-- Image preview (requires terminal with image support)
|
||||
image_preview = {
|
||||
enabled = true, -- Enable image previews
|
||||
max_width = 80, -- Maximum image width in columns
|
||||
max_height = 24, -- Maximum image height in lines
|
||||
},
|
||||
|
||||
-- Icons
|
||||
icons = {
|
||||
enabled = true, -- Enable file icons
|
||||
},
|
||||
|
||||
-- Debug options
|
||||
debug = {
|
||||
show_scores = false, -- Toggle with F2 or :FFFDebug
|
||||
enabled = false, -- Enable debug mode
|
||||
show_scores = false, -- Show scoring information (toggle with F2)
|
||||
},
|
||||
})
|
||||
<
|
||||
@@ -133,24 +193,37 @@ KEY FEATURES ~
|
||||
AVAILABLE METHODS
|
||||
|
||||
>lua
|
||||
require("fff").find_files() -- Find files in current directory
|
||||
require("fff").find_in_git_root() -- Find files in the current git repository
|
||||
require("fff").scan_files() -- Trigger rescan of files in the current directory
|
||||
require("fff").refresh_git_status() -- Refresh git status for the active file lock
|
||||
require("fff").find_files_in_dir(path) -- Find files in a specific directory
|
||||
require("fff").change_indexing_directory(new_path) -- Change the base directory for the file picker
|
||||
require('fff').find_files() -- Find files in current directory
|
||||
require('fff').find_in_git_root() -- Find files in the current git repository
|
||||
require('fff').scan_files() -- Trigger rescan of files in the current directory
|
||||
require('fff').refresh_git_status() -- Refresh git status for the active file lock
|
||||
require('fff').find_files_in_dir(path) -- Find files in a specific directory
|
||||
require('fff').change_indexing_directory(new_path) -- Change the base directory for the file picker
|
||||
<
|
||||
|
||||
|
||||
COMMANDS
|
||||
|
||||
FFF.nvim provides several commands for interacting with the file picker:
|
||||
|
||||
- `:FFFFind [path|query]` - Open file picker. Optional: provide directory path or search query
|
||||
- `:FFFScan` - Manually trigger a rescan of files in the current directory
|
||||
- `:FFFRefreshGit` - Manually refresh git status for all files
|
||||
- `:FFFClearCache [all|frecency|files]` - Clear various caches
|
||||
- `:FFFHealth` - Check FFF health status and dependencies
|
||||
- `:FFFDebug [on|off|toggle]` - Toggle debug scores display
|
||||
- `:FFFOpenLog` - Open the FFF log file in a new tab
|
||||
|
||||
|
||||
MULTIPLE KEY BINDINGS
|
||||
|
||||
You can assign multiple key combinations to the same action:
|
||||
|
||||
>lua
|
||||
keymaps = {
|
||||
move_up = { '<Up>', '<C-p>', '<C-k>' }, -- Three ways to move up
|
||||
close = { '<Esc>', '<C-c>' }, -- Two ways to close
|
||||
select = '<CR>', -- Single binding still works
|
||||
move_up = { '<Up>', '<C-p>', '<C-k>' }, -- Three ways to move up
|
||||
close = { '<Esc>', '<C-c>' }, -- Two ways to close
|
||||
select = '<CR>', -- Single binding still works
|
||||
}
|
||||
<
|
||||
|
||||
@@ -170,15 +243,66 @@ Toggle scoring information display:
|
||||
- Use `:FFFDebug` command
|
||||
- Enable by default with `debug.show_scores = true`
|
||||
|
||||
>
|
||||
|
||||
#### vim-plug
|
||||
|
||||
```vim
|
||||
Plug 'MunifTanjim/nui.nvim'
|
||||
Plug 'dmtrKovalenko/fff.nvim', { 'do': 'cargo build --release' }
|
||||
|
||||
TROUBLESHOOTING ~
|
||||
|
||||
|
||||
HEALTH CHECK
|
||||
|
||||
Run `:FFFHealth` to check the status of FFF.nvim and its dependencies. This
|
||||
will verify:
|
||||
|
||||
- File picker initialization status
|
||||
- Optional dependencies (git, image preview tools)
|
||||
- Database connectivity
|
||||
|
||||
|
||||
VIEWING LOGS
|
||||
|
||||
If you encounter issues, check the log file:
|
||||
|
||||
>vim
|
||||
:FFFOpenLog
|
||||
<
|
||||
|
||||
Or manually open the log file at `~/.local/state/nvim/log/fff.log` (default
|
||||
location).
|
||||
|
||||
|
||||
COMMON ISSUES
|
||||
|
||||
**File picker not initializing:**
|
||||
|
||||
- Ensure the Rust backend is compiled: `cargo build --release` in the plugin directory
|
||||
- Check that your Neovim version is 0.10.0 or higher
|
||||
|
||||
**Image previews not working:**
|
||||
|
||||
- Verify your terminal supports images (kitty, iTerm2, WezTerm, etc.)
|
||||
- For terminals without native image support, install one of: `chafa`, `viu`, or `img2txt`
|
||||
- If using snacks.nvim, ensure it’s properly configured
|
||||
|
||||
**Performance issues:**
|
||||
|
||||
- Adjust `max_threads` in configuration based on your system
|
||||
- Reduce `preview.max_lines` and `preview.max_size` for large files
|
||||
- Clear cache if it becomes too large: `:FFFClearCache all`
|
||||
|
||||
**Files not being indexed:**
|
||||
|
||||
- Run `:FFFScan` to manually trigger a file scan
|
||||
- Check that the `base_path` is correctly set
|
||||
- Verify you have read permissions for the directory
|
||||
|
||||
|
||||
DEBUG MODE
|
||||
|
||||
Enable debug mode to see scoring information and troubleshoot search results:
|
||||
|
||||
- Press `F2` while in the picker
|
||||
- Run `:FFFDebug on` to enable permanently
|
||||
- Set `debug.show_scores = true` in configuration
|
||||
|
||||
Generated by panvimdoc <https://github.com/kdheepak/panvimdoc>
|
||||
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||
|
||||
+29
-6
@@ -1,3 +1,5 @@
|
||||
use std::path::MAIN_SEPARATOR;
|
||||
|
||||
use crate::{
|
||||
git::is_modified_status,
|
||||
path_utils::calculate_distance_penalty,
|
||||
@@ -23,6 +25,7 @@ pub fn match_and_score_files<'a>(
|
||||
sort: false,
|
||||
};
|
||||
|
||||
let query_contains_path_separator = context.query.contains(MAIN_SEPARATOR);
|
||||
let haystack: Vec<&str> = files.iter().map(|f| f.relative_path.as_str()).collect();
|
||||
tracing::debug!(
|
||||
"Starting fuzzy search for query '{}' in {} files",
|
||||
@@ -48,9 +51,21 @@ pub fn match_and_score_files<'a>(
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut filename_matches =
|
||||
neo_frizbee::match_list(context.query, &haystack_of_filenames, options);
|
||||
filename_matches.par_sort_unstable_by_key(|m| m.index_in_haystack);
|
||||
// if there is a / in the query we don't even match filenames
|
||||
let filename_matches = if query_contains_path_separator {
|
||||
vec![]
|
||||
} else {
|
||||
let mut list = neo_frizbee::match_list_parallel(
|
||||
context.query,
|
||||
&haystack_of_filenames,
|
||||
options,
|
||||
context.max_threads,
|
||||
);
|
||||
|
||||
list.par_sort_unstable_by_key(|m| m.index_in_haystack);
|
||||
|
||||
list
|
||||
};
|
||||
|
||||
let mut next_filename_match_index = 0;
|
||||
let mut results: Vec<_> = path_matches
|
||||
@@ -81,13 +96,21 @@ pub fn match_and_score_files<'a>(
|
||||
Some(filename_match) if filename_match.exact => {
|
||||
filename_match.score as i32 / 5 * 2 // 40% bonus for exact filename match
|
||||
}
|
||||
// 20% bonus for fuzzy filename match but only if the score of matched path is
|
||||
// 16% bonus for fuzzy filename match but only if the score of matched path is
|
||||
// equal or greater than the score of matched filename, thus we are not allowing
|
||||
// typoed filename to score higher than the path match
|
||||
Some(filename_match) if filename_match.score >= path_match.score => {
|
||||
Some(filename_match)
|
||||
if filename_match.score >= path_match.score
|
||||
&& !query_contains_path_separator =>
|
||||
{
|
||||
base_score = filename_match.score as i32;
|
||||
|
||||
base_score / 5
|
||||
(base_score / 6)
|
||||
// for large queries around ~300 score the bonus is too big
|
||||
// it might lead to situations when much more fitting path with a larger
|
||||
// base score getting filtered out by combination of score + filename bonus
|
||||
// so we cap it at 10% of the roughly largest score you can get
|
||||
.min(30)
|
||||
}
|
||||
// 5% bonus for special file but not as much as file name to avoid sitatuions
|
||||
// when you have /user_service/server.rs and /user_service/server/mod.rs
|
||||
|
||||
Reference in New Issue
Block a user