There are two 'types' to be aware of with a quickfix window:
- entry: the actual line content (e.g.
:grep foo
will show a specific line that matched within a file). - file: the actual file itself (e.g. the path to the file that contained the match).
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.txt
example2.txt
The 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
cfdo
with%s/foo/bar/e | update
which will write the buffer once, rather than the multiple times compared tocdo
withs/foo/bar/e | update
. It's also much more efficient usingcfdo
as 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
Awesome notes 👏 Now I understand the difference between cdo and cfdo.
Thank you