Recording Macro
Need for Macro
The repeat command can only repeat the last change. It also gets overwritten with every editing command. The q
command allows user to record any sequence of editing commands to effectively create a user defined command, which can then be applied on other text across files. It can also be prefixed with a number to repeat the command. Powerful indeed!
Steps
- Press
q
to start recording session - Use any alphabet to store the recording, say
a
- Use the various editing commands in combination with movement commands to accomplish the sequence of editing required
- Press
q
again to stop recording - Use
@a
(the alphabet typed in step 2) to execute the recorded command elsewhere5@a
execute 5 times@@
execute last recorded macro
Example 1
qwceHello<Esc>q
q
start recording- save recording to
w
register ce
change till end of wordHello
literally type these characters<Esc>
denotes pressingEsc
key, one can type it in Insert or Command Line mode by pressingCtrl+v
followed by pressingEsc
key- Note-1: It looks like
^[
but is a single character - Note-2: if you are using
gvim
andCtrl+v
is mapped to something else,Ctrl+q
can be used instead
- Note-1: It looks like
q
stop recording- Now, in Normal mode, wherever you press
@w
, it will clear text until end of word and insert the charactersHello
- To use the last recorded macro,
@@
can be used without having to remember which register was used to save the recording
What if you made a mistake and you wanted 'Hello!'
instead of Hello
? Instead of meticulously recording the sequence again, we can take advantage of the fact that we are using registers to record and play the macro
"wp
will paste contents ofw
register, which isceHello<Esc>
- Note that in Vim, it will look like
ceHello^[
- Note that in Vim, it will look like
- change it to
ce'Hello!'<Esc>
- then visually text the sequence and press
"wy
to replace the contents ofw
register to this new sequence- this can be achieved in non-visual mode as well by placing cursor at start of sequence and then
"wy
followed by appropriate movement to copy till end of sequence
- this can be achieved in non-visual mode as well by placing cursor at start of sequence and then
- now
@w
will clear text until end of word and insert the characters'Hello!'
- to use this recording in a portable manner, add
let @w = "ce'Hello!'<Esc>"
to~/.vimrc
- Note again that you need to type the
<Esc>
key usingCtrl+v
followed byEsc
key in Insert mode
- Note again that you need to type the
Now, suppose, you wanted to change only the starting word of a line, irrespective of where the current position of cursor is
^ce'Hello!'<Esc>
How about changing starting word of multiple lines bunched together?
^ce'Hello!'<Esc>j
we need to first end the recording by going to next line5@w
whatever count of lines to modify
Hmm, all this is fine, but how to change only those lines in the file whose starting word is Hi
to 'Hello!'
And they are not bunched next to each other
:g/^Hi/ normal @w
use the:g
command to filter the lines and then execute the Normal mode command@w
- Note: This particular editing can easily be done using
:% s/^Hi/'Hello!'/
This example was used to only show how to use theq
macro recording
Example 2
Suppose, we forgot braces in Perl for single statement control structures
if($a > 4)
print "$a is greater than 4\n";
# some other code here
if($word eq reverse($word))
print "$word is a palindrome\n";
o{<Esc>jo}<Esc>
record the sequence for one statement in a register sayp
:g/\<if(/ normal @p
execute the macro for all occurences- When dealing with multiple lines, recording macro with
q
might be cleaner than using:s
if($a > 4)
{
print "$a is greater than 4\n";
}
# some other code here
if($word eq reverse($word))
{
print "$word is a palindrome\n";
}
Example 3
Suppose we need to convert these lines in markdown text
# <a name="intro-guide"></a>Intro Guide
# <a name="basic-steps"></a>Basic steps
# <a name="advanced-usage"></a>Advanced Usage
# <a name="further-reading"></a>Further Reading
to table of contents, like this
* [Intro Guide](#intro-guide)
* [Basic steps](#basic-steps)
* [Advanced Usage](#advanced-usage)
* [Further Reading](#further-reading)
$T>d$0r*la[<Esc>pa]<Esc>lcf"(#<Esc>f"C)<Esc>j
say this is saved inb
register$
move to end of lineT>
move to character after last occurence of '>' in the lined$
delete upto end of line0
move to first column of liner*
replace '#' with '*'l
move cursor one character righta[<Esc>
append '[' and change to Normal modep
paste the earlier deleted contenta]<Esc>
append ']' and change to Normal modelcf"(#<Esc>
move cursor one character right, clear text upto next double quote, insert '(#' and change to Normal modef"C)<Esc>j
move cursor to next double quote, clear text till end of line, insert ')', change to Normal mode and move cursor one line down
4@b
on first line, as they are bunched together- or
vip: normal @b
- or
- Note: again, this is a demonstration and
s/\v.*"(.*)".*\>(.*)/* [\2](#\1)/
is perhaps better option