Зачем это нужно? Каждый выход в нормальный режим и возврат обратно - это разрыв потока: руки уходят с домашнего ряда, фокус мысли смещается с "что я пишу" на "как я навигируюсь". Трюки insert-режима убирают этот разрыв для самых частых микрозадач. Набираете и поняли, что нужно вставить только что скопированное имя переменной? <C-r>0 - и продолжаете печатать. Опечатались в начале слова? <C-w> стирает слово целиком. Нужно дополнить длинное имя функции? <C-n> подберёт его из открытых буферов. Это не "продвинутая магия для гиков", а базовая гигиена эффективного ввода.
В этой главе мы пройдём весь арсенал: вставку регистров, одиночные команды нормального режима, удаление слов и строк, управление отписами, и главное - встроенное автодополнение с его подрежимом Ctrl-X. Завершим вводом спецсимволов через Ctrl-V и диграфы.
Вставка содержимого: <C-r> и его вариантыДоговоримся об обозначениях: <C-r> означает Ctrl+r. Большинство сочетаний этой главы работают в режиме вставки. Отдельно отметим: у <C-r> есть "родственники" в командной строке Vim (вставка слова/файла/строки из-под курсора) - у них своя справка (c_CTRL-R_*), и в insert-режиме они не действуют. Мы явно проговорим, где какой контекст.
Регистры мы подробно разбирали в главе 8. В режиме вставки их можно вставлять без выхода в нормальный режим - командой <C-r>{регистр}.
После <C-r> Vim ждёт имя регистра и вставляет его содержимое прямо в точку курсора, как будто вы его набрали. Это особенно ценно, когда вы в потоке набора кода и вспомнили, что нужное значение уже лежит в буфере.
Код: Выделить всё
Сочетание | Что вставляет
-----------+------------------------------------------------------------
<C-r>0 | Регистр 0 - последний *yank* (не затрагивается удалениями)
<C-r>" | Безымянный регистр (последний yank/delete)
<C-r>+ | Системный буфер обмена
<C-r>% | Имя текущего файла
<C-r>/ | Последний поисковый паттерн
<C-r>: | Последняя выполненная команда :
<C-r>= | Результат вычисления выражения (см. ниже)
<C-r>a | Содержимое именованного регистра a
Код: Выделить всё
Скопировали имя: yiw на user_name (попало в "0)
Печатаем: const -> <C-r>0 -> const user_name
<C-r>= открывает мини-командную строку, куда вы вводите выражение Vimscript, а его результат вставляется в текст. Это калькулятор прямо в потоке набора:
Код: Выделить всё
Печатаем: Итого: -> <C-r>= -> 19*1.2<CR> -> Итого: 22.8
Литеральная вставка: <C-r><C-r> и <C-r><C-o>
Обычный <C-r> вставляет регистр так, будто текст набран с клавиатуры - а значит, на него влияют 'autoindent', аббревиатуры и опции форматирования. Для многострочного кода это иногда ломает отступы. Чтобы вставить регистр дословно, есть варианты:
- <C-r><C-r>{рег} - вставляет содержимое буквально, без обработки "как при наборе" (аббревиатуры, авто-раскладка). Но учтите: форматирование по 'textwidth'/'formatoptions' всё ещё применяется.
- <C-r><C-o>{рег} - вставить регистр буквально и без автоотступа (ведёт себя как paste средней кнопкой мыши; для построчного регистра вставляет над текущей строкой, как P). Это самый "дословный" вариант - никакого автоотступа и форматирования.
- <C-r><C-p>{рег} - вставляет с исправлением отступа под текущее окружение.
<C-r><C-w> и друзья: захват слова из-под курсора (это командная строка, не insert)
Важное уточнение, в котором часто путаются. Сочетания <C-r><C-w>, <C-r><C-a>, <C-r><C-f>, <C-r><C-l> захватывают слово/WORD/имя файла/строку из-под курсора - но это команды командной строки Vim (:, /, ?), а не режима вставки. В insert-режиме после <C-r> Vim ждёт имя регистра, а <C-w> регистром не является (там работают лишь <C-r><C-r>, <C-r><C-o>, <C-r><C-p> из раздела выше). Их справка - c_CTRL-R_CTRL-W и соседние (см. :help cmdline.txt).
Стоя курсором на слове в нормальном режиме, вы открываете командную строку и подтягиваете это слово:
Код: Выделить всё
Сочетание (в командной строке) | Что вставляет
--------------------------------+-----------------------------------------------------------------------------------------------
<C-r><C-w> | Слово под курсором (word)
<C-r><C-a> | WORD под курсором - непрерывная последовательность непробельных символов (включая пунктуацию)
<C-r><C-f> | Имя файла под курсором
<C-r><C-l> | Текущую строку целиком
Код: Выделить всё
:%s/<C-r><C-w>//g -> паттерн уже заполнен словом из-под курсора
<C-o>: одна команда нормального режима
<C-o> - это "выгляни в нормальный режим ровно на одну команду и вернись". Vim выполняет следующую введённую команду как нормальную, после чего автоматически возвращает вас в insert ровно туда, где вы были.
Зачем? Чтобы не делать ритуал <Esc> -> команда -> i/a ради одного движения или правки.
Код: Выделить всё
Печатаем длинную строку, нужно вставить пустую строку выше:
... текущий текст| -> <C-o>O -> курсор уходит на новую строку выше
- <C-o>D - удалить всё от курсора до конца строки и продолжить печатать.
- <C-o>zz - отцентрировать экран, не прерывая ввод.
- <C-o>0 - прыгнуть в начало строки одним движением (а <C-o>$ - в конец).
- <C-o>p - вставить регистр через нормальный p (с его семантикой) посреди ввода.
Удаление на лету: <C-w>, <C-u>, <C-h>
Стирать набранное по одному символу <BS> - медленно. В insert-режиме есть "оптовые" удаления, знакомые всем по shell (readline):
Код: Выделить всё
Сочетание | Действие
-----------+----------------------------------------------
<C-h> | Удалить символ слева (то же, что <BS>)
<C-w> | Удалить слово слева от курсора
<C-u> | Удалить до начала набранного / начала строки
Код: Выделить всё
Опечатались в имени:
function calculuate( -> <C-w> -> function | -> дописываем calculate(
Гранулярный undo: <C-g>u
По умолчанию весь текст, набранный за одну сессию вставки (от i до <Esc>), откатывается одним u целиком. Иногда это неудобно: вы написали абзац, а отменить хотите только последнее предложение - но u сносит всё.
<C-g>u ставит разрыв в последовательности undo прямо посреди ввода, не выходя из режима вставки. После него последующий u остановится на этой точке, а не отмотает всю сессию.
Код: Выделить всё
Сочетание | Действие
-----------+------------------------------------------------------------------------------------------
<C-g>u | Разорвать undo-последовательность (начать новый шаг отмены)
<C-g>U | Не разрывать undo при следующем движении курсора (чтобы . и undo вели себя предсказуемо)
Код: Выделить всё
inoremap <C-w> <C-g>u<C-w>
inoremap <C-u> <C-g>u<C-u>
Повтор вставленного: <C-a> и <C-@>
Внутри одной сессии вставки доступны два "повторителя":
Код: Выделить всё
Сочетание | Действие
-----------+------------------------------------------------------
<C-a> | Вставить текст, введённый в предыдущей сессии insert
<C-@> | То же, что <C-a>, но сразу выйти в нормальный режим
<C-@> (это Ctrl+@, на многих раскладках Ctrl+Space) делает то же и моментально возвращает в нормальный режим - то есть "вставь предыдущий ввод и всё". Будьте аккуратны: на некоторых терминалах <C-@> совпадает с нулевым байтом и может вести себя неожиданно; <C-a> надёжнее.
Отступы прямо из вставки: <C-t> и <C-d>Не путайте insert-режимный <C-a> с нормальным <C-a> (инкремент числа под курсором) - это разные команды в разных режимах.
Поправить отступ строки, не выходя из ввода:
Код: Выделить всё
Сочетание | Действие
-----------+-------------------------------------------------------------
<C-t> | Добавить один уровень отступа (shiftwidth) к текущей строке
<C-d> | Убрать один уровень отступа
0<C-d> | Снести весь отступ строки до нуля
^<C-d> | Снести отступ на этой строке, но восстановить на следующей
Код: Выделить всё
Печатаем тело if, строка недо-отступлена:
return result;| -> <C-t> -> Tabreturn result;|
Это самая мощная часть главы. Vim умеет дополнять текст прямо при наборе встроенными средствами - без единого плагина.
Базовое дополнение по словам: <C-n> / <C-p>
Начните печатать слово и нажмите:
- <C-n> - дополнить следующим подходящим словом (next);
- <C-p> - дополнить предыдущим (previous).
Код: Выделить всё
Печатаем: calc -> <C-n> -> меню: calculateTotal / calculateTax / ...
ещё <C-n> листает, <C-y> принимает
После <C-x> Vim входит в подрежим дополнения, где следующая клавиша выбирает источник. Это позволяет дополнять не "чем попало из буфера", а конкретным видом данных:
Код: Выделить всё
Сочетание | Источник дополнения
-------------------------+---------------------------------------------------------------------
<C-x><C-n> / <C-x><C-p> | Слова только из текущего файла
<C-x><C-i> | Ключевые слова из текущего и включённых файлов (#include и т.п.)
<C-x><C-l> | Целые строки (whole-line completion)
<C-x><C-f> | Имена файлов и путей из ФС
<C-x><C-d> | Определения и макросы (по #define, из текущего и включённых файлов)
<C-x><C-o> | Omni-дополнение (умное, по 'omnifunc')
<C-x><C-u> | Пользовательское дополнение через 'completefunc'
<C-x><C-]> | Дополнение по тегам (tags)
<C-x><C-k> | По словарю ('dictionary')
<C-x><C-t> | По тезаурусу ('thesaurus')
<C-x><C-s> | Орфографические варианты (нужен 'spell')
<C-x><C-v> | Команды командной строки Vim
И ещё пара пунктов подрежима <C-x>, которые не дополняют текст, но полезны рядом:
Код: Выделить всё
Сочетание | Действие
-------------------------+---------------------------------------------------------------------------------------------------------------------
<C-x><C-e> / <C-x><C-y> | Прокрутить окно вверх/вниз на строку, не выходя из режима вставки
<C-x><C-z> | Остановить текущее дополнение, оставив текст как есть (в отличие от <C-e>, который откатывает к набранному вручную)
<C-x><C-l> - дополнение целой строкой. Незаменимо, когда нужно повторить уже существующую строку (лог-вызов, импорт, повторяющийся паттерн). Печатаете начало строки, <C-x><C-l> находит во всех буферах строки с таким префиксом.
Код: Выделить всё
Печатаем: import { -> <C-x><C-l> -> меню всех строк, начинающихся так
Код: Выделить всё
Печатаем: ./src/comp -> <C-x><C-f> -> ./src/components/ ...
Навигация по меню дополненияNeovim 0.11+: встроенное LSP-дополнение включается per-buffer через vim.lsp.completion.enable() (обычно в autocmd LspAttach), после чего работает уже автоматически по мере набора. А Neovim 0.12 (релиз - март 2026) принёс нативный insert-автокомплит через стабильную опцию 'autocomplete' (vim.o.autocomplete) - без сторонних движков. Подробно про LSP и современные движки дополнения - в главе 25 и главе 26. Встроенные механизмы из этой главы остаются фундаментом: понимать <C-x>-подрежим полезно, даже если поверх стоит плагин.
Код: Выделить всё
Клавиша | Действие в открытом меню
---------------+--------------------------------------------------------
<C-n> / <C-p> | Следующий / предыдущий кандидат
<C-y> | Подтвердить выбранный
<C-e> | Закрыть меню и откатить к тому, что вы набрали вручную
<C-x><C-z> | Закрыть меню, но оставить уже выбранный текст как есть
<C-x><C-x>... | Сменить источник, не закрывая дополнение
Поведение меню управляется опцией 'completeopt' (например, menuone,noselect - показывать меню даже для одного варианта и не выбирать его автоматически).
Спецсимволы: <C-v> и диграфы
Иногда нужно ввести символ, которого нет на клавиатуре, или вставить управляющий символ буквально.
<C-v> - литеральный ввод
<C-v> говорит "следующий ввод - буквально". Применения:
- Управляющие символы. <C-v><Esc> вставляет реальный символ Escape (^[), <C-v><Tab> - настоящий таб, <C-v><CR> - символ возврата каретки. Это критично при редактировании макросов как текста (см. главу 16).
- По коду символа. Числа после <C-v> задают код:
- <C-v>065 - десятичный код -> A
- <C-v>u00e9 - Unicode (4 hex-цифры) -> é
- <C-v>U0001F600 - Unicode (8 hex) -> эмодзи
- <C-v>x41 - hex-код -> A
Код: Выделить всё
Печатаем: cafe -> <C-v>u0301 -> café (комбинируемый акут)
<C-k> - диграфы<C-v> против <C-q>. Это синонимы: i_CTRL-Q делает ровно то же, что i_CTRL-V. Зачем дубликат? Во многих терминалах (и в эмуляторах с включённым flow control) Ctrl+V перехватывается системой - классически под "вставку" (paste) или под XON/XOFF, - и до Vim сочетание просто не доходит. В такой ситуации используйте <C-q>: оно работает идентично, но обычно не перехватывается. Если <C-v><Tab> "ничего не делает" - первым делом попробуйте <C-q><Tab>.
Диграфы - это мнемонические двухсимвольные имена для спецсимволов. <C-k>{симв1}{симв2} вставляет соответствующий знак. Список всех доступных - командой :digraphs.
Код: Выделить всё
Ввод | Результат | Мнемоника
---------+------------------------+-----------------------
<C-k>a: | ä | a + умляут
<C-k>e' | é | e + акут
<C-k>-> | стрелка вправо | мнемоника со стрелкой
<C-k>Co | © | copyright
<C-k><- | стрелка влево | парная стрелка
<C-k>14 | ¼ | дробь
<C-k>OK | галочка (check mark) | OK
<C-k>SE | § | section
Лучшие практики 2026
- Не выходите в нормальный режим ради мелочей. Вставка регистра (<C-r>), одна команда (<C-o>), удаление слова (<C-w>) - всё это дешевле полного цикла <Esc>...i. Сознательно ловите себя на ритуале "вышел-сделал-вернулся" и заменяйте его insert-командой.
- <C-r>0 для надёжной вставки yank. Поскольку регистр 0 не перезаписывается удалениями, <C-r>0 спасает от классической ловушки yank/delete. Для системного буфера - <C-r>+. В Neovim 0.10+ при работе по SSH + авто-подхватывает OSC52, так что <C-r>+ часто работает "из коробки" без xclip/wl-clipboard (детали - в главе 8).
- <C-x><C-f> вместо угадывания путей. При написании импортов и ссылок на файлы дополнение по ФС исключает опечатки в путях и экономит память на структуре проекта.
- <C-x><C-l> для повторяющихся строк дешевле копипасты и не засоряет регистры.
- Опирайтесь на нативный LSP-omnifunc в Neovim. Даже без плагина-движка <C-x><C-o> (или включённое vim.lsp.completion.enable() в 0.11+) даёт рабочее семантическое дополнение. Полноценный движок ставьте, когда нужны сниппеты, ранжирование и UX (см. главу 26) - но не как обязательную замену встроенного.
- Настройте 'completeopt' под себя. menuone,noselect - разумный дефолт 2026: меню показывается всегда, ничего не выбирается автоматически, вы осознанно жмёте <C-n>/<C-y>.
- Гранулярный undo через <C-g>u. Повесьте inoremap <C-w> <C-g>u<C-w> и аналогично для <C-u> и <CR>, чтобы крупные удаления и абзацы откатывались по отдельности, а не всей сессией вставки.
- Если <C-v> не срабатывает - берите <C-q>. В терминалах Ctrl+V часто перехвачен под paste/flow control; <C-q> делает то же самое и обычно проходит.
- Диграфы вместо запоминания кодов. Для типографики (->, ©, - , "") <C-k> читабельнее и быстрее, чем <C-v>u.....
- <C-r> ломает отступ при многострочной вставке. Обычный <C-r> пропускает текст через autoindent. <C-r><C-r>{рег} убирает раскладку "как при наборе", но форматирование ('textwidth'/'formatoptions') всё ещё применяется. Для полностью буквальной вставки без автоотступа используйте <C-r><C-o>{рег}.
- Путают insert-<C-a> (повтор ввода) и normal-<C-a> (инкремент числа). Это разные команды в разных режимах. В insert <C-a> повторяет предыдущую сессию набора.
- <C-w>/<C-u> "упираются в стену" на старом Vim. Причина - опция 'backspace'. Проверьте :set backspace?; в Neovim/Vim 9 дефолт indent,eol,start уже корректен.
- <C-@> ведёт себя странно в терминале. На ряде терминалов Ctrl+@ = нулевой байт. Если повтор нужен без выхода - берите <C-a>.
- Ждут, что omni-дополнение "само знает" язык. <C-x><C-o> работает только если задан 'omnifunc'. В Neovim это обеспечивает LSP; в чистом Vim - ftplugin или ваша функция. Без omnifunc меню будет пустым.
- Считают, что нужен nvim-cmp/blink.cmp для любого дополнения. Базовое <C-n>/<C-x>-дополнение встроено и не требует ничего. Плагины добавляют UX, а не саму возможность.
- <C-x><C-f> ищет относительно неожиданного каталога. По умолчанию пути считаются от текущего рабочего каталога Vim, а не от каталога файла. Проверяйте :pwd, если предложения "не те".
- Вставка регистров. Скопируйте слово через yiw, затем удалите другое слово через diw. В режиме вставки наберите строку, используя <C-r>0 и <C-r>" - убедитесь, что 0 отдаёт скопированное, а " - удалённое.
- Одна команда нормального режима. Печатая длинную строку, посреди ввода добавьте пустую строку выше через <C-o>O, затем отцентрируйте экран через <C-o>zz, не выходя из режима вставки.
- Дополнение путём. Создайте пару вложенных каталогов с файлами. В новом буфере напишите require(' и через <C-x><C-f> дойдите дополнением до нужного файла, не печатая путь руками.
- Дополнение строкой. Напишите три похожие строки логирования. На четвёртой наберите общий префикс и вызовите <C-x><C-l>; пролистайте кандидатов <C-n> и подтвердите <C-y>.
- Захват слова. Встаньте курсором на имя переменной в нормальном режиме, войдите в командную строку :%s/ и вставьте слово через <C-r><C-w>, дополнив команду замены.
- Спецсимволы. Введите строку cafe, превратите e в é через диграф <C-k>e'. Затем вставьте стрелку <C-k>-> и символ копирайта <C-k>Co. Сравните с вводом тех же символов через <C-v>u.....
- Режим вставки - это полноценная среда с Ctrl-командами, а не просто "ввод текста".
- <C-r>{рег} вставляет регистр; <C-r>0 - надёжный yank, <C-r>+ - системный буфер, <C-r>= - выражение. Для дословной вставки - <C-r><C-r>, а полностью без автоотступа/форматирования - <C-r><C-o>. Захват слова из-под курсора (<C-r><C-w> и друзья) - это командная строка, а не insert.
- <C-o> выполняет одну команду нормального режима и возвращает в insert.
- <C-w>/<C-u> удаляют слово/строку; <C-t>/<C-d> правят отступ; <C-a> повторяет предыдущий ввод. <C-g>u ставит точку отмены посреди вставки для гранулярного undo.
- Автодополнение встроено: <C-n>/<C-p> по словам, подрежим <C-x> выбирает источник - <C-x><C-l> (строки), <C-x><C-f> (файлы), <C-x><C-o> (omni/LSP), <C-x><C-u> (completefunc), <C-x><C-i> (включённые файлы), <C-x><C-d> (определения). <C-y> подтверждает, <C-e> откатывает, <C-x><C-z> останавливает с сохранением выбора; <C-x><C-e>/<C-x><C-y> скроллят окно не выходя из вставки.
- <C-v> вводит символ буквально или по коду; <C-k> - диграфы для типографики.
- В Neovim omni-дополнение питается от LSP; современные движки (глава 26) - это надстройка над встроенным механизмом, а не замена ему.