Cari / ganti-suka fitur untuk bertukar teks

12

Saya sering menemukan diri saya mencoba untuk menggantikan misalnya foodengan bardan bardengan foodi buffer.

Cara saya biasanya melakukannya adalah:

  • 3 permintaan-Menggantikan: aaa -> @@@, bbb -> aaa,@@@ -> bbb
  • menyerah pada otomatisasi dan lakukan penggantian dengan tangan

Saya kira itu mungkin untuk mendapatkan sesuatu yang bekerja menggunakan ,sintaks query-replace-regexpuntuk menguji apakah string yang cocok adalah aaaatau bbb. Tetapi sintaks yang dihasilkan akan terlalu rumit, jadi saya tidak pernah benar-benar mencobanya.

Masalahnya adalah, mengingat betapa umum tugas itu, saya pikir harus ada yang lebih baik, satu langkah, cara melakukannya, baik built-in atau dalam paket yang ada. Disana?

T. Verron
sumber
Mungkin ada satu langkah langkah, tetapi cara pertama Anda tidak buruk, IMO. Dan jika Anda memilih string pengganti tepat maka Anda bisa melakukan penggantian no-query untuk pass kedua.
Drew
@Rew Untuk biasa query-replace, saya tahu bahwa biasanya lebih cepat M-% str1 str2daripada memindahkan titik dan melakukan perubahan dengan tangan. Itu bagus, karena saya tidak perlu membuang waktu untuk memikirkan apa yang akan tercepat, bahkan jika hanya ada satu kejadian str1. Idealnya, saya ingin inversi teks sama cepatnya, sehingga saya bisa menggunakannya tanpa memikirkannya juga.
T. Verron
Seseorang akan memberikan jawaban yang sederhana. Anda pasti dapat melakukan apa yang Anda minta, misalnya, dengan menggunakan ekspresi Lisp untuk penggantian, merujuk teks yang akan diganti. Misalnya, gunakan sesuatu yang mirip dengan idiom swap (setq a (prog1 b (setq b a))). Dan bahkan mungkin ada cara yang lebih sederhana.
Drew
2
Saya tidak menemukan \,(if \1 "b" "a")sangat jelek (terhadap regexp \(a\)\|b), tetapi masih kata-kata harus diketik dua kali, jika itu mengganggu Anda.
politza
2
Mengapa tidak \(aaa\)\|bbb?
politza

Jawaban:

8

Ini adalah perintah kecil yang akan melakukan ini:

(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))
link0ff
sumber
Terima kasih, itu jauh lebih rumit daripada sesuatu yang saya tulis sendiri! Mungkin Anda bisa menguraikan fitur yang diimplementasikan? Saya melihat bahwa dengan argumen awalan Anda mundur, bahwa ia melakukan penggantian hanya di wilayah jika diperlukan ... Atau apakah itu hanya penulisan ulang query-replaceuntuk inversi, sehingga ia mempertahankan semua fitur-fiturnya? Itu tidak cocok dengan 100% definisi di emacs saya, tapi saya masih dengan 24.5 ...
T. Verron
@ T.Verron Ini hanya badan standar dari query-replacekeluarga fungsi dari versi terbaru, jadi ia mempertahankan semua fitur. Di akhir fungsi saya menambahkan cara yang disarankan untuk menukar string yang disebutkan dalam manual Emacs.
link0ff
Saya mungkin menerima terlalu cepat. Fungsi ini hanya berfungsi di sini (emacs 24.3) jika saya berkomentar backwarddan region-noncontiguous-pdari panggilan ke perform-replace. Apakah ini masalah umum, atau apakah itu berarti antarmuka perform-replacetelah berubah antar versi?
T. Verron
Ya, antarmuka telah berubah dengan 2 argumen ini ditambahkan dalam versi terbaru, sehingga tidak ada dalam yang sebelumnya,
link0ff
2
Solusi ini juga tampaknya baik-baik saja sekarang.
Namai
9

Pasang plur

dan jalankan perintah plur-query-replace

dan input {foo,bar}dan penggantinya{bar,foo}

Hit yuntuk mengganti kejadian yang diinginkan.

Ada juga varian non-interaktif, dan mirip-pencarian, dari perintah ini.

InHarmsWay
sumber
Terima kasih! Tujuan plur juga sesuatu yang kadang-kadang saya cari, saya pasti akan melihatnya. Satu-satunya keraguan saya berasal dari komentar penulis paket di atas ...;)
T. Verron
1
plurmembutuhkan emacs 24.4.
T. Verron