Макросы в Vim
Очень странно, с одной стророны тема довольно банальная, а с другой ни тут, ни на просторах интернета не видно хорошего понимания такой важной темы, которая может иногда сильно упростить задачу редактирования текста. К написанию меня подтолкнуло обсуждение макросов в Emacs в блоге Avdi Grimm'а, где в своё время никто не смог внятно объяснить, что в Vim есть то, чего ожидает автор поста от достойного текстового редактора. Исправим это, в первую очередь в себе, а потом пойдём и скажем этим из интернета, что они не правы.
Какие задачи редактирования текста помогут решить макросы? Например, такую: вот в этой самой строке, которую вы читаете, взять и все запятые поменять на 0. Можно вспомнить регулярные выражения, но не все их любят, и уж тем более не все помнят, как вставлять с их помощью перенос строки, а если вам нужно заменять какие-то символы, которые используются в регулярных выражениях как служебные, вы уже отвлеклись от своей основной задачи и вместо редактирования текста занимаетесь написанием регулярного выражения для поиска и замены, пробуя и ошибаясь.
Макросы позволят это сделать быстрее, с меньшим отвлечением на вспоминание и написание чего-либо. Запомнить как работают макросы очень легко, и это войдёт в ваш ежедневный аресенал наряду с прыжками по тексту.
В этом топике мы научимся использовать макросы с этой самой задачей.
Давайте сначала вспомним, как это сделать вручную.
f,r0
После чего можно нажимать последовательно ;
для повторного поиска и .
для повторения предыдущего действия. Но в какой-то момент это может стать не так просто, например, вам нужно добавить пару каких-то знаков между делом. Точка уже не сработает и нужно будет опять нажимать r0
. Или этих запятых окажется довольно много, и щёлкать поочерёдно ;
и .
придётся довольно много раз. В этот момент что-то вам уже подсказывает, что такой механический труд можно автоматизировать.
Основы
Многократные повторения и рекурсивный вызов
Редактирование макросов
Вечные макросы
Всякое
Основы
Для записи и хранения макросов в Vim используются регистры. Те самые, в которые можно копировать текст и те самые, на которые можно ставить пометки. Регистры обозначаются латинскими буквами с учётом регистра (a и A — разные регистры), цифрами, и даже специальными символами, то есть хватит их на всех.
Важно. В регистрах хранится не что-то магическое, в регистрах хранится простой текст.
Для записи макроса в регистр a
вопспользуемся следующей командой:
qaf,r0q
Первый кю q
запускает запись макроса, и так до нажатия q для подтверждения записи.
Теперь, чтобы запустить макрос повторно, нам нужно нажать @a
, и запустится на выполнение макрос, хранящийся в регистре a
. Мы можем традиционно для Vim написать 100@a
, и макрос будет выполнен 100 раз, заменив 100 или меньше (если в строке их меньше) запятых на 0
.
Многократные повторения и рекурсивный вызов
Иногда сколько у нас запятых в строке мы не знаем, поэтому после запуска 100@a
нам приходится вручную проверять, не осталось ли ещё.
Можно довольно просто сделать так, чтобы макрос вызывал сам себя. Запишем тот же самый макрос, который нужно будет вызывать всего один раз, а дальше он будет сам вызывать себя:
qaf,r0@aq
В данном случае, его запись ещё не произозшла, но запуск уже указан. Важно, чтобы в этом регистре ничего на момент записи не хранилось. Для этого есть два способа. Первый — это чистить содержимое регистра перед записью ещё тремя нажамиями, qaq
, то есть записью пустой последовательности. Второй — это делать вызов последнего вызыванного макроса с помощью @@
.
Важно. Выполнение цепочки или серии исполнения макросов приостанавливается в тот самый момент, когда одна из команд fFtT
, то есть поиска символа в строке, не удаётся. То есть, например, у нас не осталось больше в строке запятых. Естественно, даже если вы указали, что макрос нужно выполнить 100 раз, а запятых было всего две, макрос выполнится два раза, а на третий остановится на поиске и больше продолжать не будет. Точно так же с рекурсивным макросом.
Удобно то, что при записи макроса происходит его первое исполнение, то есть мы сразу видим, правильно ли его записали.
Редактирование макросов
Если что-то пошло не так, и хочется увидеть, что же мы записали, можно воспользоваться стандартной функцией Vim, и вставить содержимое регистра a
прямо в текст: "ap
.
Прямо в редакторе вы увидите текст, который является последовательностью команд:
af,r0@a
Допустим, вы решили, что менять текст нужно не на 0
, а на 1
, и вы редактируете текст макроса:
af,r1@a
и копируете его в регистр a
с помощью 0"ay$
.
Вечные макросы
Стоит заметить, что регистры латинский букв в верхнем регистре (A
-Z
) постоянны. Если вы выйдете из Vim, а потом зайдёте снова, содержимое регистра останется неприкосновенным. Хранится оно по умолчанию в файле ~/.viminfo
.
Важно. Содержимое регистра легко случайно перезаписать, и если вы хотите, чтобы какие-то макросы существовали в каких-то регистрах постоянно, имеет смысл добавить их в .vimrc
, или лучше в отдельный файл с макросами, включаемый в .vimrc
:
let @a='af,r1@a'
Всякое
Макросы совсем не обязательно действуют в рамках одной строки, попробуйте прыжки по параграфам в макросах для изменения регистра первого слова на верхний.
Чтобы избежать случайных переходов по нажатию Q
в Ex режим, имеет смысл назначить Q
на вызов предыдущего макроса:
nnoremap Q @@
Полезная информация:
:help registers
:help :registers
:help :recording
Для дальнейшего изучения:
Продвинутые макросы Vim (англ.)
Автор: philpirj