5

Macros can be repeated for every line matching a pattern with the global command as explained in this answer.

This applies to every single line, but is it possible to do it for every single match? so if I save in a macro ysiw" (yank surround in word ") I repeat it for every matching regex, for example: match1\|match2 So that:

match1 nomatch match2

would become

"match1" nomatch "match2"
2
  • 1
    Aside: my mnemonic for ys is « you surround »
    – D. Ben Knoble
    Oct 19, 2019 at 13:18
  • @d-ben-knoble. I like that. Thank you for the tip!
    – Blasco
    Oct 20, 2019 at 21:51

3 Answers 3

6

Another way that also works across files is to use :h :vimgrep with g flag:

            Without the 'g' flag each line is added only once.
            With 'g' every match is added.

The workflow is:

  • Init your search pattern with /your pattern, record your macro in q.
  • Find all matching in your interested files:
    vimgrep //g  **/*.cpp **/*.h
  • Reverse quickfix result with this command:
    command! ReverseQuickFixList call setqflist(reverse(getqflist()))

This step is necessary, as there might be multiple matches in a line, the second matching position might be invalidated after you apply your macro on the 1st matching. You need to do this in reverse order, but there has no creversedo.

  • Apply your macro
    cdo norm! @q

Note that :h :cdo doesn't stop if an error occured in the middle. If that's a problem, jump to 1st matching with :cfirst, record a another macro:

qp@q:cnext<cr>q
          ^-------carriage return

Repeat it with sufficient large number, it will stop at 1st error.

1000@p
1
  • If we go with the macro approach, another convenient way is to use CtrlSF plugin to go between files as we can directly edit the search buffer.
    – Blasco
    Oct 20, 2019 at 21:56
4

Search for your pattern using /, then play your macro @@—you can record a new macro for this by doing

/pattern<CR>qqn@aq

Assuming @a holds your original macro. Then @q will jump to the next occurrence and play your macro. (For this case, you may need qqn@anq.)

In this case, you also do

:%substitute/pattern/"&"/g
5
  • But this will apply the macro to the next match, not to all of them right? I'm not sure if I understood it correctly. I'm looking for a way to apply the macro to every single (all of them) matching pattern at once
    – Blasco
    Oct 19, 2019 at 13:16
  • Yes—it applies to each match. You could hammer @, or or you could @999q, if you wanted to hit all. Unfortunately, global is just too linewise to use it here.
    – D. Ben Knoble
    Oct 19, 2019 at 13:17
  • The proposed method doesn't work quite good. If you do ysiw" with vim fugitive it will position you in such a way that when you repeat it goes into the same word, so it keeps adding quotes to the same match.
    – Blasco
    Oct 19, 2019 at 13:21
  • surround, not fugitive, @Blasco, but point taken. See my substitute addendum. The first method works for most macros, but you could always add another n after @a for this case
    – D. Ben Knoble
    Oct 19, 2019 at 13:23
  • You can play the macro multiple times if you do n@@ too.
    – eyal karni
    Oct 19, 2019 at 13:26
1

Another possible answer is using vim-visual-multi.

First, select the pattern everywhere. To do so, use \\/ and then \\A to select all. And then \\@ with the macro register.

In your case, you could have done S" instead of using the macro after \\A.

2
  • Unfortunately vim-visual-multi doesn't play quite well with plugins
    – Blasco
    Oct 20, 2019 at 21:46
  • Really, with what plugins? Maybe the keyboard mapping are similar
    – eyal karni
    Oct 21, 2019 at 6:53

This site is temporarily in read-only mode and not accepting new answers.

Not the answer you're looking for? Browse other questions tagged .