Зачем это нужноЧасть VI. Современный Neovim 2026
Представьте проект на тысячи файлов. Вам нужно открыть user_repository.go, и вы помните только, что в имени есть "repo". В netrw вы будете кликать по дереву каталогов, в IDE - лезть мышью в боковую панель. В Neovim 2026 вы нажимаете <leader>ff, печатаете usrepo (не подряд, с пропусками!) - и нужный файл уже подсвечен в списке с превью содержимого справа. Это и есть fuzzy-поиск: нечёткое сопоставление, при котором введённые символы ищутся как подпоследовательность, а результаты ранжируются по близости.
Fuzzy-finder - это, пожалуй, главный "суперспособности-плагин" современного Neovim. Один и тот же интерфейс с окном-поповером, строкой ввода и живым превью становится универсальным входом ко всему: файлы проекта, поиск по содержимому (grep), открытые буферы, теги справки, ссылки и определения от LSP, история, git-коммиты, символы документа. Вы перестаёте помнить десятки разных команд - вы помните один паттерн "открыть picker и набрать запрос".
В этой главе мы разберём три актуальных движка-пикера 2026 года - Telescope, fzf-lua и snacks.picker - поймём, чем они отличаются, как их настроить, какие маппинги стали де-факто стандартом, и что выбрать. Базовую механику навигации по файлам и netrw мы уже затрагивали в главе 15; здесь идёт речь именно о современных Lua-пикерах. LSP-источники (lsp_references и подобные) опираются на материал главы 25.
Что такое picker и почему их триТолько Neovim. Все три пикера написаны на Lua и требуют Lua-движка Neovim - в классическом Vim (даже 9.1) они не работают. Если вы на Vim, ближайшие аналоги - fzf.vim (обёртка над тем же fzf) или ctrlp.vim. Всё, что описано ниже, предполагает Neovim.
Picker (пикер) - это плагин, реализующий обобщённый интерфейс выбора из списка. У него три части: source (источник данных - список файлов, строк grep, буферов), matcher/sorter (алгоритм нечёткого сопоставления и ранжирования) и UI (окно ввода + список результатов + опциональное окно превью).
Почему пикеров несколько и почему это нормально:
- Telescope.nvim - исторический стандарт, появившийся первым и собравший огромную экосистему расширений. Зрелый, документированный, расширяемый. Минус - на гигантских списках сортировка на чистом Lua заметно медленнее (лечится нативным C-сортировщиком telescope-fzf-native).
- fzf-lua - обёртка вокруг внешней утилиты fzf (написана на Go). Источники генерируются в Neovim, а тяжёлый fuzzy-matching и рендеринг отдаёт сверхбыстрому fzf-процессу. Лидер по скорости на огромных списках (монорепозитории в сотни тысяч файлов).
- snacks.picker - встроенный в мета-плагин folke/snacks.nvim, оформился в 2026 как третий крупный игрок. Чистый Lua, быстрый старт, встроенная frecency (ранжирование по частоте+давности обращений) и множество готовых раскладок (ivy, vertical, dropdown, sidebar). Дефолтный пикер в LazyVim 2026.
Внешние зависимости: ripgrep и fd
Любой современный пикер опирается на два внешних CLI-инструмента - установите их через системный пакетный менеджер до настройки плагина:
- ripgrep (rg) - сверхбыстрый grep, уважает .gitignore, движок для поиска по содержимому (live_grep). Подробнее про rg как grepprg - в главе 14.
- fd (fd-find) - быстрая замена find для перечисления файлов (find_files), тоже уважает .gitignore.
Код: Выделить всё
# macOS
brew install ripgrep fd
# Debian/Ubuntu
sudo apt install ripgrep fd-find
# Arch
sudo pacman -S ripgrep fd
Telescope.nvim: пикеры и установка
На 2026 год Telescope (ветка 0.1.x) поднял минимум до Neovim >= 0.11 - конкретный требуемый патч сверяйте с актуальным README плагина. Базовая установка через lazy.nvim (про менеджер плагинов - глава 23):
Код: Выделить всё
-- lua/plugins/telescope.lua
return {
'nvim-telescope/telescope.nvim',
branch = '0.1.x',
dependencies = {
'nvim-lua/plenary.nvim',
-- нативный C-сортировщик: ускоряет fuzzy-matching на больших списках
{ 'nvim-telescope/telescope-fzf-native.nvim', build = 'make' },
},
cmd = 'Telescope',
keys = {
{ '<leader>ff', '<cmd>Telescope find_files<cr>', desc = 'Найти файлы' },
{ '<leader>fg', '<cmd>Telescope live_grep<cr>', desc = 'Grep по проекту' },
{ '<leader>fb', '<cmd>Telescope buffers<cr>', desc = 'Буферы' },
{ '<leader>fh', '<cmd>Telescope help_tags<cr>', desc = 'Справка' },
{ '<leader>fr', '<cmd>Telescope oldfiles<cr>', desc = 'Недавние файлы' },
},
config = function()
local telescope = require('telescope')
local actions = require('telescope.actions')
telescope.setup({
defaults = {
-- здесь мы НЕ трогаем дефолтные <C-u>/<C-d> - они прокручивают превью
-- (см. таблицу навигации ниже)
},
pickers = {
buffers = {
mappings = {
-- delete_buffer осмыслен только в пикере buffers, поэтому вешаем его
-- сюда, а не в глобальные defaults: <M-d> закрывает буфер из списка,
-- не затрагивая <C-u>/<C-d> (прокрутка превью) в остальных пикерах
i = { ['<M-d>'] = actions.delete_buffer },
},
},
},
})
telescope.load_extension('fzf') -- активируем нативный сортировщик
end,
}
Ключевые встроенные пикеры
Код: Выделить всё
Пикер (:Telescope ...) | Что делает | Зависимость
-------------------------------+----------------------------------------------+---------------------
find_files | Найти файл по имени во всём проекте | fd (фолбэк на find)
live_grep | Живой поиск по содержимому всех файлов | rg (обязательно)
grep_string | Grep по слову под курсором / выделению | rg
buffers | Список открытых буферов | -
oldfiles | Недавно открытые файлы (история) | -
help_tags | Поиск по тегам встроенной :help | -
keymaps | Все активные маппинги с описаниями | -
current_buffer_fuzzy_find | Fuzzy-поиск строк в текущем буфере | -
resume | Открыть последний picker с тем же запросом | -
lsp_references | Все ссылки на символ под курсором | LSP (глава 25)
lsp_definitions | Перейти к определению (со списком) | LSP
lsp_document_symbols | Символы текущего файла | LSP
lsp_dynamic_workspace_symbols | Символы всего проекта | LSP
diagnostics | Все диагностики LSP списком | LSP
Окно открывается в insert mode - вы сразу печатаете запрос. Управление результатами:
Код: Выделить всё
Клавиша | Действие
---------------+--------------------------------------------------------
<C-n> / <C-p> | Следующий / предыдущий результат
<C-j> / <C-k> | То же (вниз / вверх)
<CR> | Открыть выбранное
<C-x> | Открыть в горизонтальном сплите
<C-v> | Открыть в вертикальном сплите
<C-t> | Открыть в новой вкладке
<C-u> / <C-d> | Прокрутить окно превью
<Tab> | Пометить запись (multi-select)
<C-q> | Отправить результаты (или помеченные) в quickfix
<Esc> | Перейти в normal mode внутри picker; ещё раз - закрыть
Практический пример: найти и открыть файл
Код: Выделить всё
Задача: открыть lua/config/keymaps.lua
Нажимаем: <leader>ff
Печатаем: cfgkeym
Видим: список сужается до lua/config/keymaps.lua (символы c-f-g-k-e-y-m
нашлись как подпоследовательность в пути)
Нажимаем: <CR>
Стало: файл открыт в текущем окне
Код: Выделить всё
Задача: найти все вызовы deprecated-функции old_api() и собрать в quickfix
Нажимаем: <leader>fg
Печатаем: old_api(
Видим: live_grep показывает все строки с совпадением + превью
Нажимаем: <C-q>
Стало: все совпадения в quickfix; теперь :cfdo s/old_api/new_api/ge | update
Главная сила Telescope - экосистема. Расширения подключаются через telescope.load_extension('name') и вызываются как :Telescope name:
- telescope-fzf-native - нативный fzf-сортировщик (обязателен для скорости).
- telescope-ui-select - перенаправляет vim.ui.select в Telescope, и тогда меню выбора LSP code action рисуется как picker.
- telescope-frecency - ранжирование файлов по frecency (частота + давность); в snacks.picker это встроено, здесь нужен отдельный плагин.
- telescope-file-browser - файловый менеджер на базе Telescope.
- telescope-project, telescope-undo, telescope-symbols и десятки других.
fzf-lua (ibhagwan/fzf-lua) делает то же самое, но отдаёт fuzzy-matching внешнему процессу fzf. На больших списках это ощутимо быстрее, потому что fzf написан на Go и оптимизирован под потоковую обработку.
Код: Выделить всё
-- lua/plugins/fzf-lua.lua
return {
'ibhagwan/fzf-lua',
dependencies = { 'nvim-tree/nvim-web-devicons' },
cmd = 'FzfLua',
keys = {
{ '<leader>ff', '<cmd>FzfLua files<cr>', desc = 'Найти файлы' },
{ '<leader>fg', '<cmd>FzfLua live_grep<cr>', desc = 'Grep по проекту' },
{ '<leader>fb', '<cmd>FzfLua buffers<cr>', desc = 'Буферы' },
{ '<leader>fh', '<cmd>FzfLua helptags<cr>', desc = 'Справка' },
{ '<leader>fr', '<cmd>FzfLua oldfiles<cr>', desc = 'Недавние файлы' },
},
opts = {
'default-title', -- профиль внешнего вида
},
}
Код: Выделить всё
fzf-lua | Аналог в Telescope
----------------------+----------------------
files | find_files
live_grep | live_grep
grep_cword | grep_string
buffers | buffers
oldfiles | oldfiles
helptags | help_tags
lsp_references | lsp_references
lsp_document_symbols | lsp_document_symbols
diagnostics_document | diagnostics
snacks.picker: встроенный пикер 2026
snacks.picker - часть мета-плагина folke/snacks.nvim, который объединяет десяток мелких модулей (dashboard, индикатор, lazygit-интеграция, нотификации и picker). В 2026 это дефолтный пикер LazyVim. Главные плюсы: чистый Lua без внешних matcher-зависимостей, очень быстрый старт, встроенная frecency (matcher = { frecency = true }) и обилие готовых раскладок.
Код: Выделить всё
-- lua/plugins/snacks.lua
return {
'folke/snacks.nvim',
priority = 1000,
lazy = false,
opts = {
picker = {
matcher = { frecency = true }, -- ранжирование по частоте+давности
},
},
keys = {
{ '<leader>ff', function() Snacks.picker.files() end, desc = 'Найти файлы' },
{ '<leader>fg', function() Snacks.picker.grep() end, desc = 'Grep по проекту' },
{ '<leader>fb', function() Snacks.picker.buffers() end, desc = 'Буферы' },
{ '<leader>fh', function() Snacks.picker.help() end, desc = 'Справка' },
{ '<leader>fr', function() Snacks.picker.recent() end, desc = 'Недавние файлы' },
{ '<leader>fs', function() Snacks.picker.lsp_symbols() end, desc = 'Символы файла' },
{ 'gd', function() Snacks.picker.lsp_definitions() end, desc = 'Определение' },
{ 'grr', function() Snacks.picker.lsp_references() end, desc = 'Ссылки' },
},
}
Типовые маппинги: <leader>f как префикс
Сложилось де-факто соглашение: префикс <leader>f ("find") для всех пикеров, и which-key (глава 21) показывает подсказку после нажатия <leader>f. Этот набор переносим между всеми тремя движками - меняется только правая часть.
Код: Выделить всё
Маппинг | Назначение | Telescope | fzf-lua | snacks
------------+---------------------------+-----------------------------+----------------+-----------
<leader>ff | Найти файл | find_files | files | files
<leader>fg | Grep по проекту | live_grep | live_grep | grep
<leader>fw | Grep слова под курсором | grep_string | grep_cword | grep_word
<leader>fb | Буферы | buffers | buffers | buffers
<leader>fr | Недавние файлы | oldfiles | oldfiles | recent
<leader>fh | Справка | help_tags | helptags | help
<leader>fk | Маппинги | keymaps | keymaps | keymaps
<leader>/ | Поиск в текущем буфере | current_buffer_fuzzy_find | lgrep_curbuf | lines
Лучшие практики 2026
- Не включайте все три пикера одновременно. Выберите один основной. Если переходите на snacks.picker, явно выключите старые (enabled = false для telescope/fzf-lua и telescope-frecency), уберите их кеймапы и добавьте буфер snacks_picker_input в игнор-лист blink.cmp (глава 26) - иначе автодополнение лезет в строку ввода пикера и появляются двойные бинды.
- Ставьте ripgrep и fd обязательно, даже если пикер формально стартует без них: live_grep без rg практически бесполезен, а find_files без fd медленнее и не уважает .gitignore единообразно. Проверяйте :checkhealth.
- Для Telescope компилируйте telescope-fzf-native (build = 'make') и загружайте расширение fzf. Без него на крупном репозитории сортировка ощутимо лагает. fzf-lua и snacks.picker такой проблемы лишены by design.
- Используйте frecency. В snacks.picker это matcher = { frecency = true } из коробки; в Telescope - отдельный telescope-frecency; в fzf-lua frecency нет. Frecency радикально улучшает files/recent, поднимая часто открываемые файлы наверх.
- Свяжите пикеры с LSP. Заменяйте "голые" vim.lsp.buf.references() на lsp_references пикера - список со снипетами и превью удобнее. Дефолтные кеймапы 0.11 (grr, gri, gO) можно переназначить на picker-версии (глава 25).
- Перенаправьте vim.ui.select в пикер. В Telescope - расширением telescope-ui-select; snacks.picker и fzf-lua подхватывают vim.ui.select сами при настройке. Тогда меню code action и прочие выборы рисуются единым красивым UI.
- Ленивая загрузка через cmd/keys. Не грузите пикер на старте - указывайте cmd и keys, чтобы плагин подгружался при первом обращении (глава 23). Исключение - snacks.nvim как мета-плагин обычно грузят рано (lazy = false, высокий priority), но сам picker внутри ленив.
- Освойте resume. Он открывает последний picker с прежним запросом - незаменимо, когда случайно закрыли список длинного grep. Команда переносима между движками: :Telescope resume, :FzfLua resume и Snacks.picker.resume() соответственно.
- Multi-select + quickfix. <Tab> для пометки и <C-q> для выгрузки в quickfix превращают пикер в инструмент пакетного рефакторинга (связка с :cfdo из главы 14).
- Не установлен rg/fd. live_grep молча пуст или ругается. Симптом лечится установкой ripgrep/fd и :checkhealth.
- Забыли build = 'make' для telescope-fzf-native или не вызвали load_extension('fzf') - нативный сортировщик не активен, и Telescope тормозит на больших списках, хотя "вроде установлен".
- Включили несколько пикеров сразу без отключения старых - конфликтуют кеймапы, дублируются vim.ui.select-обработчики, frecency считается дважды.
- Ждёте frecency в fzf-lua - её там нет; для частотного ранжирования берите snacks.picker или Telescope+telescope-frecency.
- blink.cmp лезет в строку ввода snacks.picker - автодополнение всплывает в поле запроса. Добавьте буфер snacks_picker_input (или соответствующий filetype) в игнор автодополнения.
- live_grep != grep_string. live_grep ищет то, что вы печатаете в реальном времени; grep_string ищет фиксированную строку (слово под курсором или выделение). Путаница приводит к "почему он ищет старое слово".
- Печатаете regex в find_files. Источник файлов - это fuzzy-сопоставление подпоследовательности, а не regex; спецсимволы тут не магия. Regex-синтаксис уместен в grep-источнике (это rg), а не в списке файлов.
- Пробел в live_grep Telescope. По умолчанию пробел в запросе live_grep трактуется как разделитель токенов (логическое "И" между подстроками), а не как буквальный пробел в regex. Поэтому foo bar найдёт строки, где есть и foo, и bar в любом порядке, но не обязательно фразу foo bar подряд. Чтобы искать фразу с пробелом дословно, передавайте rg флаг --fixed-strings (через live_grep с additional_args) или используйте grep_string/специальный режим точного поиска. У fzf-lua и snacks поведение пробела/"И" тоже своё - сверяйтесь с их докой, если результат удивляет.
- Загрузили пикер на старте без lazy-триггеров - лишние миллисекунды к запуску; проверяйте :Lazy profile.
- Базовый набор. Установите один пикер (рекомендую начать с Telescope для экосистемы или snacks.picker, если используете LazyVim), а также ripgrep и fd. Настройте маппинги <leader>ff, <leader>fg, <leader>fb, <leader>fh. Проверьте :checkhealth.
- Fuzzy-навыки. Откройте find_files и потренируйтесь искать файлы, вводя символы с пропусками (например cfgopt для config/options.lua). Прочувствуйте, как подпоследовательность сужает список.
- Grep в quickfix. Через live_grep найдите все вхождения какого-нибудь идентификатора в своём проекте, пометьте несколько <Tab>, выгрузите в quickfix <C-q> и выполните массовую замену через :cfdo s/old/new/ge | update (повторите материал главы 14).
- LSP-пикеры. На любом проекте с настроенным LSP (глава 25) свяжите <leader>fr/grr с lsp_references и <leader>fs с lsp_document_symbols. Сравните вывод picker-версии с "голым" vim.lsp.buf.references().
- Frecency. Включите frecency (snacks.picker или telescope-frecency). Несколько дней поработайте - убедитесь, что часто открываемые файлы всплывают в начале списка files/recent.
- Скорость (опционально). Если у вас есть большой монорепозиторий, поставьте параллельно fzf-lua и сравните отзывчивость live_grep на нём с вашим основным пикером. Сделайте вывод, оправдан ли переход.
- Telescope - берите, если важна зрелая экосистема расширений и вы готовы доставить telescope-fzf-native ради скорости. Лучший выбор "по умолчанию" для тех, кто собирает конфиг с нуля и хочет максимум готовых интеграций.
- fzf-lua - берите, если работаете с огромными списками (монорепозитории, сотни тысяч файлов) и цените максимальную отзывчивость; вы получаете мощь нативного fzf и его синтаксис запросов ценой внешней зависимости.
- snacks.picker - берите, если хотите минимум зависимостей, быстрый старт и frecency из коробки, или если уже живёте на LazyVim (где это дефолт). Самый "батарейки-внутри" вариант 2026 года.
Главное из главы
- Picker - обобщённый fuzzy-интерфейс выбора: источник + matcher + UI с превью. Один паттерн "открыть picker, набрать запрос" заменяет десятки команд.
- Три актуальных движка 2026: Telescope (зрелая экосистема), fzf-lua (скорость на гигантских списках), snacks.picker (минимум зависимостей, frecency из коробки, дефолт LazyVim).
- Обязательно ставьте ripgrep и fd - без них live_grep и find_files неполноценны. Проверяйте :checkhealth.
- Ключевые пикеры: find_files, live_grep, buffers, help_tags, oldfiles, плюс LSP-источники (lsp_references, lsp_document_symbols).
- Де-факто маппинги: <leader>ff (файлы), <leader>fg (grep), <leader>fb (буферы), <leader>fh (справка) - переносимы между всеми движками.
- Внутри окна: <C-n>/<C-p> навигация, <Tab> пометка, <C-q> в quickfix, <C-v>/<C-x>/<C-t> сплиты/вкладки.
- Для Telescope компилируйте telescope-fzf-native; включайте frecency там, где можете; не держите несколько пикеров одновременно.
- Связка picker + <Tab> + <C-q> + :cfdo - мощный инструмент пакетного рефакторинга (главы 14, 25).