开发者

Is there any way to have Emacs save your undo history between sessions?

Is th开发者_如何学编程ere any way to have EMACS save your undo history between sessions?

I'm aware of the savehist lib, the saveplace lib, the desktop lib, and the windows lib, these all provide some session control but none seem to save the undo history.


From version 0.4 onwards, undo-tree supports persistent storage of undo-tree data between sessions "out of the box". (Note that there are significant bug-fixes related to this feature in more recent versions; the latest version at the time of writing is 0.6.3.)

Simply enable the undo-tree-auto-save-history customization option to automatically save and load undo history in undo-tree buffers. Or use the undo-tree-save/load-history commands to save and load undo history manually.

You need at least Emacs version 24.3 for this to work reliably, but with a recent enough Emacs it works very well.


Add the following to your .emacs file :

(global-undo-tree-mode)
(setq undo-tree-auto-save-history t)
(setq undo-tree-history-directory-alist '(("." . "~/.emacs.d/undo")))

Explanation

  • (global-undo-tree-mode) enables undo tree.

  • (setq undo-tree-auto-save-history t) enables auto save of undo history.

  • (setq undo-tree-history-directory-alist '(("." . "~/.emacs.d/undo"))) so that your project does not get littered with undo-history savefiles.


Here's some code I wrote which seems to do the trick. It isn't bullet-proof, as in, it doesn't handle all the file handling intricacies that Emacs does (e.g. overriding where auto-save files are put, symlink handling, etc.). But, it seemed to do the trick for some simple text files I manipulated.

(defun save-undo-filename (orig-name)
  "given a filename return the file name in which to save the undo list"
  (concat (file-name-directory orig-name)
          "."
          (file-name-nondirectory orig-name)
          ".undo"))

(defun save-undo-list ()
  "Save the undo list to a file"
  (save-excursion
    (ignore-errors
      (let ((undo-to-save `(setq buffer-undo-list ',buffer-undo-list))
            (undo-file-name (save-undo-filename (buffer-file-name))))
        (find-file undo-file-name)
        (erase-buffer)
        (let (print-level
              print-length)
          (print undo-to-save (current-buffer)))
        (let ((write-file-hooks (remove 'save-undo-list write-file-hooks)))
          (save-buffer))
        (kill-buffer))))
  nil)

(defvar handling-undo-saving nil)

(defun load-undo-list ()
  "load the undo list if appropriate"
  (ignore-errors
    (when (and
           (not handling-undo-saving)
           (null buffer-undo-list)
           (file-exists-p (save-undo-filename (buffer-file-name))))
      (let* ((handling-undo-saving t)
             (undo-buffer-to-eval (find-file-noselect (save-undo-filename (buffer-file-name)))))
        (eval (read undo-buffer-to-eval))))))

(add-hook 'write-file-hooks 'save-undo-list)
(add-hook 'find-file-hook 'load-undo-list)


desktop-save-mode does not save buffer-undo-list by default. You just have to tell him!

(add-to-list 'desktop-locals-to-save 'buffer-undo-list)


Emacs Session appears to support this:

(add-to-list 'session-locals-include 'buffer-undo-list)


I have managed to get the undo history working by using the information provided here: http://emacs.stackexchange.com/q/3725/2287

Instead of patching the original file desktop.el.gz I created an advice that temporarily overrides (buffer-local-variables) then I use it together with the function that gathers information about the buffer.

(defun +append-buffer-undo-list-to-buffer-local-variables-advice (orig-fn &rest args)
  "Override `buffer-local-variables' and call ORIG-FN with ARGS.
There is a bug in Emacs where the `buffer-undo-list' data is
missing from the output of `buffer-local-variables'. This
advice temporarily overrides the function and appends the
missing data."
  (let ((orig-buffer-local-variables-fn (symbol-function 'buffer-local-variables)))
    (cl-letf (((symbol-function 'buffer-local-variables)
               #'(lambda () (append (funcall orig-buffer-local-variables-fn)
                               `(,(cons 'buffer-undo-list buffer-undo-list))))))
      (apply orig-fn args))))

(advice-add #'desktop-buffer-info :around #'+append-buffer-undo-list-to-buffer-local-variables-advice)
(push 'buffer-undo-list desktop-locals-to-save)
(desktop-save-mode 1)

I hope this helps someone else.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜