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
:cdoand:ldo