chore: import upstream snapshot with attribution
Python CI / Python bindings (ubuntu-latest) (push) Failing after 0s
Build & Publish / Build Neovim aarch64-linux-android (push) Failing after 0s
Build & Publish / Build Neovim aarch64-unknown-linux-gnu (push) Failing after 0s
Build & Publish / Build MCP x86_64-unknown-linux-musl (push) Failing after 1s
Build & Publish / Build Python wheels aarch64 (ubuntu-latest) (push) Failing after 0s
Build & Publish / Build Python wheels x86_64 (ubuntu-latest) (push) Failing after 1s
Build & Publish / Build Python sdist (push) Failing after 1s
Rust CI / Fuzz Tests (ubuntu-latest) (push) Failing after 1s
Rust CI / Build i686-unknown-linux-gnu (push) Failing after 0s
Rust CI / cargo clippy (push) Failing after 1s
e2e Tests / e2e (ubuntu-latest) (push) Failing after 1s
Lua CI / luacheck lint (push) Failing after 1s
Build & Publish / Build Neovim aarch64-unknown-linux-musl (push) Failing after 1s
Build & Publish / Build Neovim x86_64-unknown-linux-gnu (push) Failing after 0s
Build & Publish / Build Neovim x86_64-unknown-linux-musl (push) Failing after 1s
Build & Publish / Build C FFI aarch64-linux-android (push) Failing after 0s
Build & Publish / Build C FFI aarch64-unknown-linux-gnu (push) Failing after 0s
Build & Publish / Build C FFI aarch64-unknown-linux-musl (push) Failing after 1s
Build & Publish / Build C FFI x86_64-unknown-linux-gnu (push) Failing after 0s
Build & Publish / Build C FFI x86_64-unknown-linux-musl (push) Failing after 1s
Build & Publish / Build MCP aarch64-unknown-linux-gnu (push) Failing after 1s
Build & Publish / Build MCP aarch64-unknown-linux-musl (push) Failing after 0s
Build & Publish / Build MCP x86_64-unknown-linux-gnu (push) Failing after 1s
Spelling / Spell Check with Typos (push) Failing after 0s
Rust CI / Test (ubuntu-latest) (push) Failing after 0s
Rust CI / cargo fmt (push) Failing after 0s
Stylua / Check lua files using Stylua (push) Failing after 1s
Lua CI / lua-language-server type check (push) Failing after 12m29s
e2e Tests / e2e (alpine-musl) (push) Successful in 57m31s
e2e Tests / e2e (macos-latest) (push) Has been cancelled
Build & Publish / Build C FFI aarch64-apple-darwin (push) Has been cancelled
Rust CI / Test (windows-latest) (push) Has been cancelled
e2e Tests / e2e (windows-latest) (push) Has been cancelled
Nix CI / check (push) Has been cancelled
Python CI / Python bindings (macos-latest) (push) Has been cancelled
Python CI / Python bindings (windows-latest) (push) Has been cancelled
Build & Publish / Build Neovim aarch64-apple-darwin (push) Has been cancelled
Build & Publish / Build Neovim aarch64-pc-windows-msvc (push) Has been cancelled
Build & Publish / Build Neovim x86_64-apple-darwin (push) Has been cancelled
Build & Publish / Build Neovim x86_64-pc-windows-msvc (push) Has been cancelled
Build & Publish / Build C FFI aarch64-pc-windows-msvc (push) Has been cancelled
Build & Publish / Build C FFI x86_64-apple-darwin (push) Has been cancelled
Build & Publish / Build C FFI x86_64-pc-windows-msvc (push) Has been cancelled
Build & Publish / Build MCP aarch64-apple-darwin (push) Has been cancelled
Build & Publish / Build MCP aarch64-pc-windows-msvc (push) Has been cancelled
Build & Publish / Build MCP x86_64-apple-darwin (push) Has been cancelled
Build & Publish / Build MCP x86_64-pc-windows-msvc (push) Has been cancelled
Build & Publish / Build Python wheels aarch64 (macos-latest) (push) Has been cancelled
Build & Publish / Build Python wheels x86_64 (macos-latest) (push) Has been cancelled
Build & Publish / Build Python wheels x86_64 (windows-latest) (push) Has been cancelled
Build & Publish / Release (push) Has been cancelled
Build & Publish / Publish Python wheels to PyPI (push) Has been cancelled
Build & Publish / Publish Rust crates (push) Has been cancelled
Build & Publish / Publish npm packages (push) Has been cancelled
Rust CI / Fuzz Tests (windows-latest) (push) Has been cancelled
Rust CI / Test (macos-latest) (push) Has been cancelled
Rust CI / Fuzz Tests (macos-latest) (push) Has been cancelled
Python CI / Python bindings (ubuntu-latest) (push) Failing after 0s
Build & Publish / Build Neovim aarch64-linux-android (push) Failing after 0s
Build & Publish / Build Neovim aarch64-unknown-linux-gnu (push) Failing after 0s
Build & Publish / Build MCP x86_64-unknown-linux-musl (push) Failing after 1s
Build & Publish / Build Python wheels aarch64 (ubuntu-latest) (push) Failing after 0s
Build & Publish / Build Python wheels x86_64 (ubuntu-latest) (push) Failing after 1s
Build & Publish / Build Python sdist (push) Failing after 1s
Rust CI / Fuzz Tests (ubuntu-latest) (push) Failing after 1s
Rust CI / Build i686-unknown-linux-gnu (push) Failing after 0s
Rust CI / cargo clippy (push) Failing after 1s
e2e Tests / e2e (ubuntu-latest) (push) Failing after 1s
Lua CI / luacheck lint (push) Failing after 1s
Build & Publish / Build Neovim aarch64-unknown-linux-musl (push) Failing after 1s
Build & Publish / Build Neovim x86_64-unknown-linux-gnu (push) Failing after 0s
Build & Publish / Build Neovim x86_64-unknown-linux-musl (push) Failing after 1s
Build & Publish / Build C FFI aarch64-linux-android (push) Failing after 0s
Build & Publish / Build C FFI aarch64-unknown-linux-gnu (push) Failing after 0s
Build & Publish / Build C FFI aarch64-unknown-linux-musl (push) Failing after 1s
Build & Publish / Build C FFI x86_64-unknown-linux-gnu (push) Failing after 0s
Build & Publish / Build C FFI x86_64-unknown-linux-musl (push) Failing after 1s
Build & Publish / Build MCP aarch64-unknown-linux-gnu (push) Failing after 1s
Build & Publish / Build MCP aarch64-unknown-linux-musl (push) Failing after 0s
Build & Publish / Build MCP x86_64-unknown-linux-gnu (push) Failing after 1s
Spelling / Spell Check with Typos (push) Failing after 0s
Rust CI / Test (ubuntu-latest) (push) Failing after 0s
Rust CI / cargo fmt (push) Failing after 0s
Stylua / Check lua files using Stylua (push) Failing after 1s
Lua CI / lua-language-server type check (push) Failing after 12m29s
e2e Tests / e2e (alpine-musl) (push) Successful in 57m31s
e2e Tests / e2e (macos-latest) (push) Has been cancelled
Build & Publish / Build C FFI aarch64-apple-darwin (push) Has been cancelled
Rust CI / Test (windows-latest) (push) Has been cancelled
e2e Tests / e2e (windows-latest) (push) Has been cancelled
Nix CI / check (push) Has been cancelled
Python CI / Python bindings (macos-latest) (push) Has been cancelled
Python CI / Python bindings (windows-latest) (push) Has been cancelled
Build & Publish / Build Neovim aarch64-apple-darwin (push) Has been cancelled
Build & Publish / Build Neovim aarch64-pc-windows-msvc (push) Has been cancelled
Build & Publish / Build Neovim x86_64-apple-darwin (push) Has been cancelled
Build & Publish / Build Neovim x86_64-pc-windows-msvc (push) Has been cancelled
Build & Publish / Build C FFI aarch64-pc-windows-msvc (push) Has been cancelled
Build & Publish / Build C FFI x86_64-apple-darwin (push) Has been cancelled
Build & Publish / Build C FFI x86_64-pc-windows-msvc (push) Has been cancelled
Build & Publish / Build MCP aarch64-apple-darwin (push) Has been cancelled
Build & Publish / Build MCP aarch64-pc-windows-msvc (push) Has been cancelled
Build & Publish / Build MCP x86_64-apple-darwin (push) Has been cancelled
Build & Publish / Build MCP x86_64-pc-windows-msvc (push) Has been cancelled
Build & Publish / Build Python wheels aarch64 (macos-latest) (push) Has been cancelled
Build & Publish / Build Python wheels x86_64 (macos-latest) (push) Has been cancelled
Build & Publish / Build Python wheels x86_64 (windows-latest) (push) Has been cancelled
Build & Publish / Release (push) Has been cancelled
Build & Publish / Publish Python wheels to PyPI (push) Has been cancelled
Build & Publish / Publish Rust crates (push) Has been cancelled
Build & Publish / Publish npm packages (push) Has been cancelled
Rust CI / Fuzz Tests (windows-latest) (push) Has been cancelled
Rust CI / Test (macos-latest) (push) Has been cancelled
Rust CI / Fuzz Tests (macos-latest) (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,451 @@
|
||||
*fff.nvim.txt*
|
||||
For Neovim >= 0.10.0 Last change: 2026 June 30
|
||||
|
||||
==============================================================================
|
||||
Table of Contents *fff.nvim-table-of-contents*
|
||||
|
||||
1. fff.nvim |fff.nvim-fff.nvim|
|
||||
|
||||
==============================================================================
|
||||
1. fff.nvim *fff.nvim-fff.nvim*
|
||||
|
||||
The best file search picker for Neovim. Frecency-ranked, typo-resistant,
|
||||
git-award, very fast.
|
||||
|
||||
Demo on the Linux kernel repo (100k files, 8GB):
|
||||
|
||||
|
||||
https://github.com/user-attachments/assets/5d0e1ce9-642c-4c44-aa88-01b05bb86abb
|
||||
|
||||
|
||||
INSTALLATION ~
|
||||
|
||||
|
||||
LAZY.NVIM
|
||||
|
||||
>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',
|
||||
},
|
||||
},
|
||||
}
|
||||
<
|
||||
|
||||
|
||||
VIM.PACK
|
||||
|
||||
>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' })
|
||||
<
|
||||
|
||||
|
||||
PUBLIC API ~
|
||||
|
||||
>lua
|
||||
require('fff').find_files() -- find files in current repo
|
||||
require('fff').live_grep() -- live content grep
|
||||
require('fff').live_grep_under_cursor() -- grep <cword> in normal, selection in visual
|
||||
require('fff').scan_files() -- force rescan
|
||||
require('fff').refresh_git_status() -- refresh git status
|
||||
require('fff').find_files_in_dir(path) -- find in a specific dir
|
||||
require('fff').change_indexing_directory(new_path) -- change root
|
||||
|
||||
-- Programmatic search (no UI). Useful for plugin integrations.
|
||||
require('fff').file_search(query, opts) -- fuzzy search files / dirs / mixed
|
||||
require('fff').content_search(query, opts) -- programmatic grep
|
||||
<
|
||||
|
||||
|
||||
FILE_SEARCH(QUERY, OPTS)
|
||||
|
||||
Returns a structured result `{ items, scores, total_matched, total_files?,
|
||||
total_dirs?, location? }`. Each item has a `type` field (`"file"` or
|
||||
`"directory"`) and `name` / `relative_path`. File items also expose `size`,
|
||||
`modified`, `git_status`, `is_binary`, and frecency scores.
|
||||
|
||||
>lua
|
||||
local r = require('fff').file_search('button', {
|
||||
mode = 'mixed', -- 'files' (default) | 'directories' | 'mixed'
|
||||
max_results = 50,
|
||||
page = 0, -- 0-based pagination
|
||||
current_file = nil, -- path to deprioritize for distance scoring
|
||||
max_threads = 4,
|
||||
cwd = nil, -- switch indexed root if different (see below)
|
||||
wait_for_index_ms = nil, -- override the default scan wait timeout
|
||||
})
|
||||
for _, item in ipairs(r.items) do
|
||||
print(item.type, item.relative_path)
|
||||
end
|
||||
<
|
||||
|
||||
|
||||
CONTENT_SEARCH(QUERY, OPTS)
|
||||
|
||||
Returns a `GrepResult` `{ items, total_matched, total_files_searched,
|
||||
total_files, filtered_file_count, next_file_offset, regex_fallback_error? }`.
|
||||
Each match item has `relative_path`, `name`, `line_number`, `col`,
|
||||
`line_content`, `match_ranges`, plus the same file metadata as `file_search`.
|
||||
|
||||
>lua
|
||||
local r = require('fff').content_search('TODO', {
|
||||
mode = 'plain', -- 'plain' (default) | 'regex' | 'fuzzy'
|
||||
max_file_size = 10 * 1024 * 1024,
|
||||
max_matches_per_file = 100,
|
||||
smart_case = true,
|
||||
page_size = 50,
|
||||
file_offset = 0,
|
||||
time_budget_ms = 0,
|
||||
trim_whitespace = false,
|
||||
cwd = nil, -- switch indexed root if different
|
||||
wait_for_index_ms = nil, -- override the default scan wait timeout
|
||||
})
|
||||
for _, m in ipairs(r.items) do
|
||||
print(string.format('%s:%d %s', m.relative_path, m.line_number, m.line_content))
|
||||
end
|
||||
<
|
||||
|
||||
Both functions accept the same constraint syntax as the UI pickers (e.g.
|
||||
`git:modified`, `*.rs`, `!test/`, glob patterns).
|
||||
|
||||
|
||||
CWD AND INDEXING
|
||||
|
||||
Both `file_search` and `content_search` honour an optional `cwd` field. The
|
||||
first call to either function lazily initialises the picker at
|
||||
`config.base_path` (your Neovim cwd by default).
|
||||
|
||||
- If `cwd` matches the currently indexed root, the call returns immediately against the existing index.
|
||||
- If `cwd` differs, the picker is re-indexed at the new root and the call **blocks** (default up to 10 s) until the new picker is installed and its initial scan completes — so callers always get results from the right tree.
|
||||
- If the index is still warming up after a `change_indexing_directory`, you can pass `wait_for_index_ms = N` to block for up to `N` ms regardless of whether `cwd` triggered the swap. Pass `0` to skip waiting entirely (useful for fire-and-forget calls where partial results are acceptable).
|
||||
- Invalid or non-existent `cwd` paths return an empty result and emit an error via `vim.notify`.
|
||||
|
||||
|
||||
COMMANDS ~
|
||||
|
||||
- `:FFFScan`. Rescan files.
|
||||
- `:FFFRefreshGit`. Refresh git status.
|
||||
- `:FFFClearCache [all|frecency|files]`. Clear caches.
|
||||
- `:FFFHealth`. Health check.
|
||||
- `:FFFDebug [on|off|toggle]`. Toggle the scoring display.
|
||||
- `:FFFOpenLog`. Open `~/.local/state/nvim/log/fff.log`.
|
||||
|
||||
|
||||
CONFIGURATION ~
|
||||
|
||||
Defaults are sensible. Override only what you care about.
|
||||
|
||||
>lua
|
||||
require('fff').setup({
|
||||
base_path = vim.fn.getcwd(),
|
||||
prompt = '> ',
|
||||
title = 'FFFiles',
|
||||
max_results = 100,
|
||||
max_threads = 4,
|
||||
lazy_sync = true,
|
||||
prompt_vim_mode = false,
|
||||
follow_symlinks = false,
|
||||
-- Allow indexing the user's $HOME directory. Enabled by default.
|
||||
-- Disable if you strictly sure you don't want this, as it makes whole fff error hard
|
||||
enable_home_dir_scanning = true,
|
||||
-- Allow indexing a filesystem root (e.g. `/`, `C:\`). Disabled by default
|
||||
enable_fs_root_scanning = false,
|
||||
layout = {
|
||||
height = 0.8,
|
||||
width = 0.8,
|
||||
prompt_position = 'bottom', -- or 'top'
|
||||
preview_position = 'right', -- 'left' | 'right' | 'top' | 'bottom'
|
||||
preview_size = 0.5,
|
||||
-- Border style for the picker windows. Leave unset (nil) to follow the
|
||||
-- global `vim.o.winborder`; set it to override fff's borders independently.
|
||||
border = nil, -- 'single' | 'double' | 'rounded' | 'solid' | 'shadow' | 'none'
|
||||
flex = { size = 130, wrap = 'top' },
|
||||
min_list_height = 10, -- do not display anything except the list below this threshold
|
||||
show_scrollbar = true,
|
||||
path_shorten_strategy = 'middle_number', -- 'middle_number' | 'middle' | 'end' | 'start'
|
||||
anchor = 'center',
|
||||
},
|
||||
preview = {
|
||||
enabled = true,
|
||||
max_size = 10 * 1024 * 1024,
|
||||
chunk_size = 8192,
|
||||
binary_file_threshold = 1024,
|
||||
imagemagick_info_format_str = '%m: %wx%h, %[colorspace], %q-bit',
|
||||
line_numbers = false,
|
||||
cursorlineopt = 'both',
|
||||
wrap_lines = false,
|
||||
filetypes = {
|
||||
svg = { wrap_lines = true },
|
||||
markdown = { wrap_lines = true },
|
||||
text = { wrap_lines = true },
|
||||
},
|
||||
},
|
||||
keymaps = {
|
||||
close = '<Esc>',
|
||||
select = '<CR>',
|
||||
select_split = '<C-s>',
|
||||
select_vsplit = '<C-v>',
|
||||
select_tab = '<C-t>',
|
||||
move_up = { '<Up>', '<C-p>' },
|
||||
move_down = { '<Down>', '<C-n>' },
|
||||
preview_scroll_up = '<C-u>',
|
||||
preview_scroll_down = '<C-d>',
|
||||
toggle_debug = '<F2>',
|
||||
cycle_grep_modes = '<S-Tab>',
|
||||
-- grep mode only: jump cursor to first match of next/prev file group
|
||||
grep_jump_to_next_file = { '<C-A-n>', '<A-Down>' },
|
||||
grep_jump_to_prev_file = { '<C-A-p>', '<A-Up>' },
|
||||
cycle_previous_query = '<C-Up>',
|
||||
toggle_select = '<Tab>',
|
||||
send_to_quickfix = '<C-q>',
|
||||
focus_list = '<leader>l',
|
||||
focus_preview = '<leader>p',
|
||||
},
|
||||
frecency = {
|
||||
enabled = true,
|
||||
db_path = vim.fn.stdpath('cache') .. '/fff_nvim',
|
||||
},
|
||||
history = {
|
||||
enabled = true,
|
||||
db_path = vim.fn.stdpath('data') .. '/fff_queries',
|
||||
min_combo_count = 3,
|
||||
combo_boost_score_multiplier = 100,
|
||||
},
|
||||
git = {
|
||||
status_text_color = false, -- true to color filenames by git status
|
||||
},
|
||||
select = {
|
||||
-- Return winid to open the chosen file in, or nil to open in the original window
|
||||
select_window = function(current_buf, action) --[[ default impl ]] end,
|
||||
},
|
||||
grep = {
|
||||
max_file_size = 10 * 1024 * 1024,
|
||||
max_matches_per_file = 100,
|
||||
smart_case = true,
|
||||
time_budget_ms = 150,
|
||||
modes = { 'plain', 'regex', 'fuzzy' },
|
||||
trim_whitespace = false,
|
||||
enable_filename_constraint = false, -- treat filename-like tokens (e.g. `score.rs`) in a grep query as a file-path filter scoping the search; off = searched as literal text
|
||||
location_format = ':%d:%d', -- printf format for line:col prefix in grep results, e.g. ':%d' for line-only
|
||||
},
|
||||
debug = {
|
||||
enabled = false, -- show the file info panel next to the preview
|
||||
show_scores = false, -- inline scores in the file list
|
||||
-- Per-section toggles for the file info panel. Accepts a boolean shorthand
|
||||
-- (`show_file_info = true|false`) to flip everything at once. The panel
|
||||
-- adapts to width: narrow renders sections vertically, wide renders them
|
||||
-- as a two-column grid. Disable a section to also shrink the panel.
|
||||
show_file_info = {
|
||||
file_info = true, -- size, type, git status, frecency
|
||||
score_breakdown = true, -- total + match type, bonuses, modifiers, penalty
|
||||
-- modified + accessed timestamps; pass a table to hide individual rows:
|
||||
-- timings = { modified = false, accessed = true }
|
||||
timings = true,
|
||||
full_path = true, -- relative path at the bottom (wraps if too long)
|
||||
},
|
||||
},
|
||||
logging = {
|
||||
-- logs will be written in a parent directory of this file path in files like
|
||||
-- `<stem>+<UTC-timestamp>+<pid>.<ext>`. Run :FFFOpenLog to open current one
|
||||
log_file = vim.fn.stdpath('log') .. '/fff.log',
|
||||
log_level = 'info',
|
||||
retain_runs = 20,
|
||||
},
|
||||
})
|
||||
<
|
||||
|
||||
|
||||
LIVE GREP MODES ~
|
||||
|
||||
`<S-Tab>` cycles between `plain`, `regex`, and `fuzzy`. The list is
|
||||
configurable via `grep.modes`, and single-mode setups hide the indicator
|
||||
entirely.
|
||||
|
||||
Per-call override:
|
||||
|
||||
>lua
|
||||
require('fff').live_grep({ grep = { modes = { 'fuzzy', 'plain' } } })
|
||||
require('fff').live_grep({ query = 'search term' }) -- pre-fill
|
||||
<
|
||||
|
||||
|
||||
CONSTRAINTS ~
|
||||
|
||||
Both find and grep accept these tokens to refine a query:
|
||||
|
||||
- `git:modified`. One of `modified`, `staged`, `deleted`, `renamed`, `untracked`, `ignored`.
|
||||
- `test/`. Any deeply nested children of `test/`.
|
||||
- `!something`, `!test/`, `!git:modified`. Exclusion.
|
||||
- `./**/*.{rs,lua}`. Any valid glob, powered by zlob <https://github.com/dmtrKovalenko/zlob>.
|
||||
|
||||
Grep-only:
|
||||
|
||||
- `*.md`, `*.{c,h}`. Extension filter.
|
||||
- `src/main.rs`. Grep inside a single file.
|
||||
|
||||
Mix freely: `git:modified src/**/*.rs !src/**/mod.rs user controller`.
|
||||
|
||||
|
||||
OPEN IN INVOKING WINDOW ~
|
||||
|
||||
By default fff.nvim will try to open a file in the most suitable window, so any
|
||||
non-file buffers are not affected. You can customize or disable this by
|
||||
providing:
|
||||
|
||||
>lua
|
||||
require('fff').setup({
|
||||
select = {
|
||||
select_window = function(_current_buf, _action) return nil end,
|
||||
},
|
||||
})
|
||||
<
|
||||
|
||||
Caveat: the chosen file replaces the buffer in the invoking window even if
|
||||
it’s a non-modifiable / special buftype. `winfixbuf` windows still fall back
|
||||
to `:split` to avoid `E1513`.
|
||||
|
||||
|
||||
MULTI-SELECT AND QUICKFIX ~
|
||||
|
||||
- `<Tab>`. Toggle selection (shows a thick `▊` in the signcolumn).
|
||||
- `<C-q>`. Send selected files to the quickfix list and close the picker.
|
||||
|
||||
|
||||
GIT STATUS HIGHLIGHTING ~
|
||||
|
||||
Sign-column indicators are on by default. To color filename text by git status,
|
||||
set `git.status_text_color = true` and adjust the `hl.git_*` groups. See `:help
|
||||
fff.nvim` for the full list.
|
||||
|
||||
|
||||
FLOAT COLORS ~
|
||||
|
||||
The picker maps its float content to `NormalFloat` (via `hl.normal`) and the
|
||||
border to `FloatBorder`. Default `FloatBorder` links to `NormalFloat`, so
|
||||
border and content share a background out of the box and the picker reads as a
|
||||
single popup. Override `hl.normal = 'Normal'` to make the picker blend with the
|
||||
editor instead.
|
||||
|
||||
For finer control, set `hl.winhl` to override the per-window `winhighlight`. It
|
||||
accepts either a single string applied to every picker window, or a table with
|
||||
optional `prompt`, `list`, `preview`, and `file_info` keys. Missing keys fall
|
||||
back to the default built from `hl.normal`, `hl.border`, and `hl.title`.
|
||||
|
||||
>lua
|
||||
-- Apply the same winhighlight to all picker windows
|
||||
hl = { winhl = 'Normal:NormalFloat,FloatBorder:FloatBorder,FloatTitle:Title' }
|
||||
|
||||
-- Or override specific windows only
|
||||
hl = {
|
||||
winhl = {
|
||||
prompt = 'Normal:Pmenu,FloatBorder:FloatBorder',
|
||||
list = 'Normal:NormalFloat,FloatBorder:FloatBorder',
|
||||
preview = 'Normal:NormalFloat,FloatBorder:FloatBorder',
|
||||
},
|
||||
}
|
||||
<
|
||||
|
||||
|
||||
FILE INFO PANEL ~
|
||||
|
||||
Enable with `debug.enabled = true`. The panel sits above the preview and shows
|
||||
file metadata, score breakdown, timestamps and the full absolute path. It
|
||||
adapts to the panel width: at narrow widths sections stack vertically (B2), at
|
||||
wide widths sections render as a two-column grid (H2). Each section can be
|
||||
disabled individually via `debug.show_file_info`.
|
||||
|
||||
Customise the panel via `hl`:
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
key default used for
|
||||
----------------------- ----------------- --------------------------------
|
||||
file_info_section Title section header label
|
||||
|
||||
file_info_separator FloatBorder dashes that act as section
|
||||
borders
|
||||
|
||||
file_info_label Comment row labels (Size, Type, Git, …)
|
||||
|
||||
file_info_value Normal fg plain values
|
||||
|
||||
file_info_value_dim NonText dim values, separators inside
|
||||
rows
|
||||
|
||||
file_info_size Number file size value
|
||||
|
||||
file_info_type Type filetype value
|
||||
|
||||
file_info_path Directory full path
|
||||
|
||||
file_info_total_score bold + Number total score (bold)
|
||||
|
||||
file_info_match_type bold + Special match type (bold)
|
||||
|
||||
file_info_score_pos DiagnosticOk positive score components
|
||||
|
||||
file_info_score_neg DiagnosticError negative score components
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
FILE FILTERING ~
|
||||
|
||||
FFF honours `.gitignore`. For picker-only ignores that do not touch git, add a
|
||||
sibling `.ignore` file:
|
||||
|
||||
>gitignore
|
||||
*.md
|
||||
docs/archive/**/*.md
|
||||
<
|
||||
|
||||
Run `:FFFScan` to force a rescan.
|
||||
|
||||
|
||||
TROUBLESHOOTING ~
|
||||
|
||||
- `:FFFHealth` verifies picker init, optional dependencies, and DB connectivity.
|
||||
- `:FFFOpenLog` opens the current session’s log file.
|
||||
- Historical log files are stored near the main log file `<state>/log/fff+<UTC-timestamp>+<pid>.log` (up to 20 files)
|
||||
- For a crash backtrace, run `lldb -- nvim` or `gdb -- nvim` and reproduce
|
||||
|
||||
Generated by panvimdoc <https://github.com/kdheepak/panvimdoc>
|
||||
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||
Reference in New Issue
Block a user