每行视觉选择的 Vim 宏

我希望对所选内容中的每一行都运行一个宏,而不是在头脑中累计行数。例如,我可以编写一个宏来转换:

Last, First

进入

First Last

我想让它在所有这些线上运行:

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

Vim 大师有什么想法吗?

编辑: 这只是一个例子,很明显这是一个普通的可重复可表示的实例,但是还有一些实例并不是那么简单,所以我更愿意使用宏。

25949 次浏览

Select the lines then press : to enter command mode. Vim will automatically fill in '<,'>, which restricts the range to the selected lines. For your example you can use the :s command to do the swap:

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

This will swap two words separated by a comma on every line in the visual selection.

You can also use '< and '> like any other bookmark or line position, e.g. as part of a movement command, so in normal mode d'< will delete from the current cursor position to the start of the first line in the visual selection. The marks remain in effect even if the block is not longer visually highlighted.

If you want to replay a recorded macro on every line the you need to execute the macro with the :normal command. Unfortunately the :normal command does not operate on a range of lines, but you can fix that with the :global command. This runs an :ex command on every line that matches a regex, so you can do this:

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

Explanation:

:'<,'>       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

Suppose you had a macro q that ran (and remained) on a single line. Then you could run it on every line in your selection with:

:'<,'>normal @q

(if you already have a group of lines selected, hitting : produces :'<,'> on the command line)

For example, the following macro capitalizes every word but the first on a line:

:let @q="^dwgU$P"

So running it on the following (where the + lines are selected)

 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.

With the above normal @q command, produces:

 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.

You can add the function below to your ~/.vimrc or simply copy it on your browser and running :@+

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

The advantage is that you can apply any macro on the visual selection. You need to give the macro letter as argument, like:

:Rover a