2011-02-07 17 views
7

Come posso fare in modo che Emacs conservi la sua cronologia di annullamento per il mio buffer dopo aver ripristinato il buffer o utilizzando la modalità di ripristino automatico?C'è un modo per mantenere l'elenco di annullamenti in Emacs dopo aver ripristinato un buffer dal file?

In Vim, se un file aperto in un buffer viene modificato sul disco, Vim mi chiede di ricaricare il file. Posso quindi semplicemente fare clic su "u" per annullare la ricarica se lo desidero e anche tornare indietro da quel momento. Emacs sembra cancellare tutte le informazioni di annullamento nel momento in cui ripristino il buffer.

risposta

2

Credo che l'approccio più ovvio sarebbe una funzione che uccide il contenuto del buffer corrente e quindi chiama insert-file per leggere il contenuto corrente dal file.

Se le modifiche apportate al file includevano modifiche alla codifica dei caratteri, potrebbero esserci dei problemi? Non l'ho provato.

Ecco il mio tentativo corrente. È un po 'IMO peloso, ma funziona bene.

;; Allow buffer reverts to be undone 
(defun my-revert-buffer (&optional ignore-auto noconfirm preserve-modes) 
    "Revert buffer from file in an undo-able manner." 
    (interactive) 
    (when (buffer-file-name) 
    ;; Based upon `delphi-save-state': 
    ;; Ensure that any buffer modifications do not have any side 
    ;; effects beyond the actual content changes. 
    (let ((buffer-read-only nil) 
      (inhibit-read-only t) 
      (before-change-functions nil) 
      (after-change-functions nil)) 
     (unwind-protect 
      (progn 
      ;; Prevent triggering `ask-user-about-supersession-threat' 
      (set-visited-file-modtime) 
      ;; Kill buffer contents and insert from associated file. 
      (widen) 
      (kill-region (point-min) (point-max)) 
      (insert-file-contents (buffer-file-name)) 
      ;; Mark buffer as unmodified. 
      (set-buffer-modified-p nil)))))) 

(defadvice ask-user-about-supersession-threat 
    (around my-supersession-revert-buffer) 
    "Use my-revert-buffer in place of revert-buffer." 
    (let ((real-revert-buffer (symbol-function 'revert-buffer))) 
    (fset 'revert-buffer 'my-revert-buffer) 
    ;; Note that `ask-user-about-supersession-threat' calls 
    ;; (signal 'file-supersession ...), so we need to handle 
    ;; the error in order to restore revert-buffer. 
    (unwind-protect 
     ad-do-it 
     (fset 'revert-buffer real-revert-buffer)))) 

(ad-activate 'ask-user-about-supersession-threat) 

Fastidiosamente, ho appena notato tutte le informazioni rilevanti per la ricerca nelle revert-buffer documenti, quindi non c'è probabilmente un molto modo più semplice per fare questo.

Se il valore di revert-buffer-function non è pari a zero, è chiamata a fare tutto il lavoro per questo comando. In caso contrario, i ganci before-revert-hook e after-revert-hook vengono eseguiti all'inizio e alla fine e se revert-buffer-insert-file-contents-function è non nullo, viene chiamato invece di rileggere il contenuto del file visitato.

+0

Penso che questo sia un ottimo approccio. Ho intenzione di provare a modificarlo da solo. Grazie! – Sarah

+0

Prego. Ho trovato le soluzioni ad alcuni problemi con quel codice e ho aggiornato la risposta: ora imposta il buffer aggiornato come non modificato, e ho trovato che '(set-visited-file-modtime)' era il modo per impedire che si problema. Ciò significa che se annulli il ripristino, non ti farà più la domanda se tenti di modificare nuovamente il file, che è decisamente più in linea con la funzionalità originale. Se trovi una soluzione migliore, ti preghiamo di inviare una nuova risposta qui. – phils

3

È possibile utilizzare il prima gancio per salvare il precedente buffer contenuto al kill-ring:

(add-hook 'before-revert-hook (lambda() (kill-ring-save (point-min) (point-max)))) 
8

Emacs consente di impostare revert-buffer-function per ignorare il comportamento. Ecco un'implementazione del buffer di ripristino che mantiene la cronologia.

;; emacs doesn't actually save undo history with revert-buffer 
;; see http://lists.gnu.org/archive/html/bug-gnu-emacs/2011-04/msg00151.html 
;; fix that. 
(defun revert-buffer-keep-history (&optional IGNORE-AUTO NOCONFIRM PRESERVE-MODES) 
    (interactive) 

    ;; tell Emacs the modtime is fine, so we can edit the buffer 
    (clear-visited-file-modtime) 

    ;; insert the current contents of the file on disk 
    (widen) 
    (delete-region (point-min) (point-max)) 
    (insert-file-contents (buffer-file-name)) 

    ;; mark the buffer as not modified 
    (not-modified) 
    (set-visited-file-modtime)) 

(setq revert-buffer-function 'revert-buffer-keep-history) 
+0

Sarebbe bello se anche la posizione del punto venisse preservata;) –

3

Il prossimo Emacs-24.4 fa quello che vuoi per impostazione predefinita.

Problemi correlati