Kill-buffer prompt dengan opsi untuk melakukan perubahan

8

The save-some-bufferspetunjuknya perintah untuk menyimpan atau mengabaikan setiap file yang dimodifikasi, dan juga menyediakan pilihan untuk diff file dimodifikasi terhadap file itu mengunjungi.

Saya ingin perilaku yang sama dari kill-bufferatau kill-this-buffer. Jika buffer diubah sudah ada ya / tidak prompt tetapi saya juga ingin opsi untuk melihat diffs.

Apakah ada cara bawaan untuk melakukan ini, atau titik ekstensi yang sesuai? Atau haruskah saya mengikat perintah kill-buffer saya sendiri?

glukas
sumber
Anda mungkin ingin melihatnya defadvice. Ini akan memungkinkan Anda untuk dengan mudah memperpanjang built-in kill-buffer.
pengasuh
Menggunakan saran 'sebelum' di sini tampaknya sebanding dengan menulis perintah saya sendiri, yang dapat saya lakukan: Saya akan menampilkan prompt saya sendiri, dan jika pengguna ingin melanjutkan dan membunuh buffer, saya kira saya dapat mengatur buffer-modified-pdan memanggil yang asli kill-bufferuntuk melanjutkan membunuh tanpa perintah lain. Saya bertanya-tanya apakah ada cara yang lebih baik, tetapi mungkin mencoba ini.
glucas
Wow. Saya telah menggunakan save-some-buffersselama beberapa tahun dan tidak pernah tahu ia memiliki difffitur ... Terima kasih!
mbork
@nanny akhirnya saya menggunakan saran untuk ini - lihat jawaban saya sendiri di bawah ini. Sejauh ini tampaknya berfungsi dengan baik, terima kasih.
glukas

Jawaban:

6

Pertanyaan besarnya adalah apakah Anda menginginkan perilaku ini untuk kill-bufferdirinya sendiri, yang berarti tidak hanya ketika Anda menyebutnya secara interaktif tetapi untuk setiap penggunaannya dalam kode Lisp yang ada, atau apakah Anda menginginkannya hanya untuk penggunaan interaktif.

Saya akan menganggap yang terakhir. Dalam hal ini, biarkan kill-buffersendiri, tentukan perintah Anda sendiri yang melakukan apa yang Anda inginkan, dan remap kunci yang biasanya terikat pada kill-bufferperintah Anda:

(global-set-key [remap kill-buffer] 'my-kill-buffer)

Untuk my-kill-bufferperintah Anda , cukup periksa di awal apakah buffer telah dimodifikasi, dan jika demikian luncurkan ediffuntuk itu.

Untuk memeriksa apakah sudah dimodifikasi, gunakan buffer-modified-p.

Untuk ediffAnda mungkin ingin mengambil file (yaitu, buffer telah disimpan), dan berbeda terhadap buffer yang dimodifikasi saat ini. Anda mungkin perlu sedikit bermain-main - saya tidak tahu ediffperintah yang ada yang melakukan itu.

Tapi mungkin yang Anda butuhkan hanyalah sesuatu highlight-changes-mode. Lihat manual Emacs, simpul Highlight Interactively. Dengan kata lain, mungkin yang Anda butuhkan hanyalah memanggil highlight-changes-modejika buffer telah dimodifikasi.

Drew
sumber
Terima kasih @Drew, saya akan menulis perintah bunuh saya sendiri. Beberapa bit yang berguna: Saya dapat menggunakan diff-buffer-with-fileuntuk menghasilkan diff. Sepertinya saya perlu menelepon set-buffer-modified-pjika ingin melanjutkan dan membunuh tanpa diminta lagi dari implementasi asli.
glucas
5

Berdasarkan jawaban dan komentar lain, inilah perintah kill custom yang memberikan opsi untuk mengubah buffer yang dimodifikasi dengan file yang dikunjungi. Saya sudah memetakan ini C-x C-ktetapi juga bisa memetakan kembali kill-bufferseperti yang disarankan dalam jawaban @ Drew.

(defun my/kill-this-buffer ()
  (interactive)
  (catch 'quit
    (save-window-excursion
      (let (done)
        (when (and buffer-file-name (buffer-modified-p))
          (while (not done)
            (let ((response (read-char-choice
                             (format "Save file %s? (y, n, d, q) " (buffer-file-name))
                             '(?y ?n ?d ?q))))
              (setq done (cond
                          ((eq response ?q) (throw 'quit nil))
                          ((eq response ?y) (save-buffer) t)
                          ((eq response ?n) (set-buffer-modified-p nil) t)
                          ((eq response ?d) (diff-buffer-with-file) nil))))))
        (kill-buffer (current-buffer))))))

Menggunakan implementasi dasar yang sama, Anda juga bisa memberi saran kill-buffer. Dengan pendekatan ini Anda mendapatkan opsi untuk melihat perbedaan di mana saja yang kill-bufferdisebut - misalnya, ketika membunuh buffer ditandai dari Ibuffer.

(defun my/kill-buffer (orig-func &optional buffer-or-name)
  (catch 'quit
    (save-window-excursion
      (with-current-buffer buffer-or-name
        (let (done (buf (current-buffer)))
          (when (and buffer-file-name (buffer-modified-p))
            (while (not done)
              (let ((response (read-char-choice
                               (format "Save file %s? (y, n, d, q) " (buffer-file-name buf))
                               '(?y ?n ?d ?q))))
                (setq done (cond
                            ((eq response ?q) (throw 'quit nil))
                            ((eq response ?y) (save-buffer) t)
                            ((eq response ?n) (set-buffer-modified-p nil) t)
                            ((eq response ?d) (diff-buffer-with-file) nil))))))
          (apply orig-func (list (current-buffer))))))))

(advice-add 'kill-buffer :around #'my/kill-buffer)
glukas
sumber
Satu masalah sekarang karena saya telah menggunakan ini sedikit: loop read-char tidak memungkinkan untuk menggulirkan diffs atau mengambil tindakan lain. Saya mungkin perlu menggunakan pendekatan yang diambil oleh map-y-atau-np.
glucas