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
qto 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
qagain to stop recording - Use
@a(the alphabet typed in step 2) to execute the recorded command elsewhere5@aexecute 5 times@@execute last recorded macro
Example 1
qwceHello<Esc>qqstart recording- save recording to
wregister cechange till end of wordHelloliterally type these characters<Esc>denotes pressingEsckey, one can type it in Insert or Command Line mode by pressingCtrl+vfollowed by pressingEsckey- Note-1: It looks like
^[but is a single character - Note-2: if you are using
gvimandCtrl+vis mapped to something else,Ctrl+qcan be used instead
- Note-1: It looks like
qstop 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
"wpwill paste contents ofwregister, 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
"wyto replace the contents ofwregister to this new sequence- this can be achieved in non-visual mode as well by placing cursor at start of sequence and then
"wyfollowed 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
@wwill 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+vfollowed byEsckey 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>jwe need to first end the recording by going to next line5@wwhatever 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 @wuse the:gcommand 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 theqmacro 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 @pexecute the macro for all occurences- When dealing with multiple lines, recording macro with
qmight 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>jsay this is saved inbregister$move to end of lineT>move to character after last occurence of '>' in the lined$delete upto end of line0move to first column of liner*replace '#' with '*'lmove cursor one character righta[<Esc>append '[' and change to Normal modeppaste 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>jmove cursor to next double quote, clear text till end of line, insert ')', change to Normal mode and move cursor one line down
4@bon 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