To avoid performance issues, it is not recommended to run undo-tree-update-visualization-buffer
on the post-command-hook
-- thus, here we use run-with-idle-timer
instead. To try this out, place undo-tree.el/elc
in the load-path
, then paste the following code in a *scratch*
buffer and type M-x eval-buffer
(require 'undo-tree)
(defun undo-tree-update-visualization-buffer ()
(let ((update-visualization-buffer nil)
(tree nil)
(selected-window (selected-window))
(current-buffer (current-buffer)))
(when (and undo-tree-mode (not (get-buffer undo-tree-visualizer-buffer-name)))
(undo-tree-visualize))
(when (and undo-tree-mode (not (get-buffer-window undo-tree-visualizer-buffer-name)))
(let ((display-buffer-mark-dedicated 'soft))
(display-buffer undo-tree-visualizer-buffer-name)))
(when undo-tree-mode
(when (memq 'undo-tree-kill-visualizer before-change-functions)
(remove-hook 'before-change-functions 'undo-tree-kill-visualizer 'local))
(unless (equal buffer-undo-list '(nil undo-tree-canary))
(setq update-visualization-buffer t)
(undo-list-transfer-to-tree))
(setq tree buffer-undo-tree)
(with-current-buffer undo-tree-visualizer-buffer-name
(unless (eq undo-tree-visualizer-parent-buffer current-buffer)
(setq update-visualization-buffer t)
(setq undo-tree-visualizer-parent-buffer current-buffer)
(setq undo-tree-visualizer-parent-mtime
(and (buffer-file-name current-buffer)
(nth 5 (file-attributes (buffer-file-name current-buffer)))))
(setq undo-tree-visualizer-initial-node (undo-tree-current tree))
(setq undo-tree-visualizer-spacing (undo-tree-visualizer-calculate-spacing)))
(when update-visualization-buffer
(let ((inhibit-read-only t))
(erase-buffer)
(setq buffer-undo-tree tree)
(undo-tree-draw-tree tree)
(goto-char (point-max))
(when (re-search-backward "x" nil t)
(set-window-point (get-buffer-window undo-tree-visualizer-buffer-name) (point)))))))
(unless (eq selected-window (selected-window))
(select-window selected-window))))
(run-with-idle-timer 1.5 'repeat #'undo-tree-update-visualization-buffer)