Поиск и замена с помощью списка быстрых ссылок в 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