How do I make a macro conditionally execute commands based on line content?
Answer
:if condition | execute 'normal cmd' | endif
Explanation
How it works
Vim macros can include Ex commands with conditional logic. By using :if ... | ... | endif inside a macro, you can make the macro behave differently depending on the content of the current line, a variable value, or any other Vimscript expression.
During macro recording, you type the full :if command on the command line and press Enter. The pipe | character separates multiple Ex commands on a single line. The execute command runs a string as an Ex command, and normal executes normal-mode keystrokes.
The conditional can test anything:
getline('.') =~ 'pattern'-- current line matches a patterncol('$') > 80-- line is longer than 80 charactersline('.') % 2 == 0-- current line number is even@a != ''-- registerais not empty
Example
To record a macro that comments out lines containing TODO and skips others:
- Record:
qa:if getline('.') =~ 'TODO' | execute 'normal I// ' | endif<CR>jq - This checks if the current line contains
TODO - If yes, it prepends
//to comment it out - Either way, it moves down with
j - Run
20@ato process 20 lines
Given:
int x = 1;
// TODO: fix this
int y = 2;
TODO: refactor
After running the macro on each line:
int x = 1;
// // TODO: fix this
int y = 2;
// TODO: refactor
This technique bridges the gap between simple macros and full Vimscript functions, letting you add branching logic without leaving macro recording.