Follow

Хочу поделиться опытом изучения макросов в Vim. Попробовал использовать их в реальной работе и на определённых задачах вижу как они здорово ускоряют работу.

Покажу на упрощенном примере. Есть следующий код (очень синтетический, чисто для примера):
1 struct Record
2 {
3 int position{0};
4 int count{0};
5 };
6
7 struct AdditionalInfo
8 {
9 int weight{0};
10 bool visible{false};
11 };
12
13 struct RecordEx
14 {
15 Record record;
16 AdditionalInfo additionalInfo;
17 };
18
19 void ProcessRecord(const Record& record, const AdditionalInfo& info)
20 {
21 // Processing record
22 }
23
24 void ProcessRecordEx(const RecordEx& record)
25 {
26 // Processing record with additional info
27 }
28 RecordEx CreateRecordWithAdditionalInfo(int position, int count, int weight, bool visible)
29 {
30 return RecordEx{position, count, weight, visible};
31 }
32
33
34 int main()
35 {
36 // records from 1st source
37 ProcessRecord(Record{20, 30}, AdditionalInfo{900, false});
38 ProcessRecord(Record{100, 50}, AdditionalInfo{100, true});
39 ProcessRecord(Record{200, 21}, AdditionalInfo{800, false});
40
41 // records from 2nd source
42 ProcessRecord(Record{901, 2}, AdditionalInfo{750, false});
43 ProcessRecord(Record{905, 5}, AdditionalInfo{25, true});
44 ProcessRecord(Record{991, 12}, AdditionalInfo{15, true});
45
46 return 0;
47 }

Задача: заменить вызов ProcessRecord(Record{...}, AdditionalInfo{...}) на ProcessRecordEx(CreateRecordWithAdditionalInfo(...)).

Общая идея: в макрос происходит запись редактирования одной строки, а далее в VISUAL режиме для каждой строки выделенного текста применяются действия, записанные в данном макросе. При записи макроса значения аргументов position, count, weight и visible будут записаны в регистры a, b, c, d соответственно, а далее они будут использованы в новым вызове.

Редактирование начинается с вызова команды qr, осуществляющая запись макроса в регистр r.
Внизу появится вот такое сообщение:
recording @r
Далее происходит вызов следующих команд:
0 - переход в начало строки
/ProcessRecord<cr> - происк текста ProcessRecord и перемещение к нему
<C-a> - перемещение курсора к ближайшему числу справа и увеличение его на 1, далее см. команду ниже
<C-x> - уменьшение числа на 1, выполняется чтобы число осталось тем же самым, какие было до вызова <C-a> (т.е. вызов двух команд <C-a><C-x> нужен чтобы переместиться к числу в строке)
wb - перемещение в начало числа, т.к. команды выше установят курсор на конец числа
"ayw - запись значения слова под курсором в регистр a
W - перемещение к следующему слову (это будет второе число в строке)
"byw - запись значения слова под курсором в регистр b
f, - перемещение к ближайшей запятой справа
<C-a><C-x> - уже известная пара команд, которая осуществит переход к третьему числу
wb - перемещение в начало числа
"cyw - запись значения слова под курсором в регистр c
W - перемещение к следующему слову (четвёртный аругмент типа bool)
"dyw - запись значения слова под курсором в регистр d
S - удаление все строки и переход в режим INSERT, внизу появится следующая -- INSERT --recording @r
Вводится текст:
ProcessRecordEx(CreateRecordWithAdditionalInfo(
новый вызов функции (можно использовать комплишн <C-n>)
<C-r>a - вставка значения регистра a в режиме INSERT
, - вставка запятой и пробела
<C-r>b - вставка значения регистра b в режиме INSERT
, - вставка запятой и пробела
<C-r>c - вставка значения регистра c в режиме INSERT
, - вставка запятой и пробела
<C-r>d - вставка значения регистра d в режиме INSERT
)); - вставка двух закрывающих скобок и ;
q - завершить запись макроса

Далее выполняется выделение блока текст, с помощью вызова команда V и перемещения курсора вниз, используя j
и происходит выполенеие команды
:'<,'>normal @r
которая для выделенных строк применит действия хранящиеся в макросе r.
Итоговый результат выглядит следующим образом:

...
// records from 1st source
ProcessRecordEx(CreateRecordWithAdditionalInfo(20, 30, 900, false));
ProcessRecordEx(CreateRecordWithAdditionalInfo(100, 50, 100, true));
ProcessRecordEx(CreateRecordWithAdditionalInfo(200, 21, 800, false));

// records from 2nd source
ProcessRecordEx(CreateRecordWithAdditionalInfo(901, 2, 750, false));
ProcessRecordEx(CreateRecordWithAdditionalInfo(905, 5, 25, true));
ProcessRecordEx(CreateRecordWithAdditionalInfo(991, 12, 15, true));
...

Вполне допускаю какие-то вещи можно сделать проще и оптимальнее, это была всего лишь первая попытка знакомства с макросами в Vim.

@noxdev @r Класс, спасибо за информацию! Я хотел очень когда-то освоить вим или неовим, что практически как я понимаю одно и то же, но, к сожалению орка, скринридер под линукс, который я использую имеет проблемы с ним, например клавиши перемещения работают не так как ожидается, ещё что-то, но есть отдельный скринридер для неовима. Вообще хочу попробовать вим вместо ВС кода.

@Sevapopov я сейчас стараюсь как можно больше использовать vim вместо VS Code, не всегда правда получается. У vim уж очень и очень высокий порой входа. Он заставляет иначе думать в процессе редактирования текста и прямо ощущается, что нужно "перестраиваться". Плюс еще тонкий момент: не получается эффективно работать над сложной задачей и при этом выполнять продвинутые действия в vim. Просто еще не хватает скиллов и из-за этого выполнение задачи замедляется, происходит лишнее переключение контекста в голове. Так что есть над чем работать и как совершенствоваться.

Sign in to participate in the conversation
Qoto Mastodon

QOTO: Question Others to Teach Ourselves
An inclusive, Academic Freedom, instance
All cultures welcome.
Hate speech and harassment strictly forbidden.