Closed alienbogart closed 4 years ago
Make 30 changes on a files an save each step
Is there some specific set of changes needed for this? I tried with the below and got no errors (this doesn't load evil, but as far as I understand the bug is not related to evil-mode).
~/src/emacs$ emacs -Q -l bug-1074evil-undo-tree/setup.el -f bug-1074-do-changes -f kill-emacs
~/src/emacs$ emacs -Q -l bug-1074evil-undo-tree/setup.el -f bug-1074-undo --eval '(sit-for 2)' -f bug-1074-redo
Where is bug-1074evil-undo-tree/setup.el
is
(defconst bug-1074-dir
(file-name-directory (or load-file-name buffer-file-name)))
(setq undo-limit 78643200)
(setq undo-outer-limit 104857600)
(setq undo-strong-limit 157286400)
(setq undo-tree-mode-lighter " UN")
(setq undo-tree-auto-save-history t)
(setq undo-tree-enable-undo-in-region nil)
(setq undo-tree-history-directory-alist `(("." . ,(expand-file-name "undo" bug-1074-dir))))
(add-hook 'undo-tree-visualizer-mode-hook
(lambda ()
(undo-tree-visualizer-selection-mode)
(setq display-line-numbers nil)))
(add-to-list 'load-path (expand-file-name "../elpa/packages/undo-tree/" bug-1074-dir))
(require 'undo-tree)
(global-undo-tree-mode 1)
(defun bug-1074-do-changes ()
(interactive)
(let ((file (expand-file-name "xx.txt" bug-1074-dir)))
(with-current-buffer (find-file-noselect file)
(pop-to-buffer-same-window (current-buffer))
(dotimes (i 30)
(insert (format "%d\n" i))
(save-buffer)))))
(defun bug-1074-undo ()
(interactive)
(let ((file (expand-file-name "xx.txt" bug-1074-dir)))
(with-current-buffer (find-file-noselect file)
(pop-to-buffer-same-window (current-buffer))
(dotimes (i 30)
(undo-tree-undo)))))
(defun bug-1074-redo ()
(interactive)
(let ((file (expand-file-name "xx.txt" bug-1074-dir)))
(with-current-buffer (find-file-noselect file)
(pop-to-buffer-same-window (current-buffer))
(dotimes (i 30)
(undo-tree-redo)))))
You're correct that the problem is with undo-tree
. I have this problem, too. And it's a nightmare. The undo simply isn't reliable. I've lost work many times because of this.
Unfortunately, there are two problems here. First, while it is reasonable to expect a set of steps to reproduce the error, a definitive way to reproduce it has yet to be found. Refer to the links @mrbig033 provided to see various other suggested steps. No one has found a way to reproduce it reliably. Second, the package author is unlikely to fix the problem any time soon. To quote the author from one of the linked bug reports,
The undo-tree undo-in-region code is fiendishly complex, hard to test, and under-tested.
He's apparently a busy man, too.
The previous link suggests recompiling Evil without the undo-tree
dependency. There has to be a better way!
Maybe there's a way to disable the loading of undo-tree
in the first place? I'm not very experienced with Elisp, but is there something I can do help find a solution?
The previous link suggests recompiling Evil without the
undo-tree
dependency. Maybe there's a way to disable the loading ofundo-tree
in the first place?
From what I read there, recompiling simply has the same effect as (global-undo-tree-mode -1)
(i.e., you lose redo, though I guess if you can get used to Emacs' redo-via-undoing-undo flow it could be workable).
I'm not very experienced with Elisp, but is there something I can do help find a solution?
Well, finding a way to reproduce the problem, that's really what we're missing.
I've never not been able to reproduce this issue with my config and stopped using undo tree entirely a while ago. @lawlist may know how to reliably reproduce this problem. From my understanding, he has fixed this issue for various cases in his fork.
(setq undo-tree-enable-undo-in-region nil)
See: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=16377#55
Quote from Dr. Cubitt:
No, the new error checking just helpfully revealed an existing bug in
undo-tree's undo-in-region support (which frankly has always been flaky,
as it's extraordinarily difficult to reliably reproduce undo
bugs). There's even an `undo-tree-enable-undo-in-region' toggle to
disable undo-in-region support, for exactly this reason. Probably I
should make it default to "off" for now.
That's been in my config and has never affected/prevented corruption (with persistent undo). Based on the linked spacemacs issues, other users have had the same experience. Are you saying that this is the cause of corruption (or is at least the cause with persistence disabled)?
I am going to go out on a limb and assume corruption with persistent undo might mean that Emacs crashes or fails to load the undo-tree history file. If that is the case, there are two causes I have encountered: (1) on OSX, the undo tree is rather large and Emacs 26+ cannot handle it; or, (2) the undo-tree history file contains #
and Emacs cannot read it; e.g., #<marker in no buffer>
or #<overlay in no buffer>
. This can be determined by manually inspecting the undo-tree history file and searching for the #
symbol. The remedies for 1 and 2 are different. If you are referring to a third situation I have not yet seen, then I'd be interested in documenting it. Although Eli strongly discourages this (setq-default bidi-display-reordering nil)
at least temporarily while inspecting the undo-tree history file, permits me to go through that buffer without Emacs bogging down -- remove that setting after you are finished debugging.
Chiming in with another report that (setq undo-tree-enable-undo-in-region nil)
does not solve the issue. It seems to me that the bug is triggered almost 100% of the time when there is a branch in the tree. If I undo backward past the branch and they try to go forward again from the branch point, I get the canary error. However, I have not tested this scientifically, so it could be my brain playing tricks on me.
For me, It happens even with persistent mode off. It's not causing problem though, since I don't trust it anymore and simply don't rely on it.
I have a more basic problem with undo-tree; It bundles too many changes as a single change. E.g., I have typed, deleted, inserted a new line, then ran a command I didn't like, and so I undo, and go back to the beginning.
@NightMachinary for that you can try experimenting with evil-want-fine-undo
.
@NightMachinary -- see my answer on stackexchange: https://emacs.stackexchange.com/a/47349/2287
Maybe there's a way to disable the loading of
undo-tree
in the first place? I'm not very experienced with Elisp, but is there something I can do help find a solution?
I am more experienced with Elisp now.
It seems that evil
will default to (Emacs) undo
if it can't find undo-tree
. Removing undo-tree
from the load-path
seems to do the trick. This can be done as follows:
undo-tree
, either by looking in ~/.emacs.d/elpa/
or by looking at the value of load-path
after undo-tree
has been loaded (and using C-h v load-path
).load-path
to itself with undo-tree
removed: (setq load-path (remove "/home/lorem/.emacs.d/elpa/undo-tree-0.6.5" load-path))
Altogether, that section of my init.el
looks like:
(package-initialize)
(require 'package)
(add-to-list 'package-archives
'("melpa" . "http://melpa.org/packages/") t)
(package-refresh-contents)
;; Don't load undo-tree.
(setq load-path (remove "/home/lorem/.emacs.d/elpa/undo-tree-0.6.5" load-path))
Unfortunately, you can't just delete undo-tree
altogether. Some of the navigation requires goto-chg.el
which uses it. The top matter of evil.el states,
;; Evil requires
goto-last-change' and
goto-last-change-reverse' ;; function for the corresponding motions g; g, as well as the ;; last-change-register `.'. One package providing these functions is ;; goto-chg.el: ;; ;; http://www.emacswiki.org/emacs/GotoChg ;; ;; Without this package the corresponding motions will raise an error.
I wonder whether one of the packages mentioned on the emacswiki, which don't rely on undo-tree
,
could be used instead?
;; Don't load undo-tree. It's the devil. (setq load-path (remove "/home/lorem/.emacs.d/elpa/undo-tree-0.6.5" load-path))
What's your version of evil? This solution didn't work at least since January 2017. I tried your solution both with the older evil and the most recent one. Trying redo
after applying the changes always results in Wrong type argument: commandp, redo
.
FTR emacs stackexchange question about this bug has a similar answer, with the same effect.
I'm running evil 1.2.14. When I use C-r
for redo
, I also get the message Wrong type argument: commandp, redo
. This is expected.
By default, C-r
runs the undo-tree-redo
command. Removing undo-tree
from the load path means that the undo-tree-redo
function is no longer available. The evil-normal-state-map
references something that doesn't exist. Hence, we would anticipate some error (i.e. the message) and expect normal undo/redo Emacs behavior. And that's what we see.
Emacs doesn't have a native "redo" function, per se. It only has undo
. To redo, you must "undo the undo". In practice this means:
<ESC>
or j
undo
, by pressing u
or C-/
, to "undo the undo"Admittedly, not loading undo-tree
is kind of a kludge. But it does produce the desired behavior (i.e. replacing an unreliable undo/redo with a reliable one (via native Emacs undo
)) as well as frees up a two-key combo :).
You can learn more about how Emacs undo
works by looking at the undo documentation and this reddit post that has nice pictures.
A new undo-tree release has been made (0.7), which looks like it goes some way toward mitigating errors people are seeing. Let me know if you experience problems with the new version.
It seems, ELPA haven't updated yet the package, so here's a few links so people wouldn't search them:
It's definitely on ELPA: https://elpa.gnu.org/packages/undo-tree.html
It's definitely on ELPA: https://elpa.gnu.org/packages/undo-tree.html
Oh, indeed, this is odd. I'm still seeing latest version as 20170706.246 even when I package-list-packages
from emacs -Q
. Oh well, it's probably then something on my side.
I'm still seeing latest version as 20170706.246
That sounds like a MELPA version. Not sure how, as undo-tree doesn't seem to be present in MELPA. Maybe it used to be?
@Hi-Angel In the list-packages
view click on undo-tree
and 0.7
should show up under Other versions:
.
Having learned the potential root causes from this blog post, I sparked a discussion about this new release regarding possible suggestions and further improvements <Lost or corrupted `undo-tree' history>. Feel free to join.
I am now using undo-fu and it's working well for me.
I've recently made some updates to undo-fu, namely, ensuring redo doesn't undo after existing undo/redo commands.
I think this is suitable for evil-mode.
I think this is suitable for evil-mode.
undo-fu seems to lack saving history to file, so I don't think it is.
There are existing packages that can save the undo history although I didn't try them out yet: see, https://stackoverflow.com/questions/2985050
Said differently, if this feature is important, it may be best to support via existing packages made for the purpose of restoring the session.
Stability is a feature too, over the years there have been many reports of bugs, this should be taken into account when considering alternatives to undo-tree, exactly how it's done - I'm not so fussed - undo-tree could be optional or there could be a way to switch out undo back-ends.
I think this is suitable for evil-mode.
undo-fu seems to lack saving history to file, so I don't think it is.
Just looked into undohist, extended it a little and think this can support undo-fu without having to merge them into a single package. (link to repo)
Update, undo-fu-session is now available on melpa for use with undo-fu
.
Reconsider switching to undo-fu
please.
doom has dropped undo-tree
and switched to undo-fu
https://github.com/hlissner/doom-emacs/issues/2339
Despite recent updates, undo-tree
is still very unstable package (e.g. it yields random freezes on file saving and it prevents opening files with undo-tree-mapc: Wrong type argument: listp, \.\.\.
error). Switching to undo-fu
can actually be a good idea.
@lockie -- have you by chance altered the settings for print-level
and/or print-length
that both have a default value of nil
? The error message is most likely caused because the data was truncated with three dots ....
@lawlist thanks for the tip, but no, I haven't set those explicitly and, as describe-variable
shows, they are both set to nil
.
Please correct me if I am wrong, but my understanding is once we have undo-redo
(https://github.com/emacs-mirror/emacs/blob/bbbab82a7117e08a77433f5ad39b34f5e03a014c/etc/NEWS#L77) Evil won't need to depend on undo-tree
.
@b3n right, although I'd argue evil could already make undo-tree optional, as undo-fu is an existing alternative to undo-tree.
@b3n right, although I'd argue evil could already make undo-tree optional, as undo-fu is an existing alternative to undo-tree.
I am now using Doom Emacs which comes with undo-fu by default. It presents no issues.
Can we please have the ability to set undo package in evil without resorting to Doom Emacs? As mentioned before, undo-tree is very unstable (matter of fact, it just froze my Emacs completely on file saving).
You don't really need to resort to doom, if you don't want to. Doom just disables global-undo-tree-mode
and uses undo-fu.
You can put (global-undo-tree-mode -1)
after (evil-mode)
and use undo-fu.
I'd rather have undo-tree opt-in, but this workaround seems to work for now.
@wedens that did the trick, thanks!
You don't really need to resort to doom, if you don't want to. Doom just disables
global-undo-tree-mode
and uses undo-fu.You can put
(global-undo-tree-mode -1)
after(evil-mode)
and use undo-fu.I'd rather have undo-tree opt-in, but this workaround seems to work for now.
That what I was doing before switching to Doom.
Hi guys, so finally we still cannot remove undo-tree (or set is as optional) in spacemacs?
Personally, I'd rather move to native undo-redo
(as provided by the upcoming Emacs 28 release, backportable to 27.1 and probably earlier) than using undo-fu
. In any case, a pluggable undo system is needed. I'm not sure how to do this in a non-breaking/-annoying way, here's some options:
(evil-undo-enable 'undo-tree)
or (evil-undo-enable 'undo-fu)
or (evil-undo-enable 'undo-redo)
to their init file. The evil-undo-enable
function would then load up the relevant package (or fail with an appropriate error suggesting you to install it/upgrade Emacs). Clean, but users would need to adjust their init file to contain that call. Bonus: Change the undo/redo command so that it tells you to do that.evil-undo-system
) for choosing the preferred undo system with a setter doing something similar to the above suggestion. The problem with that is what the default should be, undo-tree would be an obvious one but few people would actively change the default. Picking something else would be annoying to people who prefer undo-tree (for example the ones without persistent undo). Maybe not pick anything at all and make the undo/redo command tell you to customize it.Another problem I've noticed is that the existing integration of undo-tree is already pretty magic and does lots of key remapping. For example Evil binds C-r
to redo
(the relevant commit speaks of not directly using undo-tree commands) and undo-tree remaps redo
to undo-tree-redo
. I'd rather not trample over the elisp function namespace (there's a redo and redo+ package defining such a function), but doing any changes there would break any customizations doing similar tricks. I've searched GitHub and found a few users remapping other keys to point to undo
and redo
, to reach those I'd need to do something like Magit's nagging popups telling you to customize something so that it goes away (like said proposed customizable).
Feedback on this is welcome.
@wasamasa agree using undo-redo seems a good/reasonable default. Then at least alternatives can be optionally supported.
If undo-redo
had existed I might not have written undo-fu
, however it still provides switching between linear/non-linear undo traversal in a way that's quite convenient, so there is still use in supporting it IMHO, even if it's using undo-redo under the hood.
Either of the first two suggestions seem fine. The second option (evil-undo-system
) would cause the least complaints from existing users if it defaults to undo-tree.
Note that there is undo-fu-session
, a standalone package for persistent undo that works with emacs built-in undo system (undo-redo
and undo-fu
).
@ideasman42 Please test https://github.com/emacs-evil/evil/pull/1360, it allows you to (setq evil-undo-system 'undo-fu)
.
@wasamasa tested evil-undo-system
:
I needed to set this in the :init
section of use-package, it didn't work when set from :config
. (not sure if that should be noted in docs?)
When setting to undo-tree
, calling evil-undo
reports user-error: Undo-tree mode not enabled in buffer
undo-fu
works as expected.
:init
is intentional, it's the same as nearly all customizables in this regard: Either customize before Evil has been loaded (that's what :init
does) or use custom.el to customize at any time. Or use the evil-set-undo-system
helper function directly, your choice.
I've run into that undo-tree error initially when fixing the test cases, but didn't have it when trying with my normal installation. I guess evil-set-undo-system
requires some of the now deleted undo-tree integration code? In any case, I'll figure out what the issue with my installation is and hope the error manifests itself normally for me.
@ideasman42 See https://github.com/emacs-evil/evil/pull/1360#issuecomment-705443960 for my latest progress on this.
Undo-tree author+maintainer here. I turned Evil recently :) So might be able to help investigate this...
The "unrecognized entry in undo list undo-tree-canary" error when using undo-tree and Evil may due to a small number of evil-mode
commands directly manipulating buffer-undo-list
. You can't do that and just expect undo-tree-mode
to make sense of it. In particular evil-paste-pop
, maybe evil-repeat-pop
mess around with buffer-undo-list
in ways I'm not sure are safe. (A number of other evil-mode
commands push new elements onto buffer-undo-list
, but just pushing elements onto the list is safe.)
Undo-tree-mode puts the symbol 'undo-tree-canary
at the very end of buffer-undo-list
, to detect when Emacs GC has discarded undo history. (See this post for a more in-depth explanation.) Evil commands need to ensure they maintain the invariant that the final two elements of buffer-undo-list
are always '(nil undo-tree-canary)
when undo-tree-mode
is enabled. Otherwise they are likely to break undo.
If anyone has a recipe to reproduce the error, starting from emacs -Q
, I'd be happy to look into it further as and when I have time.
Toby
This seems to be a case where evil-repeat-pop
causes the error:
Unrecognized entry in undo list undo-tree-canary
With the evil
and undo-tree
packages installed.
emacs -q --load C:\Users\username\AppData\Roaming\.custom-init.el
(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
(add-to-list 'package-archives '("org" . "https://orgmode.org/elpa/") t)
(setq ring-bell-function 'ignore)
(setq user-emacs-directory "C:/Users/username/AppData/Roaming/.custom.emacs.d")
(setq package-user-dir "C:/Users/username/AppData/Roaming/.custom.emacs.d/elpa/")
(setq-default frame-title-format '("Custom init.el"))
(package-initialize)
(require 'evil)
(evil-mode 1)
(evil-set-undo-system 'undo-tree)
(global-undo-tree-mode)
(add-hook 'evil-local-mode-hook 'turn-on-undo-tree-mode)
(message "Custom packages Loaded")
On startup the variable buffer-undo-list
has the value:
(nil
(409 . 798)
(#("
" 0 1
(face variable-pitch help-echo "For information about GNU Emacs and the GNU system, type C-h C-a.")
1 2
(face variable-pitch help-echo "For information about GNU Emacs and the GNU system, type C-h C-a."))
. 409)
(3 . 412)
(nil keymap nil 2 . 3)
(nil rear-nonsticky nil 2 . 3)
(nil display nil 2 . 3)
(1 . 3)
(t . 0))
C-x b
a prompt appears: Switch to buffer (default *scratch*):
Confirm: RET
i
a
ESC
yy
p
u
p
.
(press period)C-.
(press Ctrl and period)C-.
The minibuffer shows:
Unrecognized entry in undo list undo-tree-canary
When the steps above (from switch buffer...), are followed right after starting Emacs -q, without checking the buffer-undo-list
first, then it has the value:
(nil undo-tree-canary nil
(nil rear-nonsticky nil 147 . 148)
(#("
" 0 1
(fontified nil))
. -149)
(147 . 150)
146)
I don't know if it's helpful but if the buffer-undo-list
variable is checked right after starting Emacs.
C-h v
buffer undo list
(Emacs fills in the dashes between the words automatically)RET
*Help*
buffer: C-w j
(or C-x o
)C-f
(repeat 4 times to scroll to the bottom)Then follow the steps above from (switch buffer...),
now the buffer-undo-list
variable has the value:
(nil . #1=(undo-tree-canary nil
(nil rear-nonsticky nil 147 . 148)
(#("
" 0 1
(fontified nil))
. -149)
(147 . 150)
146 nil . #1#))
evil-20210109.807
undo-tree-0.7.5
GNU Emacs 27.1 (build 1, x86_64-w64-mingw32) of 2020-08-21
Windows 10 Version 2004
@duianto You are a genius at coming up with these steps-to-reproduce! As always, this was really helpful. At least for this example, the problem is indeed evil-mode
making assumptions about how buffer-undo-list
behaves that are not valid in undo-tree-mode
.
The problem here is buried within the evil-with-undo
macro, and the evil-undo-pop
function. But it's subtle.
The evil-with-undo
macro executes its body with buffer-undo-list
let-bound to nil, then nconc's any new undo entries that get generated onto the front of buffer-undo-list
at the end of the macro. I don't fully understand at the moment why it does things this way. Surely prepending new undo entries onto the front of buffer-undo-list
is what Emacs does anyway, so why bypass that mechanism and then do the same thing by hand? Ultimately, doing this is what causes the bug (see below). Is it just to temporarily enable undo in buffers where it's disabled? If so, there may be safer ways of doing this.
In any case, whatever the reason for it, at first sight this way of doing things might appear to be safe. As long as no undo-tree
command is called, undo-tree-mode
doesn't touch buffer-undo-list
(or do anything at all, in fact - undo-tree-mode
code only ever runs when an undo or redo command is called), and buffer-undo-list
gets appended to exactly as in vanilla Emacs. Just with an extra undo-tree-canary
entry at the very end; but that gets left intact by evil-with-undo
's nconc, as required.
However, @duianto's sequence up to the C-.
(evil-repeat-pop
) leaves u
(evil-undo
) as the entry-before-last in evil-repeat-ring
, and the C-.
causes that undo operation to be repeated. So the above assumption is false: an undo-tree
command does get called whilst inside evil-with-undo
, namely undo-tree-undo
(via repeating the evil-undo
). undo-tree-undo
sees the empty buffer-undo-list
value let-bound by evil-with-undo
, and adds an undo-tree-canary
on the end of it, as it's supposed to when it encounters an empty buffer-undo-list
. evil-with-undo
then nconc's that onto the front of the real buffer-undo-list
, which puts an undo-tree-canary
value in the middle of buffer-undo-list
(as well as the original one still at the end of buffer-undo-list
).
The second C-.
then calls evil-undo-pop
, which call's Emacs vanilla undo
function. That's definitely wrong anyway when in undo-tree-mode
- it's very unlikely to work correctly, since undo
takes its undo history from buffer-undo-list
, whereas undo-tree-mode
transfers the history to buffer-undo-tree
whenever it gets an opportunity. (This could potentially account for other instances of corrupted undo history in evil-mode
+ undo-tree-mode
.) But combined with the above evil-with-undo
-induced bug, it results in undo
trying to undo changes from the b0rked buffer-undo-list
with undo-tree-canary
in the middle, triggering the "Unrecognized entry" error.
A kludgy fix for this particular issue would be for evil-with-undo
to strip any undo-tree-canary
value it finds from evil-temporary-undo
before nconc'ing it onto the front of buffer-undo-list
. In (very rudimentary) testing, this at least prevents the error in this particular example. I'm not entirely certain if this kludge produces the correct behaviour, as I haven't wrapped my head around what the expected behaviour of the two sequential C-.
's is.
A slightly less kludgy fix might be to not short-circuit Emacs' undo system in evil-with-undo
, and just let Emacs do its thing. But I'm not sure if this is viable, as I don't fully understand what evil-with-undo
is supposed to do. In fact, at the moment, I don't see how that macro does anything useful at all. The docstring says "If undo is disabled in the current buffer, the undo information is stored in evil-temporary-undo
instead of buffer-undo-list
." But evil-temporary-undo
is only set after the macro body has already been called. And then evil-temporary-undo
gets set to null at the end of the macro, before any other code gets to see the value. The only effect of evil-with-undo
I can see is to temporarily enable undo in the buffer if it's disabled (i.e. if buffer-undo-list
is t
), and then discard any undo information in that case. Probably I'm missing something here. I tried redefining evil-with-undo
to be a no-op (i.e. just call body and return), and again in very rudimentary testing this at least seems to prevent the error in this particular example. However, it produces different behaviour to the other kludgy fix, above, so presumably one (or both!) fixes aren't producing the correct behaviour.
However, both of these "fixes" paper over the underlying problem. I strongly suspect there will be other cases that neither change will fix. The real problem this is that every evil-mode
function and macro that directly manipulates buffer-undo-list
is probably doing the wrong thing in undo-tree-mode
. In undo-tree-mode
, those functions should be interfacing with buffer-undo-tree
. Even a cast-iron guarantee that no undo-tree
commands can ever get invoked whilst they're manipulating buffer-undo-list
isn't sufficient. Firstly, as @duianto's example shows, this is fragile and very difficult to guarantee in all edge cases. But, worse still, recent versions of undo-tree
have a setting (not enabled by default) whereby undo history gets transferred to buffer-undo-tree
by a timer function.
A proper fix may take more time and effort, as I don't understand every detail of what those evil-mode
functions and macros are supposed to be doing, and the evil-mode
maintainers presumably don't understand every nuance of how undo-tree-mode
works. But identifying the problem is a start...
What about redefining evil-with-undo
something like this:
(defmacro evil-with-undo (&rest body)
"Execute BODY with enabled undo.
If undo is disabled in the current buffer, the undo information
is discarded."
`(unwind-protect
(let ((undo-disabled (eq buffer-undo-list t)))
(when undo-disabled (setq buffer-undo-list nil))
(unwind-protect
(progn ,@body)
(unless (null (car-safe buffer-undo-list))
(push nil buffer-undo-list))))
(when undo-disabled (setq buffer-undo-list t))))
(I took the opportunity to fix the docstring at the same time. The current docstring misleadingly implies body
can find something useful in evil-temporary-undo
, which I don't believe is true.)
Not sure yet if this fixes every evil-mode
/ undo-tree-mode
compatibility issue. But it fixes @duianto's example by getting rid of the problematic nconc
, and this ought to fix more than just this example. Does this break any evil-mode
functionality? The above seems functionally equivalent to the current evil-with-undo
implementation. Or am I missing something?
Issue
Undo tree is an undo package that cannot keep undos.
Environment
Emacs version: Emacs 26.1.50 Operating System: Manjaro (current) Evil version: Evil version 1.2.13 Evil installation type: MELP Graphical/Terminal: Graphical Tested in a
make emacs
session (see CONTRIBUTING.md): Yes Undo configurations:Reproduction steps
Expected behavior
You should be able to undo and/or redo every single change
Actual behavior
When it works, I'm able to undo 5 changes at the most. Half the time I can't undo anything at all. Sometimes I get the message
unrecognized entry in undo list undo-tree-canary
while I'm performing the undo.Further notes
It is not just me:
https://old.reddit.com/r/emacs/comments/85t95p/undo_tree_unrecognized_entry_in_undo_list/ https://debbugs.gnu.org/cgi/bugreport.cgi?bug=16523 https://debbugs.gnu.org/cgi/bugreport.cgi?bug=16377 https://lists.ourproject.org/pipermail/implementations-list/2014-November/002091.html https://github.com/syl20bnr/spacemacs/issues/298 https://github.com/syl20bnr/spacemacs/issues/9903
I also must add that I had this same problem before with entirely different configurations, other versions of Emacs and operating systems.