Tags: #vim #replace #macro #quickfix
There are two ‘types’ to be aware of with a quickfix window:
:grep foo will show a specific line that matched within a file).To replace content using vim (via the quickfix window) you need to choose whether you want to apply the change via the quickfix ‘entry’ or via the ‘file’ as a whole.
If you use cdo, then your ‘action’ (i.e. how you’re going to replace content) will be applied to every entry in the quickfix window.
If you use cfdo, then your action will be applied to each file in the quickfix window.
Using cdo is more straight forward, but cfdo is probably more efficient/performant.
To understand the difference, let’s consider an example scenario:
We have quickfix window that has two files:
example1.txtexample2.txtThe file example1.txt shows up multiple times, while example2.txt only shows up once.
The file example1.txt shows up multiple times because we searched for a phrase such as foo and that phrase happened to appear multiple times within example1.txt, while it only appeared once within example2.txt.
If you wanted to replace foo with bar using a subtitution like s/foo/bar/, and you used cdo, then all occurences of foo would be replaced because the substitution would be executed across each entry in the quickfix window. But if you used cfdo then the substitution would only be applied once to the file because you didn’t use % (e.g. :%s/foo/bar/ meaning apply the substitution across the entire buffer) so only the first line of the file would have the substitution applied.
You could still use cfdo but you would need to specify %.
NOTE: I’ve found that my quickfix window is updated frequently/dynamically when using certain build tools (e.g. vim-go with gopls), in this case I’m better off using
cfdowith%s/foo/bar/e | updatewhich will write the buffer once, rather than the multiple times compared tocdowiths/foo/bar/e | update. It’s also much more efficient usingcfdoas it won’t write the buffer multiple times.
To execute a substitution for every ‘entry’ listed in the quickfix window use cdo:
:cdo s/v2/v3/ | update
To execute a macro for every ‘file’ listed in the quickfix window, you would still use cdo and not cfdo! This is interesting because you might expect the macro to execute across the entire file, but remember that macros only execute once and if you need them to be executed multiple times then you need to tell them to execute across a ‘range’ (e.g. the entire buffer or a section of lines). So by using cdo instead it means you can rely on the macro being executed against every instance of the thing you’re searching for (even if it appears multiple times within a file).
:cdo execute "norm @q" | update