tags:

views:

101

answers:

2

Is there 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.

A: 

My hunch is "no", simply because by default, emacs throws away your undo history when you re-visit a file.

offby1
I downvoted because I don't think a "hunch" makes for a good answer.
Bryan Oakley
Where there's a will, there's a way.
Trey Jackson
can't argue with that.
offby1
+5  A: 

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)
Trey Jackson
nice man, this looks great, I use undo-tree so it's not working out of the box for me, but i bet i can get this to work with undo-tree
openist
@openist It looks like you could simply check for `buffer-undo-tree` and save that the same way as the code saves `buffer-undo-list`.
Trey Jackson
Indeed, that's what i assumed as well, unfortunately though I'm still not able to get it to work with undo-tree mode disabled. I'm still working on debugging it, I'm pretty new to ELISP, but when I load up a file the undo history is not available. The hooks are being called, but I'm not sure where it's falling apart for me.
openist