Есть ли способ сохранить список отмен в Emacs после возврата буфера из файла? - PullRequest
8 голосов
/ 07 февраля 2011

Как я могу заставить Emacs сохранять свою историю отмен для моего буфера после выполнения revert-buffer или использования auto-revert-mode?

В Vim, если файл, открытый в буфере, изменяется на диске, Vim предлагает мне перезагрузить файл. Затем я могу просто нажать «и», чтобы отменить перезагрузку, если я так хочу, и даже вернуться дальше. Кажется, что Emacs удаляет всю информацию об отмене, когда я возвращаю буфер.

Ответы [ 4 ]

9 голосов
/ 06 сентября 2012

Emacs позволяет вам установить функцию revert-buffer для переопределения поведения. Вот реализация обратного буфера, которая хранит историю.

;; 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)
4 голосов
/ 05 апреля 2014

Предстоящий Emacs-24.4 делает то, что вы хотите по умолчанию.

4 голосов
/ 07 февраля 2011

Вы можете использовать before-hook для сохранения предыдущего содержимого буфера в kill-ring:

(add-hook 'before-revert-hook  (lambda () (kill-ring-save (point-min) (point-max))))
3 голосов
/ 07 февраля 2011

Полагаю, очевидным подходом будет функция, которая убивает текущее содержимое буфера, а затем вызывает insert-file для чтения текущего содержимого из файла.

Если изменения в файле включали изменения в кодировку символов, могут быть проблемы? Я не проверял это.

Вот моя текущая попытка. Это немного волосатое ИМО, но работает нормально.

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

Досадно, я только что заметил всю соответствующую информацию в revert-buffer документах, так что, вероятно, есть намного более простой способ сделать это.

Если значение revert-buffer-function не равно нулю, оно вызывается сделать всю работу для этой команды. В противном случае крючки before-revert-hook и after-revert-hook запускаются в начале и конец, и если revert-buffer-insert-file-contents-function не ноль, он вызывается вместо перечитывания содержимого посещенного файла.

...