Reusable Editing With Macros
Vim loves saving you time and hassle, and offers you lots of ways in which you can repeat commands:
- The
.
command lets you repeat the last change. - The
;
and,
commands let you repeat the last character search forwards and backwards respectively. n
andN
let you repeat the last search also forwards and backwards./
and?
also let you repeat the last search forwards or backwards.:@
and@@
let you repeat Ex commands.
Vim macros take this power of repetition to the next level by allowing you to record a collection of commands as you type them, and then replay them at will. As such, macros become reusable editing actions that can save you a lot of time.
Creating a New Vim Macro
You create a new macro by following this process:
- Type
q{register}
to start recording a macro (e.g.qq
will start recording a macro to registerq
) inside a register. - Perform the different actions you want to include in the macro.
- When you’re done, type
q
to end the recording.
From then on, you can replay the macro whenever you want:
- Type
@{register}
(e.g.@q
) to execute the macro that lives in a givenregister
.
Once you’ve run a macro once, you can repeat the last macro by typing @@
. This follows the same spirit of the other repeater commands in Vim.
Macros in Action
Let’s use an example to illustrate the use of macros in Vim. Imagine that you have a list of some common items that you could find in any 8-bit fantasy RPG shop sold by an extremely boring NPC. They are separated by commas like this:
rusty sword,obsidian dagger,silver poniard,broadsword
And now imagine that you want to grab that list and turn that into HTML. Web 1.0 here we come. The resulting HTML would look like this:
<ul>
<li>rusty sword</li>
<li>obsidian sword</li>
<li>silver poniard</li>
<li>broadsword poniard</li>
</ul>
A possible approach to solve this problem is to create a macro that encapsulates the process of grabbing an item from a list and putting inside a li
element.
So, starting with the cursor in the first letter of the list:
v
rusty sword,obsidian dagger,silver poniard,broadsword
we can do as follows:
- Start by recording the macro in the
q
register withqq
. - Then use
f,
to find the first,
. - Type
cw<Enter><ESC>k
to remove the comma and move the list but for the first item to the next line then back up:
--- cursor is here
/
/
|
v
rusty sword
obsidian dagger,silver poniard,broadsword
- Now
I<li><ESC>
to insert the opening tag. - Then
A</li><ESC>
to insert the closing tag. - Move to the beginning of the line below
j0
. - Finish recording the macro by typing
q
:
<li>rusty sword</li>
obsidian dagger,silver poniard,broadsword
^
\
\
----- cursor is here
Now just type @q
to replay the macro and you’ll get this:
<li>rusty sword</li>
<li>obsidian dagger</li>
silver poniard,broadsword
Now type @@
to repeat the last macro:
<li>rusty sword</li>
<li>obsidian dagger</li>
<li>silver poniard</li>
broadsword
If you try to use our macro again, you’ll be surprised to find that nothing happens. Why? Because Vim can’t find any comma, the macro stops executing. We can fix this by adding a comma at the end before we start processing the line of items:
rusty sword,obsidian dagger,silver poniard,broadsword,
And now if we combine the power of counters with macros we can process the whole line of items at once. Type 4@q
:
<li>rusty sword</li>
<li>obsidian dagger</li>
<li>silver poniard</li>
<li>broadsword</li>
You’ve completed your task (victory dance).
I hope this example was illustrative of the power of macros and it serves as inspiration in you future coding sessions. The greatest thing about macros is that you can use the same techniques (motions, operators, counts, etc) you normally use to write code and package them so that they can be reused later.
Written by Jaime González García , dad, husband, software engineer, ux designer, amateur pixel artist, tinkerer and master of the arcane arts. You can also find him on Twitter jabbering about random stuff.