Хочу поделиться опытом изучения макросов в 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 Класс, спасибо за информацию! Я хотел очень когда-то освоить вим или неовим, что практически как я понимаю одно и то же, но, к сожалению орка, скринридер под линукс, который я использую имеет проблемы с ним, например клавиши перемещения работают не так как ожидается, ещё что-то, но есть отдельный скринридер для неовима. Вообще хочу попробовать вим вместо ВС кода.

Follow

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

Sign in to participate in the conversation
CleverLibre Social

CleverLibre Social is an inclusive social instance for open discussion, learning, and community.
All cultures welcome.
Hate speech and harassment strictly forbidden.