Здесь вы не найдёте новых команд (почти). Вместо этого мы соберём изученное в боевые воркфлоу-рецепты, разберём тренажёры для целенаправленной прокачки, выстроим поэтапный план обучения на месяцы вперёд и обсудим, как замерять прогресс, не выгорая. Это глава-навигатор: она показывает, что осваивать, в каком порядке и как не утонуть в возможностях редактора, у которого их буквально тысячи.
Зачем нужны рецепты, а не отдельные команды
Главная ошибка новичка - учить команды списком, как словарные слова. Но сила Vim в композиции: оператор плюс движение даёт команду, а знание N движений и M операторов даёт вам NxM команд (подробнее в главе 5). Реальная продуктивность рождается не из количества выученных комбинаций, а из умения на лету собрать нужную команду под конкретную задачу.
Рецепт - это собранный паттерн под класс задач: "массово переименовать символ во всём проекте", "вычистить логи от шума", "переставить колонки в CSV". Запомнив рецепт, вы запоминаете не клавиши, а способ мышления: какой инструмент Vim соответствует какой форме задачи. Дальше клавиши подтягиваются сами.
Рецепт 1. Рефакторинг в одном файле через cgn
Классический сценарий: переименовать переменную count в total по всему файлу, но выборочно - не везде, а с визуальным контролем каждого вхождения. Многие тянутся к :%s/count/total/gc с подтверждением. Есть способ изящнее и повторяемее - связка поискового паттерна, cgn и точки-команды (главы 7 и 11).
gn - это движение/текстовый объект "следующее совпадение текущего поискового паттерна". cgn меняет это совпадение, а . повторяет правку для следующего - без флага c, полностью под вашим контролем.
Важная тонкость механики: gn оперирует совпадением под курсором (если курсор стоит на совпадении - gn выделяет именно его, см. :help gn). А * не просто задаёт паттерн - он ещё и прыгает на следующее совпадение. Поэтому если нажать * со слова и сразу cgn, поправится не то слово, на котором вы стояли, а то, куда * увёл курсор. Чтобы поправить слово под курсором, паттерн нужно задать без перемещения - через :let @/=... (ровно это делает маппинг ниже).
Код: Выделить всё
Было: let count = items.count; // count growing
Курсор на ПЕРВОМ count. Задаём паттерн БЕЗ перемещения курсора:
:let @/='\<count\>'<CR> (курсор остался на первом count)
Нажимаем: cgn -> печатаем total -> <Esc>
Стало: let total = items.count; // count growing
Дальше: n чтобы перейти к следующему совпадению, или . чтобы заменить его
Канонический маппинг как раз и задаёт паттерн без перемещения курсора (берёт слово, ставит его как паттерн с границами \<...\> и сразу меняет совпадение под курсором):Если бы мы вместо этого нажали *, курсор прыгнул бы на count внутри items.count, и cgn поправил бы именно его (let count = items.total;). Поэтому для правки слова под курсором задавайте паттерн без прыжка - * подходит, только если вы готовы начать правки со следующего совпадения.
Код: Выделить всё
nnoremap <Leader>c :let @/='\<'.expand('<cword>').'\>'<CR>cgn
xnoremap <Leader>c "sy:let @/=@s<CR>cgn
Подводный камень: cgn опирается на "последний поисковый паттерн" (@/). После холодного старта без заданного @/ поведение неинтуитивно. Всегда задавайте паттерн через *, / или маппинг перед cgn.
Рецепт 2. Многофайловый рефакторинг через quickfixПодводный камень (wrapscan): gn (а значит и прогон cgn + .) ищет совпадения по всему буферу и при включённой по умолчанию опции 'wrapscan' заворачивает поиск в начало файла, дойдя до конца. При невнимательном долбёжке . это может зациклить вас на уже исправленных строках и привести к повторным/лишним правкам. Чтобы правки шли строго от курсора до конца файла и останавливались там, временно отключите заворот: :set nowrapscan (вернёте :set wrapscan). Так после последнего совпадения gn честно сообщит "pattern not found" вместо тихого прыжка в начало.
Когда правка не помещается в один файл, в дело вступает quickfix (глава 14). Рабочий конвейер 2026: наполнить quickfix поиском через ripgrep, при необходимости сузить список, затем прогнать замену по файлам.
Сначала настройте grepprg под ripgrep - это даёт быстрый, .gitignore-aware поиск с разбираемым форматом:
Код: Выделить всё
set grepprg=rg\ --vimgrep\ --no-heading\ --smart-case
set grepformat=%f:%l:%c:%m
Код: Выделить всё
:grep! 'getUserName' " ! - не прыгать сразу на первый результат
:copen " открыть окно quickfix, осмотреть
:packadd cfilter " подключить встроенный фильтр (Vim/Neovim)
:Cfilter /src/ " оставить только записи из src/ (по имени файла и тексту)
:cfdo s/getUserName/getDisplayName/ge | update
Код: Выделить всё
Команда | Что делает | Грабли
-------------+---------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------+---------------------------------------------------------------------------
:cdo {cmd} | выполняет {cmd} на каждую запись quickfix | для s///g обработает файл с N совпадениями N раз
:cfdo {cmd} | выполняет {cmd} один раз на файл | правильный выбор для :substitute с флагом g
s///ge | флаг e подавляет ошибку "pattern not found" | без e :cfdo упадёт на первом файле без совпадения
\ | update | сохраняет изменённый буфер | :cfdo не сохраняет автоматически - без \ | update изменения останутся в незаписанных буферах и потеряются при выходе
set hidden | разрешает уход из изменённого буфера без записи | без 'hidden' переход :cfdo/:cdo к следующему файлу при несохранённых правках в текущем падает с ошибкой E37: No write since last change
Рецепт 3. Прогон макроса по совпадениям через :global и :normal
Иногда правка слишком сложна для :substitute - нужна последовательность действий на каждой подходящей строке. Здесь связка :global + :normal (главы 12 и 16) часто чище рекурсивного макроса, потому что диапазон задаётся декларативно, а не "до первой ошибки".
Код: Выделить всё
" Записали макрос в регистр q, который правит одну строку
" Прогнать его только на строках со словом TODO:
:g/TODO/normal @q
" Или на каждой строке буфера:
:%normal @q
" Или на визуальном выделении:
:'<,'>normal @q
Код: Выделить всё
" Вариант через :global + :normal:
:g/error/normal I"<C-v><Esc>A"
" Вариант через :substitute (без макроса), где & - весь матч:
:g/error/s/.*/"&"/
Код: Выделить всё
Идиома | Эффект
----------------------+----------------------------------------
:g/pat/d | удалить все строки с паттерном
:v/pat/d (:g!/pat/d) | удалить все строки кроме совпадающих
:g/pat/m$ | собрать все совпадения в конец файла
:g/pat/t. | продублировать каждую совпавшую строку
:g/pat/normal @q | прогнать макрос по совпадениям
Колоночные данные - вотчина визуального блочного режима <C-v> (глава 17) и счётчиков. Допустим, нужно добавить префикс к каждой строке или поправить третью колонку.
Код: Выделить всё
Добавить // в начало 10 строк:
<C-v> -> 9j (выделяем колонку нулевой ширины на 10 строк)
-> I// -> <Esc> (вставка применится ко всем строкам)
Было: Стало:
name,age,city // name,age,city
alice,30,boston // alice,30,boston
Код: Выделить всё
Поменять местами первую и вторую колонки:
:%s/\v^([^,]+),([^,]+)/\2,\1/
Было: alice,30,boston -> Стало: 30,alice,boston
Код: Выделить всё
:%s/\v\d+/\=submatch(0)*2/g
Было: qty: 5, price: 10 -> Стало: qty: 10, price: 20
Логи - это много шума и редкие важные строки. Инструменты: :global/:vglobal для фильтрации, fold для сворачивания, :sort для группировки.
Код: Выделить всё
Оставить только строки с ERROR и WARN, удалив остальное:
:v/\v(ERROR|WARN)/d
Удалить timestamp-префикс у всех строк:
:%s/\v^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} //
Найти и собрать все уникальные коды ошибок:
:sort u (после извлечения нужного столбца)
Рецепт 6. Массовые правки "на расстоянии" с точкой-командой
Самый недооценённый рецепт - превратить серию однотипных правок в "один штрих + N точек". Ключ - выбирать текстовые объекты (ciw, ci", cit), а не движения (cw, ct"), потому что объекты курсор-независимы и . ведёт себя предсказуемо (главы 6 и 7).
Код: Выделить всё
Задача: во всех вызовах заменить аргумент в первых скобках на новое значение.
Меняем содержимое первых скобок:
ci( -> печатаем новое -> <Esc>
Прыгаем к следующему вызову: f( (или n по паттерну)
Жмём: . (повторяет ci( с тем же текстом)
Тренажёры: где целенаправленно прокачиваться
Реальная работа - лучший тренажёр, но у неё есть слепые зоны: вы используете то, что уже умеете, и не выходите из зоны комфорта. Специализированные тренажёры закрывают конкретные пробелы.
Код: Выделить всё
Тренажёр | Что тренирует | Формат
----------------------------+-----------------------------------------------------------+-------------------------------------------------
vimtutor | базовые движения и операторы | встроенная команда, ~30 мин, обязательный старт
vim-be-good (ThePrimeagen) | дрилл motion, относительных прыжков, удалений | Neovim-плагин, игровой
VimGolf | минимизация числа нажатий, мышление "оператор + объект" | веб, vimgolf.com
Vim Adventures | базовая навигация через геймификацию | браузерная игра
openvim | интерактивный туториал в браузере | веб, без установки
vim-be-good - плагин, превращающий тренировку в мини-игры: "удали выделенную строку быстрее", "прыгни на нужную строку относительным счётчиком". Он целенаправленно ломает привычку зажимать j и заставляет считать строки.
VimGolf - челленджи "преврази текст A в текст B за минимум нажатий". Вы сравниваете решение с лучшими и подсматриваете элегантные приёмы. Это прокачивает именно мышление операторами и текстовыми объектами, а не зубрёжку.
Vim Adventures и openvim хороши на самом старте: они геймифицируют движения и не требуют установки. Но не задерживайтесь на них - они не покрывают реальную грамматику.
Важный принцип: тренажёры дополняют, но не заменяют ежедневную работу. Перенос motion-словаря во все инструменты (shell set -o vi, браузер с Vimium/Tridactyl, IDE с IdeaVim/vscode-neovim - глава 31) закрепляет навык быстрее, чем любой тренажёр, потому что вы тренируетесь весь день.
Поэтапный план обучения
Учить всё сразу - антипаттерн: навык не оседает. Работающая стратегия - осваивать слоями, где каждый следующий опирается на автоматизм предыдущего. Вот план на несколько месяцев.
Неделя 1-2: выживание и базовые движения
- Пройти vimtutor целиком.
- Цель: уверенно входить/выходить из режимов, двигаться hjkl, w/b/e, 0/$, gg/G, искать / и n/N.
- Базовое редактирование: i/a/o, x, dd, yy, p, u, <C-r>.
- Включить set number relativenumber и приучить себя к прыжкам <count>j/k.
- Запрет стрелок: nnoremap <Up> <Nop> и т.д. - болезненно, но работает.
- Освоить связку "оператор + движение": d, c, y, gU, gq в комбинации с w, $, }, f{char}.
- Текстовые объекты: iw/aw, i(/a(, i"/a", ip/ap, it/at. Это самый высокий по отдаче навык.
- Точка-команда . - сознательно искать возможности её применить.
- Установить hardtime.nvim, чтобы плагин ругался на спам hjkl и навязывал эффективные motion.
- :substitute с \v (very magic), группами и флагами.
- :global/:vglobal как движок пакетных правок.
- Регистры (глава 8): осознать "0 (последний yank), "_ (blackhole), "+ (системный буфер).
- Буферы, окна, вкладки (глава 13); базовый fuzzy-поиск файлов.
- Quickfix и :cfdo для проектных правок.
- Макросы: запись, @q, @@, прогон через :normal, рекурсивные макросы.
- Визуальный блочный режим <C-v> для колоночных правок.
- Метки и прыжки (глава 9): <C-o>/<C-i>, глобальные метки A-Z, g;/g,.
- Свёртки и встроенное автодополнение (глава 19).
- Собрать init.lua с разумными дефолтами (глава 20), задать leader в начале файла.
- Менеджер плагинов: lazy.nvim с lazy-loading, или присмотреться к встроенному vim.pack (Neovim 0.12) для минималистичных конфигов.
- Нативный LSP через vim.lsp.config/vim.lsp.enable (глава 25), Treesitter (глава 27), автодополнение blink.cmp (глава 26).
- Git внутри редактора, fuzzy-пикеры, отладка (главы 28-30).
Опытным Vim-пользователям мигрировать на Neovim без причины не обязательно: если конфиг работает - он работает. Разумная стратегия - Neovim там, где вы контролируете окружение, и сохранять беглость в Vim для серверов, где нельзя ставить софт (Vim легче по памяти и почти везде предустановлен).
Как замерять прогресс и не выгореть
Прогресс в Vim неочевиден: вы не получаете "уровней". Поэтому нужны искусственные ориентиры.
Метрики, которые работают:
- Правило 1-2 команды в неделю. Сознательно выбирайте одну-две новые команды и весь день ищите случаи их применить. К концу недели они становятся рефлексом. Это в разы эффективнее, чем зубрить десять команд разом.
- Замечайте боль. Если вы трижды за день сделали что-то неудобно (зажали j, выделяли мышкой, повторяли :%s руками) - это сигнал, что есть инструмент, который вы не используете. Боль - лучший указатель на следующий навык.
- VimGolf как бенчмарк. Раз в пару недель решите пару челленджей и сравните счёт со своим прошлым. Снижение числа нажатий - измеримый прогресс.
- Не пытайтесь освоить "весь Vim". Его невозможно знать целиком, и это нормально. 20% команд покрывают 80% задач.
- Не настраивайте конфиг бесконечно. "Configuration rabbit hole" - известная ловушка: вы тратите часы на тюнинг вместо работы. Возьмите готовый дистрибутив и правьте по мере реальной потребности.
- Давайте навыку осесть. После интенсивного изучения новой темы сделайте паузу на дни "просто работы", чтобы выученное закрепилось, прежде чем брать следующий слой.
- Помните про эргономику (глава 32): modal-редактирование снижает работу мышью, но без нейтральных запястий и микропауз перенапряжение всё равно копится. Прогресс в скорости не стоит RSI.
- Не воюйте с тем, что лучше делает специализированный инструмент. Для многофайлового find&replace в Neovim 2026 де-факто стандарт - grug-far.nvim (редактируемые результаты с синком в файлы), а не ручной :cfdo для каждой задачи. Но понимать :cfdo обязательно: это фундамент, на котором работает всё остальное, и единственный путь на голом Vim/сервере.
- Делайте свои правки повторяемыми. Предпочитайте cgn/. и текстовые объекты движениям - это делает . предсказуемым. Для кастомных маппингов на Neovim используйте нативный operatorfunc + g@ вместо зависимости от tpope/vim-repeat (глава 7).
- В скриптах фиксируйте магический режим. Любой нетривиальный паттерн начинайте с \v (или \V для почти-литералов). В Vimscript/Lua-генерации паттернов это обязательно, иначе он сломается у пользователя с нестандартной опцией magic.
- Сужайте перед массовой заменой. :Cfilter по quickfix безопаснее ручной чистки списка перед :cfdo. Используйте nvim-bqf для визуального контроля больших результатов.
- Используйте inccommand в Neovim (set inccommand=split) для живого предпросмотра :substitute - это снижает зависимость от флага c.
- Переносите навык во все среды. set -o vi в shell, Vimium/Tridactyl в браузере, IdeaVim/vscode-neovim в IDE с единым leader и набором маппингов = одна мышечная память, которая прокачивается весь день (глава 31).
- Зубрить команды списком вместо паттернов. Учите грамматику (оператор + объект), а не отдельные комбинации - иначе знание не масштабируется.
- Путать :cdo и :cfdo. Для s///g нужен :cfdo (раз на файл), иначе файл с N совпадениями обрабатывается N раз.
- Забывать | update после :cfdo/:cdo. Изменения остаются в незаписанных буферах. Без флага e в s///ge команда вообще упадёт на первом файле без совпадения.
- cgn без заданного паттерна. После холодного старта @/ пуст - задайте паттерн через * или маппинг.
- Учить всё сразу и выгорать. Берите 1-2 команды в неделю, давайте навыку осесть.
- Бесконечно настраивать конфиг вместо работы. Возьмите дистрибутив, правьте по реальной потребности.
- Считать тренажёры заменой работе. Они дополняют ежедневное использование, а не заменяют его.
- Рекурсивный макрос на непустом регистре. Перед записью очистите регистр (qaq), иначе при рекурсии выполнится старое содержимое (глава 16).
- Рефакторинг через cgn. Возьмите любой свой файл, выберите часто встречающееся имя переменной. Поставьте курсор на него и задайте паттерн без перемещения курсора - :let @/='\<имя\>'<CR> (или повесьте маппинг из рецепта). Затем cgn, впечатайте новое имя и пройдите по файлу, чередуя . (заменить) и n (пропустить). Помните: если задать паттерн через *, курсор прыгнет на следующее совпадение и правки начнутся с него. Цель - ни разу не использовать :%s.
- Многофайловая замена. В небольшом проекте настройте grepprg под ripgrep, выполните :grep! 'someFunction', откройте :copen, сузьте список через :Cfilter, затем :cfdo s/someFunction/newName/ge | update. Проверьте git diff, что заменилось ровно нужное.
- Макрос по паттерну. Возьмите список из 20 строк. Запишите макрос, который преобразует одну строку (например, оборачивает её в JSON-объект). Прогоните его двумя способами: :%normal @q и :g/pattern/normal @q. Сравните результат.
- CSV-перестановка. Создайте CSV из трёх колонок. Поменяйте местами первую и третью колонки одной командой :substitute с \v и группами. Затем удвойте все числа во второй колонке через \=submatch().
- Чистка лога. Скачайте или сгенерируйте лог-файл. Одной командой оставьте только строки ERROR/WARN, другой - удалите timestamp-префиксы. Включите inccommand=split и понаблюдайте за живым предпросмотром.
- План на неделю. Выпишите 2 команды, которыми вы пока не владеете уверенно (например, gn/cgn и :cfdo). Всю неделю сознательно ищите случаи их применить в реальной работе. В конце недели оцените, стали ли они рефлексом.
- Рецепты важнее команд. Запоминайте способ мышления "какой инструмент Vim под какую форму задачи", а клавиши подтянутся.
- Однофайловый рефакторинг - связка "паттерн без перемещения курсора" (:let @/=... или маппинг) + cgn + .: выборочно, с контролем, повторяемо, без флага c. Помните: * уводит курсор на следующее совпадение, а gn правит совпадение под курсором.
- Многофайловый рефакторинг - :grep! (ripgrep) -> :copen -> :Cfilter -> :cfdo s///ge | update. Помните: :cfdo (на файл), e (подавить ошибку), | update (сохранить). На современном Neovim для этого есть grug-far.nvim.
- Пакетные правки - :global/:vglobal + :normal @q; колоночные - <C-v>; трансформации - :substitute с \v, группами и \=submatch().
- Тренажёры - vimtutor (старт), vim-be-good (дрилл motion), VimGolf (минимизация нажатий), Vim Adventures/openvim (геймификация). Дополняют, но не заменяют ежедневную работу.
- План обучения - слоями: выживание -> грамматика и текстовые объекты -> поиск/замена/многофайловость -> автоматизация -> конфигурация и современный Neovim. 1-2 новые команды в неделю.
- Не выгорать - не учить всё сразу, не зарываться в конфиг, давать навыку осесть, беречь запястья.