【问题标题】:Is there a way to retain the undo list in Emacs after reverting a buffer from file?从文件恢复缓冲区后,有没有办法在 Emacs 中保留撤消列表?
【发布时间】:2011-06-22 21:39:52
【问题描述】:

在执行 revert-buffer 或使用 auto-revert-mode 后,如何让 Emacs 为我的缓冲区保留其撤消历史记录?

在 Vim 中,如果在缓冲区中打开的文件在磁盘上发生更改,Vim 会提示我重新加载文件。然后,如果我愿意,我可以简单地单击“u”来撤消重新加载,甚至可以从那时起返回更远的地方。在我恢复缓冲区的那一刻,Emacs 似乎丢弃了所有的撤消信息。

【问题讨论】:

    标签: emacs elisp undo


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      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)
      

      【讨论】:

      • 如果点位置也被保留了会很棒;)
      • Reverting but keeping undo 部分下的emacswiki.org/emacs/RevertBuffer 上接近吗?
      • 这种方式会导致光标跳转到页面顶部,是否可以阻止?
      【解决方案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 的值不为nil,则调用它 为这个命令做所有的工作。否则,钩子 before-revert-hookafter-revert-hook 在开头运行 最后,如果revert-buffer-insert-file-contents-function 是 非零,它被调用而不是重新读取访问过的文件内容。

      【讨论】:

      • 我认为这是一个非常好的方法。我要自己调整一下。谢谢!
      • 不客气。我找到了该代码一些问题的解决方案,并更新了答案:它现在将更新的缓冲区设置为未修改,我发现(set-visited-file-modtime) 是阻止它成为问题的方法。这意味着如果您撤消还原,如果您尝试重新修改文件,它就不再询问您问题,这肯定更符合原始功能。如果您提出改进的解决方案,请在此处发布新答案。
      【解决方案4】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-08-05
        • 1970-01-01
        • 2013-05-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-02
        • 1970-01-01
        相关资源
        最近更新 更多