Есть ли способ использовать запрос-замену из режимов вывода grep / ack / ag?

31

Я знаю find-grep-dired, отмечая соответствующие файлы, а затем нажимая, Qчтобы запустить dired-do-query-replace-regexpотмеченные файлы. К сожалению, для этого требуется перезапустить grep и больше не использовать git-grep, ack или ag и переключиться на использование find-grepс другим синтаксисом поиска.

Я также знаю, multi-occurи occur-edit-mode, но это требует перезапуска поиска с использованием происходят. Наконец, ag-diredкажется, что совпадает с именем файла, а не с содержимым файла.

Мой текущий подход состоит в том, чтобы сгенерировать вывод grep, а затем запустить макрос, который запускается в буфере grep, посещает каждое совпадение и изменяет его. Я предпочел бы использовать query-replaceнепосредственно над набором найденных совпадений.

То, что я хотел бы сделать, - это либо быстро построить буфер с задержкой из существующего вывода grep, чтобы я мог пометить соответствующие файлы и вызвать на них запрос-regexp, либо преобразовать вывод grep в список буферов, multi-occurчтобы я мог использовать его occur-edit-modeдля отредактируйте его на месте и запустите query-replaceна этом буфере.

Существует ли эта функциональность, или есть другой рабочий процесс, который решает эту проблему?

dgtized
источник

Ответы:

28

@Malabarba упомянул об использовании wgrepпакета для редактирования результатов grep / ack / ag.

Я хотел бы написать подробное описание того, как я использую agпакет и wgrep-agпакеты, чтобы добиться редактирования «согласованных результатов» с помощью multiple-cursorsпакета.

Эти пакеты доступны через Melpa. Вам также необходимо установить agaka the_silver_searcher в вашей системе.

Это пошаговое руководство применимо к случаям, когда вы ищете способ сделать однострочное редактирование во всех agнайденных / выбранных местах .

  • Установите agв вашей системе и вышеупомянутые пакеты emacs.

  • agподдерживает поиск файлов с содержимым, которое соответствует указанному регулярному выражению. Самый простой способ узнать, agгде находится корень проекта - поместить туда пустую .gitпапку. Затем выполните поиск, используя M-x ag-project-regexp.

  • По умолчанию буфер результатов поиска ag не редактируется. Чтобы сделать его редактируемым, M-x wgrep-change-to-wgrep-modeиспользуйте или используйте wgrepпривязку -default C-c C-p.

  • Теперь, если вам нужно изменить «abcdef» на «ghijkl» во всех ваших файлах, вам нужно искать «abcdef», и в буфере результатов ag будут отображаться все строки, содержащие эту строку. Затем вы делаете этот буфер редактируемым и изменяете эти строки вручную, и эти изменения будут отражаться в реальных файловых буферах при выполнении M-x wgrep-finish-editили использовании привязки по умолчанию C-c C-e. Вы также можете использовать query-replace-regexpдля этого поиска заменить.

  • Я предпочитаю использовать multiple-cursorsдля быстрого рефакторинга, чтобы в режиме реального времени видеть обратную связь о том, где одновременно происходит несколько моих правок. Выделите строку, которую вы хотите заменить, в этом буфере результатов ag и вызовите ее, M-x mc/mark-all-like-thisа затем отредактируйте с благоговением, поскольку вы видите, что материал редактируется в нескольких точках одновременно.

  • Как только вы будете довольны изменениями, как я упоминал выше, сделайте, C-c C-eчтобы «отразить» изменения в реальных буферах. Буферы еще не сохранены.

  • Чтобы сохранить все буферы, я обычно делаю это за один раз, используя C-x s !привязку по умолчанию для emacs .

Вот пример использования со скриншотами:

Он показывает процесс замены всех экземпляров bind-to-modi-mapto bind-to-my-mapв моем ~/.emacs.d/.

Когда я bind-to-modi-mapвыполняю поиск в моей папке установки emacs, я получаю следующий агрегированный результат:Ag результаты, без изменений

Этот буфер только для чтения.

После того M-x wgrep-change-to-wgrep-mode, как я выделю, -modi-mapвыделите все экземпляры этого выделения, используя M-x mc/mark-all-like-thisи после редактирования этих выделений -my-map, оно будет выглядеть следующим образом: ag результаты, модифицированные с использованием нескольких курсоров

Синяя подсветка показывает, какие строки будут изменены при нажатии C-c C-e.

При нажатии C-c C-eвы можете увидеть изменения, отраженные в реальном файле на этом снимке экрана: Ag результаты, после окончания редактирования

Затем я бы сохранил все измененные файлы, используя C-x s !.

Каушал Моди
источник
Это действительно лучший способ заменить строку. Содержащиеся в проекте, не обращая внимания на ag-exclude, простую партию, все еще будучи в состоянии проверить, что вы заменяете правильную вещь.
PascalVKooten
13

То, что я хотел бы сделать, это либо быстро создать буфер с задержкой из существующего вывода grep [...], либо преобразовать вывод grep в список буферов для многократного появления [...].

Вам не нужно преобразовывать буфер результатов grep во что-либо, уже есть режим, специально предназначенный для редактирования вывода grep (и, конечно, отражения изменений в файлах).

  1. Установите wgrep пакет из Melpa.
  2. (require 'wgrep) в вашем файле инициализации.
  3. После выполнения поиска grep, нажмите C-c C-pи отредактируйте!
  4. Сохраните ваши изменения с C-c C-e

Это даже работает с ack и ag.

Malabarba
источник
2
Вот что я делаю (с ag.el). Вместе с мультикурсорным редактированием Magnars простые рефакторинги действительно просты.
Том Регнер
4

Эта функциональность существует в projectile ( projectile-replace). Он будет использовать ag / ack / git grep / grep, если он доступен (в таком порядке), чтобы найти вхождения и tags-query-replaceвыполнить запрос-замену.

shosti
источник
Это страдает от тех же проблем, что и find-grep-dired. Он не использует существующий вывод grep. Есть похожие проблемы с множеством снарядов. Я предпочел бы начать замену запроса после просмотра списка совпадений, а не менять метод основного поиска. Это альтернативный рабочий процесс, хотя.
dgtized
То, что вы описываете, звучит так, как будто это можно легко сделать, сделав очень быстрый макрос для замены текста и многократного вызова M-g n C-x e(т. Е. Используйте next-errorдля прокрутки вхождений).
Шости
1

Вот другой подход, использующий сосульки .

В *grep*выходном буфере Emacs нажмите Cc `(это обратная цитата Cc), которая в режиме Icicle связана с буфером *grep*для команды icicle-compilation-search. Это позволяет быстро перемещаться между любыми поисковыми попаданиями ( grepпопаданиями) по вашему выбору в любом порядке.

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

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

См. Поиск сосулек - Компилировать или Grep . Вступление к поиску Сосульки находится здесь , и информация о замене совпадений во время поиска Сосульки здесь .

Нарисовался
источник
0

Я использую эту утилиту, которую я написал xah_find.el

Я написал это потому что:

  • Чистая элисп. Больше не нужно беспокоиться о передаче grep в Windows или Unicode между emacs и операционной системой. Emacs Grep проблема
  • Если вы большой пользователь Unicode, в Unix-инструментах есть некоторые полуглюги. Linux Uniq проблема
  • Я нахожу / заменяю каждую неделю 5k файлов. Я использовал dired-do-query-replace-regexp в течение многих лет. Я нахожу, что интерактивная природа действительно сократила мое время, но мне все же нужно проверить результаты изменений. Итак, мое решение теперь запускается пакетно, но у меня есть хороший отчет, который я могу сканировать при любых результатах поиска / замены, с возможностью записи в файл.

Эта утилита elisp, возможно, в 5-10 раз медленнее, чем вызов unix grep в emacs, но у меня сработала нормально.

Ха Ли
источник