Vim Macros

3 Jul 2012

The problem

Today I was writing some code for handling interrupts. At one point I needed the following piece of code

extern void isr0(void), isr1(void), isr2(void), isr3(void), isr4(void), isr5(void), isr6(void), isr7(void), isr8(void), isr9(void), isr10(void), isr11(void), isr12(void), isr13(void), isr14(void), isr15(void), isr16(void), isr17(void), isr18(void), isr19(void), isr20(void), isr21(void), isr22(void), isr23(void), isr24(void), isr25(void), isr26(void), isr27(void), isr28(void), isr29(void), isr30(void), isr31(void), isr32(void), isr33(void), isr34(void), isr35(void), isr36(void), isr37(void), isr38(void), isr39(void), isr40(void), isr41(void), isr42(void), isr43(void), isr44(void), isr45(void), isr46(void), isr47(void);

The solution

Vim macros.

I've been using this site and my rewrite of my operating system as an excuse to learn vim. And today it payed off. To write the above piece of code I used the key presses

iisr0(void),<esc>0qayyp3l<ctrl>a0q46@a47k48J$r;Iextern void <esc>

Couldn't be easier!

OK, so maybe it could... Let's break it down.

Let's start with

iisr0(void),<esc>

i puts vim in Insert mode. There we write isr0(void), and finally leave Insert mode with the escape key.

Next is 0 to bring the pointer to the beginning of the line. Then comes the macro.

qayyp3l<ctrl>a0q

qa starts recording a macro into register a.

yyp yanks the current line and pastes it below.

3l skips over the i, s and r.

Ctrl+a increases the number under the pointer by one.

Finally 0 goes back to the beginning of the line and q stops the macro recording.

The next part:

46@a47k48J

runs the macro 46 times, steps up 47 times and joins the current line with the next 48 times. We now have

isr0(void), isr1(void), isr2(void), isr3(void), isr4(void), isr5(void), isr6(void), isr7(void), isr8(void), isr9(void), isr10(void), isr11(void), isr12(void), isr13(void), isr14(void), isr15(void), isr16(void), isr17(void), isr18(void), isr19(void), isr20(void), isr21(void), isr22(void), isr23(void), isr24(void), isr25(void), isr26(void), isr27(void), isr28(void), isr29(void), isr30(void), isr31(void), isr32(void), isr33(void), isr34(void), isr35(void), isr36(void), isr37(void), isr38(void), isr39(void), isr40(void), isr41(void), isr42(void), isr43(void), isr44(void), isr45(void), isr46(void),

and all we need to do now is replace the last comma with a semicolon using $r; and insert extern void at the beginning of the line using I.

Another example of macros

Starting with

INTNOERR 0

I used

qayypcwINTNOERR<esc>$<ctrl>a0q
qsyypcwINTERR<esc>$<ctrl>a0q
dd6@a@s@a5@s33@a

and ended up with

INTNOERR 0
INTNOERR 1
INTNOERR 2
INTNOERR 3
INTNOERR 4
INTNOERR 5
INTNOERR 6
INTNOERR 7
INTERR 8
INTNOERR 9
INTERR 10
INTERR 11
INTERR 12
INTERR 13
INTERR 14
INTNOERR 15
...
INTNOERR 45
INTNOERR 46

I love vim!

Application

So where did I use this? I've been writing some code for handling interrupts in the os. You can find it in Git commit 26dd8e4c75.

Comments

comments powered by Disqus
© 2012 Thomas Lovén - @thomasloven - GitHub