在从文件还原缓冲区后,是否有办法在Emacs中保留撤消列表?

在从文件还原缓冲区后,是否有办法在Emacs中保留撤消列表?,emacs,elisp,undo,Emacs,Elisp,Undo,在执行恢复缓冲区或使用自动恢复模式后,如何使Emacs保留其对我的缓冲区的撤消历史记录 在Vim中,如果缓冲区中打开的文件在光盘上被更改,Vim会提示我重新加载该文件。如果我愿意的话,我可以简单地单击“u”来撤销重新加载,甚至可以从那以后再返回。在我还原缓冲区时,Emacs似乎会丢弃所有撤消信息。您可以使用before钩子将以前的缓冲区内容保存到kill环: (add-hook 'before-revert-hook (lambda () (kill-ring-save (point-min)

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

在Vim中,如果缓冲区中打开的文件在光盘上被更改,Vim会提示我重新加载该文件。如果我愿意的话,我可以简单地单击“u”来撤销重新加载,甚至可以从那以后再返回。在我还原缓冲区时,Emacs似乎会丢弃所有撤消信息。

您可以使用before钩子将以前的缓冲区内容保存到kill环:

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

我想最明显的方法是使用一个函数,它先删除当前缓冲区内容,然后调用
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)
令人烦恼的是,我只注意到
还原缓冲区
文档中所有相关的外观信息,所以可能有一种更简单的方法来实现这一点

如果
恢复缓冲区函数的值为非nil,则调用该函数
执行此命令的所有工作。否则,挂钩
还原挂钩之前的
和还原挂钩之后的
在开始时运行
最后,如果恢复缓冲区插入文件内容功能
非nil,将调用它,而不是重新读取访问的文件内容


Emacs允许您设置恢复缓冲区功能以覆盖该行为。下面是一个保留历史记录的还原缓冲区实现

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

即将推出的Emacs-24.4在默认情况下满足您的需求。

我认为这是一个非常好的方法。我自己也要试着调整一下。谢谢不客气。我找到了该代码中一些问题的解决方案,并更新了答案:它现在将更新后的缓冲区设置为未修改,我发现
(set visted file modtime)
是防止出现问题的方法。这意味着,如果您撤消恢复,那么如果您尝试重新修改文件,它将不再向您再次询问问题,这肯定更符合原始功能。如果您提出了一个改进的解决方案,请在此处发布一个新的答案。如果还保留了点位置,那就太好了;)是否类似于在“还原但保持撤消”部分下继续操作?这种方法会导致光标跳到页面顶部,是否有可能阻止它?