12

Я нахожусь в процессе украшения некоторого исходного кода, используя vim. {1}

Я создал пару макросов vim, которые выполняют отдельные шаги: удаление конечного пространства, удаление пустых строк после { , удаление пустых строк перед { , такого рода вещи.

Теперь я хочу создать макрос, который последовательно выполняет все отдельные макросы. Однако, как только первый рекурсивный макрос завершает свою работу (так как он больше не может найти совпадения -> ошибка соответствия), мой макрос "обертка" также завершается.

Есть ли способ заставить макрос vim продолжить после того, как submacro сгенерировал ошибку?

{1} Я знаю об автоматических переформаторах. Я мог бы даже использовать их в моей текущей проблеме. Я просто упомянул источник переформатирования для примера. Не размещайте никаких ответов об этом источнике красоты или что. Вопрос не в переформатировании кода как таковом, а в макросах vim.

Пример:

  • Макрос 1 - усечение завершающего пробела - qw/\s\+$d$@wq
  • Макрос 2 - удаление пустых строк перед} - qe/\n\n *}dd@eq
  • Wrapper Macro - retabbing, Макрос 1, Макрос 2 - qr:retab@w@eq

Когда я выполняю обертку - @r - она перезагружается, затем выполняет Макрос 1 до тех пор, пока не будут найдены завершающие пробелы, затем завершается (без выполнения Макро 2).

Разъяснение:

Что я ищу, так это как вызвать submacro, чтобы, когда этот submacro завершается, вызывающий макрос продолжается?

3 ответа3

20

Если неудачная команда является заменой, которая не находит своего шаблона, например,

:%s/foo/bar/

когда foo не существует в буфере, вы можете добавить флаг e чтобы игнорировать эту ошибку, например,

:%s/foo/bar/e

Увидеть

:help :s_flags

Вы можете сказать Vim игнорировать ошибки некоторых команд:ex, предшествуя им :silent! , Увидеть

:help :silent


Изменить после добавления примера к вопросу

Макрос 1 и Макрос 2 оба рекурсивны, и ни один не имеет какого-либо явного механизма завершения рекурсии. Я предполагаю, что запускается один из внутренних тестов Vim на неограниченную рекурсию, который выдает ошибку. Если Macro 1 генерирует такую ошибку, то эта ошибка прекратит выполнение Wrapper Macro сразу после @w .

Я бы предложил ограничить количество выполнений ваших макросов, переписав их как:ex команды и ограничив диапазон строк, в которых они выполняются. Например:

qw:%s/\s\+$//^Mq
qe:%s/\n\n *}/\r}/^Mq

где ^M означает ввод вашей клавиши ввода или возврата. Я не проверял их вместе в вашем макросе Wrapper, но думаю, вы сможете исправить любые ошибки, которые я мог допустить.

12

Я предлагаю вам использовать :try "поглотить" ошибку субмакро.

Вот глупый пример:

:let @a='f|dt|@a'
:let @q=':try|exe "norm! @a"|endtry^Mj0@q'
@q

Ваш макрос-обертка будет выглядеть примерно так:

let @r=':retab^M:try|exe "norm! @w"|endtry|try|exe "norm! @e"|endtry^M'
1

Я регулярно создаю макросы на лету, когда мне нужно выполнить повторяющуюся задачу среди множества файлов. В моем случае в VIM установлено NERDtree (http://www.vim.org/scripts/script.php?script_id=1658), которое создает окно vsplit , а слева у меня есть список всех файлов. в текущем каталоге. В одном примере мне нужно найти первый экземпляр строки MY_TEST в файле, а затем удалить, если имеется, префикс, помеченный как CUSTOM_PREFIX- из этой строки, сохранить файл, а затем перейти к следующей.

Вот как у меня работает этот макрос на 2000 файлов в текущем каталоге. Я мог бы написать скрипт bash для этого, но в моем случае это быстрее в VIM. + Обозначает одновременное нажатие клавиш

# Start recording a macro sequence to register 'A'

q, a

# Search silently for the string "MY_TEST"; DO NOT report an error
# if the string could not be found.
:silent! /MY_TEST


# Replace, on just the current line, the string "CUSTOM_PREFIX-", with
# nothing (ie: delete it), and suppress any warning messages if the
# string could not be found on the current line.
:s/CUSTOM_PREFIX-//e


# Now issue some UI commands. CTRL-W then and arrow key lets you hope
# between tabs/splits/windows within vim.

CTRL+W,

# Scroll down to the next file in the list in NERDtree



# Open the next file

ВОЙТИ

# End the macro

Q

# Run the macro a thousand times in VIM

1000, @, a

Надеюсь это поможет!

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .