Привет, коллеги. Продолжаем вникать в тонкости привязок. Первая часть тут, вторая тут, а сегодня обсудим ключи, позволяющие настроить поведение привязки, и префиксы, дающие возможность привязкам не конфликтовать.
Рассмотрим ключи, то есть модификаторы, позволяющие изменить поведение команд типа map. Они ставятся сразу после команды, перед определяемой клавишей/комбинацией и имеют вид <buffer>. Обсудим их.
Ключ <buffer> означает, что привязка локальна для буфера. Это полезно, если у вас много разнородных файлов открыто.
Вот пример:
let @n=0 | inoremap <buffer> <CR> <CR><ESC>:let @n=@n+1<CR>i<C-R>n._
В режиме вставки переопределена клавиша ввода. При нажатии на нее увеличивается регистр n и вставляется в начале строки. Добавляется точка и пробел, который здесь изображен символом _. В итоге можно вводить список:
1. один
2. два
3. и так
4. далее
В соседнем окне это поведение только мешает. А в данном можно вбрасывать что-то по ходу чтения текста, а нумерация сама будет вестись.
Локальные привязки имеют приоритет перед глобальными: если к одной и той же клавише привязаны две разные команды, сработает локальная для буфера.
Ещё этот ключ позволяет удалить привязки в данном буфере.
Ключ <unique> не позволяет переопределять привязку. Если у вас задана привязка, скажем, на <F2> и вы создали новую, старая пропадет. С этим ключом вы получите сообщение об ошибке и можете назначить другую клавишу.
Ключ <expr> трактует правую часть привязки как выражение, которое надо вычислить, а уже его результат работает как обычная правая часть: в режиме вставки это текст, а в нормальном режиме — команды.
Например,
imap pi acos(-1.0)
вместо pi вставит текст acos(-1.0), но мы-то имели в виду другое. Можно так:
imap pi <ESC>:let @p=string(acos(-1.0))<CR>"pPa
то есть мы выйдем из режима вставки, вычислим выражение, положим результат в регистр p, вставим его в текст и вернемся в режим вставки. Но это неизящно, зачем-то выходим из режима вставки (иногда это важно), занимаем регистр, в котором что-то может быть, и вообще как-то "костыльно". Надо так:
imap <expr> pi string(acos(-1.0))
Функция string нужна потому, что вещественное число в строку автоматически не преобразуется. А лучше использовать printf, контролируя заодно и точность.
Конечно, число пи так вводить глуповато, а вот текущую дату или время — весьма разумно.
Штука небезопасная, так что заблокирована возможность изменять буферы и команда :normal.
Можно использовать функцию getchar, чтобы получить код следующего введенного символа. Пример из справки:
inoremap <expr> <C-L> nr2char(getchar())
Причем если есть привязка <C-L>x, то Вим будет ждать символа после <C-L>, и если это х, то сработвает вторая привязка, а если нет, то будет выведен символ, как будто ничего и не произошло.
Ключ <silent> предписывает привязке не выводить ничего в командной строке: поиск, замена и всё такое обычно отображается, а можно скрыть. Сообщения от команд, выполняемых в привязке, выводятся все равно, но команды можно выполнять через :silent.
Ключ <nowait> заставляет привязку срабатывать сразу, как он совпала. Например, если есть привязка qq и другая, qqq. Обычно, Вим будет ждать одну секунду, потом примет решение, что qq было привязкой. Если опция timeout сброшена (по умолчанию она выставлена), Вим будет ждать нажатия следующей клавиши. Но вот тут и может пригодиться ключ <nowait>. Время задержки, конечно, можно изменить: timeoutlen задает его в миллисекундах.
Это пригождается, если привязки имеют префиксы? о которых далее. Например, \q или ,q
Ключ <special> включает распознавание спецклавиш в форме <F2>. Обычно они и так распознаются, но в poptions это можно выключить для совместимости или для удобства (ну, может вам по удобно <F задействовать для чего-то), вот в этом случае ключ настаивает на своем.
Ключ <script> по сути запрещает рекурсию, так как допускает, при выполнении привязки, только те привязки, что определены в скрипте и содержат специальный символ <SID>, делающий привязки (и функции) уникальными для скрипта. Скажем, если вне скрипта определена привязка qq, а внутри двух скриптов привязки <SID>qq, то это три разные привязки. При этом один скрипт вполне может использовать привязку другого — но если хочет этого. Ключ <script> это запрещает, позволяя пользоваться только "местными" привязками.
Теперь обсудим префиксы. Когда привязок много и они идут пакетами, несложно "подраться" и одни привязки перезапишут другие. Ключ <special> не спасет, так как при запуске скрипта с привязками ваши привязки не пострадают, но конфликтующие не загрузятся и вообще скрипт вылетит по ошибке, что не очень хорошо.
Но есть возможность указать в левой части, в начале, символ <leader>. Вот прямо так в угловых скобочках. При этом по умолчанию это будет заменено на слеш, то есть привязка
map <leader>q <nop>
сработает как
map \q <nop>
Но можно заменить лидирующий символ на другой, задав переменную (не опцию!) mapleader:
:let mapleader = ","
И тогда команда выше создаст првязку ,q
Можно и локально в буфере использовать <LocalLeader> и переменную maplocalleader.
Значение переменной играет роль при создании привязок, а на уже созданные привязки не влияет. То есть, если у вас возникли конфликты, вы просто меняете значение переменной и создаете набор привязок с другим лидером, и всё.
Пример. У вас есть привязка \q. Скрипт, помогающий вставлять греческие буквы, создал привязку <leader>q, и она конфликтует с вашей. Вы задаете переменную mapleader, положив туда ; и у вас привязка ;q , которая уже не конфликтует. Вы загрузили скрипт привязок для математических символов, и он тоже норовит создать привязку <leader>q. Что же, вы, перед запуском скрипта, меняете значение переменной на * и получаете *q.
Про уже упомянутый символ <SID> мы поговорим отдельно, пожалуй.
Удачи, коллеги!