More Vim: Save Time With Macros

by Matthew Russell

The following is a section that we left out of this week's Mac DevCenter article What Is Vim (It's Easier than You Think) because of length constraints. I hope you find it useful as one more point on your radar screen as you ponder the productivity that Vim may be able to add to your daily workflow.

Save Time With Vim Macros

Do you find yourself frequently whipping out the python interpreter or cooking up regular expressions in Perl just to munge some text? Even if you're already really good, I bet Vim macros can still make you even better. A Vim macro is simply a set of keystrokes that you can record and use over again to perform repetitious tasks.

But wait a tick. "What's wrong with regexes," you ask? We'll, consider this conventional wisdom:

Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems. --Jamie Zawinski, in comp.lang.emacs

Although I do commonly use regular expressions in production level code that I write, day-to-day events involving a quick transform of a text file hardly require the effort of cooking up a regex. Read on to see why.


2006-07-12 00:46:36

Ach, the regex in vim is only:

:%s/^[0-9]* -- \(.*\) \(([0-9]*)\)$/<li><em>\1<\/em> \2<\/li>/

It's pretty straightforward. :-) I suppose, in vim style, followed up with :

  • 1GO

  • <ol>

  • press escape

  • 0Go

  • </ol>

  • press escape

2006-07-12 04:40:32
By the way, one thing that would makes long regexes involving forward slashes easier to read (for me, anyway) would be to substitute the forward slashes that separate the actual pieces of the substitute command with something else, like hash characters. i.e. instead of substituting a command with :%s/foo/bar/ you can type :%s#foo#bar Sometimes that ends up saving you some trouble. At any rate, the first time I discovered that (you can do it with Perl too as I recall), I thought it was pretty neat.
2006-07-12 09:36:19
I use this recording all the time. One question I have, is there any way to save this recorded macro? Granted, these are usually just throw away scripts, but there are times it'd be nice to save.
2006-07-12 19:09:33
A book I recommend to everyone I know is Stephen Covey's Seven Habits of Highly Effective People. I just ran across a document by the primary developer of Vim himself that uses this particular motif. It's a really good read too. I highly recommend reading it. It has some good tips in it:

2006-07-12 19:12:35
@Mark: Unfortunately, I'm not aware of a way to save the macro itself between sessions. To repeat this sequence of keystrokes, I believe you'd have to write a Vim script that you could call or else map the series of keystrokes with one of the "map" commands. Of course, you could always send in feature request to Bram Moolenaar and ask him to provide this capability for you (or hack at it yourself, if you dare!)
2006-07-13 08:37:37
You can insert the contents of the register into a text buffer using the " command. Using the article as an example, you could type (in normal mode)


and this would insert the contents of the w register (where the macro was stored) at the current cursor location. You can read more about working with registers by typing

:help registers.

2006-07-13 11:13:10
@Clint: Awesome tip! that's the thing about Vim...just when you think you're getting good, you find out there's a whole lot you never even knew about!
2006-07-14 09:24:36
@Clint: ditto. This is really an amazing program. And just when you think you've learned all you'll need, you can always get plugins to make it do more. A quick and dirty favorite of mine is "Align". If you have a section of code with say "='s" and you want them all lined up (as you should!), you can use Align to quickly neaten things up.Like most things vim, it does much more too.

2006-07-18 08:32:37
@Mark: Registers can indeed be saved between sessions. I have the following line in my ~/.vimrc file:

set viminfo=%,'50,\"100,n~/.viminfo

"100 tells vim to save the first 100 lines of each register in the viminfo file. Once I've recorded a macro, it is available in all future vim sessions until I overwrite it.

:help 'viminfo'
:help viminfo

2006-07-22 22:49:47
Only problem with this macro, is that you really need 2 or use a small regex.
xxxxx Works for the first 9 lines, then you need xxxxxx otherwise you end up with a leading space.

Still, I have learnt some things here, and it's a bit of a wake up call, to learn some of the more advanced Vim features! :-D

2006-08-10 17:59:44
Instead of


you can use


followed by a space (in normal mode, of course). This will overcome the preceding space problem and can be extended to lists with more than 99 elements.

2007-03-25 16:39:22
For anyone who sees this in the future you can also use d2W or 2dW to delete the first 2 WORDS.

see help for word for the difference betweens words and WORDS.

2007-10-15 00:54:25
This is great, people. You finally forced me to learn macros. I've escaped regex Hell!
2007-12-20 16:25:26
Nice tip! I am a 20 year vi user just being forced onto PC's from Unix and learning VIM. I love it! Do you know if it is possible to save a recorded macro so that it can be used next week or next year? Can it be predefined in the .vimrc file? Thanks.
2008-01-19 15:58:07
Instead of "$a" to append at EOL you can use "A"
2008-03-28 20:18:09
personally I would do it with three quick regex find and replaces which are quicker than recording the macro or doing the whole search and replace in a single line with \1 captures.

:%s:.*-- :

  • :
    :%s: (:
  • :
    2008-03-28 20:21:20
    stupid comment system ... whats the verbatim tag round here? Theres sposed to be html tags in the comment above ...
    2008-04-22 12:28:45
    You can also use regexp's in a series for doing one-off transformations, you don't have write a big complicated single one.

    I do wish that vim supported 'normal' extended regexp's though (so you could do /^.*? -- /); not having that makes it a little harder to do it right:

    :%s/^\d\d* --/<li><em>/g
    :%s,\( (\d\d*)\),</em>\1</li>,g

    And for the macro'ed version I would use:

    0d2Wi<li><em> .escape. t(i</em> .escape. A</li> .escape. j

    0 - goto start of line
    d2W - delete 2 words
    i - insert ... escape
    t( -- go to the next (
    i - insert ... escape
    A - append to end of line
    j - down a line

    P J Moy
    2008-08-03 13:02:49
    Thanks! I've been looking for a replacement for the VMS TPU editor's learn and repeat commands.

    This seems to fit the bill, and is a nice writeup.

    Brian H
    2008-08-03 15:07:45
    Actually I would tackle this a different way:

    :%s/^\d\+ --
    gg c-v G I

  • :%s: (:

  • G o
    gg O

      But that's just how I've evolved.

    Brian H
    2008-08-03 15:16:11
    This comment system could use a cheatsheet.

    :%s/^\d\+ -- <cr>
    gg <c-v> G I <li><em><esc>
    :%s: (:</em>&<cr>
    G o <ol><esc>
    gg O </ol><esc>