Funzione di ricerca / sostituzione simile per lo scambio di testo


12

Mi trovo spesso a cercare di sostituire, ad esempio, foocon bare barcon fooin un buffer.

Il modo in cui lo faccio di solito è:

  • 3 di query-sostituisce: aaa -> @@@, bbb -> aaa,@@@ -> bbb
  • rinunciare all'automazione e basta fare la sostituzione a mano

Suppongo che sia possibile far funzionare qualcosa usando la ,sintassi query-replace-regexpper verificare se la stringa corrispondente è aaao bbb. Ma la sintassi risultante sarebbe troppo ingombrante, quindi non l'ho mai veramente provato.

Il fatto è che, dato quanto sia comune un compito, penso che ci debba essere un modo migliore, in un solo passaggio, di farlo, integrato o in un pacchetto esistente. È lì?


Potrebbe esserci un modo in un solo passaggio, ma il tuo primo modo non è male, IMO. E se scegli correttamente la stringa di sostituzione, puoi semplicemente fare la sostituzione senza query per il secondo passaggio.
Drew

@Drew Per il normale query-replace, so che di solito è più veloce M-% str1 str2che spostare il punto e fare il cambio a mano. È bello, perché non devo perdere tempo a pensare a ciò che sarà più veloce, anche se si verifica una sola occorrenza str1. Idealmente, mi piacerebbe che l'inversione del testo fosse altrettanto veloce, in modo da poterla usare anche senza pensarci.
T. Verron,

Qualcuno fornirà una risposta semplice. Non c'è dubbio che puoi fare ciò che chiedi, ad esempio, usando un'espressione Lisp per la sostituzione, facendo riferimento al testo da sostituire. Ad esempio, utilizzare qualcosa di simile al linguaggio degli swap (setq a (prog1 b (setq b a))). E potrebbe esserci anche un modo più semplice.
Drew

2
Non trovo \,(if \1 "b" "a")particolarmente brutto (contro una regexp di \(a\)\|b), ma le parole devono essere digitate due volte, se questo ti dà fastidio.
politza,

2
Perché no \(aaa\)\|bbb?
politza,

Risposte:


8

Ecco un piccolo comando che farà questo:

(defun query-swap-strings (from-string to-string &optional delimited start end)
  "Swap occurrences of FROM-STRING and TO-STRING."
  (interactive
   (let ((common
          (query-replace-read-args
           (concat "Query swap"
                   (if current-prefix-arg
                       (if (eq current-prefix-arg '-) " backward" " word")
                     "")
                   (if (use-region-p) " in region" ""))
           nil)))
     (list (nth 0 common) (nth 1 common) (nth 2 common)
           (if (use-region-p) (region-beginning))
           (if (use-region-p) (region-end)))))
  (perform-replace
   (concat "\\(" (regexp-quote from-string) "\\)\\|" (regexp-quote to-string))
   `(replace-eval-replacement replace-quote (if (match-string 1) ,to-string ,from-string))
   t t delimited nil nil start end))

Grazie, è molto più elaborato di qualcosa che mi sarei scritto da solo! Forse potresti approfondire le funzionalità implementate? Vedo che con l'argomento prefisso vai indietro, che esegue la sostituzione solo nella regione se necessario ... O è solo una riscrittura query-replaceper l'inversione, in modo che mantenga tutte le sue caratteristiche? Non corrisponde al 100% della definizione nei miei emacs, ma sono ancora con 24.5 ...
T. Verron

@ T.Verron Questo è solo un corpo standard della query-replacefamiglia di funzioni dell'ultima versione, quindi mantiene tutte le funzionalità. Alla fine della funzione ho aggiunto il mio modo consigliato di scambiare le stringhe menzionato nel manuale di Emacs.
link0ff

Probabilmente ho accettato troppo in fretta. La funzione funziona qui (emacs 24.3) solo se commento backwarde region-noncontiguous-pdalla chiamata a perform-replace. È un problema generale o significa che l'interfaccia perform-replaceè cambiata tra le versioni?
T. Verron,

Sì, l'interfaccia è cambiata con questi 2 argomenti aggiunti nell'ultima versione, quindi non esistono in quelli precedenti,
link0ff

2
Anche questa soluzione sembra andare bene ora.
Nome

9

Installa plur

ed esegui il comando plur-query-replace

e input {foo,bar}e la sua sostituzione{bar,foo}

Premi yper sostituire le occorrenze come desiderato.

Esistono anche varianti non interattive e simili a isearch di questo comando.


Grazie! Lo scopo di Plur è anche qualcosa che a volte stavo cercando, lo guarderò sicuramente. La mia unica esitazione deriva dal commento dell'autore del pacchetto sopra ...;)
T. Verron

1
plurrichiede emacs 24.4.
T. Verron,
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.