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. Грамматика: учить надо не команды, а правила
Центральная идея всей статьи. Команда нормального режима — не «горячая клавиша», а предложение по формуле:
[счётчик] оператор [счётчик] движение_или_текстовый_объект
Вы учите операторы (глаголы) и движения (дополнения) по отдельности, а комбинации получаются сами — их произведение, а не сумма.
| Оператор | Значение | Пример | Движение | Куда | |
|---|---|---|---|---|---|
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, походили стрелками, исправили что-то в трёх местах и вышли — . повторит непредсказуемую кашу.
Реалистичный план обучения
- День 0:
vimtutorв терминале — 25–30 минут, поставляется с Vim, лучше ничего для старта нет. Пройдите дважды: сразу и через неделю. - Неделя 1: только режимы,
hjkl,i a o,:w :q,u. Больше ничего. - Недели 2–3:
w b e,f t,0 ^ $,gg G,dd yy p, поиск/ n *. - Неделя 4: осознанно связывать операторы с движениями —
dw,ci(,ct,,y}. - Месяц 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 трёхуровневая, и её путают чаще всего:
main.go"] end subgraph W2["Окно 2"] B2["Буфер 2
util.go"] end subgraph W3["Окно 3"] B1b["Буфер 1 снова
другая часть файла"] end end B1 -.-> F1[("Файл на диске
main.go")] B1b -.-> F1 B2 -.-> F2[("Файл на диске
util.go")]
Буфер — содержимое файла в памяти, существует даже если не виден. Окно — прямоугольник на экране, показывающий буфер; один буфер может быть виден в нескольких окнах. Вкладка — не «файл», как в браузере, а набор окон; это ломает интуицию у всех, кто пришёл из 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. Практика: что делать прямо сейчас
Три упражнения на реальном коде, не на тренажёре.
- Переименование без мыши. Найдите переменную через
*, переименуйте первое вхождение черезciw, пройдите остальные черезn+.. Засеките время, повторите завтра. Через неделю это быстрее IDE-рефакторинга для файла среднего размера. - Правки внутри скобок. Найдите вызов функции с тремя аргументами. Не двигая курсор точно, нажмите
ci(и наберите новые аргументы. Затемci"внутри строкового литерала, затемct,— переписать первый аргумент до запятой. Это три самые частые правки в коде, и все три — по три нажатия. - 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