vim: Продовжити макрос після помилки в субмакросі?


15

Я в процесі прикраси деякого вихідного коду за допомогою vim. {1}

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

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

Чи є спосіб змусити макрос vim продовжуватись після появи субмакросу помилки?

{1} Мені відомо про автоматичні переформатори. Я навіть можу використовувати їх у моїй поточній проблемі. Я просто згадав переформатування джерела заради прикладу. Не публікуйте жодних відповідей щодо цього кращого джерела чи іншого. Питання полягає не в переформатуванні коду як такого , а в макросах vim.

Приклад:

  • Макрос 1 - обрізка пробілів пробілів - qw/\s\+$d$@wq
  • Макрос 2 - видалення порожніх рядків до} - qe/\n\n *}dd@eq
  • Макрос обгортки - повторне тестування, макрос 1, макрос 2 - qr:retab@w@eq

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

Пояснення:

Що я шукаю - це як викликати субмакро, щоб після закінчення цього субмакросу макрос виклику продовжувався?

Відповіді:


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'

У той час як garyjohn передбачений обхідний шлях для НЕ має помилки в submacro, це єдина відповідь , який на самому справі обробляти таку помилку. Я маю вибачення, хоча; Я не перевірив вашу відповідь вчасно, щоб отримати (зараз термін дії) щедрості ... :-(
DevSolar

26

Якщо збіжна команда є заміною, яка не знаходить свого шаблону, наприклад,

:%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означає введення клавіші Enter або Return. Я не перевіряв їх разом у вашому Wrapper Macro, але, думаю, ви зможете виправити будь-які помилки, які я могла допустити.


У моєму випадку це не заміна, а проста знахідка (тобто /foo). Хоча :silent!справді хитрість рекурсивного субмакросу не припиняла макрос обгортки, тепер субмакроза зовсім не припиняється ... і я підозрюю, що зробити так, щоб якимось чином знову закінчився, знову також припинить макрос обгортки. Здається, я застряг. : - \
DevSolar

Важко сказати, що може бути не так, не бачачи макросів, які ви використовуєте, чи простого прикладу, який виявляє ту ж проблему.
garyjohn

Додано приклад.
DevSolar

2

Для мене працювало поєднання відповідей @Peter Rincker та @garyjohn. Окремо я просто продовжував отримувати дивні проблеми.

nnoremap <leader>rt :silent! %s/\s\+$//e<CR>
let @r='\rt'
let @t=':try|silent! exe "norm! @r"|endtry|w^M'

Я думаю, що клавіші " silent!in" <leader>rtта "pipe" між клавішами endtryта the wбули клавішами - просто перерив лінії після endtryневдачі. Програма tryпрацювала, коли я просто вводив їх, але коли запускати як макрос, помилка щодо тексту пошуку не знайдена, і надалі збільшуватиметься.


1

Я регулярно створюю макроси на ходу, коли мені потрібно робити багаторазове завдання серед багатьох файлів. У моєму випадку я маю NERDtree ( http://www.vim.org/scripts/script.php?script_id=1658 ), встановлений у VIM, який створює 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

ENTER

# End the macro

q

# Run the macro a thousand times in VIM

1000, @,a

Сподіваюся, це допомагає!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.