在从文件恢复缓冲区后,有没有办法在Emacs中保留撤消列表?

时间:2011-02-07 17:28:46

标签: emacs elisp undo

在执行恢复缓冲区或使用自动恢复模式后,如何让Emacs保留其缓冲区的撤消历史记录?

在Vim中,如果在光盘上更改了缓冲区中打开的文件,Vim会提示我重新加载该文件。然后,如果我愿意的话,我可以简单地点击“你”来撤消重新加载,甚至可以从那时起再往前走。当我恢复缓冲区时,Emacs似乎会删除所有撤消信息。

4 个答案:

答案 0 :(得分:9)

Emacs允许您设置revert-buffer-function来覆盖行为。这是一个保留历史记录的恢复缓冲区实现。

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

答案 1 :(得分:4)

您可以使用 before-hook 将之前的缓冲区内容保存到kill-ring:

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

答案 2 :(得分:4)

即将推出的Emacs-24.4可以默认执行您想要的操作。

答案 3 :(得分:3)

我想明显的方​​法是杀死当前缓冲区内容的函数,然后调用insert-file来读取文件中的当前内容。

如果对文件的更改包含对字符编码的更改,可能会出现问题?我没有测试过。

这是我目前的尝试。这是一个有点毛茸茸的IMO,但它可以正常工作。

;; 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-hookafter-revert-hook在开头运行   最后,如果是revert-buffer-insert-file-contents-function   非零,它被调用而不是重读受访文件内容。