Найти тему
Блокнот математика

Рубрика "Секреты Вим". Горячие клавиши.

Как повесить команду на горячую клавишу? Например, чтобы выйти по F10, сохраняться по F2, а F5 чтобы вставляло окружение LaTeX или громоздкий оборот? Часто бывает полезно назначить вспомогательной клавише некоторую команду или переопределить команду.

Это можно делать в нормальном режиме, задействуя не только функциональные клавиши, а также и Q, _, табуляцию и другие --- если то, что они делают исходно, вам не очень нужно. Можно это делать и в режиме вставки --- здесь, конечно, чаще используются "непечатные" клавиши вроде функциональных, но не обязательно (о чем ниже). Например, можно в режиме вставки приспособить Tab для автодополнения слов, F5 пусть вводит какой-нибудь часто встречающийся оборот, а qq тоже вставляет что-нибудь часто нужное и длинное.

Для этого предназначены команды семейства map.

: map команда действие определяет новую команду. Их называют привязками. Команда назначает клавише, сочетанию клавиш или последовательности нажатий --- строку, а там уж дело ваше. Строка выполняется так, как будто вы нажимаете соответствующие клавиши. В принципе, это похоже на макросы, только макрос повешен на клавишу, сочетание клавиш или последовательность клавиш.

Можно делать это в разных режимах: нормальном, вставки/замены, визуальном, когда выделен текст и к нему можно применять команды, режиме выделения, когда текст выделен в режиме вставки (как в обычном редакторе), в режиме командной строки (после :, / и ?), а также в особом режиме, когда ожидается команда движения: после d, y, c и т.п. Для этого и служат различные команды семейства map.

Сама команда map назначает горячую клавишу в нормальном, визуальном режимах, режиме выделения и операторном. Есть отдельно nmap и другие --- для каждого режима отдельно. Так, map! работает в режимах вставки и командной строки, а imap --- вставки и замены.

Можно использовать нотацию угловых скобок: <F5>, <C-G> (это CONTROL), <S-F6> (с SHIFT), <CR> (Enter), <ESC>, <Bslash> (\).

Клавишу ALT лучше не применять из-за тонкостей работы терминала. Если хотите попробовать: она кодируется как M, например, <M-Q> или <M-M>. M --- потому что meta.

Например, : map <F2> :w<CR> - и теперь можно сохранять файл по F2.
: imap <F2> <ESC>:w<CR> - то же для режима вставки - выход в нормальный режим с сохранением.
: map <C-F2> :w!<CR> - сохранение без вопросов.
:map <C-D> :.,.g/^\s*$/d<CR>:noh<CR> - применяет команду обработки строк к одной (текущей) строке, удаляя ее если она пустая.
Это удобно, когда надо удалить пустую строку без риска промахнуться и удалить непустую.

У меня висит сохранение на F2, язык на F3 (хотя ctrl+^, он же ctrl+6, не особо сложнее), текущий каталог в новой вкладке на F4, bash на F5, перезагрузка файла с диска на F6 (если файл изменен вне Вима), проверка орфографии на F7, кодировка на F8, вставка визуальной закладки на F9 (и снятие на <C-F9>).

Кое-что из этого делается с помощью меню, о которых в другой раз; команда map привязывает к клавише как раз меню.

Обязательно надо переопределить Y на y$ - по историческим причинам Y работает как yy, а не более логичное y$.
Это делается так: map Y y$

Заметьте, что никто не мешает повесить что-то на букву:

imap z с учетом вышеперечисленного и принимая во внимание ряд аспектов, подробно обсуждаемых далее...

Теперь можно, нажав z, получить эту длинную фразу. Правда, саму z вы ввести не сможете. В некоторых языках некоторые буквы не используются, так что...

Однако можно повесить команду на пару букв, скажем, на qq --- вряд ли это сочетание часто встречается в ваших текстах. При этом ввести qq все равно можно: если нажать быстро, сработает команда, а если медленно, то вставится две q. Что значит "быстро", определяют опции timeout/notimeout --- если включена, то Вим ждет секунду или сколько указано в timeoutlen.

Поэтому что-то такое: imap zz double precision --- вполне жизнеспособно, хотя для этих целей есть механизм аббревиатур, о котором в другой раз.
Он позволяет проделывать такие вещи проще: пишешь dblpr или то же qq, а получаешь double precision.

То же самое верно для нормального режима. Если очень хочется, можно повесить что-то на 42, например:

map 42 iforty two<ESC>

Интересно, что map 6 i666<ESC> позволит нажатием на 6 ввести 666, а 56 введет 666 пять раз. При этом повторить команду 56 раз вы не сможете.

Если вы задаете команду клавише в режиме вставки и это не про вставку (вы можете повесить на <C-Q> или F3 свою фамилию, почему нет), то начинайте с <ESC>. Например, imap <F2> <ESC>:w!<CR>i --- по F2 Вим выходит в нормальный режим, выполняет команду сохранения без вопросов, и возвращается в режим вставки.

Удалить привязку позволяет семейство команд unmap: unmap, iunmap, cunmap, unmap! и т.п. Например, unmap zz

Команда map и другие без аргументов покажет список всех команд в том числе предопределенных. Как на скриншоте внизу.

Если будете экспериментировать, то вам это пригодится: посмотрели на созданные привязки и удалили неудачные.

Команды семейства map рекурсивны: если в правой части встретится привязка, она будет выполнена. Команды семейства noremap не рекурсивны; их используют для переопределения команд.

Если в правой части есть левая, но не в начале, то рекурсия станет бесконечной и выйти можно только по ошибке, в том числе по <C-C>. Например, imap q qwerty нормально сработает, а вот imap q ytrewq небезопасно. Иногда Вим распознает бесконечную рекурсию и выдаст ошибку. Но без гарантий. Сохраните все вкладки, прежде чем экспериментировать!

Можно даже такое проделывать:

noremap k j

noremap j k

Поменять местами команды!

mapclear (семейство) убирает все привязки, в том числе стандартные.

Есть специальные аргументы. Опишу несколько:

<buffer> --- только для данного файла. map <buffer> <C-Q> :set wrap!<CR> В другом файле можете повесить на горячую клавишу что-то другое.

<silent> --- команда не отображается в командной строке.

<unique> --- не переопределяет существующие привязки.

<expr> --- трактует строку как выражение, которое нужно вычислить (выполнить). Так можно запустить функцию или скрипт и делать очень сложные вещи. Есть возможность определить свой оператор, то есть команду, которая работает с текстом, указанным командой движения. Об этом в другой раз, но это можно: например, <C-Q>$ вызовет функцию, которой будет передан текст от курсора до конца строки.

Привязки. В основном, стандартные, но вверху видны несколько моих.
Привязки. В основном, стандартные, но вверху видны несколько моих.

Удачи, коллеги. Настройте Вим, как вам надо!

Путеводитель по каналу.