Amelio Vazquez-Reina
Amelio Vazquez-Reina

Reputation: 96264

Emacs: Cleaning up undo-tree

I have noticed that in long editing sessions, calling undo-tree (C-x C-u) becomes slower and slower. I presume that the reason is that as the tree grows bigger it takes longer to parse it (as it keeps track of all my edits since I opened the file)

Is there any way to clear up the tree of undos on an open file? I have tried C-x C-v (find-alternate-file), but this re-opens the file which resets the cursor (and in modes like org-mode collapses my lists)

Upvotes: 12

Views: 5494

Answers (4)

Wolfgang
Wolfgang

Reputation: 141

Occasionally I have to flush a buffer's undo-tree because I pasted some text that contained characters that cannot be displayed in the buffer/file's current encoding. So I found the function of @Amelio Vazquez-Reina very helpful. However, I don't want the function to be called by accident, so a added a confirmation prompt and a check that buffer-undo-tree really is a buffer local variable:

(defun clean-undo-tree ()
"Clear current buffer's undo-tree.
Undo-tree can cause problems with file encoding when characters
are inserted that cannot be represented using the files current
encoding. This is even the case when characters are only
temporarily inserted, e.g. pasted from another source and then
instantly deleted. In these situations it can be necessary to
clear the buffers undo-tree before saving the file."
  (interactive)
  (let ((buff (current-buffer)))
    (if (local-variable-p 'buffer-undo-tree)
        (if (y-or-n-p "Clear buffer-undo-tree? ")
            (progn
              (setq buffer-undo-tree nil)
              (message "Cleared undo-tree of buffer: %s" (buffer-name buff)))
          (message "Cancelled clearing undo-tree of buffer: %s" (buffer-name buff)))
      (error "Buffer %s has no local binding of `buffer-undo-tree'" (buffer-name buff)))))

Upvotes: 4

Toby Cubitt
Toby Cubitt

Reputation: 453

Note that this tip may be obsolete in recent undo-tree versions. From version 0.6 onwards, undo-tree uses "lazy tree-drawing" by default. This significantly speeds up visualization of large undo trees, by only drawing the visible portion (and extending it as necessary as you move around the tree). See the docstring for the undo-tree-visualizer-lazy-drawing variable for further details.

If you nonetheless want to discard the entire undo tree, manually setting buffer-undo-tree to nil is a good one-off solution. A longer-term solution is to reduce the values of undo-limit, undo-strong-limit, and undo-outer-limit to limit the undo tree size, by limiting how much undo history it stores before discarding older data.

Manually calling undo-tree-discard-history is pointless. It gets called automatically whenever you do anything undo-related.

Upvotes: 4

user4815162342
user4815162342

Reputation: 154886

Reset the buffer-undo-tree variable using M-: (setq buffer-undo-tree nil). This discards the entire undo history of the buffer, as recorded by undo-tree.el.

This can also be made into a command and bound to a key with code like this:

(defun clear-undo-tree ()
  (interactive)
  (setq buffer-undo-tree nil))
(global-set-key [(control c) u] 'clear-undo-tree)

Upvotes: 11

npostavs
npostavs

Reputation: 5027

You can prune the tree instead of discarding the whole thing:

undo-tree-discard-history is a compiled Lisp function in
`undo-tree.el'.

(undo-tree-discard-history)

Discard undo history until we're within memory usage limits
set by `undo-limit', `undo-strong-limit' and `undo-outer-limit'.

Upvotes: 1

Related Questions