Поиск и замена с помощью списка быстрых ссылок в Vim

До сих пор я всегда использовал EasyGrep для замены текста в нескольких файлах. К сожалению, это довольно медленно, когда проект становится больше. Одна вещь, которая кажется удивительно быстрой, - это Ggrep of fugitive.vim, который выполняет поиск только файлов с контролируемой версией. Все результаты также сохраняются в списке quickfix.

Как я могу использовать результаты Ggrep для простой замены всех найденных файлов? Можно ли как-то использовать %s/foo/bar/cg для всех файлов в списке quickfix или есть ли лучшие способы?

Ответ 1

Update: Теперь у Vim есть cdo, см. ответ Sid.

Исходный ответ:

Vim имеет bufdo, windo, tabdo и argdo, которые позволяют выполнять одну и ту же команду во всех открытых буферах, окнах или файлах в списке аргументов. Нам действительно нужно что-то вроде quickfixdo, которое будет вызывать команду для каждого файла в списке quickfix. К сожалению, этой функции не хватает от Vim, но здесь решение Al, прокатанного раствора. Используя это, можно было бы запустить:

:QFDo %s/foo/bar/gc

И это приведет к замене foo/bar для всех файлов в списке quickfix.

Команды bufdo, windo, tabdo и argdo имеют некоторое общее поведение. Например, если текущий файл не может быть оставлен, все эти команды потерпят неудачу. Я не уверен, что приведенная выше команда QFDo соответствует тем же соглашениям.

Я адаптировал Al решение для создания команды под названием Qargs. Выполнение этой команды заполняет список аргументов всеми файлами, перечисленными в списке быстрого списка:

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(values(buffer_numbers))
endfunction

Используя это, вы можете выполнить следующие шаги, чтобы выполнить поиск по всему проекту и заменить:

:Ggrep findme
:Qargs
:argdo %s/findme/replacement/gc
:argdo update

Изменить: (с подсказкой шляпы Питеру Ринкеру)

Или вы могли бы присоединиться к последним 3 командам в одной строке:

:Ggrep findme
:Qargs | argdo %s/findme/replacement/gc | update

Ответ 2

Команда

cdo добавлена! После grep вы можете использовать cdo для выполнения данной команды для каждого термина в списке быстрого списка:

cdo %s/<search term>/<replace term>/cg

(Посмотрите на git commit, и этот vim разработчики google group для получения дополнительной информации о cdo и мотивах добавления его.)

Ответ 3

Ответ на nelstrom довольно всеобъемлющий и отражает его блестящий вклад в vimdom. Это также немного отличается от того, что здесь строго необходимо; шаг quickfix может быть опущен в пользу заполнения args результатом команды оболочки:

:args `git grep -l findme`
:argdo %s/findme/replacement/gc
:argdo update

должно быть всем, что вам нужно.

Редактировать: как отмечает Домонт: установить скрытое нужно сначала, если оно еще не установлено!

Ответ 4

Внешний grep

(использует grepprg, grepformat, например, в makeprg/errorformat, если grepprg == 'internal' идентичен внутреннему grep)

:grep fopen *.c
:copen
:cnext

Внутренний grep

:vimgrep /\<myVimregexp\>/ **/*.c
:copen
:cnext

и др.

Список местоположений внутренний grep

:lvimgrep /\<myVimregexp\>/ **/*.c
:lopen
:lnext

и др.

Бонус: выполнение внешней grep для загруженных буферов:

:silent bufdo grepadd fstream %
:copen
:cnext

и др.

Внешний для всех аргументов:

:silent argdo grepadd fstream %
:copen
:cnext

Ответ 5

Используя quickfix-reflector.vim, вы можете редактировать результаты поиска в окне быстрого исправления. Затем команда write сохранит изменения в ваших файлах.

:copen
:%s/foo/bar/cg
:write

Ответ 6

Там есть патч для добавления команды cdo (Quickfix do) в vim, но она еще не вытащена (по состоянию на 2015-03-25):

https://groups.google.com/forum/#!topic/vim_dev/dfyt-G6SMec

Вы можете исправить vim самостоятельно, чтобы получить этот патч:

brew install hg # install mercurial, e.g. with homebrew
hg clone https://vim.googlecode.com/hg/ vim
cd vim
# copy/download patch to . folder
patch -b -p1 < cdo.diff
./configure
make && make install