Kill-Buffer-Eingabeaufforderung mit Option zum Ändern der Änderungen

8

Der save-some-buffersBefehl fordert Sie auf, jede geänderte Datei zu speichern oder zu ignorieren, und bietet außerdem die Möglichkeit, die geänderte Datei von der besuchten Datei zu unterscheiden.

Ich möchte das gleiche Verhalten von kill-bufferoder kill-this-buffer. Wenn der Puffer geändert wird, gibt es bereits eine Ja / Nein-Eingabeaufforderung, aber ich möchte auch die Option, die Unterschiede anzuzeigen.

Gibt es eine integrierte Möglichkeit, dies zu tun, oder einen geeigneten Erweiterungspunkt? Oder sollte ich einfach meinen eigenen Kill-Buffer-Befehl binden?

Glucas
quelle
Vielleicht möchten Sie einen Blick darauf werfen defadvice. Auf diese Weise können Sie die integrierte Funktion problemlos erweitern kill-buffer.
Kindermädchen
Die Verwendung des Vorher-Ratschlags hier scheint vergleichbar mit dem Schreiben meines eigenen Befehls zu sein, was ich tun könnte: Ich würde meine eigene Eingabeaufforderung präsentieren, und wenn der Benutzer den Puffer löschen möchte, kann ich buffer-modified-pdas Original festlegen und aufrufen, kill-bufferum fortzufahren töten ohne eine weitere Aufforderung. Ich frage mich, ob es einen besseren Weg gibt, aber ich könnte es versuchen.
Glucas
Beeindruckend. Ich benutze es save-some-buffersseit einigen Jahren und wusste nie, dass es eine diffFunktion hat ... Danke!
mbork
@nanny Schließlich habe ich dafür Ratschläge verwendet - siehe meine eigene Antwort unten. Bisher scheint es gut zu funktionieren, danke.
Glucas

Antworten:

6

Die große Frage ist, ob Sie dieses Verhalten für sich kill-bufferselbst möchten , dh nicht nur, wenn Sie es interaktiv aufrufen, sondern für jede Verwendung in vorhandenem Lisp-Code, oder ob Sie es nur für die interaktive Verwendung möchten.

Letzteres nehme ich an. Lassen Sie in diesem Fall in kill-bufferRuhe, definieren Sie Ihren eigenen Befehl, der das tut, was Sie wollen, und ordnen Sie die Schlüssel neu zu, die normalerweise an kill-bufferIhren Befehl gebunden sind :

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

my-kill-bufferÜberprüfen Sie für Ihren Befehl einfach zu Beginn, ob der Puffer geändert wurde, und starten ediffSie ihn dann, wenn dies der Fall ist .

Verwenden Sie, um zu überprüfen, ob es geändert wurde buffer-modified-p.

Um ediffSie wollen vermutlich die Datei packen (dh der Puffer als gespeichert) und diff es gegen den Strom, modifizierte Puffer. Möglicherweise müssen Sie ein wenig herumfummeln, um das zu tun - ich kenne keinen vorhandenen ediffBefehl, der das tut.

Aber vielleicht ist alles, was Sie wirklich brauchen, so etwas wie highlight-changes-mode. Siehe das Emacs-Handbuch, Knoten Highlight Interactively. Mit anderen Worten, möglicherweise müssen Sie nur aufrufen, highlight-changes-modewenn der Puffer geändert wurde.

Drew
quelle
Danke @Drew, ich schreibe meinen eigenen Kill-Befehl. Ein paar nützliche diff-buffer-with-filePunkte : Ich kann sie verwenden , um die Unterschiede zu erzeugen. Sieht auch so aus, als müsste ich anrufen, set-buffer-modified-pwenn ich fortfahren und beenden möchte, ohne erneut von der nativen Implementierung aufgefordert zu werden.
Glucas
5

Basierend auf den anderen Antworten und Kommentaren finden Sie hier einen benutzerdefinierten Kill-Befehl, der die Option bietet, einen geänderten Puffer von der Datei zu unterscheiden, die er besucht. Ich habe dies zugeordnet, C-x C-kkönnte es aber auch neu zuordnen, kill-bufferwie in @ Drews Antwort vorgeschlagen.

(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))))))

Mit der gleichen Grundimplementierung können Sie auch beraten kill-buffer. Mit diesem Ansatz haben Sie die Möglichkeit, Unterschiede überall dort anzuzeigen, wo sie kill-bufferaufgerufen werden - beispielsweise beim Löschen markierter Puffer von 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)
Glucas
quelle
Ein Problem, das ich jetzt ein wenig benutzt habe: Die Read-Char-Schleife erlaubt es nicht, durch die Diffs zu scrollen oder andere Aktionen auszuführen. Ich muss wahrscheinlich den Ansatz von map-y-or-np verwenden.
Glucas