Редакторы и IDE vi и Vim: модальность, основы, движения и первые 20 команд
0%

vi и Vim: модальность, основы, движения и первые 20 команд

vi и Vim: модальность, основы, движения и первые 20 команд

Vim — единственный массовый редактор, у которого есть грамматика. Не набор горячих клавиш, которые надо зазубрить, а маленький язык: глаголы, дополнения, числительные. Выучив десяток символов, вы получаете сотни осмысленных комбинаций — включая те, которые никто специально не программировал. Это главная причина, по которой сорокалетний редактор до сих пор жив, а его раскладку копируют VS Code, JetBrains, Zed, Obsidian и браузеры.

Разберём, откуда взялась модальность (и почему это не историческая случайность), как устроены режимы, как читать команду вроде 2d3w, какие 20 команд закрывают 80 % работы, как выглядит честный минимальный .vimrc — и разберём настоящую публичную конфигурацию вместе с её ошибками. Без фанатизма: в конце прямой разговор о том, где Vim проигрывает и когда его брать не надо. Обзор трека — в карте трека.


1. Откуда взялась модальность: 300 бод и телетайп

  • 1969, ed. Кен Томпсон пишет строчный редактор для Unix. Экрана нет — телетайп печатает на бумаге. Вы не «видите» файл, а задаёте ему вопросы: 1,5p — напечатай строки 1–5, s/foo/bar/ — замени. Команды короткие, потому что каждый символ физически стучит по бумаге.
  • 1976, ex. Билл Джой в Беркли расширяет ed. Появляется visual mode — команда :visual, рисующая содержимое файла на экране видеотерминала целиком.
  • 1978, vi. Visual mode отделяется в отдельную программу и попадает в BSD. Ключевое ограничение: терминал соединён с машиной на 300–1200 бод, перерисовка экрана стоит секунды. Значит, команды должны быть предельно короткими, а редактор — перерисовывать минимум.

Отсюда два решения, странные сегодня и логичные тогда. Во-первых, никаких модификаторов: Ctrl/Alt-аккорды на терминалах были неудобны и непереносимы, значит команда — обычная буква. Но если буквы это команды, куда девать ввод текста? В отдельный режим. Во-вторых, hjkl вместо стрелок: на клавиатуре ADM-3A, за которой работал Джой, стрелки были нарисованы прямо на клавишах H, J, K, L, а Escape стоял там, где сегодня Tab.

Модальность родилась из ограничения полосы пропускания. Но у неё оказался побочный эффект, переживший причину: если буквы — команды, их можно комбинировать по правилам языка. Это и оказалось главным.

vi и Vim — не синонимы. vi стандартизирован в POSIX (спецификация) — это минимум, который вы найдёте на любом сервере, в busybox, в спасательном initramfs. Vim — надмножество. Всё из разделов 2–6 работает в обоих; всё про плагины и Plug — только Vim/Neovim.


2. Пять режимов и как между ними не заблудиться

Главная причина, по которой новички бросают Vim в первые 20 минут, — они не понимают, в каком режиме находятся, и нажимают буквы, которые молча портят файл.

Режим Как войти Что делает Как понять, что вы в нём
Normal Esc Буквы — команды, а не текст Курсор блок, внизу пусто
Insert i a I A o O Печатаете текст Внизу -- INSERT --
Visual v / V / Ctrl-v Выделяете символы / строки / прямоугольник -- VISUAL --, -- VISUAL LINE --
Command-line : / ? Ex-команды и поиск Курсор в нижней строке
Replace R Печать поверх, как Insert на клавише -- REPLACE --

Три правила выживания. Normal — это дом, а не «режим команд, куда иногда выходят»: отредактировали слово — Esc. Привычка сидеть в Insert «чтобы быстрее» ломает всё остальное — точку ., счётчики, макросы. Esc всегда возвращает домой: потерялись — нажмите два-три раза. Ничего не надо сохранять «на всякий случай»: u откатывает, Ctrl-r возвращает, а история отмен в Vim — дерево, а не список (см. продвинутый Vim).

Сразу настройте Esc по-человечески. Тянуться мизинцем в угол клавиатуры сотни раз в час — реальная нагрузка на кисть. Варианта два: переназначить Caps Lock в Escape на уровне ОС (setxkbmap -option caps:escape, Karabiner на macOS, PowerToys на Windows) либо добавить inoremap jk <Esc> в конфиг. Первый лучше — он работает везде, включая less, psql и чужие машины по SSH.


3. Грамматика: учить надо не команды, а правила

Центральная идея всей статьи. Команда нормального режима — не «горячая клавиша», а предложение по формуле:

[счётчик] оператор [счётчик] движение_или_текстовый_объект

Грамматика команды нормального режима Vim

Вы учите операторы (глаголы) и движения (дополнения) по отдельности, а комбинации получаются сами — их произведение, а не сумма.

Оператор Значение Пример Движение Куда
d delete — удалить в регистр dw — удалить слово h j k l влево, вниз, вверх, вправо
c change — удалить и войти в Insert cw — переписать слово w b e начало след./пред. слова, конец слова
y yank — скопировать y$ — до конца строки W B E то же, но «слово» = кусок без пробелов
> < сдвинуть отступ >ap — сдвинуть абзац 0 ^ $ начало / первый непробел / конец строки
gU gu в верхний/нижний регистр gUiw — СЛОВО КАПСОМ gg G {n}G начало / конец файла / строка n
= переформатировать отступы =G — до конца файла f{c} t{c} на символ {c} / до символа {c}
gq переразбить по textwidth gqip — абзац { } % пред./след. пустая строка, парная скобка

Движения курсора внутри строки

Разница f и t — ключевая. f) ставит курсор на скобку, t)перед ней. Значит dt) удалит содержимое до скобки, оставив её, а df) съест и скобку. Повторить последний f/t; вперёд, , назад.

Прочитайте как предложения — ни одна из этих комбинаций не «запрограммирована» отдельно, все выводятся из правил:

d2w      удалить 2 слова           >4j      сдвинуть текущую и 4 строки ниже вправо
c$       переписать до конца строки d/foo    удалить всё от курсора до первого foo
y}       копировать до пустой строки ct,     переписать всё до ближайшей запятой

Именно это отличает Vim от Emacs и VS Code, где Ctrl-Shift-K — атомарная неразложимая сущность, которую можно только запомнить.

Текстовые объекты: «внутри» и «вокруг»

Второй уровень грамматики — вместо движения подставить текстовый объект: оператор + [i|a] + объект, где i = inner (внутри, без границ), a = around (вместе с границами и пробелом).

Команда Что делает Команда Что делает
ciw переписать слово под курсором ci{ / ciB переписать тело блока {...}
ci" переписать строковый литерал, кавычки останутся dap удалить абзац вместе с пустой строкой
ci( / cib переписать содержимое круглых скобок dit удалить содержимое HTML/XML-тега

Магия ci( в том, что курсор может стоять где угодно внутри скобок — Vim сам найдёт границы. Ради этого люди ставят Vim-режим в JetBrains и VS Code: «переписать аргументы функции» в обычном редакторе — точный двойной клик, протаскивание мышью и молитва, а тут три символа из домашнего ряда.


4. Первые 20 команд: минимальный рабочий набор

Не «список всех команд Vim», а честный минимум, после которого можно работать и не бояться.

# Команда Что делает Комментарий
1 i / a вставка перед / после курсора a = append, нужен чаще, чем i
2 I / A вставка в начало / конец строки заглавная = «усиленная» версия
3 o / O новая строка ниже / выше + Insert самый частый способ добавить код
4 Esc вернуться в Normal или Caps Lock, если перевесили
5 h j k l курсор влево/вниз/вверх/вправо не отучайтесь от стрелок насильно
6 w / b / e по словам вперёд / назад / к концу слова основа быстрой навигации
7 0 / ^ / $ начало / первый непробел / конец строки
8 gg / G начало / конец файла 42G или :42 — на строку 42
9 Ctrl-d / Ctrl-u полэкрана вниз / вверх глаза не теряют контекст
10 x / D удалить символ / до конца строки D эквивалентно d$
11 dd / yy удалить / скопировать строку удвоенный оператор = «на строку»
12 p / P вставить после / до курсора строчный yank вставляется новой строкой
13 u / Ctrl-r undo / redo
14 . повторить последнее изменение самая недооценённая клавиша Vim
15 /шаблон ?шаблон поиск вперёд / назад n / N — следующее / предыдущее
16 * искать слово под курсором мгновенный «где ещё это используется»
17 v / V / Ctrl-v визуальное выделение символы / строки / блок
18 :w :q :wq :q! сохранить / выйти / оба / выйти без сохранения ZZ = :wq, ZQ = :q!
19 :%s/old/new/g заменить во всём файле добавьте c в конец — с подтверждением
20 ciw ci" ci( переписать слово / литерал / аргументы текстовые объекты

Точка . — то, из-за чего Vim быстрый

. повторяет последнее изменение (не движение и не команду :). Это превращает редактирование в цикл «сделал один раз — размножил»:

" Задача: во всём файле заменить strcpy( на safe_strcpy(
/strcpy(      " находим первое вхождение
cw            " переписываем слово
safe_strcpy   " печатаем новое
<Esc>         " возвращаемся в Normal
n             " следующее вхождение
.             " повторить изменение
n . n . n .   " дальше — по две клавиши на замену

Почему не :%s/strcpy(/safe_strcpy(/g? Потому что глобальная замена слепа: заденет my_strcpy(, строку в комментарии и текст в тесте. Связка n + . даёт замену с визуальным контролем каждого случая при почти той же скорости. Это очень частый паттерн: массовое, но не безусловное изменение.

Отсюда правило: делайте изменения повторяемыми. cw + текст + Esc — одно изменение, . его повторит. А если вы вошли в Insert, походили стрелками, исправили что-то в трёх местах и вышли — . повторит непредсказуемую кашу.

Реалистичный план обучения

  1. День 0: vimtutor в терминале — 25–30 минут, поставляется с Vim, лучше ничего для старта нет. Пройдите дважды: сразу и через неделю.
  2. Неделя 1: только режимы, hjkl, i a o, :w :q, u. Больше ничего.
  3. Недели 2–3: w b e, f t, 0 ^ $, gg G, dd yy p, поиск / n *.
  4. Неделя 4: осознанно связывать операторы с движениями — dw, ci(, ct,, y}.
  5. Месяц 2: точка, счётчики, свой минимальный .vimrc. Месяц 3+: регистры, макросы, буферы, quickfix.

Две вещи ускоряют кривую радикально. Не ставьте плагины первый месяц — соблазн собрать «IDE на Neovim» в первый день главная причина, по которой время уходит в конфиг вместо навыка; плагины закроют базовые механики, и вы не поймёте, что редактор уже умеет сам. И не запрещайте себе стрелки: популярный совет nnoremap <Up> <NOP> — вредный догматизм, стрелки отомрут сами за две недели, потому что w/b объективно быстрее.

Честная оценка стоимости: первые 2–3 недели вы будете медленнее на 20–40 %. Возврат к прежней скорости — месяц ежедневной работы, ощутимый выигрыш — 2–3 месяца. Не готовы к этому провалу — это нормальная причина взять Vim-режим в текущей IDE вместо полного переезда (раздел 8).


5. Поиск, замена и Ex-команды

Vim унаследовал от ed целый пласт строчных команд с синтаксисом :[диапазон]команда[аргументы][флаги].

Команда Что делает
:s/old/new/g заменить все вхождения в текущей строке
:%s/old/new/gc во всём файле (% = 1,$), с подтверждением каждого
:10,20s/old/new/g только в строках 10–20
:'<,'>s/old/new/g только в визуальном выделении (диапазон подставляется сам)
:g/TODO/d удалить все строки, содержащие TODO
:v/foo/d удалить все строки, не содержащие foo
:g/pattern/normal @q выполнить макрос q на каждой подходящей строке
:r file / :r !date вставить содержимое файла / вывод shell-команды
:!make test выполнить команду оболочки

:g (global) — недооценённый инструмент: :g/^\s*$/d удаляет все пустые строки, :g/console\.log/d вычищает отладку. В связке с макросами он заменяет одноразовые скрипты на sed.

set ignorecase   " поиск без учёта регистра...
set smartcase    " ...но если в запросе есть заглавная — регистр учитывается
set incsearch    " подсвечивать совпадение по мере набора
set hlsearch     " подсвечивать все совпадения

ignorecase + smartcase — очень удачная эвристика: /user найдёт и User, и USER, а /User — только точное совпадение. Ровно так работает поиск в современных IDE; Vim умел это в 1996 году.


6. Файлы, буферы и окна — необходимый минимум

Модель Vim трёхуровневая, и её путают чаще всего:

Буфер — содержимое файла в памяти, существует даже если не виден. Окно — прямоугольник на экране, показывающий буфер; один буфер может быть виден в нескольких окнах. Вкладка — не «файл», как в браузере, а набор окон; это ломает интуицию у всех, кто пришёл из VS Code.

:e file.go       " открыть файл в текущем окне
:ls              " список буферов
:b 3 / :b util   " перейти к буферу по номеру или подстроке имени
:bn :bp :bd      " следующий / предыдущий / закрыть буфер

:sp file.go      " горизонтальное разделение
:vs file.go      " вертикальное разделение
Ctrl-w h/j/k/l   " перемещение между окнами
Ctrl-w =         " выровнять размеры
Ctrl-w o         " закрыть все окна кроме текущего

:tabnew file.go  " новая вкладка
gt / gT          " следующая / предыдущая вкладка

Типичная ошибка новичка — работать через вкладки, потому что это похоже на привычный редактор. Идиоматичный Vim: много буферов, мало окон, вкладки только под разные задачи (например, «код» и «тесты»). Переключение через :b имя с автодополнением быстрее любых вкладок. Полный разбор — в следующей статье.


7. Минимальный .vimrc, который не стыдно

Конфиг, который я бы дал человеку на второй месяц: ни одного плагина, но Vim заметно приятнее. Каждая строка объяснена — если вы не можете объяснить строку в своём конфиге, её там быть не должно.

" ~/.vimrc — минимальный рабочий конфиг без плагинов
set nocompatible          " не притворяться настоящим vi (в Neovim не нужно)
filetype plugin indent on " подсветка и отступы по типу файла
syntax enable
set encoding=utf-8

" --- Интерфейс --------------------------------------------------------
set number relativenumber " абсолютный номер текущей строки + относительные вокруг
set cursorline            " подсветка текущей строки
set scrolloff=5           " не подпускать курсор ближе 5 строк к краю экрана
set signcolumn=yes        " колонка знаков всегда видна — текст не «прыгает»
set laststatus=2          " статусная строка всегда
set showcmd               " показывать набираемую команду в углу
set wildmenu wildmode=longest:full,full   " визуальное автодополнение команд по Tab

" --- Поиск и отступы --------------------------------------------------
set ignorecase smartcase
set incsearch hlsearch
nnoremap <Esc><Esc> :nohlsearch<CR>   " двойной Esc гасит подсветку поиска
set expandtab tabstop=4 shiftwidth=4 softtabstop=4
set autoindent smartindent

" --- Файлы и надёжность ----------------------------------------------
set hidden                " можно уйти из изменённого буфера, не сохраняя
set autoread              " перечитывать файл, изменённый снаружи
set undofile              " ПОСТОЯННАЯ история отмен — переживает перезапуск
set undodir=~/.vim/undo// " не забудьте: mkdir -p ~/.vim/undo
set noswapfile            " осознанный выбор: нет .swp-мусора, есть undofile
set backupcopy=yes        " не ломать симлинки и inotify-вотчеры сборщиков

" --- Мелочи, которые реально экономят время --------------------------
set clipboard=unnamedplus " y/p работают с системным буфером (нужен +clipboard)
set mouse=a               " мышь работает: не стыдно, удобно при ресайзе окон
set splitbelow splitright " новые окна открываются там, где ожидаешь
set timeoutlen=500        " сколько ждать продолжения последовательности клавиш
set ttimeoutlen=10        " а Esc-последовательности терминала — почти мгновенно

" --- Немного маппингов (без фанатизма) -------------------------------
let mapleader = " "                      " пробел — удобнейший лидер
nnoremap <leader>w :w<CR>
nnoremap <leader>b :ls<CR>:b<Space>      " быстрый переход по буферам
nnoremap <C-h> <C-w>h
nnoremap <C-j> <C-w>j
nnoremap <C-k> <C-w>k
nnoremap <C-l> <C-w>l

" Поиск файлов без плагинов: :find по дереву проекта
set path+=**
set wildignore+=**/node_modules/**,**/.git/**,**/dist/**
nnoremap <leader>f :find<Space>

" Возврат на позицию, где закрыли файл
autocmd BufReadPost * if line("'\"") > 0 && line("'\"") <= line("$")
      \ | exe "normal! g`\"" | endif

Две настройки чаще всего понимают неправильно. undofile — вероятно, самая ценная строка: Vim хранит дерево отмен на диске, и u работает между сессиями — закрыли файл, вернулись через неделю, откатили изменение; ни в одном популярном редакторе такого нет из коробки. ttimeoutlen объясняет, почему Esc иногда «залипает» на полсекунды: терминал передаёт функциональные клавиши escape-последовательностями, начинающимися с того же байта, и Vim ждёт, не придёт ли продолжение. Значение 10 убирает лаг, не ломая распознавание клавиш.

vim --version | head -3          # версия и дата сборки
vim --version | grep clipboard   # +clipboard или -clipboard?
vim --startuptime /tmp/vim.log +q && sort -k2 -nr /tmp/vim.log | head -20

Последняя команда — профилирование запуска. Ориентир: чистый Vim стартует за 20–40 мс, конфиг с десятком разумных плагинов — 80–150 мс, всё, что дольше 300 мс, стоит разбирать.


8. Разбор реальной публичной конфигурации

Полезнее абстрактных советов — живой .vimrc, которым человек реально пользуется каждый день. Возьмём публичный репозиторий github.com/the-homeless-god/Dotfiles. Это не эталон, а нормальная рабочая конфигурация, выросшая органически. Именно поэтому она поучительна: у вас будет такая же через год.

Что там устроено

Dotfiles/
├── configs/              # собственно конфиги
│   ├── .vimrc            # ~1000 строк
│   ├── .zshrc  .gitconfig  .editorconfig
│   ├── .alacritty.toml   # терминал
│   ├── .config/tmux/.tmux.conf
│   ├── .config/lf/lfrc   # файловый менеджер lf
│   ├── fonts/            # FiraCode + MesloLGS NF (нужны для иконок и powerline)
│   └── tools.json        # декларативный список инструментов
├── scripts/
│   ├── install-tools.sh  # установщик, есть режим --interactive
│   └── customs/rgfzf.sh  # свой скрипт ripgrep + fzf
├── ci/test-install.sh    # тест установки
├── Dockerfile            # окружение целиком воспроизводится в контейнере
└── .github/workflows/    # CI: сборка и публикация образа в ghcr.io

Три архитектурных решения стоит копировать независимо от содержимого конфигов. tools.json — декларативный манифест: список нужного софта вынесен из bash-скрипта в данные, скрипт становится тупым исполнителем, а список — читаемым и диффабельным. Dockerfile + CI: каждый push собирает образ и прогоняет установку, отвечая на вопрос «а мой setup вообще ставится на чистую машину?» — вопрос, на который у 95 % dotfiles-репозиториев ответ «не знаю». Шрифты лежат в репозитории — не «поставьте Nerd Font сами», а конкретные .ttf; мелочь, экономящая полчаса при переезде.

Сам .vimrc собран в трёх слоях: шпаргалка-комментарий на 50 строк в начале (все хоткеи списком), блок plug#begin/plug#end с плагинами и три функции — s:initVimVariables(), s:initVimStartup(), s:initVimHotkeys(), вызываемые в конце. Разделение «переменные / автокоманды / маппинги» здравое, а шпаргалка в шапке — отличная практика: конфиг документирует сам себя.

Философия заявлена прямо в комментариях: «сделать как VS Code». Отсюда <C-s> на сохранение, <C-z> на undo, <C-a> на «выделить всё», <C-p> на поиск файлов, контекстное меню по правой кнопке мыши через popup_menu() с пунктами «Перейти к определению» и «Переименовать символ», vim-visual-multi для мультикурсора.

Что перенять, а что нет

Стоит копировать: шпаргалку хоткеев в шапке файла (конфиг перестаёт быть write-only); vim-which-key — всплывающую подсказку по нажатию лидера, отличное решение проблемы «настроил 80 маппингов, помню 12»; undofile с undodir; интеграцию с внешними инструментами вместо плагинов-велосипедов — lf как файловый менеджер, ripgrep + fzf для поиска, floaterm как обёртка (редактор не обязан уметь всё сам); автосохранение сессий через vim-obsession/vim-prosession.

Перенимать не стоит — и это ровно те болезни, которые появятся у вас:

Проблема Что именно Почему плохо
Четыре движка автодополнения сразу YouCompleteMe, coc.nvim, asyncomplete, ale_completion_enabled=1 Конкурируют за <Tab> и <CR>, дублируют LSP-запросы, тормозят старт. Нужен один.
set paste в initVimVariables Классический капкан: глобально отключает все маппинги insert-режима, автоотступы и аббревиатуры. UltiSnips и coc после него просто не работают.
set hidden и set nohidden + bufhidden=wipe обе есть в файле Побеждает последняя и уничтожает буферы при уходе — ломая :b, buffergator и восстановление сессий, то есть ровно то, что настраивается рядом.
Конфликтующие маппинги <C-h> — то «окно влево», то :%s///g; <C-f> — то :Rg, то / Побеждает объявленный последним. Симптом: «клавиша делает не то». Диагностика — :verbose nmap <C-h>.
inoremap ( ()<Left> вместе с coc-pairs секция автопарности Два механизма дают (()). Нужен один.
set termwinsize = "10*0" initVimVariables Пробелы вокруг = в :set недопустимы, и формат значения неверный (нужно 10x0). Строка молча не работает.
set tabline=2 там же tabline — строка формата, а не число. Скорее всего имелось в виду showtabline=2.
Дубликаты плагинов и маппингов vim-floaterm и vim-fugitive объявлены дважды, <leader>f — трижды Работает последнее объявление; остальное — мёртвый код и сигнал, что файл давно не перечитывали целиком.

Отдельно про философию «сделать как VS Code». Это легитимный выбор, и называть его ересью я не буду: человеку удобнее, он продуктивен — вопрос закрыт. Но платят за него конкретной монетой. <C-z> вместо u делает неудобными счётчики (3u) и связку с точкой; <C-a> на «выделить всё» отбирает нативную и очень полезную команду «увеличить число под курсором». Копируя чужие маппинги, вы копируете и чужие компромиссы — часто не замечая, что именно потеряли.

Как читать чужие dotfiles

Правило: никогда не копируйте чужой .vimrc целиком — копируйте структуру и отдельные решения. Хороший тест: объясните вслух каждую строку своего конфига; всё, что не объяснили, удаляйте — если что-то сломается, вы заметите и вернёте осознанно.

Второе правило — nnoremap, а не nmap. map рекурсивно раскрывает правую часть через другие маппинги, давая неотлаживаемые циклы и сюрпризы после установки плагина. noremap — буквальная привязка. nmap легитимен ровно в одном случае: когда нужен <Plug>-маппинг плагина. Разбор современной конфигурации на Lua, с LSP и Treesitter — в статье про Neovim.


9. Честное сравнение: vi, Vim, Neovim, Vim-режим в IDE

Критерий POSIX vi Vim 9.x Neovim 0.11+ Vim-режим в IDE
Где есть везде, всегда почти везде ставится вручную VS Code, JetBrains, Zed
Плагины нет Vimscript/Lua, огромная экосистема Lua, современная экосистема ограниченный набор
LSP из коробки нет нет (нужен coc/ALE) да да — родной для IDE
Асинхронность нет с 8.0 да, дизайн-принцип да
Скриптовый язык ex-команды Vimscript / Vim9script Lua + Vimscript Kotlin/JS/…
Стоимость входа низкая средняя средняя + время на конфиг низкая
Рефакторинги уровня IDE нет ограниченно ограниченно да
Отладчик нет Termdebug DAP-плагины да, зрелый
Работа по SSH идеально идеально идеально нет

Vim/Neovim — правильный выбор, если много работы на удалённых машинах и в контейнерах; если работа идёт с текстом как таковым (логи, конфиги, миграции, markdown, массовые правки); если языки с лёгкой семантикой (Go, Python, Rust, C), где LSP закрывает почти всё; если настройка инструмента вам в удовольствие, а не в тягость.

Vim — неправильный выбор, если это крупный Java/Kotlin/C#-проект с тяжёлыми рефакторингами: IntelliJ и Rider делают «переименовать через 400 файлов с учётом рефлексии и Spring-конфигов» надёжнее любого LSP (см. про JetBrains). Или если нужен визуальный отладчик прямо сейчас, а не через два вечера настройки DAP. Или если в команде важнее общий setup и парное программирование. Или если дедлайн через неделю — учить Vim в этот момент прямой путь его сорвать.

Компромисс, который недооценивают: Vim-режим внутри IDE. IdeaVim в JetBrains, VSCodeVim в VS Code, встроенный vim mode в Zed покрывают 90 % описанного в этой статье — модальность, движения, операторы, текстовые объекты, точку, макросы. Вы получаете грамматику редактирования, не отказываясь от индексации, отладчика и рефакторингов. Для большинства работающих инженеров это объективно лучший размен, и признать это честнее, чем агитировать за «чистый Neovim» из принципа. Подробнее — в сравнении редакторов.


10. Типичные ошибки и как их лечить

Симптом Причина Лечение
«Не могу выйти из Vim» нажали : в Insert или застряли в Ex-режиме (Q) Esc, затем :q! (или visual + Enter из Ex)
Вставка кода «лесенкой» автоотступ сработал на каждой строке set clipboard=unnamedplus и "+p вместо Ctrl-V терминала
«Vim завис» нажали Ctrl-s — терминал остановил вывод Ctrl-q возобновляет; отключить: stty -ixon в .zshrc
E325: ATTENTION, swap-файл предыдущая сессия упала r — восстановить, сравнить с диском, удалить .swp; либо noswapfile + undofile
Esc «залипает» на полсекунды Vim ждёт продолжение escape-последовательности set ttimeoutlen=10
Стрелки печатают A B C D в Insert терминал шлёт escape-коды, нет nocompatible set nocompatible, проверить $TERM
Клавиша делает не то, что настроили конфликт маппингов :verbose nmap <C-h> покажет файл и строку победителя
Русский текст ломает команды в Normal раскладка переключена в ОС set keymap=russian-jcukenwin + set iminsert=0
y/p не работают с системным буфером сборка без +clipboard vim --version | grep clipboard; поставить vim-gtk3 или Neovim
Стартует секунду разросшийся конфиг vim --startuptime /tmp/vim.log +q, смотреть верх отсортированного лога

Отдельно про set paste: он выключает автоотступ, автопарность, аббревиатуры и все маппинги insert-режима. Это правильный инструмент ровно для одного случая — вставки текста средствами терминала в старом эмуляторе. Держать его постоянно в конфиге, как в разобранном выше репозитории, значит молча отключить половину собственных настроек. Современные терминалы поддерживают bracketed paste, а Vim 8+ и Neovim распознают его сами — set paste не нужен.


11. Практика: что делать прямо сейчас

Три упражнения на реальном коде, не на тренажёре.

  1. Переименование без мыши. Найдите переменную через *, переименуйте первое вхождение через ciw, пройдите остальные через n + .. Засеките время, повторите завтра. Через неделю это быстрее IDE-рефакторинга для файла среднего размера.
  2. Правки внутри скобок. Найдите вызов функции с тремя аргументами. Не двигая курсор точно, нажмите ci( и наберите новые аргументы. Затем ci" внутри строкового литерала, затем ct, — переписать первый аргумент до запятой. Это три самые частые правки в коде, и все три — по три нажатия.
  3. Ex-команды на логе. Удалите все строки уровня DEBUG: :g/DEBUG/d. Оставьте только ошибки: :v/ERROR/d. Обычно ради этого пишут одноразовый скрипт на awk — здесь 8 символов, и результат видно глазами.

Метрика прогресса, работающая лучше секундомера: сколько раз за день вы потянулись к мыши. В первую неделю — постоянно, к концу месяца — несколько раз. Когда рука перестаёт уходить с домашнего ряда, основная часть пути пройдена.


Мини-итог

  • Модальность появилась из-за терминалов на 300 бод, но выжила потому, что дала редактированию грамматику: [счётчик] оператор [счётчик] движение.
  • Учить надо слова языка: операторы (d c y > gU), движения (w b e f t 0 $ gg G), текстовые объекты (iw a" i( ap). Комбинации выводятся сами — их произведение, а не сумма.
  • Normal — состояние по умолчанию, Esc возвращает домой. Делайте изменения повторяемыми: тогда работает ., а это основной источник скорости.
  • Двадцати команд из раздела 4 хватает для полноценной работы. Плагины — не раньше второго месяца.
  • undofile, ignorecase+smartcase, hidden, ttimeoutlen — четыре настройки с лучшим отношением пользы к длине.
  • Чужие dotfiles читают, а не копируют. Разбор реального .vimrc показал типичный набор болезней: несколько движков автодополнения, set paste, противоречащие set-опции, конфликтующие маппинги. Теперь вы знаете симптомы.
  • Vim не обязателен. Vim-режим внутри IDE — честный и часто оптимальный компромисс.

Источники

  • vimtutor — встроенный интерактивный курс на 30 минут, запускается командой vimtutor в терминале.
  • Vim documentation online — вся справка в вебе; начните с usr_02.txt («The first steps in Vim») и usr_03.txt («Moving around»).
  • Bram Moolenaar. Seven habits of effective text editing — эссе автора Vim о том, как вообще думать об эффективности редактирования.
  • Drew Neil. Practical Vim, 2nd ed. — лучшая книга по Vim: 121 рецепт вокруг идеи повторяемых изменений и точки.
  • POSIX-спецификация vi — что гарантированно работает на любой Unix-машине.
  • vim-galore — открытый справочник с разбором частых недоразумений; Vim Cheat Sheet — компактная шпаргалка.
  • neovim.io/doc и :help vim_diff — чем Neovim отличается от Vim.
  • github.com/the-homeless-god/Dotfiles — разобранная в статье публичная конфигурация: .vimrc, zsh, tmux, alacritty, установщик и Docker-образ окружения.
  • Исходники Vim и vim.org — Vim распространяется как charityware в пользу ICCF Holland.

Что дальше

Мы разобрали грамматику и научились жить в Normal-режиме. Дальше — то, что превращает Vim из «быстрого редактора» в инструмент массовых преобразований текста: регистры (их десятки, и это не один буфер обмена), макросы как записанные программы, полный набор текстовых объектов, управление буферами и окнами и quickfix-список — механизм, связывающий Vim с компилятором, линтером и grep.

Продвинутый Vim: регистры, макросы, текстовые объекты, буферы, окна, quickfix

Нашли неточность? Выделите фрагмент текста — рядом появится жучок.

Нужен разбор именно вашей ситуации?

Статья описывает общий случай. Если у вас частный — можно разобрать его отдельно, платно. А если не хватает целого материала, предложите тему: её оплачивают вскладчину, и она выходит открытой для всех.

Доска запросов