| ч17. Сопоставление, оператор ожидания | Содержание | ч19.Строка статуса {status line} |
Идея операторов и перемещений одна из самых важных концепций в Vim, и это одна из главных причин, по которой Vim настолько эффективен. Давайте немного попрактикуемся в определении новых перемещений, потому что изучение этой мощной идеи делает Vim невероятным.
Допустим, вы пишете некоторый текст *.markdown используя для этого язык разметки Markdown. Если вы раньше не использовали Markdown, не волнуйтесь, здесь всё очень просто. Введите следующее:
Первый заголовок.
=========
Это какой-то текст по первой теме.
В нем несколько абзацев.
Второй заголовок.
=========
Это некоторый текст по теме номер два. В нем всего один абзац.
Строки, "подчеркнутые" символами [ = ], рассматриваются Markdown как заголовки. Давайте создадим некоторые сопоставления, которые позволят нам выделять заголовки перемещением. Выполните следующую команду:
:onoremap ih :<c-u>execute "normal! ?^==\\+$\r:nohlsearch\rkvg_"<cr>
Это сопоставление довольно сложное, поэтому наведите курсор на один из абзацев (не на заголовки) и введите [ cih ]. Vim удалит заголовок раздела в котором вы находитесь, и переведет вас в режим вставки ("изменить содержимое заголовка" {change inside heading}).
Мы использовали то, что никогда раньше не делали, поэтому давайте рассмотрим каждую часть по отдельности. Первая часть сопоставления - [:onoremap ih] это просто команда сопоставления, которую мы видели раньше, поэтому мы пропустим это. <c-u> пока тоже пропустим.
Теперь посмотрим на оставшуюся часть строки:
:execute "normal! ?^==\\+$\r:nohlsearch\rkvg_"<cr>
normal
[ :normal ] это команда которая принимает набор символов и выполняет их как если бы они были введены в обычном режиме. Мы рассмотрим её более подробно в следующий раз, мы уже встречались с нею несколько раз, так что пришло время ее испытать. Запустите эту команду:
:normal gg
Vim переместит вас в начало файла. Теперь выполните эту команду:
:normal >>
Vim сделает отступ для текущей строки.
На данный момент не беспокойтесь о [ ! ] после normal, мы позже поговорим о то, что он означает.
execute
[ execute ] Команда принимает строку Vimscript (которую мы рассмотрим более подробно позже) и выполняет ее как команду. Запустите это:
:execute "write"
Vim запишет ваш файл так же, как если бы вы набрали [ :write<cr> ]. Теперь выполните эту команду:
:execute "normal! gg"
Vim переместит вас в начало файла. Но зачем нам делать это, когда мы можем просто запустить [ normal! ] ?
Посмотрите на следующую команду и попытайтесь угадать, что она будет делать:
:normal! gg/a<cr>
Кажется, что это должно сделать следующее:
- Переместится в начало файла.
- Запустите поиск.
- Ввести символ "a" в качестве цели поиска.
- Нажать return, чтобы начать поиск.
Но Vim лишь переместится в начало файла и больше ничего!
Проблема в том, что [ normal! ] он не распознает "специальные символы", наподобие [ <cr> ]. Есть несколько способов обойти это, но самый простой [ execute ].
Когда [ execute ] просматривает строку на выполнение, которую вы ей указали, перед запуском она заменит все специальные символы. В данном случае [ \r ] это escape-последовательность, которая означает "возврат каретки". Двойная обратная косая черта также является escape-последовательностью, которая помещает обратную косую черту в строку.
Если мы выполним эту замену в нашем сопоставлении и посмотрим на результат, мы увидим, что сопоставление будет выполняться:
:normal! ?^==\+$<cr>:nohlsearch<cr>kvg_
____________________^^^^____________^^^^
______________________||__________________||
Фактически это возвраты каретки, а не четыре символа [ <cr> ]
"левая угловая скобка", "c", "r", и "правая угловая скобка".
Итак, теперь normal! выполнит эти символы так, как если бы мы ввели их в обычном режиме. Давайте разделим их на части, чтобы понять, что они делают:
?^==\+$
:nohlsearch
kvg_
Первая часть [ ?^==\+$ ] выполняет поиск в обратном направлении [?]для любой строки, начинающиеся [ ^ ] с двух или более знаков равенства [==], строчка должна полностью состоять из знаков равенства [ \+$ ] и больше ничего. Это поставит наш курсор на первом символе строки со знаками равенства.
Мы ищем в обратном направлении, так как наша цель "изменить текущий заголовок", и это логично, ведь когда наш курсор находится в разделе текста, мы, вероятно, захотим изменить заголовок этого раздела, а не следующего.
Вторая часть - [ :nohlsearch ] это команда просто удаляет выделение поиска из поиска, чтобы он не отвлекал.
Последняя часть представляет собой последовательность из трех команд обычного режима:
- [ k ]: перемещение вверх по строке. Поскольку мы остановились на первом символе строки со знаками равенства, теперь мы переходим к первому символу текста заголовка.
- [ v ]: войдите в (символьный) визуальный режим.
- [ g_ ]: перейти к последнему непустому символу текущей строки. Мы используем его вместо [ $ ] потому что [ $ ]также выделяет символ новой строки, а это не то, что мы хотим.
Результаты
Мы рассмотрели каждую часть сопоставления. Резюмируем:
- Мы создали сопоставление в операторе ожидания для ("изменить содержимое заголовка" {change inside heading}).
- Мы использовали execute и normal! для запуска обычных команд, необходимых для выбора заголовка, и получили возможность использование специальных символов.
- Наше сопоставление выполняет поиск строки со знаками равенства, которая обозначает заголовок, удаляет его и приглашает нас ввести новый заголовок.
Давайте рассмотрим еще одно сопоставление, прежде чем двигаться дальше.
:onoremap ah :<c-u>execute "normal! ?^==\\+$\r:nohlsearch\rg_vk0"<cr>
Попробуйте поместить курсор в текст раздела и ввести [ cah ]. На этот раз Vim удалит не только текст заголовка, но и строку со знаками равенства которые обозначают заголовок. Вы можете думать об этом движении как "вокруг заголовка этого раздела". {"around this section's heading"})
Чем же отличаются эти сопоставления? Давайте посмотрим:
:onoremap ih :<c-u>execute "normal! ?^==\\+$\r:nohlsearch\rkvg_"<cr>
:onoremap ah :<c-u>execute "normal! ?^==\\+$\r:nohlsearch\rg_vk0"<cr>
Единственное отличие это самый конец строки.
Внутри загаловка (ih) : kvg_
Вокруг загаловка (ah): g_vk0
[ kvg_ ] мы разобрали чуть раньше.
[ g_ ] : перейти к последнему непустому символу в строке.
[ v ] : Переключиться в визуальный режим.
[ k ] : переместиться вверх на одну строку. Так мы перейдем к строке, содержащей текст заголовка.
[ 0 ] : перейти к первому символу строки.
В результате мы получим выделение знаков равенства и название заголовка.
Упражнения
У Markdown также могут быть заголовки, разделенные символами [ - ]. Настройте регулярное выражение в этих сопоставлениях, чтобы оно работало для любого типа заголовка. Возможно, вы захотите прочитать :help pattern-overview. Помните, что регулярное выражение находится внутри строки, поэтому обратные косые черты необходимо экранировать.
Добавьте две автокоманды в свой ~/.vimrc файл, которые создадут эти сопоставления. Убедитесь, что они отображаются только в соответствующих буферах (*.txt), и обязательно cгруппируйте их, чтобы они не дублировались при каждом source ~/.vimrc.
Прочти :help normal.
Прочти :help execute.
Прочти :help expr-quote, чтобы увидеть escape-последовательности, которые вы можете использовать в строках.
Создайте сопоставление в операторе ожидания "следующий адрес электронной почты", чтобы вы могли сказать "изменить адрес электронной почты". Сопоставление [ in@ ] будет хорошим кандидатом для ключа. Возможно вы, захотите использовать /...some regex...<cr> для этого.
| ч17. Сопоставление, оператор ожидания | Содержание | ч19.Строка статуса {status line} |