casouri / vundo Goto Github PK
View Code? Open in Web Editor NEWVisualize the undo tree.
Visualize the undo tree.
Vundo is now available on ELPA! Vundo (visual undo) displays the undo history as a tree and lets you move in the tree to go back to previous buffer states. To use vundo, type M-x vundo RET in the buffer you want to undo. An undo tree buffer should pop up. To move around, type: f to go forward b to go backward n to go to the node below when at a branch point p to go to the node above a to go back to the last branching point w to go forward to the next branching point e to go forward to the end/tip of the branch l to go to the last saved node r to go to the next saved node m to mark the current node for diff u to unmark the marked node d to show a diff between the marked (or parent) and current nodes q to quit, you can also type C-g C-c C-s (or whatever binding you used for save-buffer) to save the buffer at the current undo state n/p may need some more explanation. In the following tree, n/p can move between A and B because they share a parent (thus at a branching point), but not C and D. To make it clear, branches you can switch between are highlighted with bold face. A C ──○━━○──○──○──○ ┃ ↕︎ ┗━━○──○──○ B D By default, you need to press RET to “commit” your change and return to the buffer. If instead you quit with q or C-g, the changes made by vundo are rolled back. You can set ‘vundo-roll-back-on-quit’ to nil to disable rolling back. You might see some green nodes in the tree, those are the buffer states that have been saved to disk; the last saved node is emphasized in bold. You can type "l" to jump to the last saved node. Note: vundo.el requires Emacs 28. Customizable faces: - vundo-default - vundo-node - vundo-stem - vundo-highlight - vundo-saved - vundo-last-saved If you want to use prettier Unicode characters to draw the tree like this: ○──○──○ │ └──● ├──○ └──○ set vundo-glyph-alist by (setq vundo-glyph-alist vundo-unicode-symbols) Your default font needs to contain these Unicode characters, otherwise they look terrible and don’t align. You can find a font that covers these characters (eg, Symbola, Unifont), and set ‘vundo-default’ face to use that font: (set-face-attribute 'vundo-default nil :family "Symbola") Diff: Vundo uses Emacs' facilities to provide diffs among arbitrary undo states: just (m)ark and (d)iff. By default, vundo's diff window is buried when vundo quits; see `vundo-diff-quit' for other options. Terminal users may encounter unwanted control characters in the diff output. Emacs colors diff buffers itself, so this can be remedied by instructing diff not to print color codes: (setq diff-switches "-u --color=never") Comparing to undo-tree: Vundo doesn’t need to be turned on all the time nor replace the undo commands like undo-tree does. Vundo displays the tree horizontally, whereas undo-tree displays a tree vertically. Diff is provided on-demand between any nodes. Tests: You can run tests by loading test/vundo-test.el and M-x ert RET t RET to run those tests interactively, or use the following batch command: emacs --batch \ -l vundo.el \ -l test/vundo-test.el \ -f ert-run-tests-batch-and-exit Changelog (full changelog in NEWS.txt): <2023-02-16 Fri>: Version 2.3.0: navigate among all saved nodes. Automatically bury the vundo-diff window when vundo quits. <2023-12-17 Sun>: Version 2.2.0: vundo-diff introduced, supporting on-demand diff to parent or any marked node. Improved tree draw speed. <2022-04-04 Mon>: Version 1.0.0 <2022-03-29 Tue>: vundo--mode and vundo--mode-map are now vundo-mode and vundo-mode-map. A new custom option vundo-compact-display is added. <2022-03-23 Wed>: UI now defaults to ASCII mode. ASCII mode also draws differently now, it now draws o--o--o instead of o--o--o | `--x | +--* |--o |--o `--o +--o <2021-11-26 Fri>: Variable vundo-translate-alist changed to vundo-glyph-alist and has different value now.
Normal: I comment a paragraph, it changes code block's color, and I use undo
, it uncomment back, color restore.
vundo: I comment a paragraph, it changes code block's color, and I use vundo-prev
and vundo-confirm
, it uncomment back, but color don't restore.
Does it relate to read-only mode ? I checkout e136164, it's OK.
Hi @casouri, since vundo is not available on Melpa, I can't get the lastest changes without using something like quelpa, do you mind making a new release please? It's been a while.
When at the beginning of the undo history run vundo-stem-root
, this results in an error.
Debugger entered--Lisp error: (wrong-type-argument vundo-m nil)
vundo--eqv-list-of(nil)
vundo--calculate-shortest-route(#s(vundo-m :idx 0 :children ... <SNIP>
vundo--move-to-node(#s(vundo-m :idx 0 :children ... :parent nil :prev-eqv nil :next-eqv ... :undo-list nil :point 2) nil #<buffer creator.c> (... ... ... ... ... ... ... ... ... ... ... ... ... ... ...))
vundo-stem-root()
funcall-interactively(vundo-stem-root)
command-execute(vundo-stem-root)
Edit, this also happens running vundo-stem-root
when at the stem end too.
It would be good if quitting vundo
would also close the vundo-diff
buffer & window.
So viewing a vundo-diff
buffer doesn't leave this buffer open once I've finished using vundo
(which I need to manually exit). I'm not so fussed on this being on by default or not, just that it would be nice if it's a toggle.
Of course it's possible to write advice that does this but it seems like something users might want to enable without the hassle of implementing this themselves.
Note that vundo-post-exit-hook
can't easily be used for this as the vundo buffer has been deleted (which is needed to access the name of the diff buffer).
This advice for vundo-quit
works but it involves using internal names.
(advice-add
'vundo-quit
:around
#'(lambda (old-fn &rest args)
(let* ((orig vundo--orig-buffer)
(oname (buffer-name orig))
(diff-buf (get-buffer (concat "*vundo-diff-" oname "*"))))
(when diff-buf
(let ((diff-window (get-buffer-window diff-buf)))
(when diff-window
(delete-window diff-window))
(kill-buffer diff-buf)))
(let ((result (apply old-fn args)))
result))))
You might want to incorporate this, or the package will be very unpleasant for people with other configs:
(defun night/h-vundo-buf-setup (orig-fn &rest args)
(let ((vundo-buf (apply orig-fn args)))
(with-current-buffer vundo-buf
(toggle-truncate-lines 1)
(evil-insert-state))
vundo-buf))
(advice-add 'vundo-1 :around #'night/h-vundo-buf-setup)
As outlined in #68, when undo chains get quite lengthy (exacerbated by saving undo history), vundo and emacs in general slow down. It's highly sensitive to line length (M-: (current-column)
tells you how long your lines are). Once past say 5k-10k columns, slowdown becomes apparent, and at >20k it becomes very noticeable, not just in vundo, but in all buffers while vundo is open. We increased the draw speed by ~10x in da90207, but that only affects how quickly vundo is drawn, not the slow-down from having such long lines around at all.
Here is an idea to mitigate this:
I saw this package adds itselft to evil-emacs-state-modes
.
I understand that is for preventing problems with the bindings.
while evil-mode adds vim like functionality to emacs, it doesn't deal with most third party packages.
For that reason evil-collection
was created to add that vim like funcionality.
I guess most people that use evil-mode either use evil-collection or are used to deal with those problems themselves.
There are different strategies to better integrate packages to the evil workflow.
Some users might set emacs-state for special modes, some might use evil's motion-state,
others might just locally override evil-normal-state bindings.
Vundo enables evil-emacs-state by default, this might interfere with strategies that evil-mode users already developed.
evil-collection-vundo.el is part of evil-collection. that file for example sets evil-state back to normal-state and rebinds the keys to use "hjkl" for motions in vundo-mode.
I assume most evil users would like to have those bindings, if they are not using evil-collection they are likely going to try to remap the keys and have to first realize, that vundo sets the state to emacs-state (it took me a while to find that issue).
For that reason, i recommend not setting any evil specific things to try to make some bindings work in evil-mode.
Those bindings are not evilish anyways.
Or at least make the state change optional and mention it inside the readme file.
What do you think?
Thanks
Hello,
I uses evil, and u & C-r keys are for undo and redo for me respectively.
Right now, it doesn't seem it is possible to bring up the vundo buffer and undo or redo right away.
If in the future there is to be integration with the evil-undo-system, IMO, it would then be beneficial to implement something like this.
Such that the following would be possible:
(setq evil-undo-function #'vundo-forward
evil-redo-function #'vundo-backward)
What is your recommendation for this?
Thank you
Is there a way to throw away all undo/redo history information for the current buffer?
I try to do this in the following scenarios:
Of course this would also help for #68.
Hi
Can you please make 2.5.0 release official so that it can be picked by elpa
Elpa is still using 2.1.0
Thanks !
From reddit user nv-elisp.
Pretty cool. I find the graph easier to follow horizontally than the vertical orientation undo-tree has.
A few ideas/suggestions:
I would expect vundo-next to work here as well and follow the diagonal of the graph. From here:
o--x--o
`--o
to here:
o--o--o
`--x
And I would expect vundo-previous to work similarly:
o--o--o
`--x
would lead to here:
o--x--o
`--o
Basically follow the lines of the graph when pressed instead of hopping to the the parallel point in the graph. This was just my initial impression, though. I could see getting used to the way it currently works as well.
It would be neat if one could click on any of the unselected points in the graph and show a buffer diffing current position in the graph with that point.
Another idea is to record/display some information about each point in the graph when navigating. Perhaps the time the edit was made?
Food for thought.
By convention double-dash is for internal/private symbols, in the case of key-maps - this is something users are likely to want to customize.
Suggest to name this vundo-mode-map
.
It would be better to wrap the kill-buffer-and-window
with the
(with-current-buffer vundo--orig-buffer
(setq-local inhibit-modification-hooks nil
buffer-read-only nil))
together, don't use it directly. After all, vundo-quit
would invoke it at least.
not sure if others have seen this, but with lazily loaded vundo on 28, the first C-x u is strangely long
This would allow you to save the buffer and continue to explore the undo history.
One UX nicety of undo-tree is that if you hit back to a branch point, and then hit forward, you go forward in whatever branch you were just on.
undo-tree visualizes this by coloring the currently "selected" branch slightly differently.
Is it feasible/realistic to have that in vundo?
Currently, as a user used to undo-tree, this feels like a big efficiency loss, because I am so used to being able to toggle between any two adjacent nodes by just hitting by back/forward keys (my thinking and muscle memory doesn't have to be predicated on whether or not I'm just in front of a branch boundary).
However, as I get used to vundo's capabilities, I may stop wanting this:
So I'm not advocating for this to have high priority. But it seems like a nicety worth adding if it's fairly easy.
evil-mode prevents that cursor hiding in the vundo-undo-tree buffer somehow.
I missed the "diff" function of undo-tree. You don't always need it, but for complex changes, it can be very helpful to figure out which branch you want. I cobbled together something that works for me — an "on demand" diff on key "d". I didn't study vundo
's source closely enough to do this more intelligently, but it would be lovely if something like this made it into vundo.
Thanks for this simple, robust, and great tool.
(defun my/vundo-diff ()
(interactive)
(let* ((orig vundo--orig-buffer)
(source (vundo--current-node vundo--prev-mod-list))
(dest (vundo-m-parent source)))
(if (or (not dest) (eq source dest))
(message "vundo diff not available.")
(let ((buf (make-temp-name (concat (buffer-name orig) "-vundo-diff"))))
(vundo--move-to-node source dest orig vundo--prev-mod-list)
(with-current-buffer (get-buffer-create buf)
(insert-buffer orig))
(vundo--refresh-buffer orig (current-buffer) 'incremental)
(vundo--move-to-node dest source orig vundo--prev-mod-list)
(vundo--refresh-buffer orig (current-buffer) 'incremental)
(diff-buffers buf orig)
(kill-buffer buf)))))
(define-key vundo-mode-map "d" #'my/vundo-diff)
Hi,
I have tried vundo, but the diff feature didn't work properly for me. It does work in init.el
buffer, but it doesn't work in 15.py
- the diff is not shown at all:
After a bit of digging, I have found that the problem is caused by vundo-diff--cleanup-diff-buffer
- before it is called, the diff is shown.
Seems like an issue with the regexp:
(rx-to-string `(and bol ,pat (+ space)
(group (group (+ (not ?\t)))
(* any))
eol))
In particular, when I replace the greedy operators +
and *
by their non-greedy variant:
(rx-to-string `(and bol ,pat (+ space)
(group (group (+? (not ?\t)))
(*? any))
eol))
I don't know why this only happens in some buffers.
This looks like a nice package. Do you intend to merge this at some point into Emacs 28 core?
In my init I have the (setq vundo-glyph-alist vundo-unicode-symbols)
which fails and if I try evalutating it, it fails as well. Unless I run vundo
and then evaluate it, then it works just fine. I then tried putting (vundo-mode)
in my init before the setq
command and that also fails. It seems like the issue is that until I call vundo
I can't call vundo-mode
or change the variables.
When I launch Emacs I have 4 vundo
commands available in M-x
, vundo
, vundo-diff
, vundo-diff-mark
and vundo-diff-unmark
. After calling vundo
though I get 19 different commands. So it seems like somehow vundo isn't being loaded properly?
I am using Emacs 29.1 with the most up to date version of vundo
.
A recap from #62: there is one type of information that is lost when vundo trims the "useless" tails of very long undo-buffer lists — timestamps. Emacs inserts timestamps into the modification record when modifying a saved (aka unmodified) buffer. These timestamp (TS) records are simple, and look like:
(t 25616 45086 191805 680000) ; the numbers are the same format as (current-time)
Importantly, timestamps are inserted whether the modification in question is an "ordinary" modification, or an "undo/redo" modification. But vundo trims the latter to avoid the buffer-undo-list
growing exponentially (which happens fast thanks to its ability to fly around a tree of undos). In doing this trimming, timestamps associated with undo/redo modifications are lost.
These lost timestamps show up in two ways:
Here is a possible solution: for any new TS records found past the last ordinary modification, "teleport" them back to the equivalent node closest to the root with the same directionality. Said more precisely: for t
representing the newly discovered node with the timestamp, pair (t-1
, t
) is mapped to equivalent pair (p-1
, p
), for the minimal p
. Then we teleport the TS from t
→p
, overwriting any found there.
In picture form (borrowing from @casouri's excellent blog post):
To evaluate if a given node is saved, we check if the next state of that node or any equivalent node has a TS record. For example, in the diagram, node 1 is known to be saved, because its equivalent node 5 sees a TS in the next state up (node 6). This will fix problem 2 above.
Problem 1 is also fixed, as long as vundo selects a path that arrives via the adjacent TS node. So for example, in the above right-hand example, going from 0→1 is via 6→5, which works correctly. No path from 2→1 will set the buffer to unmodified, but the same would be true for regular undo/redo as well. Also note that the teleportation process, even if it overwrites an older TS, does not cause problems; undo already ignores older timestamps that do not match the file's modification time.
The cost is (sometimes) maintaining a bit more tail to track save-then-undo's. In the above example (pink node is current), normally you'd trim back to node 5. For the left scenario, you do that. For the right scenario, you trim only back to node 6.
Since there's some prior work in this space, I think it would be useful with a short paragraph about why you would want to use vundo
over UndoTree
When running vundo-stem-root
from a child of a branch besides the first, an assertion is raised.
Refreshing again (from calling vundo-next
for example) shows the action is infact completed.
I checked back to the early history of vundo
and this appears to be a bug in the initial version (not a regression).
emacs -batch -l ./vundo.el -l ./test/vundo-test.el -f ert-run-tests-batch-and-exit
Gives the following error in emacs-29 (9fab134ee8b4ed439a8944e0d7058b1898c9bc0b
).
Running 7 tests (2022-04-04 10:15:43+1000, selector ‘t’)
Undo
passed 1/7 vundo-test--1 (0.011325 sec)
passed 2/7 vundo-test--2 (0.118555 sec)
Mark set
Undo
Test vundo-test--3 backtrace:
ert-fail(((should (equal (vundo-test--buf-str-np) "acde")) :form (eq
(if (unwind-protect (setq value-137 (apply fn-135 args-136)) (setq f
(let (form-description-139) (if (unwind-protect (setq value-137 (app
(let ((value-137 'ert-form-evaluation-aborted-138)) (let (form-descr
(let* ((fn-135 #'equal) (args-136 (condition-case err (let ((signal-
(let ((vundo-glyph-alist vundo-unicode-symbols)) (vundo-test--insert
(progn (buffer-enable-undo) (let ((vundo-glyph-alist vundo-unicode-s
(unwind-protect (progn (buffer-enable-undo) (let ((vundo-glyph-alist
(save-current-buffer (set-buffer temp-buffer) (unwind-protect (progn
(let ((temp-buffer (generate-new-buffer " *temp*" t))) (save-current
(closure (t) nil (let ((temp-buffer (generate-new-buffer " *temp*" t
ert--run-test-internal(#s(ert--test-execution-info :test #s(ert-test
ert-run-test(#s(ert-test :name vundo-test--3 :documentation "This te
ert-run-or-rerun-test(#s(ert--stats :selector t :tests [#s(ert-test
ert-run-tests(t #f(compiled-function (event-type &rest event-args) #
ert-run-tests-batch(nil)
ert-run-tests-batch-and-exit()
command-line-1(("-l" "./vundo.el" "-l" "./test/vundo-test.el" "-f" "
command-line()
normal-top-level()
Test vundo-test--3 condition:
(ert-test-failed
((should
(equal
(vundo-test--buf-str-np)
"acde"))
:form
(equal "abcd" "acde")
:value nil :explanation
(array-elt 1
(different-atoms
(98 "#x62" "?b")
(99 "#x63" "?c")))))
FAILED 3/7 vundo-test--3 (0.000103 sec) at test/vundo-test.el:183
passed 4/7 vundo-test--4 (1.562135 sec)
passed 5/7 vundo-test--mod-list (0.000068 sec)
passed 6/7 vundo-test--position-only-p (0.000032 sec)
passed 7/7 vundo-test--skip-position-only (0.000027 sec)
Ran 7 tests, 6 results as expected, 1 unexpected (2022-04-04 10:15:44+1000, 1.789043 sec)
1 unexpected results:
FAILED vundo-test--3
I'm using Emacs on Windows and installed vundo
today.
I tried using M-x vundo-diff
but got an error - 'diff' is not recognized as an internal or external command, operable program or batch file.
.
The equivilant of diff
command in linux seems to be FC
as mentioned in this stackoverflow post. So is there a way to configure this in vundo?
Maybe I'm just bad at looking but I couldn't find a keybinding that takes me back to where I was before I did M-x vundo
(or perhaps to the last change, I guess they can be different), is there one?
I'm getting jit-lock errors every time I run vundo
:
Error during redisplay: (jit-lock-function 1) signaled (wrong-type-argument number-or-marker-p nil)
Running vundo ecc0e2c, emacs -Q
, tested with Emacs 28 and 29.
The errors disappear when I deactivate jit-lock-mode
via vundo-mode-hook
.
I also noticed that, in the definition of vundo-mode
, jit-lock-mode
is called like this:
(jit-lock-mode -1)
Perhaps you meant to deactivate jit-lock-mode
there? If so, this is the correct (and unusual for minor-modes) form:
(jit-lock-mode nil)
I'm a user of evil-mode. So I prefer to call Vundo when I use evil-undo-system. This is my code below:
(defun evil-undo-advice(fn &rest _)
"Hybrid evil and vundo."
(if (not (fboundp 'vundo))
(funcall fn 1)
(vundo)
(if (eq fn 'evil-redo)
(vundo-forward 1)
(vundo-backward 1))))
(advice-add 'evil-undo :around #'evil-undo-advice)
(advice-add 'evil-redo :around #'evil-undo-advice)
The problem is orig-function arguments fn
, (if (eq fn 'evil-redo)
always return nil , even I call evil-redo
, it still execute vundo-backward
, I know it's not Vundo's problem, but how should I fix it ?
Very ocasionally vundo is asserting:
cl--assertion-failed: Assertion failed: (not (and (consp buffer-undo-list) (null (car buffer-undo-list))))
I traced the problem down to undo steps that only move the cursor, (an undo step that contains a single integer representing the cursor position).
Here is a script to reproduce the issue:
(defun undo-test-only-positional-changes ()
"Use this"
(interactive)
(dotimes (n 10)
(push n buffer-undo-list)
(push nil buffer-undo-list)))
(global-set-key (kbd "<f12>") 'undo-test-only-positional-changes)
Run this on a buffer with 11 characters or more, then undo (the cursor moves).
Then try use vundo, it instantly asserts.
Having undo steps that only move the cursor position seems strange, it's possible this occurs because of logic in undo-fu-session that flattens the undo-history. Although attempting to create branching steps that are flattened - I can't force this to happen, so I'm not sure why this occurs. Nevertheless, since it seems like valid undo data that emacs undo supports, I think vundo could support it too.
I was using vundo today to unravel a mystery of an edit that happened somehow, and it helped me identify which edit had the problem.
Now I have even a tricker part would like to solve: redo all the rest of the edits, but this problematic one.
Would this be a possibility with vundo? I feel like this could be an interesting idea.
Me myself is thinking, it may be an better idea to create a new undo branch, and not directly changing the undo history, and I also do not know how to make that happen yet. Would appreciate for all advises.
Lastly, I would most certainly apreciate some feedback some this idea also!
Thanks!
The readme says that diff is an advanced feature and unlikely to be supported. Would you be able to explain the challenges involved implementing such a feature?
Great package. Thank you for making it! I particularly love
Love the option to use pretty unicode characters too.
I haven't switched from undo-tree yet, but looking at how the feature set has matured and caught up (diffs, for example) has me seriously excited about it once I start wanting any of the three benefits I just mentioned badly enough. Literally right after making this post I tried switching. My config is now simpler and for the most part things are better.
Somehow the branches of my vundo tree don't align properly, this happens with utf8 glyphs, as well as with default ascii:
My config:
(use-package vundo
:ensure t
:config
(setq vundo-glyph-alist vundo-unicode-symbols)
(set-face-attribute 'vundo-default nil :family "Symbola")
(global-set-key (kbd "C-x u") 'vundo))
Do you have any idea why this would be happening? Anything I could do to help with debugging this issue?
Hej Hej,
More of a question than an issue:
Is it intended that vundo can be called inside a read-only buffer?
If it is shouldn't the read-only state be restored after exiting vundo?
My first thoughts would be "no" and "yes", but maybe I am missing something.
Cheers and thanks for the package,
OlMon
It would be great to keep undo/redo history after restarts. It has a cost, maybe it can be limited by time and or size of history.
Hello,
to get the nodes corresponding to saves highlighted - do I have to save from the vundo buffer to get this?
Because I am using vundo-highlight-saved-nodes
-> t I and never saw such highlights. Would you consider to allow to get the highlights when the user is saving normally?
I made it work in my config, but I had to duplicate a lot of quite internal vundo code. It would be nice if you could factor out a function that does the job. So that one could use it in or as an advice of save-buffer
. Would that make sense?
TIA - Michael.
What would it take to highlight the currently saved node in the vundo-mode
buffer?
Thank you!!
A couple of issues I have noticed with the horizontal orientation of the tree:
When the history gets very long Vundo takes quite a bit of time to start up and then it is rather slow. I guess limiting the length of the history would solve this, but how can I limit the size of just the displayed history?
PS: I use
(setq undo-limit (* 96 1024 1024)) ; 96 MiB. The change group at which this size is exceeded is the last one kept.
(setq undo-strong-limit (* 128 1024 1024)) ; 128 MiB. The change group at which this size is exceeded is discarded itself (along with all older change groups). There is one exception: the very latest change group is only discarded if it exceeds ‘undo-outer-limit’.
(setq undo-outer-limit (* 1024 1024 1024)) ; 1 GiB. If at garbage collection time the undo info for the current command exceeds this limit, Emacs discards the info and displays a warning. This is a last ditch limit to prevent memory overflow.
can it slow down Vundo?
I really like the package and recommend it to others. For me personally, I use straight.el and pull the package directly from GitHub. However for new emacs users who are not ready for straight or loading a package manually, packaging this on Melpa would be very helpful. Do you have any plans to do this?
I get this error when I call vundo
:
vundo--build-tree: Symbol’s function definition is void: undo--last-change-was-undo-p
I'm not sure how to properly install vundo,
I have this set up in elpaca:
;; Emulates vim keybinds & modal editing
(use-package evil
:init
;; ...
:config
(evil-mode 1))
;; keep undo history
(use-package undo-fu
:config
(setq evil-undo-system 'undo-fu))
;; keep file's undo history between emacs sessions
(use-package undo-fu-session
:config
(undo-fu-session-global-mode))
;; make undo history a tree on-the-fly
(use-package vundo)
Every time I enter vundo
using M-x
, pressing <RET>
returns this error,
Debugger entered--Lisp error: (void-function vundo-diff--quit)
vundo-diff--quit()
vundo-confirm()
funcall-interactively(vundo-confirm)
command-execute(vundo-confirm)
And it seems like the vundo-diff.el
isn't getting loaded how hard I try, I couldn't see those functions in help page, but I do see those files cloned and compiled in the elpaca cache.
I tried different ways elpaca support
(use-package vundo
:ensure (vundo :files (:defaults "*.el")))
;; or
(use-package vundo
:ensure (vundo :files ("vundo.el" "vundo-diff.el")))
;; or
(use-package vundo
:ensure (vundo :host github :repo "casouri/vundo" :files (:defaults "*.el")))
but none seem to work.
Thanks.
Also, can installation instructions be added in the README? 👀
The simplifying "cleanup" fix e5f3b81 introduced a subtle bug: it now allows duplicate entries to appear on vundo--timestamps
, which is an alist (where only "first match" counts) but is also a time-sorted list, for which duplicates do matter. In some situations this defeats previous/next saved node navigation, since the current and target node are identical.
Update: Hotfix in #102.
Currently, the point is placed after the node glyph instead of before.
When using Emacs in some terminals, the cursor can't be hidden, and can't be restyled, especially not per-buffer (and doing it globally for the whole terminal usually makes for worse UX over-all).
One real-world example of where you basically have to use such a terminal is in on Android, in Termux. Technically that terminal supports some standard control sequences to restyle the cursor (neovim manages to do it), but Emacs doesn't seem to know how to do it? Anyway, for me this is a huge part of my daily Emacs usage.
So it's a super minor aesthetic issue, but it seems like some users would prefer it if a can't-be-hidden/changed box cursor displayed on the node rather than to its right.
See this gist for an undo/vundo stress-test function, vundo--stress-test
. It has been revealing to play with.
These setting definitely pushing the limits:
Undo stress test complete:
10000 sentences inserted
1500 undo chains of max length 12
buffer-undo-list = 1948846 bytes
Buffer has 6394 lines, 39009 words, and 278099 characters.
Launching vundo:
Elapsed time: 9.235434s (0.088656s in 1 GCs)
Mark set
this one ranges from 5-10s (6s more typical). Even with this gargantuan tree, navigation is still quite smooth (again, 8 yo hardware here). Using a
to head up the tree works reliably, even as the length of the buffer-undo-list grows beyond 1/2 million. This is really impressive @casouri.
You can start to break things by going to extremes (here I've added a navigation to root benchmark too):
Undo stress test complete:
15000 sentences inserted
5000 undo chains of max length 9
undo-limits: 50000000 strong: 80000000 outer: 100000000
buffer-undo-list: length 261871, 23663505 bytes
Buffer has 16699 lines, 103312 words, and 736540 characters.
> Launching vundo:
Elapsed time: 16.320850s (0.225208s in 2 GCs)
> Navigating to tree root:
Elapsed time: 91.042314s (5.147266s in 42 GCs)
buffer-undo-list: length 277581, 24490891 bytes
Here navigation starts to stutter (though basically still usable), and you get the dreaded "No possible route" message sometimes. Also assertions occasionally fail when navigating to a child branch:
Debugger entered--Lisp error: (cl-assertion-failed ((not (and (consp buffer-undo-list) (null (car buffer-undo-list)))) nil))
cl--assertion-failed((not (and (consp buffer-undo-list) (null (car buffer-undo-list)))))
vundo--move-to-node(#s(vundo-m :idx 4 :children ... :parent ... :prev-eqv nil :next-eqv ... :undo-list ... :point 10 :prev-saved-ts nil) #s(vundo-m :idx 14 :children ... :parent ... :prev-eqv nil :next-eqv nil :undo-list ... :point 12 :prev-saved-ts nil) #<buffer *vundo-stress-test*> [... ... ... ... ... ... ... ... ... ... ... ... ... ... ...])
vundo-forward(1)
funcall-interactively(vundo-forward 1)
command-execute(vundo-forward)
Speed seems independent of whether vundo is native-compiled, which is good (time is spent outside vundo).
Originally posted by @jdtsmith in #66 (comment)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.