Макрос Vim на каждой строке визуального выделения


86

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

Last, First

В

First Last

и я бы хотел, чтобы он запускался во всех этих строках:

Stewart, John 
Pumpkin, Freddy
Mai, Stefan
...

Есть идеи гуру Vim?

РЕДАКТИРОВАТЬ: это просто пример, очевидно, что это тривиально регулярное выражение, но есть и другие случаи, которые не так просты, что я бы предпочел использовать макросы.


1
Честно говоря, я бы, вероятно, выполнил эту конкретную задачу с помощью регулярного выражения. Но вопрос остается актуальным и для более сложных случаев.
Jamie Wong

Почему vim? На мой взгляд, sed более подходящим.
kokosing

8
@kogut: зачем выходить из редактора, чтобы редактировать текст с помощью однострочного регулярного выражения?
Стивен

1
Хорошо, вы поняли;)
kokosing

Ответы:


154

Предположим, у вас есть макрос, qкоторый запускается (и остается) в одной строке. Затем вы можете запустить его в каждой строке вашего выбора с помощью:

:'<,'>normal @q

(если у вас уже выбрана группа строк, нажатие :производит :'<,'>в командной строке)

Например, следующий макрос использует каждое слово в строке, кроме первого:

:let @q="^dwgU$P"

Итак, запустите его на следующем (где +выделены строки)

 0000: a long long time ago
 0001: in a galaxy far away
+0002: naboo was under an attack
+0003: and i thought me and qui-gon jinn
+0004: could talk the federation in
 0005: to maybe cutting them a little slack.

С помощью приведенной выше normal @qкоманды производит:

 0000: a long long time ago
 0001: in a galaxy far away
 0002: naboo WAS UNDER AN ATTACK
 0003: and I THOUGHT ME AND QUI-GON JINN
 0004: could TALK THE FEDERATION IN
 0005: to maybe cutting them a little slack.

@Roger Pate: ну да, если ты хотел поиграть в гольф :)
rampion

1
@rampion: в вашей команде опечатка? для меня это работает только так::'<,'>normal! @q
oliver

3
@oliver: проверьте свои сопоставления - возможно, вы переназначили @q. From :help normal- «Если задано [!], Сопоставления не будут использоваться».
rampion

2
@rampion: блин ... ты прав! Я использую yankring и, по-видимому, здесь проблема: ... Вы не можете выполнить макрос с помощью ": normal @a". Это по-прежнему невозможно, но вы можете выполнить это с помощью ": normal! @A" (из справочной документации yankring)
Оливер

1
Я лично хотел бы отобразить @в визуальном режиме , как это: vnoremap @ :normal @. Таким образом, вы все еще можете делать @aто, что ожидаете (хотя вам нужно будет нажать Enter после :()
LondonRob

19

Выберите строки и нажмите, :чтобы войти в командный режим. Vim автоматически заполнит '<,'>, что ограничивает диапазон выбранными строками. В вашем примере вы можете использовать :sкоманду для обмена:

:'<,'>s/\(\w\+\), \(\w\+\)/\2, \1/

Это поменяет местами два слова, разделенных запятой, в каждой строке визуального выделения.

Вы также можете использовать '<и, '>как любую другую закладку или позицию строки, например, как часть команды перемещения, поэтому в нормальном режиме d'<будет удаляться от текущей позиции курсора до начала первой строки в визуальном выборе. Метки остаются в силе, даже если блок больше не выделяется визуально.

Если вы хотите воспроизвести записанный макрос в каждой строке, вам необходимо выполнить макрос с помощью :normalкоманды. К сожалению, :normalкоманда не работает с рядом строк, но вы можете исправить это с помощью :globalкоманды. Это запускает :exкоманду в каждой строке, соответствующей регулярному выражению, поэтому вы можете сделать это:

:'<,'>g/^/ norm @a

Пояснение:

:'<,'>       for every line in the visual block
g/^/         on every line that matches the regex /^/ - i.e. every line
norm         run in normal mode
@a           the macro recorded in a

Это лучше, чем принятый ответ, потому что он поддерживает макросы, которые добавляют новые строки.
Ян Вархол

@ Dave, Кирби Может быть лучше было бы обмен ^с , .чтобы сделать запуск макроса только на линиях , что имеет какой - то текст, не будет?
SergioAraujo

1

Вы можете добавить указанную ниже функцию в свой ~/.vimrcили просто скопировать ее в своем браузере и запустить:@+

fun! RunMacroOverSelection(macroname)
    execute "'<,'>normal @". a:macroname
endfun
com -nargs=1 Rover :call RunMacroOverSelection(<f-args>)
nnoremap <leader>r :Rover<space>

Преимущество в том, что вы можете применить любой макрос к визуальному выделению. Вам нужно указать букву макроса в качестве аргумента, например:

:Rover a
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.