Мы пройдём путь от встроенного файлового менеджера netrw (он есть в любой установке и работает даже на голом сервере) к современным инструментам 2026 года: редактированию файловой системы как обычного буфера (oil.nvim) и fuzzy-поиску по тысячам файлов за миллисекунды (Telescope, fzf-lua, snacks.picker). Отдельно поговорим про закладки на "горячие" файлы проекта (harpoon) и про встроенный механизм :find/path, который многие недооценивают.
Это глава из части "Поиск и многофайловость". Поиск внутри текста мы разбирали в главе 10, организацию буферов и окон - в главе 13, а пакетную работу по всему проекту через quickfix - в главе 14. Здесь же фокус именно на том, как найти и открыть нужный файл.
Зачем вообще нужна навигация по файлам
Представь типичную задачу: "поправить обработчик ошибок в сервисе авторизации". В IDE ты обычно тянешься к мыши и кликаешь по дереву файлов слева. Это работает, но медленно: глаза уходят с кода, рука с home-row, а дерево из 300 файлов всё равно приходится скроллить.
Vim-подход другой: ты держишь руки на клавиатуре и описываешь, что тебе нужно, а не где это лежит. Помнишь часть имени? Набери auth serv в fuzzy-finder - и нужный файл всплывёт первым. Знаешь директорию? Открой её как буфер и редактируй прямо в нём. Ищешь по содержимому? Один live_grep по всему проекту, и ты на нужной строке. Навыки навигации по файлам - это множитель ко всему остальному, чему ты научился: грамматике, движениям, текстовым объектам.
Встроенный netrw: файловый менеджер из коробки
netrw - стандартный плагин, который поставляется с любым Vim и Neovim. Его главное достоинство в том, что он всегда есть: на голом сервере, в Docker-контейнере, на чужой машине - везде, где установлен vim, доступен и netrw. Это делает его навыком выживания, а не только удобства.
Открыть netrw можно несколькими способами:
Код: Выделить всё
Команда | Что делает
------------------+---------------------------------------------------------------
:Explore (:Ex) | Открыть проводник в текущем окне, в директории текущего файла
:Sexplore (:Sex) | Открыть проводник в горизонтальном сплите
:Vexplore (:Vex) | Открыть проводник в вертикальном сплите (слева)
:Texplore (:Tex) | Открыть проводник в новой вкладке
:Explore . | Открыть проводник в текущем рабочем каталоге
nvim . / vim . | Запустить редактор сразу с проводником в каталоге .
Код: Выделить всё
Клавиша | Действие в netrw
-----------------+----------------------------------------------------------------------------------------------------------
Enter | Открыть файл / войти в директорию
- | Подняться на уровень вверх (к родительской директории)
D (также <del>) | Удалить файл/директорию под курсором
R | Переименовать
% | Создать новый файл
d | Создать новую директорию
gh | Скрыть/показать "точечные" (dotfiles) файлы
i | Циклически переключить стиль листинга: thin / long / wide / tree (тонкий / подробный / широкий / дерево)
s | Сменить сортировку
v | Открыть файл в вертикальном сплите
o | Открыть файл в горизонтальном сплите
Многие путаются с тем, что netrw по умолчанию открывается "деревом" и оставляет за собой лишние буферы. Классический рецепт, популяризированный плагином vim-vinegar, - относиться к проводнику как к буферу текущей директории, в который можно прыгнуть клавишей - и так же легко выйти. Базовая настройка netrw в init.lua:
Код: Выделить всё
vim.g.netrw_banner = 0 -- убрать шапку с подсказками
vim.g.netrw_liststyle = 3 -- вид "дерево"
vim.g.netrw_winsize = 25 -- ширина сплита Vexplore в процентах
Плюсы: ноль зависимостей, есть везде, понимает удалённые протоколы (можно открыть scp://host//path/file), не требует настройки для базовой работы.
Минусы: интерфейс архаичен и местами непредсказуем; файловые операции (удаление, переименование) не всегда интуитивны; известная проблема "висящих" буферов; код плагина старый и не развивается. Поэтому в современных Neovim-конфигах netrw часто заменяют - но забывать его не стоит: на сервере, где нельзя ставить плагины, это твой единственный встроенный файловый менеджер.
oil.nvim: файловая система как буфер
Главная идея oil.nvim (исторически требует Neovim 0.8+; на практике ставь современный stable) элегантна: директория - это просто буфер, а файловые операции - это редактирование текста. Ты открываешь каталог, видишь список файлов как строки и работаешь с ним обычными vim-командами:
- удалить строку (dd) -> удалить файл;
- изменить текст строки (cw, ciw) -> переименовать файл;
- добавить новую строку с именем -> создать файл (а имя с / на конце - директорию);
- скопировать строку в другой oil-буфер (yy + p) -> скопировать/переместить файл между каталогами.
Почему это лучше дерева-сайдбара? Потому что массовый рефакторинг файловой структуры превращается в редактирование текста, где работают все твои навыки: визуальный блок, :substitute, макросы, точка-команда. Переименовать десяток файлов по шаблону через :%s/old_/new_/? В oil это естественно.
Минимальная установка через lazy.nvim:
Код: Выделить всё
{
'stevearc/oil.nvim',
opts = {
default_file_explorer = true, -- перехватывать `nvim .` и `:e dir/`
delete_to_trash = true, -- безопасное удаление в корзину
view_options = { show_hidden = true },
},
dependencies = { 'nvim-mini/mini.icons' },
}
Код: Выделить всё
Действие | Команда / клавиша
--------------------------------------------+-------------------
Открыть родительский каталог как oil-буфер | :Oil или -
Открыть oil в плавающем окне | :Oil --float
Применить накопленные изменения | :w
Отменить незаписанные изменения | :e! или u
Подняться вверх / войти внутрь | - / Enter
Код: Выделить всё
# Открыли каталог src/ через oil, видим буфер:
api.ts
utils.ts
index.ts
# Хотим переименовать utils.ts -> helpers.ts и удалить index.ts
# Наводимся на строку utils.ts, нажимаем cw helpers<Esc>
# Наводимся на index.ts, нажимаем dd
# Буфер теперь:
api.ts
helpers.ts
# Нажимаем :w -> oil показывает план:
# RENAME src/utils.ts -> src/helpers.ts
# DELETE src/index.ts
# Подтверждаем -> изменения применены в ФС
Важно: по умолчанию default_file_explorer нужно включать явно, иначе netrw продолжит перехватывать открытие каталогов, и поведение будет смешанным. И помни про delete_to_trash - без него удаление безвозвратно.Альтернатива по парадигме - mini.files (тоже редактирование ФС как буфера, но с навигацией "колонками"). А если тебе всё-таки нужен классический tree-сайдбар, как в IDE, - смотри neo-tree.nvim. Выбор между ними - вопрос вкуса: пользователям сплит-ориентированного workflow ближе oil, любителям постоянной панели слева - neo-tree.
Почему netrw нужно именно отключить, а не просто игнорировать. netrw - это не плагин, который ты вызываешь руками; он вешается на автокоманды и перехватывает любое открытие каталога ещё до того, как до него доберётся oil. При этом момент перехвата зависит от того, как открыт каталог и в каком порядке загрузились плагины:
- nvim dir/ (каталог как аргумент командной строки) обрабатывается на старте - здесь успевает первым тот файловый менеджер, чьи автокоманды зарегистрировались раньше;
- :edit dir/ (:e dir/) уже во время сессии идёт через ту же BufEnter/BufWinEnter-цепочку, и снова решает, кто перехватил событие.
Fuzzy-поиск: находить файлы, не помня путей
Fuzzy-finder ("нечёткий поиск") - это инструмент, который позволяет найти файл, набирая любые фрагменты его пути в любом порядке. Ввод cfgopt найдёт lua/config/options.lua, даже если буквы идут не подряд. Это убивает необходимость помнить точные имена и пути - а значит, и необходимость в дереве файлов.
В экосистеме 2026 года есть три крупных пикера, и им посвящена отдельная глава 28. Здесь дадим практический минимум для навигации.
Код: Выделить всё
Пикер | Сильная сторона
---------------+---------------------------------------------------------------------------------------------------------------------------
Telescope | Самая зрелая экосистема расширений, привычный UI, требует Neovim >= 0.9.0 (часть фич - 0.10; рекомендуется свежий stable)
fzf-lua | Максимальная скорость на огромных списках (обёртка над нативным fzf)
snacks.picker | Часть мета-плагина snacks.nvim; быстрый старт, встроенная frecency, много раскладок
Какой бы пикер ты ни выбрал, три действия покрывают 90% навигации:
Код: Выделить всё
Операция | Что делает
------------+------------------------------------------------------------------------
find_files | Нечёткий поиск файла по имени/пути в проекте
live_grep | Поиск по *содержимому* всех файлов (через ripgrep) с живым обновлением
buffers | Переключение между уже открытыми буферами
Пример конфигурации Telescope на префиксе <leader>f ("find"):Подвох для новичков: find_files по умолчанию НЕ показывает скрытые и заигнорированные файлы. Под капотом пикеры опираются на ripgrep/fd, которые уважают .gitignore и пропускают "точечные" файлы. Поэтому find_files "не находит" .env, .github/workflows/*.yml или файлы внутри заигнорированных каталогов - это не баг, а поведение по умолчанию. Включить их можно явно:
- Telescope: :Telescope find_files hidden=true no_ignore=true (или те же поля в opts/pickers.find_files);
- fzf-lua: require('fzf-lua').files({ hidden = true, no_ignore = true });
- snacks.picker: Snacks.picker.files({ hidden = true, ignored = true }).
Если же нужны именно файлы под контролем git (без мусора из node_modules и сборок) - бери отдельную операцию git_files (:Telescope git_files): она перечисляет ровно то, что видит git.
Код: Выделить всё
{
'nvim-telescope/telescope.nvim',
dependencies = {
'nvim-lua/plenary.nvim',
{ 'nvim-telescope/telescope-fzf-native.nvim', build = 'make' },
},
keys = {
{ '<leader>ff', '<cmd>Telescope find_files<cr>', desc = 'Find Files' },
{ '<leader>fg', '<cmd>Telescope live_grep<cr>', desc = 'Live Grep' },
{ '<leader>fb', '<cmd>Telescope buffers<cr>', desc = 'Buffers' },
{ '<leader>fr', '<cmd>Telescope oldfiles<cr>', desc = 'Recent Files' },
},
}
Аналог на fzf-lua практически дословный - require('fzf-lua').files(), .live_grep(), .buffers(). На snacks.picker - Snacks.picker.files(), .grep(), .buffers(). Важная деталь про snacks.picker: у него встроена frecency (ранжирование по частоте и свежести открытия), тогда как в Telescope для этого нужен отдельный telescope-frecency.nvim, а в fzf-lua frecency нет вовсе.
Пример сессии:
Код: Выделить всё
# Нужен файл валидатора, точное имя не помним.
# Нажимаем <leader>ff -> открывается окно поиска
# Печатаем valid
# Список сужается:
# src/auth/PasswordValidator.ts <- курсор здесь
# src/forms/validators.ts
# tests/validation_test.ts
# Жмём Enter -> файл открыт. Рука ни разу не покинула клавиатуру.
Код: Выделить всё
# Где у нас вызывается deprecated-функция legacyLogin?
# Нажимаем <leader>fg -> live_grep
# Печатаем legacyLogin
# Видим все вхождения по проекту с превью строки:
# src/auth/login.ts:42: await legacyLogin(user)
# src/auth/login.ts:88: // TODO: drop legacyLogin
# Enter -> прыгаем прямо на строку 42.
Встроенный :find и опция pathПри переходе на snacks.picker мало включить новый пикер - нужно явно отключить старые (enabled = false для telescope/fzf-lua), убрать их кеймапы и добавить буфер snacks_picker_input в игнор движка автодополнения, иначе получишь конфликты и двойные бинды.
Не всегда хочется тащить плагин. У Vim есть нативная команда :find, которая ищет файл по списку каталогов в опции path. Это "бедный fuzzy-finder", но он встроен и полезен на сервере.
Идея: настраиваешь path, чтобы он включал нужные директории рекурсивно, и тогда :find найдёт файл по имени, где бы он ни лежал.
Код: Выделить всё
" Искать рекурсивно от текущего каталога вниз
set path=.,,**
Код: Выделить всё
Команда | Действие
--------------+------------------------------------------------------------
:find <имя> | Найти и открыть файл по path (поддерживает Tab-дополнение)
:sfind <имя> | То же, но в горизонтальном сплите
:find /foo* | Поиск с глобом по подкаталогам
gf | Открыть файл, на имя которого указывает курсор (по path)
<C-w>f | То же, но в новом сплите
Код: Выделить всё
" Печатаем :find PassVal затем Tab
" Vim дополняет до :find src/auth/PasswordValidator.ts
" Enter -> открыто. Без единого плагина.
Закладки на проект: harpoon
Fuzzy-finder отлично находит любой файл, но в работе ты обычно крутишься между 4-5 "горячими" файлами: контроллер, его тест, модель, конфиг. Каждый раз искать их заново - расточительство. Здесь помогает harpoon (ThePrimeagen) - плагин "закладок", который позволяет пометить файлы и прыгать к ним по одной клавише.
Идея harpoon: ты вручную добавляешь файл в персональный короткий список (он не меняется сам, в отличие от "недавних"), а затем телепортируешься к слоту 1, 2, 3, 4 мгновенно. Это как именные регистры, но для файлов.
Код: Выделить всё
Действие | Типичный маппинг
--------------------------------+-------------------------
Добавить текущий файл в список | <leader>a
Открыть меню harpoon | <C-e>
Прыгнуть к файлу №1...4 | <leader>1 ... <leader>4
Код: Выделить всё
{
'ThePrimeagen/harpoon',
branch = 'harpoon2',
dependencies = { 'nvim-lua/plenary.nvim' },
config = function()
local harpoon = require('harpoon')
harpoon:setup()
vim.keymap.set('n', '<leader>a', function() harpoon:list():add() end, { desc = 'Harpoon Add' })
vim.keymap.set('n', '<C-e>', function() harpoon.ui:toggle_quick_menu(harpoon:list()) end)
for i = 1, 4 do
vim.keymap.set('n', '<leader>' .. i, function() harpoon:list():select(i) end)
end
end,
}
Если не хочется ставить плагин, ту же задачу частично решают глобальные метки (заглавные A-Z), которые мы подробно разбирали в главе 9. Они работают между файлами и сохраняются в shada между сессиями. Поставить mA на файл, прыгнуть к нему 'A из любого места проекта - вот и закладка без зависимостей. Плагины recall.nvim и marks.nvim делают этот механизм нагляднее.
Лучшие практики 2026
- netrw - навык выживания, не основной инструмент. Знай :Ex, :Vex и клавишу - назубок для работы на серверах и в контейнерах, но в рабочем конфиге Neovim ставь oil.nvim (или mini.files/neo-tree по вкусу) с явным default_file_explorer = true.
- Редактируй ФС как текст. oil.nvim превращает массовые файловые операции в редактирование буфера, где работают :substitute, визуальный блок и макросы. Это его ключевое преимущество перед tree-сайдбаром.
- Один префикс для всего поиска. Вешай find_files/live_grep/buffers на <leader>f-префикс с понятными desc - их подхватит which-key (см. главу 21) и покажет подсказку.
- Ставь нативный матчер. Для Telescope добавляй telescope-fzf-native (build = 'make') - он заметно ускоряет сортировку. fzf-lua быстр сам по себе.
- Выбирай пикер под себя. Нужна богатая экосистема расширений - Telescope. Гигантские монорепы и максимальная скорость - fzf-lua. Минимализм, frecency и единый мета-плагин - snacks.picker.
- harpoon для "рабочего набора", fuzzy для "всего остального". Закладывай 4-5 файлов активной задачи в harpoon, а редко открываемое ищи через find_files.
- live_grep вместо ручного :grep. Для интерактивного поиска по содержимому пикер удобнее; для пакетной правки результатов - quickfix и :cfdo (глава 14) или grug-far.nvim (глава 11).
- Знай :find и path как запасной аэродром. На машине без плагинов set path=.,,** + :find + gf закрывают базовую навигацию.
- Забыть default_file_explorer = true у oil.nvim. Тогда netrw продолжает перехватывать каталоги, и поведение становится непредсказуемым: часть путей открывает oil, часть - netrw.
- Полагаться на безвозвратное удаление в oil. По умолчанию delete_to_trash = false. Включи корзину, чтобы dd по строке файла не уничтожал данные навсегда.
- Ставить ** в path на гигантском монорепо. Рекурсивный обход может ощутимо тормозить :find. На больших проектах лучше fuzzy-finder с ripgrep, который уважает .gitignore.
- Переход на snacks.picker "наполовину". Если не отключить старые пикеры и их кеймапы и не добавить snacks_picker_input в игнор автодополнения - получишь двойные бинды и конфликты.
- Путать harpoon и "недавние файлы". harpoon - это ручной фиксированный список под текущую задачу. Список "recent"/oldfiles меняется сам и для постоянных закладок не годится.
- Открыть netrw и не знать, как выйти. В netrw нет "своего" способа закрытия - это обычный буфер. Используй :bd, <C-^> (вернуться к предыдущему буферу) или просто открой другой файл.
- Искать файл fuzzy-finder'ом по содержимому. find_files ищет по имени/пути, а live_grep - по тексту внутри. Перепутав их, не найдёшь то, что ищешь.
- Удивляться, что find_files "не видит" .env и заигнорированные файлы. По умолчанию пикеры уважают .gitignore и прячут скрытые файлы. Нужны они - добавь hidden = true / no_ignore = true (в snacks - ignored = true) или используй git_files для файлов под контролем git.
- netrw вслепую. Запусти nvim . в каком-нибудь проекте. Не пользуясь мышью и fuzzy-поиском, дойди до файла в третьем уровне вложенности через Enter/-, создай рядом новый файл клавишей %, затем удали его (D). Цель - уверенно ориентироваться там, где нет плагинов.
- Рефакторинг через oil. Установи oil.nvim. Открой каталог, переименуй два файла через cw и удали один через dd, затем примени всё одним :w. Убедись, что oil показал план операций перед подтверждением.
- Три операции пикера. Настрой Telescope (или fzf-lua/snacks.picker) на <leader>ff, <leader>fg, <leader>fb. Найди файл, которого ты не помнишь по имени; найди по содержимому строку с конкретным словом; переключись между двумя открытыми буферами. Засеки, насколько это быстрее дерева файлов.
- Нативный :find. Добавь set path=.,,** (через vim.opt.path), затем открой файл через :find с Tab-дополнением и через gf, наведя курсор на путь в коде. Сделай это без единого плагина-пикера.
- harpoon под задачу. Выбери реальную задачу, затрагивающую 4 файла. Заброси их в harpoon (<leader>a), затем в течение работы переключайся между ними только по <leader>1...<leader>4. Сравни с привычным способом навигации.
- Закладки без плагинов. Повтори предыдущее упражнение, но на глобальных метках: поставь mA-mD на четыре файла и прыгай по 'A-'D. Это покажет, насколько harpoon удобнее - и где хватает встроенного механизма.
- netrw (:Ex/:Sex/:Vex, клавиша -) - встроенный файловый менеджер, есть везде; незаменим на серверах, но архаичен - в рабочем Neovim его заменяют.
- oil.nvim реализует мощную идею: директория - это буфер, а файловые операции - редактирование текста с применением по :w. Включай default_file_explorer = true и delete_to_trash = true.
- Fuzzy-finder (Telescope / fzf-lua / snacks.picker) находит файлы по фрагментам имени. Три ключевые операции - find_files, live_grep, buffers - вешай на <leader>f-префикс. Подробное сравнение пикеров - в главе 28.
- Встроенные :find + path (set path=.,,**) и gf/<C-w>f дают навигацию без плагинов - запасной вариант для голой машины.
- harpoon держит короткий ручной список "горячих" файлов задачи с прыжками по <leader>1...4; нативная альтернатива - глобальные метки A-Z (глава 9).