vimtricks.wiki Concise Vim tricks, one at a time.

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 pattern
  • col('$') > 80 -- line is longer than 80 characters
  • line('.') % 2 == 0 -- current line number is even
  • @a != '' -- register a is not empty

Example

To record a macro that comments out lines containing TODO and skips others:

  1. Record: qa:if getline('.') =~ 'TODO' | execute 'normal I// ' | endif<CR>jq
  2. This checks if the current line contains TODO
  3. If yes, it prepends // to comment it out
  4. Either way, it moves down with j
  5. Run 20@a to 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.

Next

How do you yank a single word into a named register?