created 2004 · complexity advanced · author Mohit Kalra · version 5.7
Recursive mappings are fun to learn and really handy when you want to do repetitive tasks. One way to do this is by recording a macro, which can be done recursively. This is another way when you find that you are using the same editing pattern again and again. Recursion may seem a bit complicated at first but it is very intuitive once you get the hang of it. Here are two examples.
Suppose you have a file with the following contents:
aaa.txt bbbbbb.txt ccc.txt
You want to change the file as follows:
wc aaa.txt> aaa.log echo "HelloWorld" wc bbbbbb.txt > bbbbbb.log echo "HelloWorld" wc ccc.txt > ccc.log echo "HelloWorld"
A simple recursive mapping that will do the job is:
:map z Iwc <Esc>lyawA><Esc>pa.log<CR>echo "HelloWorld"<Esc>jz
Now type z
in the first line and everything else is magic.
Here is the breakup where {} contain the vim commands.
- Goto the beginning of the line and type "wc " and then come back to normal mode {Iwc <Esc>}
- Copy the word aaa (or bbbb or ccc). We do this by going right one character and copying the word under it. {lyaw}
- Goto the end of the line and append > and then come back to normal mode. {A><Esc>}
- Paste what we had copied {p}
- Append .log<CR>echo "HelloWorld" to the line. {a.log<CR>echo "HelloWorld"}
- Goto the next line but first we switch to the normal mode. {<Esc>j}
- Do steps 1 to 7 all overagain {z}
The recursion terminates when the j cannot take you one more line further. If you manually execute a command for one line, you will find it very intuitive to create recursive mappings.
Here is another example. Say you want to change:
#define myid 199 #define myid2 200 #define myid3 201
to:
#define myid 201 #define myid2 202 #define myid3 203
The simple mapping would be:
:map z 2^Ajz
where ^A is CTRL_V+A
- Add 2 to the number in the line
- Go down one line.
- Do steps 1 to 3 again.
References
- :help recursive_mapping
- :help CTRL-A
- :help 'nowrapscan' when using recursion with searching
Comments
>How does one stop a recursion that starts with a search?
:set nowrapscan
See the "References" section above.
The terminating condition for such a recursive mapping is that the search should not find anything. If the wrapscan is on, the search starts from the top of the document again. So setting wrapscan to off makes sure that the search has a terminating condition.
I think nmap z /^\*\*\*\*\*k"Ay}3jz
should be
nmap z /^\*\*\*\*\*<CR>k"Ay}3jz