In the video, I find all occurrences of Vimcasts.com
and change them to Vimcasts.org
. I show two different ways of doing it. This builds on material that was introduced in episodes 41, 42, 43, and 44.
Strategy #1 - run :substitute across all project files
The first strategy is to populate the arglist with all of the files in the project, then run the substitute command against them all:
:args *.txt :argdo %s/Vimcasts\.\zscom/org/ge :argdo update
This may mean that the substutite command runs in buffers that don’t contain a match.
Strategy #2 - run :substitute across project files that contain a match
The second strategy breaks the substitute command into two steps: find all matches, then run the substitute command only in those buffers that contain a match. Here are the steps:
:args *.txt :vimgrep /Vimcasts\.\zscom/g ## :Qargs :argdo %s/Vimcasts\.\zscom/org/ge :argdo update
This uses a custom :Qargs
command to prune the arglist of buffers that don’t contain a match.
The :Qargs helper command
The custom :Qargs
command sets the arglist to contain each of the files referenced by the quickfix list. You add it to Vim by copying these lines into your vimrc file:
command! -nargs=0 -bar Qargs execute 'args' QuickfixFilenames() function! QuickfixFilenames() " Building a hash ensures we get each buffer only once let buffer_numbers = {} for quickfix_item in getqflist() let buffer_numbers[quickfix_item['bufnr']] = bufname(quickfix_item['bufnr']) endfor return join(map(values(buffer_numbers), 'fnameescape(v:val)')) endfunction
Or you could install the vim-qargs plugin from github. Credit where due: I adapted this code from a Stack Overflow solution posted by Dr Al.
Proposal: :cdo
Vim needs a :cdo {cmd}
command. It would behave like the :argdo
and :bufdo
commands, except that it would iterate through the quickfix list. The :cdo {cmd}
command would work as follows:
:cfirst :{cmd} :cnfile :{cmd} etc.
If such a command existed, then we could refine Strategy #2, removing the :Qargs
step:
:args *.txt :vimgrep /Vimcasts\.\zscom/g ## :cdo %s/Vimcasts\.\zscom/org/ge :cdo update
UPDATE on June 2nd, 2013, Yegappan submitted a patch to add native :cdo
and :ldo
commands to Vim’s core.
:cdo implementations in the wild
Henrik Nye created a :Qdo
command in his fork of my Qargs plugin. This takes the slightly dirty approach of populating the arglist from the contents of the quickfix list, then using the built-in :argdo
command to iterate over the resulting arglist. Of course, this has the side-effect that it changes the contents of the arglist. That’s tolerable, but not ideal. Henrik has written up how to use :Qdo
for project wide search and replace.
Peter Jaros created vim-cdo
, which includes :Cdo
as well as :Ldo
for operating on the location list. Peter’s plugin differs slightly from the formula I described above, because it effectively uses :cnext
instead of :cnfile
.
Further reading
:help /\zs
:help :argdo
:help :bufdo
:help :vimgrep
:help :substitute
- Vimcast #41 - Meet the arglist
- Vimcast #42 - Populating the arglist
- Vimcast #43 - Using :argdo to change multiple files
- Vimcast #44 - Search multiple files with :vimgrep
- Practical Vim tip 77 - Stake the boundaries of a match
- Practical Vim tip 96 - Find and replace across multiple files
- Project wide search and replace in Vim with Qdo
- Stack overflow: Search & replace using quickfix list in Vim
- Stack overflow: How to do search & replace with ack in Vim
- Yegappan’s patch for native
:cdo
and:ldo