nialv7
nialv7

Reputation: 219

undo-tree doesn't auto load history

I was trying to make persistent undo history work in emacs.

I have (setq undo-tree-auto-save history t). The history is indeed saved when I save file. But when I open file, the undo history is not loaded until I use undo.

So if I open a file and make some changes, then run M-x undo-tree-visualize, the previous undo tree is gone, only the recent changes are there. But if I run M-x undo-tree-visualize first, then I can see the old undo tree. Or if I just use undo before making any changes, the old undo history is loaded and the undo works as expected.

Edit: My configuration looks like this: https://gitlab.com/snippets/22693

Edit2: This problem still happens with the most minimal configure file:

;;; init.el --- user init file      -*- no-byte-compile: t -*-
(load-file "~/.emacs.d/undo-tree.el")
(global-undo-tree-mode 1)
(setq undo-tree-auto-save-history t)

Upvotes: 2

Views: 1738

Answers (6)

Will B Chang
Will B Chang

Reputation: 3

Put the (global-undo-tree-mode) in the :init will auto load history if you're using use-package

Example:

(use-package undo-tree
  :init
  (global-undo-tree-mode)
  :custom
  (undo-tree-auto-save-history t)
  (undo-tree-history-directory-alist '(("." . "~/.config/emacs/undo-tree-history")))
  (undo-tree-visualizer-diff t)
  (undo-tree-visualizer-timestamps t))

Upvotes: 0

AitBits
AitBits

Reputation: 1

Reason for this behavior is that when you start up emacs and open up file in buffer even with undo-tree-auto-save-history enabled so that undo-tree-load-history is called as it should be, buffer-undo-list is initially set to nil. If you make an edit before invoking any functionality of undo-tree, buffer-undo-list will have value that doesn't end with an undo-tree-canary.

When undo-list-transfer-to-tree sees buffer-undo-list not ending with undo-tree-canary, it will discard current buffer-undo-tree and construct new one with the value of buffer-undo-list which only have undo history of your initial edit. Consequently, buffer-undo-tree previously built by undo-tree-load-history is deleted, and you are left with fresh, minimal buffer-undo-tree only with single undo history.

So what I did to prevent this from happening was to initialize buffer-undo-list with undo-tree-canary by advising undo-tree-load-history-hook which should call undo-tree-load-history with undo-tree-auto-save-history set to t, and it is also called for opening file as part of find-file-hook.

That is, I added this line of code to my init file:

(advice-add 'undo-tree-load-history-hook :after (lambda () (setq buffer-undo-list '(nil undo-tree-canary))))

Upvotes: 0

Reefersleep
Reefersleep

Reputation: 17

I just want to chime in that I experience a similar thing.

if I emacs file-x from the terminal, earlier undo tree history for file-x is not is not available to me before I undo-tree-load-history. However, when I open emacs and then :edit file-x, the history is loaded just fine.

I'm using spacemacs 0.105.19, with emacs-24.5.1.

My .spacemacs is https://pastebin.com/VNWtB0F1

Upvotes: 0

user57213
user57213

Reputation: 5

Have you tinkered with the order you are loading your plugins as well as files you open automatically via init.el or .emacs? That did the trick for me. Evil requires Undo-Tree. So everything having to do with undo-tree should fire before you load Evil. Especially if you use ":e" instead of "find-file" for loading files. A least on my system that solved this issue.

Upvotes: 0

Toby Cubitt
Toby Cubitt

Reputation: 453

When undo-tree-auto-save-history is enabled, undo history is loaded from file by the undo-tree-load-history-hook function, which gets added to find-file-hook. So undo history will be loaded automatically when you open a file with undo-tree-mode enabled.

@djangoliv is right: this will only work if global-undo-tree-mode is enabled, because undo-tree-mode needs to be enabled before find-file-hook is called. Perhaps the undo-tree-mode minor-mode function ought to attempt to load history if it detects the buffer hasn't been modified since the last undo history save. But at the moment, it doesn't.

However, your config does enable global-undo-tree-mode, so this can't be the issue.

History loading works just fine for me with global-undo-tree-mode enabled. So unless you give a complete MWE that reproduces your problem -- i.e. step-by-step instructions starting from "emacs -Q" and including Emacs and undo-tree version numbers -- you're unlikely to get much more help here. (Also, note that stackexchange is not a bug tracker. Bug reports should be sent by email to the address listed at the top of the package.)

Upvotes: 1

nialv7
nialv7

Reputation: 219

How come no one has ever noticed this? There's a bug in undo-tree.

The function undo-list-transfer-to-tree failed to append 'undo-tree-canary to buffer-undo-list, which cause it to discard the content of buffer-undo-tree.

I'm still looking into it to see if I can find a solution. Simply append 'undo-tree-canary to buffer-undo-list causing it to discard to content in buffer-undo-list instead

Edit: The solution is indeed to put canary at the end of buffer-undo-list

  (when (not (eq (last buffer-undo-list) 'undo-tree-canary))
    (setq buffer-undo-list (append buffer-undo-list '(nil undo-tree-canary))))

Upvotes: 1

Related Questions