Existe uma maneira de usar a substituição de consulta nos modos de saída grep / ack / ag?

31

Estou ciente de find-grep-diredmarcar os arquivos correspondentes e pressionar Qpara executar dired-do-query-replace-regexpnos arquivos marcados. Infelizmente, isso requer reiniciar o grep e não usar mais o git-grep, ack ou ag e alternar para usar, find-grepque possui uma sintaxe diferente para a pesquisa.

Também estou ciente de multi-occure occur-edit-mode, mas isso requer o reinício da pesquisa usando ocorrer. Finalmente, ag-diredparece corresponder ao nome do arquivo, não ao conteúdo do arquivo.

Minha abordagem atual é gerar saída grep e, em seguida, executar uma macro que é iniciada no buffer grep, visitar cada correspondência e alterá-la. Eu preferiria usar query-replacediretamente sobre o conjunto de correspondências encontradas.

O que eu gostaria de fazer é criar rapidamente um buffer direcionado a partir da saída grep existente, para que eu possa marcar os arquivos apropriados e chamar query-regexp neles, ou transformar a saída grep em uma lista de buffers para multi-occurque eu possa usar occur-edit-modepara edite-o no lugar e execute query-replacenesse buffer.

Essa funcionalidade existe ou existe outro fluxo de trabalho que resolve esse problema?

dgtized
fonte

Respostas:

28

O @Malabarba mencionou o uso do wgreppacote para editar os resultados do grep / ack / ag.

Eu gostaria de escrever uma explicação detalhada de como uso o agpacote e os wgrep-agpacotes para obter a edição de resultados 'agregados' usando o multiple-cursorspacote.

Esses pacotes estão disponíveis no Melpa. Você também precisa ter o agaka the_silver_searcher instalado no seu sistema.

Este passo a passo se aplica aos casos em que você está procurando uma maneira de fazer edições de linha única em todos os locais selecionados agencontrados.

  • Instale agno seu sistema e nos pacotes emacs mencionados acima.

  • agsuporta pesquisa de arquivos com conteúdo que corresponde ao seu regex especificado. A maneira mais simples de saber agonde a raiz do projeto é colocar uma .gitpasta vazia lá. Em seguida, faça a pesquisa usando M-x ag-project-regexp.

  • O buffer de resultados da pesquisa ag não é editável por padrão. Para torná-lo editável, M-x wgrep-change-to-wgrep-modeuse ou use a wgrepligação -default C-c C-p.

  • Agora, se você precisar alterar 'abcdef' para 'ghijkl' em todos os seus arquivos, pesquise 'abcdef' e o buffer de resultados ag exibirá todas as linhas que contêm essa sequência. Em seguida, você torna esse buffer editável e altera essas cadeias manualmente e essas alterações serão refletidas nos buffers de arquivo reais ao executar M-x wgrep-finish-editou usar a ligação padrão C-c C-e. Você também pode usar query-replace-regexppara fazer essa pesquisa substituir.

  • Prefiro usar multiple-cursorsa refatoração rápida para que eu possa ver um feedback em tempo real de onde minhas várias edições estão acontecendo simultaneamente. Destaque a string que deseja substituir no buffer de resultados e ligue M-x mc/mark-all-like-thise edite-a com admiração ao ver as coisas sendo editadas em vários pontos ao mesmo tempo.

  • Quando estiver satisfeito com as edições, como mencionei acima, faça C-c C-epara "refletir" as alterações nos buffers reais. Os buffers ainda não estão salvos.

  • Para salvar todos os buffers, costumo fazer isso de uma só vez, usando a C-x s !ligação padrão do emacs .

Aqui está um exemplo de caso de uso com capturas de tela:

Ele mostra o processo de substituição de todas as instâncias de bind-to-modi-mappara bind-to-my-mapno meu ~/.emacs.d/.

Quando procuro bind-to-modi-mapna minha pasta de configuração do emacs, recebo o resultado 'ag'ged abaixo:resultados ag, não modificados

Este buffer é somente leitura.

Depois M-x wgrep-change-to-wgrep-mode, realcei, -modi-mapselecione todas as instâncias dessa seleção usando M-x mc/mark-all-like-thise depois de editar essas seleções para -my-map, fica abaixo: resultados ag, modificados usando cursores múltiplos

O destaque azul mostra quais linhas serão modificadas quando eu pressionar C-c C-e.

Ao bater C-c C-e, você pode ver a alteração refletida no arquivo real nesta captura de tela: ag, depois de terminar as edições

Eu salvaria todos os arquivos modificados usando C-x s !.

Kaushal Modi
fonte
Essa é realmente a melhor maneira de substituir as cordas. Contido em um projeto, com exclusão direta e lote fácil de executar, ainda é possível verificar se você está substituindo a coisa correta.
PascalVKooten
13

O que eu gostaria de fazer é criar rapidamente um buffer direcionado a partir da saída grep [...] existente ou transformar a saída grep em uma lista de buffers para ocorrência múltipla [...].

Você não precisa converter o buffer de resultados grep em nada, já existe um modo específico para editar a saída grep (e refletir as alterações nos arquivos, é claro).

  1. Instale o wgrep pacote de Melpa.
  2. (require 'wgrep) no seu arquivo init.
  3. Depois de fazer uma pesquisa grep, clique C-c C-pe edite!
  4. Salve suas edições com C-c C-e

Até funciona com ack e ag também.

Malabarba
fonte
2
É o que eu faço (com ag.el). Juntamente com a edição multicursora de magnares, refatorações simples são realmente fáceis.
Tom Regner
4

Essa funcionalidade existe no projétil ( projectile-replace). Ele usará ag / ack / git grep / grep, se disponível (nessa ordem) para encontrar ocorrências e tags-query-replaceexecutar a substituição da consulta.

shosti
fonte
Isso sofre dos mesmos problemas que o find-grep-dired. Não está usando a saída grep existente. Existem problemas semelhantes com a ocorrência de projéteis. Eu preferiria iniciar a consulta substituir depois de examinar a lista de correspondências e não alterar o método da pesquisa subjacente. É um fluxo de trabalho alternativo.
usar o seguinte comando
O que você está descrevendo parece que pode ser realizado facilmente, fazendo uma macro muito rápida para substituir o texto e chamando repetidamente M-g n C-x e(ou seja, use next-errorpara rolar as ocorrências).
shosti 24/09
1

Aqui está outra abordagem, usando Sincelos .

No seu *grep*buffer de saída do Emacs , pressione Cc `(que é Cc), que no modo Icicle é vinculado no buffer *grep*ao comando icicle-compilation-search. Isso permite navegar rapidamente entre qualquer um dos hits da pesquisa (os grephits) que você escolher, em qualquer ordem.

A entrada digitada no minibuffer filtra dinamicamente (restringe) o conjunto de ocorrências de pesquisa e você pode usar a conclusão progressiva para restringir, combinando sucessivamente vários padrões (por exemplo, substrings, regexps).

Ao navegar entre os hits da pesquisa, você pode substituir qualquer um deles sob demanda - o hit inteiro (linha) ou apenas a parte correspondente à entrada atual do minibuffer.

Consulte Pesquisa de sincelos - Compilar ou Grep . Uma introdução à pesquisa de sincelos está aqui e informações sobre a substituição de correspondências durante a pesquisa de sincelos estão aqui .

Desenhou
fonte
0

Eu uso este utilitário que escrevi xah_find.el

Eu escrevi porque:

  • Elisp puro. Não precisa mais se preocupar com grep na transmissão do Windows ou Unicode entre o emacs e o sistema operacional. problema do emacs grep
  • Se você é um usuário unicode pesado, as ferramentas unix possuem alguns semi-bugs. problema do linux uniq
  • Eu encontro / substituo toda semana em arquivos de 5k. Eu estava usando dired-do-query-replace-regexp por anos. Acho que a natureza interativa realmente desperdiçou meu tempo, mas preciso verificar os resultados das alterações. Portanto, minha solução agora é executada em lote, mas tenho um bom relatório que posso verificar em todos os resultados de localização / substituição, com a opção de gravar em arquivo.

Este utilitário elisp é talvez 5 a 10 vezes mais lento do que chamar o unix grep no emacs, mas funcionou bem para mim.

Xah Lee
fonte