Hapus bagian string Isearch yang tidak cocok, atau karakter terakhir jika benar-benar cocok

11

Saya punya yang berikut ini

(defun isearch-del-fail-or-char ()
  "Delete failed isearch text, or if there is none, a single character."
  (interactive)
  (if (isearch-fail-pos)
      (delete-region (isearch-fail-pos) (point))
    (isearch-del-char)))

(define-key isearch-mode-map (kbd "DEL") 'isearch-del-fail-or-char)

Tujuan dari kode ini adalah untuk membuat deleteisearch menghapus seluruh string yang gagal (atau jika tidak ada string yang gagal hanya satu karakter).

Namun, delete-regionmenghapus teks dari buffer isearchsedang mencari, bukan buffer pencarian sendiri.

Apa cara yang tepat untuk melakukan ini? Kritik pada sisa gaya emacs lisp saya juga diterima :)

penilai
sumber

Jawaban:

12

Ah iya. Isearch membaca kunci yang Anda ketikkan, mencari di dalamnya isearch-mode-map, dan memanggil mereka di buffer saat ini .

Isearch tidak , meskipun penampilannya, menggunakan minibuffer. Ini menggunakan area gema. Artinya, apa yang Anda lihat sebenarnya adalah pesan keluaran , termasuk gema dari karakter yang Anda ketikkan.

Ini harus melakukan apa yang Anda minta:

(defun mydelete ()
  "Delete the failed portion of the search string, or the last char if successful."
  (interactive)
  (with-isearch-suspended
      (setq isearch-new-string
            (substring
             isearch-string 0 (or (isearch-fail-pos) (1- (length isearch-string))))
            isearch-new-message
            (mapconcat 'isearch-text-char-description isearch-new-string ""))))

(define-key isearch-mode-map (kbd "DEL") 'mydelete)

(BTW, pertanyaan Anda mengatakan deletekarakter, tetapi Anda menulis DEL, yang merupakan karakter backspace.)


Seperti @Malabarba tunjukkan dalam komentar, saat Anda mengatur string pencarian baru ke ""(string kosong), with-isearch-suspendeddilanjutkan dengan mencari string pencarian terakhir, alih-alih memulai dengan string pencarian kosong.

Ini adalah " fitur " dari with-isearch-suspended, secara umum. Tetapi karena Anda kadang-kadang mungkin benar-benar ingin mengosongkan string pencarian untuk dilanjutkan, dalam versi with-isearch-suspendeddi isearch + .el saya telah menambahkan variabel isearchp-if-empty-prefer-resuming-with-last, untuk mengontrol ini. Jika Anda mengikat itu ke nildan Anda mengatur isearch-new-stringuntuk ""kemudian melanjutkan dengan string pencarian kosong.

Jadi dengan Isearch + Anda dapat melakukan apa yang Anda inginkan dengan definisi ini:

(defun mydelete ()
  "Delete the failed portion of the search string, or the last char if successful."
  (interactive)
  (let ((isearchp-if-empty-prefer-resuming-with-last  nil))
    (with-isearch-suspended
        (setq isearch-new-string
              (substring
               isearch-string 0 (or (isearch-fail-pos) (1- (length isearch-string))))
              isearch-new-message
              (mapconcat 'isearch-text-char-description isearch-new-string "")))))

Saya melihat terlalu sekarang bahwa Emacs 24.4 memperkenalkan regresi, yang saya sudah mengajukan Emacs bug # 20.466 untuk, yang berarti bahwa mengikat DELdalam isearch-mode-maptidak cukup. Mereka menambahkan ikatan terpisah untuk <backspace>, selain satu untuk DEL. Itu berarti bahwa <backspace>tidak lagi diterjemahkan ke DEL, untuk Isearch (tetapi masih diterjemahkan untuk Emacs secara umum).

Jadi jika Anda ingin tombol Backspace untuk melakukan apa yang Anda minta dalam Emacs 24.4 atau lambat maka Anda tidak bisa hanya mengikat DELuntuk mydelete. Anda perlu untuk mengikat <backspace>ke mydelete. Bodoh, AFAICT, mais on progres n'arrete ...


Saya telah menambahkan perintah yang mirip dengan Isearch + dan mengikatnya C-M-l(kunci yang sama digunakan untuk menghapus ketidakcocokan penyelesaian dalam Icicles ).

Perlu diketahui juga bahwa C-gdi Isearch juga, ketika ada ketidakcocokan, hapus teks yang tidak cocok. (Tetapi C-gjuga memiliki efek ketika pencarian berhasil.)


Saya seharusnya menyebutkan bahwa Isearch + juga memiliki perilaku opsional di sepanjang baris yang sama untuk sementara waktu sekarang. M-kselama Isearch beralih di antara 3 perilaku, yang dikendalikan oleh nilai opsi isearchp-drop-mismatch:

  • replace-last- Input Anda saat ini menggantikan teks yang tidak cocok terakhir. Anda selalu dapat melihat input terakhir Anda, bahkan jika itu adalah ketidakcocokan. Dan tersedia untuk diedit menggunakan M-e.

  • nil - Input Anda saat ini ditambahkan, bahkan jika input sebelumnya memiliki porsi yang tidak cocok.

  • hal lain - Input Anda saat ini diabaikan (dihapus) jika menyebabkan ketidakcocokan. String pencarian selalu memiliki kecocokan yang berhasil.

Drew
sumber
BTW, saya sudah berpikir tentang menambahkan perintah serupa ke Isearch + sejak saya menambahkan menyoroti bagian gagal (tahun lalu, sebelum saya menambahkannya ke GNU Emacs), tetapi saya tidak pernah sempat melakukannya. Saya sudah melakukannya sekarang . (Namun, saya tidak menyertakan penghapusan karakter. Perintah yang saya tambahkan adalah no-op jika tidak ada bagian yang gagal.)
Drew
Saya menggunakan OS X. Maksud saya hapus ke belakang.
penanggung jawab
Perilaku isearch + replace-last terlihat cukup bagus. Apakah ada cara untuk membuatnya tidak membunyikan bel setiap kali pencarian gagal?
penanggung jawab
2
Saya mengunggah versi baru isearch+.el. Ini (a) memperbaiki penghapusan ketidakcocokan otomatis sehingga sampul berfungsi dengan baik. Dan itu menambahkan opsi,, isearchp-ring-bell-functionyang dapat Anda gunakan untuk menekan bel selama pencarian.
Drew
3
Malabarba, menarik. Saya mengambil bug dan berakhir dengan ini . Sebagian besar berbudaya kargo dari isearch-del-chardan jawaban Drew tetapi tampaknya berfungsi sebagaimana dimaksud. The with-isearch-suspendedmakro adalah pelakunya.
jbm