How do I make a macro that finds and operates on specific patterns?
Answer
qq /pattern<CR> {commands} q
Explanation
By incorporating a search command inside a macro, you can make it jump to the next occurrence of a pattern before performing its edits. This makes macros far more robust than relying on fixed cursor movements.
How it works
- Start recording:
qq - Search for the target:
/pattern<CR> - Perform the edit at the match
- Stop recording:
q - Replay:
@qor100@q(stops when search finds no more matches)
Example: Wrap all function calls in try-catch
qq " Start recording
/\<fetch(\><CR> " Search for fetch(
ciwtry { await fetch(<Esc> " Change and wrap
f)a) } catch(e) {}<Esc> " Complete the wrapper
q " Stop recording
100@q " Apply to all remaining matches
Why search-based macros are superior
- Position-independent: The macro finds its target regardless of where it is
- Self-terminating: When
100@qhits a search that fails (no more matches), the macro stops automatically - Pattern-precise: You operate on exactly what you want, not just whatever happens to be at the cursor
Another example: Add type annotations
qq /\vlet (\w+) =<CR> " Find 'let x =' declarations
ea: string<Esc> " Append ': string' after the variable name
q
50@q " Apply to next 50 matches
Tips
- Use
ninside a macro instead of/pattern<CR>to repeat the last search - The macro auto-aborts when the search fails — this is a feature, not a bug
- Combine with
:g/pattern/normal @qfor guaranteed execution on every match - Test the search pattern with
/patternfirst before recording the macro