вторник, 19 апреля 2011 г.

Поиск по файлам в Vim


Выдалось немного времени, решил написать, как удобно организовать поиск по файлам в vim.

Скажу стразе, что в vim есть 2 функции, которые позволяют совершить поиск по файлам grep - выводит результат поиска в консоль, а vimgrep выводит результат поиска в командную строку vim.

Читайте: help vimgrep и help grep

Но любители монструозных IDE могут упрекнуть, что мол часто нужно вывести результат в какое-то окошечко и оперативно просматривая результаты открывать/закрывать файлы с нужным нам контентом.

Но vim был бы не vim, если бы там чего-то нельзя было сделать. Итак мой пример организации поиска по файлам в vim.

Для организации поиска по файлам я использую плагин grep.vim (автор Yegappan Lakshmanan) Данный плагин позволяет удобно делать поиск и работать с результатами поиска.

Кладем grep.vim в папку $VIM_HOME/plugin/

Данный плагин использует утилиту grep. Для пользователей Windows автор предусмотрел переменную Grep_Path

:let Grep_Path = 'с:\progs\grep.exe'

У Вас появятся целая куча новых функций для работы с поиском: :Grep, :GrepAdd, :Rgrep, :RgrepAdd, :GrepBuffer, ... Тут очень детально все описано http://www.vim.org/scripts/script.php?script_id=311.

Опишу лишь то, что чаще всего использую я.

Rgrep - рекурсивный поиск по файлам
RgrepAdd - добавляет  результат поиска к результатам предыдущего поиска
GrepBuffer - поиск по всем открытым буфферам

Так же удобно забиндить какую-нибудь клавишу для поиска, я, например, использую F2 и F3.

Для этого открываем vimrc и добавляем такой код:

" F2 - Run recursive grep
nnoremap <silent> <F2> :Rgrep<cr>

" Shift-F2 - Same as ":Rgrep" but adds the results to the current results
nnoremap <silent> <S-F2> :RgrepAdd<cr>

" F3 - Search for a pattern on all open buffers
nnoremap <silent> <F3> :GrepBuffer<cr>

Все, теперь, если Вам нужно найти что-то, просто нажимаем F2 вводим паттерн, по котором нужно осуществить поиск (по умолчанию предлагается текст под курсором), нажимаем Enter, вводим путь к файлам, в которых будет происходить поиск, Enter.



В отдельном окошке появляется список строк, в котором находиться запрашиваемый Вами текст.
Чтобы открыть нужный нам фрагмент, наводим на него курсор и нажимаем Enter.

Вот и все. В лучших традициях, так сказать, жирных IDE.


Пожелание: если есть интересные задачи в vim, которые Вам не удалось самостоятельно решить, или Вы считаете, что vim такое не может, то пишите в комменты, я постараюсь найти варианты решения. За ранее благодарен.

С ув. antonfin

20 комментариев:

  1. Выделить мышкой текст и удалить :)

    ОтветитьУдалить
  2. Это легкий вопрос. Все о работе с мышью в vim тут:

    :help mouse

    Если у тебя ос и терминал поддерживают работу с мышью, тогда мышь данное действие будет выполнять без проблем, выделяешь нужный кусок кода мышью и нажимаешь d (или кнопку Delete, если тебе так удобней).

    Если у тебя мышь поддерживается, но в vim(e) не работает попробуй команду

    :set mouse=a

    Она разрешает работу мыши в любом режиме vim.

    Так же можно ограничить режимы, при которых будет работать мышь, в общем еще раз предлагаю читать :help mouse.

    vim без проблем поддерживает работу с мышью.

    ОтветитьУдалить
  3. Как цветовая схема называется? И как сделать подсветку результатов поиска?

    ОтветитьУдалить
  4. >> Как цветовая схема называется?
    Цветовая схема golden (http://www.trolocsis.com/vim/golden.vim) с небольшим допилом под себя, но сразу скажу, что в гуиншный версиях vim подсветка выглядит по другому.

    >> И как сделать подсветку результатов поиска?
    А что именно ты бы хотел еще подсвечивать? Подсветку сделать можно, но нужно писать патч к grep.vim. Напиши, что именно нужно еще подсветить и я постараюсь сделать патч.

    ОтветитьУдалить
  5. С подсветкой разобрался. Зато вот открывать файлы с найденным он у меня не хочет, поскольку "отключена опция modifiable". Подозреваю, что он в том же буфере пытается открывать. Там это где-то настраивается?

    ОтветитьУдалить
  6. >> dimio

    А как ты устанавливал vim?

    У меня есть подозрение, что он у тебя был скомпилен без поддержки флага +quickfix

    ОтветитьУдалить
  7. Судя по тому, что в выводе vim --version присутствует +quickfix - дело не в этом.

    ОтветитьУдалить
  8. А выведи, пожалуйста, vim --version в коммент

    ОтветитьУдалить
  9. Так удобней будет наверное, там довольно много всего: http://pastebin.dimio.org/pastebin.php?show=56

    ОтветитьУдалить
  10. Ты знаешь, скомпилен он у тебя нормально. Может были изменения в поточном буффере и он просит тебя их сохранить?

    А опиши подробней как ты открываешь нужный файл и какое полное сообщение при этом выскакивает.

    ОтветитьУдалить
  11. Да я в общем-то всё уже описал. Результаты поиска выводятся в новый буфер, но вот открыть их в ещё одном новом буфере я не могу - по нажатию Enter получаю ошибку "E21: изменения невозможны, так как отключена опция modifiable". Что Gvim, что Vim из X-терминала выдают её. Через неграфический терминал не пробовал.

    Такие же буферы открывает например плагин Perl-support или вызов документации по :help - не изменяемые.

    ОтветитьУдалить
  12. В данном случаи открывается специальный тип буфера (quickfix). Данный тип буфера сделан для удобной работы со списком ошибок (можешь почитать тут :help quickfix).

    Я предполагаю, что у тебя где-то срабатывает autocmd, либо на открытие нового буфера, или на нажатие Enter, или еще какая-нибудь группа. Данная команда пытается, например, сохранить данные буфера, но так как он имеет характеристику nomodifiable, то выпадает ошибка и дальнейшего действия не происходит.

    А ответь, пожалуйста:
    1) Что происходит, когда ты дабл-кликом щелкаешь на строке с найденной инфой?
    2) Что происходит, когда ты после поиска вводишь в командную строку :cnext или :cprev?

    И еще один тест:
    Попробуй воспользоваться командой vimgrep (поищи что-нибудь). Например

    :vimgrep /use/j /usr/lib/prel5/*

    Когда команда отработает, то введи в командную строку :cwindow
    Должен открыться список с найденными результатами.
    Выбери один из них и также попытайся перейти.

    ОтветитьУдалить
  13. 1. cnext и cprev: переходит к следующему и предыдущему результату в буфере с результатами поиска (по строкам скачет).

    2. :vimgrep /use/j /usr/lib/prel5/* : аналогичная проблема с "отключена опция modifiable" если нажимать enter и открывает файл по двойному клику. Также открывает по двойному клику при поиске через Rgrep.

    ОтветитьУдалить
  14. Если я правильно понял, то данная проблема у тебя только при попытки открытия с помощью Enter?

    У меня есть предположение, что у тебя Enter "замапен" на какое-то действие (см. :verbose map ).

    ОтветитьУдалить
  15. Да, только по Enter не открывает.
    Если я правильно понимаю, Enter это в привязках? Везде он завершает вызовы, отдельно на нём ничего не висит в конфиге.

    По :verbose map вот что выводит:
    o
    В последний раз опция изменена в ~/.vimrc

    ОтветитьУдалить
  16. Все понятно, у тебя где-то переобределяется поведение при нажатии на Enter (это может быть какой-то плагин).

    Получается, что при любом нажатии на Enter вызывается команда "о", которая говорит, что нужно перейти на следующую строку и перейти в режим всавки, естественно, что для не modifiable буфферов это сделать невозможно, поэтому у тебя
    vim ругается, постарайся найти в каком плагине происходит переопределение поведения клавиши Enter (воспользовавшись плагином поиска ;)) и твоя проблема решится. Или обнули действия map для Enter (поищи в :help map или :help unmap как это правильно сделать)

    ОтветитьУдалить
  17. Спасибо, теперь хоть буду знать, куда копать :)

    ОтветитьУдалить
  18. Спасибо! понравилась статья. Не подскажешь, как замапить на кнопку поиск, только чтоб VIM искал в конкретных папках? Что то типа SearchPath? Не хоцца каждый раз вводить путь поиска и маску. И второй вопрос, вот в обычных редакторах оч. мне нравится, выделил, жамкнул поиск и в окне поиска твое выделение. Уверен, что VIM можно настроить, чтоб так же делал, подскажи плиз как :)

    ОтветитьУдалить
  19. По первому вопросу.
    К сожалению в данном плагине не предусмотрено указания дефалтового пути, можно покопаться здесь http://www.vim.org/scripts/script_search_results.php я думаю можно найти что-то подходящие под твои задачи.

    Вообще использование дефалтового пути не оправдано, если у тебя будет больше 1 проекта (а рано или поздно у тебя будет больше одного проекта).

    Потом, по умолчанию поиск производиться из папки, в которой ты находился при открытии vim. Я как SSI web-программист чаще работаю с папкой ./lib из нее я открываю все нужные мне библиотеки. И если мне надо сделать поиск например найти все места, где вызывалась данная функция, я ставлю на нее курсор, F2 и 3 раза жмакаю Enter.

    По второму вопросу.
    А # или * не подходит? (см. :help #) Там конечно поиск происходит лишь того что под курсором, но как правило, этого бывает достаточно, но если нужно добавить поиск из-под визуал-мода, то по посмотри как это сделано тут http://vim.wikia.com/wiki/Search_for_visually_selected_text
    (Код добавь в .vimrc выдели текст и нажми # - vim будет искать по тексту который ты выделил)

    ОтветитьУдалить