Esiste un modo per utilizzare query-replace dalle modalità di output grep / ack / ag?


31

Sono a conoscenza find-grep-dired, contrassegnando i file corrispondenti e quindi premendo Qper eseguire dired-do-query-replace-regexpsui file contrassegnati. Sfortunatamente ciò richiede il riavvio di grep e il non utilizzo più di git-grep, ack o ag e il passaggio all'utilizzo find-grepche ha una sintassi diversa per la ricerca.

Sono anche a conoscenza di multi-occure occur-edit-mode, ma ciò richiede il riavvio della ricerca utilizzando si verificano. Infine, ag-diredsembra corrispondere al nome del file, non al contenuto del file.

Il mio approccio attuale è quello di generare output grep, quindi eseguire una macro che si avvia nel buffer grep e visita ogni corrispondenza e la modifica. Preferirei utilizzare query-replacedirettamente sull'insieme di corrispondenze trovate.

Quello che vorrei fare è sia rapidamente costruire un buffer dired dall'uscita grep esistente in modo che possa segnare i file appropriati e le chiamate su query regexp su di loro, o trasformare uscita grep in un elenco di buffer per multi-occurmodo che io possa usare occur-edit-modeper modificarlo in posizione ed eseguirlo query-replacesu quel buffer.

Esiste questa funzionalità o esiste un altro flusso di lavoro che risolve questo problema?

Risposte:


28

@Malabarba ha menzionato l'uso del wgreppacchetto per la modifica dei risultati grep / ack / ag.

Vorrei scrivere una descrizione dettagliata di come uso il agpacchetto e i wgrep-agpacchetti per ottenere la modifica dei risultati "modificati" usando il multiple-cursorspacchetto.

Questi pacchetti sono disponibili tramite Melpa. Devi anche avere agaka the_silver_searcher installato sul tuo sistema.

Questa procedura dettagliata si applica ai casi in cui stai cercando un modo per apportare modifiche a riga singola in tutte le / posizioni selezionate che sono state agtrovate.

  • Installa agsul tuo sistema e sui pacchetti emacs sopra menzionati.

  • agsupporta la ricerca di file con contenuti che corrispondono al regex specificato. Il modo più semplice per dire agdove la radice del progetto è mettere .gitlì una cartella vuota . Quindi esegui la ricerca utilizzando M-x ag-project-regexp.

  • Il buffer dei risultati della ricerca ag non è modificabile per impostazione predefinita. Per renderlo modificabile, esegui M-x wgrep-change-to-wgrep-modeo usa l' wgrepassociazione -default C-c C-p.

  • Ora se hai bisogno di cambiare 'abcdef' in 'ghijkl' in tutti i tuoi file, dovresti cercare 'abcdef' e il buffer dei risultati ag mostrerà tutte le righe che contengono quella stringa. Quindi si rende quel buffer modificabile e si modificano manualmente quelle stringhe e tali modifiche si rifletteranno nei buffer di file effettivi quando si esegue M-x wgrep-finish-edito si utilizza l'associazione predefinita C-c C-e. Puoi anche usare query-replace-regexpper sostituire quella ricerca.

  • Preferisco utilizzare multiple-cursorsper il refactoring rapido in modo da poter vedere un feedback in tempo reale su dove avvengono le mie modifiche multiple contemporaneamente. Evidenzia la stringa che vuoi sostituire in quel buffer dei risultati di AG e chiama M-x mc/mark-all-like-thise poi modifica in soggezione quando vedi cose che vengono modificate in più punti contemporaneamente.

  • Una volta che sei soddisfatto delle modifiche, come ho detto sopra, fai C-c C-e"riflesso" delle modifiche nei buffer effettivi. I buffer non sono ancora stati salvati.

  • Per salvare tutti i buffer, di solito lo faccio in una volta sola, usando l' C-x s !associazione predefinita emacs .

Ecco un esempio di utilizzo con schermate:

Mostra il processo di sostituzione di tutte le istanze di bind-to-modi-mapto bind-to-my-mapin my ~/.emacs.d/.

Quando cerco bind-to-modi-mapnella mia cartella di installazione di emacs, ottengo il risultato 'invecchiato' di seguito:risultati AG, non modificato

Questo buffer è di sola lettura.

Dopo M-x wgrep-change-to-wgrep-mode, evidenzio, -modi-mapselezionare tutte le istanze di quella selezione usando M-x mc/mark-all-like-thise dopo aver modificato quelle selezioni -my-map, appare come di seguito: risultati ag, modificati utilizzando più cursori

L'evidenziazione blu mostra quali linee verranno modificate quando premo C-c C-e.

Colpendo C-c C-e, puoi vedere il cambiamento riflesso nel file reale in questo screenshot: risultati ag, dopo aver completato le modifiche

Vorrei quindi salvare tutti i file modificati utilizzando C-x s !.


Questo è davvero il modo migliore per sostituire la stringa. Contenuti in un progetto, tenendo conto di una clausola di esclusione, facili da eseguire, pur essendo in grado di verificare che stai sostituendo la cosa corretta.
PascalVKooten,

13

Quello che vorrei fare è costruire rapidamente un buffer indirizzato dall'output grep esistente [...] o trasformare l'output grep in un elenco di buffer per multi-[...] verificarsi.

Non è necessario convertire il buffer dei risultati di grep in nulla, esiste già una modalità specifica per modificare l'output di grep (e ovviamente riflettere le modifiche ai file).

  1. Installare il wgrep pacchetto da Melpa.
  2. (require 'wgrep) nel tuo file init.
  3. Dopo aver fatto una ricerca grep, clicca C-c C-pe modifica via!
  4. Salva le tue modifiche con C-c C-e

Funziona anche con ack e ag.


2
Questo è quello che faccio (con ag.el). Insieme ai magnari, l'editing multicursor semplifica il refactoring.
Tom Regner,

4

Questa funzionalità esiste in projectile ( projectile-replace). Userà ag / ack / git grep / grep se disponibile (in quell'ordine) per trovare le occorrenze e tags-query-replaceper eseguire la query-sostituisci.


Ciò presenta gli stessi problemi di find-grep-dired. Non utilizza l'output grep esistente. Ci sono problemi simili con proiettile-multi-si verificano. Preferirei avviare la query di sostituzione dopo aver esaminato l'elenco delle corrispondenze e non modificare il metodo di ricerca sottostante. È comunque un flusso di lavoro alternativo.
dgtized

Ciò che stai descrivendo sembra che possa essere facilmente realizzato creando una macro molto veloce per sostituire il testo e chiamando ripetutamente M-g n C-x e(cioè, next-errorper scorrere tra le occorrenze).
shosti,

1

Ecco un altro approccio, usando Icicles .

Nel *grep*buffer di output di Emacs , premi Cc `(ovvero Cc backquote), che in modalità Icicle è associato a buffer *grep*per comandare icicle-compilation-search. Ciò ti consente di navigare rapidamente tra i risultati della ricerca (i greprisultati) che scegli, in qualsiasi ordine.

Inserisci il tipo di minibuffer che filtra (restringe) in modo dinamico l'insieme dei risultati della ricerca e puoi utilizzare il completamento progressivo per restringere abbinando in successione più pattern (ad es. Sottostringhe, regexps).

Quando si naviga tra i risultati della ricerca, è possibile sostituirli su richiesta: l'intero hit (linea) o solo la parte corrispondente all'input del minibuffer corrente.

Vedi Ricerca ghiaccioli - Compila o Grep . Un'introduzione alla ricerca di Icicles è qui , e le informazioni sulla sostituzione delle partite durante la ricerca di Icicles sono qui .


0

Uso questo programma di utilità che ho scritto xah_find.el

L'ho scritto perché:

  • Elisp puro. Non dovrai più preoccuparti di grep su Windows o della trasmissione Unicode tra emacs e il sistema operativo. problema di emacs grep
  • Se sei un utente unicode pesante, gli strumenti unix hanno alcuni semi-bug. problema uniq di Linux
  • Trovo / sostituisco ogni settimana su file 5k. Ho usato dired-do-query-replace-regexp per anni. Trovo che la natura interattiva abbia davvero rovinato il mio tempo, ma devo controllare i risultati delle modifiche. Quindi, la mia soluzione è ora eseguita in batch ma ho un bel rapporto che posso scansionare a tutti i risultati di ricerca / sostituzione, con l'opzione per scrivere su file.

Questo util elis è forse da 5 a 10 volte più lento rispetto a chiamare unix grep in emacs, ma ha funzionato bene per me.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.