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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.