<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<id>tag:old.nabble.com,2006:forum-1576</id>
	<title>Nabble - Emacs - Sources</title>
	<updated>2009-11-29T11:19:13Z</updated>
	<link rel="self" type="application/atom+xml" href="http://old.nabble.com/Emacs---Sources-f1576.xml" />
	<link rel="alternate" type="text/html" href="http://old.nabble.com/Emacs---Sources-f1576.html" />
	<subtitle type="html">GNU Emacs source code postings and patches</subtitle>
	
<entry>
	<id>tag:old.nabble.com,2006:post-26565043</id>
	<title>Re: undo-tree.el</title>
	<published>2009-11-29T11:19:13Z</published>
	<updated>2009-11-29T11:19:13Z</updated>
	<author>
		<name>leon-9</name>
	</author>
	<content type="html">On 2009-11-29 19:03 +0000, Toby Cubitt wrote:
&lt;br&gt;&amp;gt; Appologies for posting three versions in quick succession, but I'd like
&lt;br&gt;&amp;gt; to get one version that compiles and works correctly, and I seem to be
&lt;br&gt;&amp;gt; incapable of this.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; Third time lucky...
&lt;br&gt;&lt;br&gt;It is great fun seeing this package mature ;)
&lt;br&gt;&lt;br&gt;Leo
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26565043&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/undo-tree.el-tp26554347p26565043.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-26564909</id>
	<title>Re: undo-tree.el</title>
	<published>2009-11-29T11:03:53Z</published>
	<updated>2009-11-29T11:03:53Z</updated>
	<author>
		<name>Toby Cubitt-5</name>
	</author>
	<content type="html">Appologies for posting three versions in quick succession, but I'd like
&lt;br&gt;to get one version that compiles and works correctly, and I seem to be
&lt;br&gt;incapable of this.
&lt;br&gt;&lt;br&gt;Third time lucky...
&lt;br&gt;&lt;br /&gt;&lt;br&gt;;;; undo-tree.el --- Treat undo history as a tree
&lt;br&gt;&lt;br&gt;&lt;br&gt;;; Copyright (C) 2009 Toby Cubitt
&lt;br&gt;&lt;br&gt;;; Author: Toby Cubitt &amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26564909&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;toby-undo-tree@...&lt;/a&gt;&amp;gt;
&lt;br&gt;;; Version: 0.1.2
&lt;br&gt;;; Keywords: undo, redo, history, tree
&lt;br&gt;;; URL: &lt;a href=&quot;http://www.dr-qubit.org/emacs.php&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.dr-qubit.org/emacs.php&lt;/a&gt;&lt;br&gt;&lt;br&gt;;; This file is NOT part of Emacs.
&lt;br&gt;;;
&lt;br&gt;;; GNU Emacs is free software: you can redistribute it and/or modify it under
&lt;br&gt;;; the terms of the GNU General Public License as published by the Free
&lt;br&gt;;; Software Foundation, either version 3 of the License, or (at your option)
&lt;br&gt;;; any later version.
&lt;br&gt;&lt;br&gt;;; This program is distributed in the hope that it will be useful, but WITHOUT
&lt;br&gt;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
&lt;br&gt;;; FITNESS FOR A PARTICULAR PURPOSE. &amp;nbsp;See the GNU General Public License for
&lt;br&gt;;; more details.
&lt;br&gt;&lt;br&gt;;; You should have received a copy of the GNU General Public License along
&lt;br&gt;;; with GNU Emacs. If not, see &amp;lt;&lt;a href=&quot;http://www.gnu.org/licenses/&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.gnu.org/licenses/&lt;/a&gt;&amp;gt;.
&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; Commentary:
&lt;br&gt;;;
&lt;br&gt;;; Emacs has a powerful undo system. Unlike the standard undo/redo system in
&lt;br&gt;;; most software, it allows you to recover *any* past state of a buffer
&lt;br&gt;;; (whereas the standard undo/redo system can lose past states as soon as you
&lt;br&gt;;; redo). However, this power comes at a price: many people find Emacs' undo
&lt;br&gt;;; system confusing and difficult to use, spawning a number of packages that
&lt;br&gt;;; replace it with the less powerful but more intuitive undo/redo system.
&lt;br&gt;;;
&lt;br&gt;;; Both the loss of data with standard undo/redo, and the confusion of Emacs'
&lt;br&gt;;; undo, stem from trying to treat undo history as a linear sequence of
&lt;br&gt;;; changes. It's not. The `undo-tree-mode' provided by this package replaces
&lt;br&gt;;; Emacs' undo system with a system that treats undo history as what it is: a
&lt;br&gt;;; branching tree of changes. This simple idea allows the more intuitive
&lt;br&gt;;; behaviour of the standard undo/redo system to be combined with the power of
&lt;br&gt;;; never losing any history. An added side bonus is that undo history can in
&lt;br&gt;;; some cases be stored more efficiently, allowing more changes to accumulate
&lt;br&gt;;; before Emacs starts discarding history.
&lt;br&gt;;;
&lt;br&gt;;; The only downside to this more advanced yet simpler undo system is that it
&lt;br&gt;;; was inspired by Vim. But, after all, most successful religions steal the
&lt;br&gt;;; best ideas from their competitors!
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;; Installation
&lt;br&gt;;; ============
&lt;br&gt;;;
&lt;br&gt;;; This package has only been tested with Emacs versions 22, 23 and CVS. It
&lt;br&gt;;; will not work without modifications in earlier versions of Emacs.
&lt;br&gt;;;
&lt;br&gt;;; To install `undo-tree-mode', make sure this file is saved in a directory in
&lt;br&gt;;; your `load-path', and add the line:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; (require 'undo-tree)
&lt;br&gt;;;
&lt;br&gt;;; to your .emacs file. Byte-compiling undo-tree.el is recommended (e.g. using
&lt;br&gt;;; &amp;quot;M-x byte-compile-file&amp;quot; from within emacs).
&lt;br&gt;;;
&lt;br&gt;;; If you want to replace the standard Emacs' undo system with the
&lt;br&gt;;; `undo-tree-mode' system in all buffers, you can enable it globally by
&lt;br&gt;;; adding:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; (global-undo-tree-mode)
&lt;br&gt;;;
&lt;br&gt;;; to your .emacs file.
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;; Quick-Start
&lt;br&gt;;; ===========
&lt;br&gt;;;
&lt;br&gt;;; If you're the kind of person who likes jump in the car and drive, without
&lt;br&gt;;; bothering to first figure out whether the button on the left dips the
&lt;br&gt;;; headlights or operates the ejector seat (after all, you'll soon figure it
&lt;br&gt;;; out when you push it), then here's the minimum you need to know:
&lt;br&gt;;;
&lt;br&gt;;; `undo-tree-mode' and `global-undo-tree-mode'
&lt;br&gt;;; &amp;nbsp; Enable undo-tree mode (either in the current buffer or globally).
&lt;br&gt;;;
&lt;br&gt;;; C-_ &amp;nbsp;C-/ &amp;nbsp;(`undo-tree-undo')
&lt;br&gt;;; &amp;nbsp; Undo changes.
&lt;br&gt;;;
&lt;br&gt;;; M-_ &amp;nbsp;C-? &amp;nbsp;(`undo-tree-redo')
&lt;br&gt;;; &amp;nbsp; Redo changes.
&lt;br&gt;;;
&lt;br&gt;;; `undo-tree-switch-branch'
&lt;br&gt;;; &amp;nbsp; Switch undo-tree branch.
&lt;br&gt;;; &amp;nbsp; (What does this mean? Better press the button and see!)
&lt;br&gt;;;
&lt;br&gt;;; C-x u &amp;nbsp;(`undo-tree-visualize')
&lt;br&gt;;; &amp;nbsp; Visualize the undo tree.
&lt;br&gt;;; &amp;nbsp; (Better try pressing this button too!)
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;; In the undo visualizer:
&lt;br&gt;;;
&lt;br&gt;;; &amp;lt;up&amp;gt; &amp;nbsp;p &amp;nbsp;C-p &amp;nbsp;(`undo-tree-visualize-undo')
&lt;br&gt;;; &amp;nbsp; Undo changes.
&lt;br&gt;;;
&lt;br&gt;;; &amp;lt;down&amp;gt; &amp;nbsp;n &amp;nbsp;C-n &amp;nbsp;(`undo-tree-visualize-undo')
&lt;br&gt;;; &amp;nbsp; Undo changes.
&lt;br&gt;;;
&lt;br&gt;;; &amp;lt;left&amp;gt; &amp;nbsp;b &amp;nbsp;C-b &amp;nbsp;(`undo-tree-visualize-switch-branch-left')
&lt;br&gt;;; &amp;nbsp; Switch to previous undo-tree branch.
&lt;br&gt;;;
&lt;br&gt;;; &amp;lt;right&amp;gt; &amp;nbsp;f &amp;nbsp;C-f &amp;nbsp;(`undo-tree-visualize-switch-branch-right')
&lt;br&gt;;; &amp;nbsp; Switch to next undo-tree branch.
&lt;br&gt;;;
&lt;br&gt;;; t &amp;nbsp;(`undo-tree-visualizer-toggle-timestamps')
&lt;br&gt;;; &amp;nbsp; Toggle display of time-stamps.
&lt;br&gt;;;
&lt;br&gt;;; q &amp;nbsp;C-q &amp;nbsp;(`undo-tree-visualizer-quit')
&lt;br&gt;;; &amp;nbsp; Quit undo-tree-visualizer.
&lt;br&gt;;;
&lt;br&gt;;; , &amp;nbsp;&amp;lt;
&lt;br&gt;;; &amp;nbsp; Scroll left.
&lt;br&gt;;;
&lt;br&gt;;; . &amp;nbsp;&amp;gt;
&lt;br&gt;;; &amp;nbsp; Scroll right.
&lt;br&gt;;;
&lt;br&gt;;; &amp;lt;pgup&amp;gt;
&lt;br&gt;;; &amp;nbsp; Scroll up.
&lt;br&gt;;;
&lt;br&gt;;; &amp;lt;pgdown&amp;gt;
&lt;br&gt;;; &amp;nbsp; Scroll down.
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;; Explanation
&lt;br&gt;;; ===========
&lt;br&gt;;;
&lt;br&gt;;; To understand the different undo systems, it's easiest to consider an
&lt;br&gt;;; example. Imagine you make a few edits in a buffer. As you edit, you
&lt;br&gt;;; accumulate a history of changes, which we might visualize as a string of
&lt;br&gt;;; past buffer states, growing downwards:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(initial buffer state)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(first edit)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(second edit)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;x &amp;nbsp;(current buffer state)
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;; Now imagine that you undo the last two changes. We can visualize this as
&lt;br&gt;;; rewinding the current state back two steps:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(initial buffer state)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;x &amp;nbsp;(current buffer state)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;; However, this isn't a good representation of what Emacs' undo system
&lt;br&gt;;; does. Instead, it treats the undos as *new* changes to the buffer, and adds
&lt;br&gt;;; them to the history:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(initial buffer state)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(first edit)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(second edit)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;x &amp;nbsp;(buffer state before undo)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(first undo)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;x &amp;nbsp;(second undo)
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;; Actually, since the buffer returns to a previous state after an undo, a
&lt;br&gt;;; better way to visualize it is to imagine the string of changes turning back
&lt;br&gt;;; on itself:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(initial buffer state) &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(first edit) &amp;nbsp;o &amp;nbsp;x &amp;nbsp;(second undo)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (second edit) &amp;nbsp;o &amp;nbsp;o &amp;nbsp;(first undo)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| /
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|/
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(buffer state before undo)
&lt;br&gt;;;
&lt;br&gt;;; Treating undos as new changes might seem a strange thing to do. But the
&lt;br&gt;;; advantage becomes clear as soon as we imagine what happens when you edit
&lt;br&gt;;; the buffer again. Since you've undone a couple of changes, new edits will
&lt;br&gt;;; branch off from the buffer state that you've rewound to. Conceptually, it
&lt;br&gt;;; looks like this:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(initial buffer state)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|\
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;x &amp;nbsp;(new edit)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;;
&lt;br&gt;;; The standard undo/redo system only lets you go backwards and forwards
&lt;br&gt;;; linearly. So as soon as you make that new edit, it discards the old
&lt;br&gt;;; branch. Emacs' undo just keeps adding changes to the end of the string. So
&lt;br&gt;;; the undo history in the two systems now looks like this:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Undo/Redo: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Emacs' undo
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .\ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp;|\
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; . \ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| &amp;nbsp;| \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; . &amp;nbsp;x &amp;nbsp;(new edit) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp;o &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; (discarded &amp;nbsp;. &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| / &amp;nbsp; |
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; branch) &amp;nbsp; . &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|/ &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; . &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp; &amp;nbsp; |
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;x &amp;nbsp;(new edit)
&lt;br&gt;;;
&lt;br&gt;;; Now, what if you change your mind about those undos, and decide you did
&lt;br&gt;;; like those other changes you'd made after all? With the standard undo/redo
&lt;br&gt;;; system, you're stuck. There's no way to recover them, because that branch
&lt;br&gt;;; was discarded when you made the new edit.
&lt;br&gt;;;
&lt;br&gt;;; However, in Emacs' undo system, those old buffer states are still there in
&lt;br&gt;;; the undo history. You just have to rewind back through the new edit, and
&lt;br&gt;;; back through the changes made by the undos, until you reach them. Of
&lt;br&gt;;; course, since Emacs treats undos (even undos of undos!) as new changes,
&lt;br&gt;;; you're really weaving backwards and forwards through the history, all the
&lt;br&gt;;; time adding new changes to the end of the string as you go:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp;o &amp;nbsp; &amp;nbsp; o &amp;nbsp;(undo new edit)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp;|\ &amp;nbsp; &amp;nbsp;|\
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp;| \ &amp;nbsp; | \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp;o &amp;nbsp;| &amp;nbsp;| &amp;nbsp;o &amp;nbsp;(undo the undo)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | / &amp;nbsp; | &amp;nbsp;| &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |/ &amp;nbsp; &amp;nbsp;| &amp;nbsp;| &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp;(trying to get &amp;nbsp; o &amp;nbsp; &amp;nbsp; | &amp;nbsp;| &amp;nbsp;x &amp;nbsp;(undo the undo)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; to this state) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| /
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |/
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o
&lt;br&gt;;;
&lt;br&gt;;; So far, this is still reasonably intuitive to use. It doesn't behave so
&lt;br&gt;;; differently to standard undo/redo, except that by going back far enough you
&lt;br&gt;;; can access changes that would be lost in standard undo/redo.
&lt;br&gt;;;
&lt;br&gt;;; However, imagine that after undoing as just described, you decide you
&lt;br&gt;;; actually want to rewind right back to the initial state. If you're lucky,
&lt;br&gt;;; and haven't invoked any command since the last undo, you can just keep on
&lt;br&gt;;; undoing until you get back to the start:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp;(trying to get &amp;nbsp; o &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;x &amp;nbsp;(got there!)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; to this state) &amp;nbsp;| &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp;o &amp;nbsp; &amp;nbsp; o &amp;nbsp; &amp;nbsp; o &amp;nbsp;(keep undoing)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp;|\ &amp;nbsp; &amp;nbsp;|\ &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp;| \ &amp;nbsp; | \ &amp;nbsp; |
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp;o &amp;nbsp;| &amp;nbsp;| &amp;nbsp;o &amp;nbsp;o &amp;nbsp;(keep undoing)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | / &amp;nbsp; | &amp;nbsp;| &amp;nbsp;| /
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |/ &amp;nbsp; &amp;nbsp;| &amp;nbsp;| &amp;nbsp;|/
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp;(already undid &amp;nbsp; o &amp;nbsp; &amp;nbsp; | &amp;nbsp;| &amp;nbsp;o &amp;nbsp;(got this far)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; to this state) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| /
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |/
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o
&lt;br&gt;;;
&lt;br&gt;;; But if you're unlucky, you happen to have moved the point (say) after
&lt;br&gt;;; getting to the point labelled &amp;quot;got this far&amp;quot;. In that case, you've &amp;quot;broken
&lt;br&gt;;; the undo chain&amp;quot;. If you try to undo now, Emacs thinks you're trying to undo
&lt;br&gt;;; the undos! So to get back to the initial state you now have to rewind
&lt;br&gt;;; through *all* the changes, including the undos you just did:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp;(trying to get &amp;nbsp; o &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;x &amp;nbsp;(finally got there!)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; to this state) &amp;nbsp;| &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp;o &amp;nbsp; &amp;nbsp; o &amp;nbsp; &amp;nbsp; o &amp;nbsp; &amp;nbsp; o &amp;nbsp; &amp;nbsp; o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp;|\ &amp;nbsp; &amp;nbsp;|\ &amp;nbsp; &amp;nbsp;|\ &amp;nbsp; &amp;nbsp;|\ &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp;| \ &amp;nbsp; | \ &amp;nbsp; | \ &amp;nbsp; | \ &amp;nbsp; |
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp;o &amp;nbsp;| &amp;nbsp;| &amp;nbsp;o &amp;nbsp;o &amp;nbsp;o &amp;nbsp;| &amp;nbsp;o &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | / &amp;nbsp; | &amp;nbsp;| &amp;nbsp;| / &amp;nbsp; | &amp;nbsp;| &amp;nbsp;| /
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |/ &amp;nbsp; &amp;nbsp;| &amp;nbsp;| &amp;nbsp;|/ &amp;nbsp; &amp;nbsp;| &amp;nbsp;| &amp;nbsp;|/
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp;(already undid &amp;nbsp; o &amp;nbsp; &amp;nbsp; | &amp;nbsp;| &amp;nbsp;o&amp;lt;. &amp;nbsp; | &amp;nbsp;| &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; to this state) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| / &amp;nbsp; &amp;nbsp; : &amp;nbsp; | /
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |/ &amp;nbsp; &amp;nbsp; &amp;nbsp;: &amp;nbsp; |/
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp; &amp;nbsp; &amp;nbsp; : &amp;nbsp; o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; :
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (got this far, but
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;broke undo chain)
&lt;br&gt;;;
&lt;br&gt;;; Confused?
&lt;br&gt;;;
&lt;br&gt;;; In practice you can just hold down the undo key until you reach the buffer
&lt;br&gt;;; state that you want. But whatever you do, don't move around in the buffer
&lt;br&gt;;; to check you've got back to where you want! Because you'll break the undo
&lt;br&gt;;; chain, and then you'll have to traverse the entire string of undos again to
&lt;br&gt;;; get back to the point at which you broke the chain. Commands such as
&lt;br&gt;;; `undo-only', and undo in region (in transient-mark-mode), help to make
&lt;br&gt;;; using Emacs' undo a little easier, but nonetheless it remains confusing for
&lt;br&gt;;; many people.
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;; So what does undo-tree mode do? Remember the diagram we drew to represent
&lt;br&gt;;; the history we've been discussing (make a few edits, undo a couple of them,
&lt;br&gt;;; and edit again)? The diagram that conceptually represented our undo
&lt;br&gt;;; history, before we started discussing specific undo systems? It looked like
&lt;br&gt;;; this:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(initial buffer state)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|\
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;x &amp;nbsp;(current state)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;;
&lt;br&gt;;; Well, that's *exactly* what the undo history looks like to
&lt;br&gt;;; `undo-tree-mode'. &amp;nbsp;It doesn't discard the old branch (as standard undo/redo
&lt;br&gt;;; does), nor does it treat undos as new changes to be added to the end of a
&lt;br&gt;;; linear string of buffer states (as Emacs' undo does). It just keeps track
&lt;br&gt;;; of the tree of branching changes that make up the entire undo history.
&lt;br&gt;;;
&lt;br&gt;;; If you undo from this point, you'll rewind back up the tree to the previous
&lt;br&gt;;; state:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;x &amp;nbsp;(undo)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|\
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;;
&lt;br&gt;;; If you were to undo again, you'd rewind back to the initial state. If on
&lt;br&gt;;; the other hand you redo the change, you'll end up back at the bottom of the
&lt;br&gt;;; most recent branch:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(start here)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|\
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;x &amp;nbsp;(redo)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;;
&lt;br&gt;;; So far, this is just like the standard undo/redo system. But what if you
&lt;br&gt;;; want to return to a buffer state located on a previous branch of the
&lt;br&gt;;; history? Since `undo-tree-mode' keeps the entire history, you simply need
&lt;br&gt;;; to tell it to switch to a different branch, and then redo the changes you
&lt;br&gt;;; want:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(start here, but switch
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|\ &amp;nbsp;to the other branch)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(redo) &amp;nbsp;o &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(redo) &amp;nbsp;x
&lt;br&gt;;;
&lt;br&gt;;; Now you're on the other branch, and if you undo and redo changes you'll
&lt;br&gt;;; stay on that branch, moving up and down through the buffer states located
&lt;br&gt;;; on that branch. Until you decide to switch branches again, of course.
&lt;br&gt;;;
&lt;br&gt;;; Real undo trees might have multiple branches and sub-branches:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;____|______
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; / &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;____|__ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; __|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; / &amp;nbsp; &amp;nbsp;| &amp;nbsp;\ &amp;nbsp; &amp;nbsp; &amp;nbsp; / &amp;nbsp; \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp; &amp;nbsp; o &amp;nbsp; o &amp;nbsp; &amp;nbsp; o &amp;nbsp; &amp;nbsp; x
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; / \ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; / \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp; o &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp; o
&lt;br&gt;;;
&lt;br&gt;;; Trying to imagine what Emacs' undo would do as you move about such a tree
&lt;br&gt;;; will likely frazzle your brain circuits! But in `undo-tree-mode', you're
&lt;br&gt;;; just moving around this undo history tree. Most of the time, you'll
&lt;br&gt;;; probably only need to stay on the most recent branch, in which case it
&lt;br&gt;;; behaves like standard undo/redo, so is just as simple to understand. But if
&lt;br&gt;;; you ever need to recover a buffer state on a different branch, the
&lt;br&gt;;; possibility of switching between branches and accessing the full undo
&lt;br&gt;;; history is still there.
&lt;br&gt;;;
&lt;br&gt;;; Actually, it gets better. You don't have to imagine all these diagrams,
&lt;br&gt;;; because `undo-tree-mode' includes an undo-tree visualizer which draws them
&lt;br&gt;;; for you! In fact, it draws even better diagrams: it highlights the node
&lt;br&gt;;; representing the current buffer state, it highlights the current branch,
&lt;br&gt;;; and it can optionally display time-stamps for each buffer state. (There's
&lt;br&gt;;; one other tiny difference: the visualizer puts the most recent branch on
&lt;br&gt;;; the left rather than the right.)
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;; Drawbacks
&lt;br&gt;;; =========
&lt;br&gt;;;
&lt;br&gt;;; Emacs' undo system is deeply embedded in Emacs. In particular, garbage
&lt;br&gt;;; collection treats the `buffer-undo-list' specially: references to markers
&lt;br&gt;;; in `buffer-undo-list' don't count during the mark phase, and the sweep
&lt;br&gt;;; phase removes undo entries for markers that have been garbage-collected.
&lt;br&gt;;; This behaviour is implemented in C as part of the garbage collection code,
&lt;br&gt;;; and it is difficult or impossible to emulate in Elisp.
&lt;br&gt;;;
&lt;br&gt;;; To avoid dead markers being resurrected in `undo-tree-mode', and to allow
&lt;br&gt;;; them to be garbage-collected, `undo-tree-mode' doesn't record marker
&lt;br&gt;;; adjustments. Markers are rarely explicitly created by users, so the impact
&lt;br&gt;;; of this will primarily be through its effects on other features that make
&lt;br&gt;;; use of markers. Since marker adjustments haven't always been restored by
&lt;br&gt;;; undo, and even then it was buggy until recently (see Emacs bug#4803), it
&lt;br&gt;;; seems likely that relatively little code relies heavily on correct marker
&lt;br&gt;;; restoration.
&lt;br&gt;;;
&lt;br&gt;;; `undo-tree-mode' doesn't support &amp;quot;undo in region&amp;quot;, i.e. selectively undoing
&lt;br&gt;;; only the changes that affect the current region in
&lt;br&gt;;; `transient-mark-mode'). Support for this is planned for a future version.
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; Change Log:
&lt;br&gt;;;
&lt;br&gt;;; Version 0.1.2
&lt;br&gt;;; * fixed keybindings
&lt;br&gt;;; * renamed `undo-tree-visualizer-switch-previous-branch' and
&lt;br&gt;;; &amp;nbsp; `undo-tree-visualizer-switch-next-branch' to
&lt;br&gt;;; &amp;nbsp; `undo-tree-visualizer-switch-branch-left' and
&lt;br&gt;;; &amp;nbsp; `undo-tree-visualizer-switch-branch-right'
&lt;br&gt;;;
&lt;br&gt;;; Version 0.1.1
&lt;br&gt;;; * prevented `undo-tree-kill-visualizer' from killing visualizer when
&lt;br&gt;;; &amp;nbsp; undoing/redoing from the visualizer, which completely broke the
&lt;br&gt;;; &amp;nbsp; visualizer!
&lt;br&gt;;; * changed one redo binding, so that at least one set of undo/redo bindings
&lt;br&gt;;; &amp;nbsp; works in a terminal
&lt;br&gt;;; * bound vertical scrolling commands in `undo-tree-visualizer-map', in case
&lt;br&gt;;; &amp;nbsp; they aren't bound globally
&lt;br&gt;;; * added missing :group argument to `defface's
&lt;br&gt;;;
&lt;br&gt;;; Version 0.1
&lt;br&gt;;; * initial release
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; Code:
&lt;br&gt;&lt;br&gt;(eval-when-compile (require 'cl))
&lt;br&gt;&lt;br&gt;;; `characterp' isn't defined in Emacs versions &amp;lt;= 22
&lt;br&gt;(eval-and-compile
&lt;br&gt;&amp;nbsp; (unless (fboundp 'characterp)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (defmacro characterp (arg) `(char-valid-p ,arg))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; =====================================================================
&lt;br&gt;;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Global variables and customization options
&lt;br&gt;&lt;br&gt;(defvar buffer-undo-tree nil
&lt;br&gt;&amp;nbsp; &amp;quot;Tree of undo entries in current buffer.&amp;quot;)
&lt;br&gt;(make-variable-buffer-local 'buffer-undo-tree)
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defgroup undo-tree nil
&lt;br&gt;&amp;nbsp; &amp;quot;Tree undo/redo.&amp;quot;
&lt;br&gt;&amp;nbsp; :group 'undo)
&lt;br&gt;&lt;br&gt;(defcustom undo-tree-visualizer-spacing 3
&lt;br&gt;&amp;nbsp; &amp;quot;Horizontal spacing in undo-tree visualization.
&lt;br&gt;Must be a postivie odd integer.&amp;quot;
&lt;br&gt;&amp;nbsp; :group 'undo-tree
&lt;br&gt;&amp;nbsp; :type '(integer
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; :match (lambda (w n) (and (integerp n) (&amp;gt; n 0) (= (mod n 2) 1)))))
&lt;br&gt;(make-variable-buffer-local 'undo-tree-visualizer-spacing)
&lt;br&gt;&lt;br&gt;(defvar undo-tree-map nil
&lt;br&gt;&amp;nbsp; &amp;quot;Keymap used in undo-tree-mode.&amp;quot;)
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defface undo-tree-visualizer-default-face
&lt;br&gt;&amp;nbsp; '((((class color)) :foreground &amp;quot;gray&amp;quot;))
&lt;br&gt;&amp;nbsp; &amp;quot;*Face used to draw undo-tree in visualizer.&amp;quot;
&lt;br&gt;&amp;nbsp; :group 'undo-tree)
&lt;br&gt;&lt;br&gt;(defface undo-tree-visualizer-current-face
&lt;br&gt;&amp;nbsp; '((((class color)) :foreground &amp;quot;red&amp;quot;))
&lt;br&gt;&amp;nbsp; &amp;quot;*Face used to highlight current undo-tree node
&lt;br&gt;in visualizer.&amp;quot;
&lt;br&gt;&amp;nbsp; :group 'undo-tree)
&lt;br&gt;&lt;br&gt;(defface undo-tree-visualizer-active-branch-face
&lt;br&gt;&amp;nbsp; '((((class color) (background dark))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(:foreground &amp;quot;white&amp;quot; :weight bold))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (((class color) (background light))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(:foreground &amp;quot;black&amp;quot; :weight bold)))
&lt;br&gt;&amp;nbsp; &amp;quot;*Face used to highlight active undo-tree branch
&lt;br&gt;in visualizer.&amp;quot;
&lt;br&gt;&amp;nbsp; :group 'undo-tree)
&lt;br&gt;&lt;br&gt;(defvar undo-tree-visualizer-map nil
&lt;br&gt;&amp;nbsp; &amp;quot;Keymap used in undo-tree visualizer.&amp;quot;)
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defvar undo-tree-visualizer-buffer nil
&lt;br&gt;&amp;nbsp; &amp;quot;Parent buffer in visualizer.&amp;quot;)
&lt;br&gt;(make-variable-buffer-local 'undo-tree-visualizer-buffer)
&lt;br&gt;&lt;br&gt;(defvar undo-tree-visualizer-timestamps nil
&lt;br&gt;&amp;nbsp; &amp;quot;Non-nil when visualizer is displaying time-stamps.&amp;quot;)
&lt;br&gt;(make-variable-buffer-local 'undo-tree-visualizer-timestamps)
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; =================================================================
&lt;br&gt;;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Setup default keymaps
&lt;br&gt;&lt;br&gt;(unless undo-tree-map
&lt;br&gt;&amp;nbsp; (setq undo-tree-map (make-sparse-keymap))
&lt;br&gt;&amp;nbsp; ;; remap `undo' to `undo-tree-undo'
&lt;br&gt;&amp;nbsp; (define-key undo-tree-map [remap undo] 'undo-tree-undo)
&lt;br&gt;&amp;nbsp; ;; bind standard undo bindings (since these match redo counterparts)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-map (kbd &amp;quot;C-/&amp;quot;) 'undo-tree-undo)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-map &amp;quot;\C-_&amp;quot; 'undo-tree-undo)
&lt;br&gt;&amp;nbsp; ;; redo doesn't exist normally, so define out own keybindings
&lt;br&gt;&amp;nbsp; (define-key undo-tree-map (kbd &amp;quot;C-?&amp;quot;) 'undo-tree-redo)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-map (kbd &amp;quot;M-_&amp;quot;) 'undo-tree-redo)
&lt;br&gt;&amp;nbsp; ;; just in case something has defined it...
&lt;br&gt;&amp;nbsp; (define-key undo-tree-map [remap redo] 'undo-tree-redo)
&lt;br&gt;&amp;nbsp; ;; we use &amp;quot;C-x u&amp;quot; for the undo-tree visualizer
&lt;br&gt;&amp;nbsp; (define-key undo-tree-map (kbd &amp;quot;\C-x u&amp;quot;) 'undo-tree-visualize))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(unless undo-tree-visualizer-map
&lt;br&gt;&amp;nbsp; (setq undo-tree-visualizer-map (make-keymap))
&lt;br&gt;&amp;nbsp; ;; vertical motion keys undo/redo
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map [up]
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-undo)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;p&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-undo)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;\C-p&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-undo)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map [down]
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-redo)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;n&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-redo)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;\C-n&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-redo)
&lt;br&gt;&amp;nbsp; ;; horizontal motion keys switch branch
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map [right]
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-switch-branch-right)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;f&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-switch-branch-right)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;\C-f&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-switch-branch-right)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map [left]
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-switch-branch-left)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;b&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-switch-branch-left)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;\C-b&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-switch-branch-left)
&lt;br&gt;&amp;nbsp; ;; mouse sets buffer state to node at click
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map [mouse-1]
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualizer-set)
&lt;br&gt;&amp;nbsp; ;; toggle timestamps
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;t&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualizer-toggle-timestamps)
&lt;br&gt;&amp;nbsp; ;; horizontal scrolling may be needed if tree is very wide
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;,&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualizer-scroll-left)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;.&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualizer-scroll-right)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;&amp;lt;&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualizer-scroll-left)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;&amp;gt;&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualizer-scroll-right)
&lt;br&gt;&amp;nbsp; ;; vertical scrolling may be needed if the tree is very tall
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map [next] 'scroll-up)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map [prior] 'scroll-down)
&lt;br&gt;&amp;nbsp; ;; quit visualizer
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;q&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualizer-quit)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;\C-q&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualizer-quit))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; =====================================================================
&lt;br&gt;;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Undo-tree data structure
&lt;br&gt;&lt;br&gt;(defstruct
&lt;br&gt;&amp;nbsp; (undo-tree
&lt;br&gt;&amp;nbsp; &amp;nbsp;:named
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:constructor nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:constructor make-undo-tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(&amp;aux
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (root (make-undo-tree-node nil nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (current root)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (size 0)))
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:copier nil))
&lt;br&gt;&amp;nbsp; root current size)
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(defstruct
&lt;br&gt;&amp;nbsp; (undo-tree-node
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:type vector) &amp;nbsp; ; create unnamed struct
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:constructor nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:constructor make-undo-tree-node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(previous undo
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;aux
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (timestamp (current-time))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (branch 0)))
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:constructor make-undo-tree-node-backwards
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(next-node undo
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;aux
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (next (list next-node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (timestamp (current-time))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (branch 0)))
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:copier nil))
&lt;br&gt;&amp;nbsp; previous next undo redo timestamp branch visualizer)
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defmacro undo-tree-node-p (n)
&lt;br&gt;&amp;nbsp; (let ((len (length (make-undo-tree-node nil nil))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; `(and (vectorp ,n) (= (length ,n) ,len))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(defstruct
&lt;br&gt;&amp;nbsp; (undo-tree-visualizer-data
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:type vector) &amp;nbsp; ; create unnamed struct
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:constructor nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:constructor make-undo-tree-visualizer-data)
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:copier nil))
&lt;br&gt;&amp;nbsp; lwidth cwidth rwidth marker)
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defmacro undo-tree-visualizer-data-p (v)
&lt;br&gt;&amp;nbsp; (let ((len (length (make-undo-tree-visualizer-data))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; `(and (vectorp ,v) (= (length ,v) ,len))))
&lt;br&gt;&lt;br&gt;(defmacro undo-tree-node-lwidth (node)
&lt;br&gt;&amp;nbsp; `(when (vectorp (undo-tree-node-visualizer ,node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-visualizer-data-lwidth
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-visualizer ,node))))
&lt;br&gt;&lt;br&gt;(defmacro undo-tree-node-cwidth (node)
&lt;br&gt;&amp;nbsp; `(when (vectorp (undo-tree-node-visualizer ,node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-visualizer-data-cwidth
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-visualizer ,node))))
&lt;br&gt;&lt;br&gt;(defmacro undo-tree-node-rwidth (node)
&lt;br&gt;&amp;nbsp; `(when (vectorp (undo-tree-node-visualizer ,node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-visualizer-data-rwidth
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-visualizer ,node))))
&lt;br&gt;&lt;br&gt;(defmacro undo-tree-node-marker (node)
&lt;br&gt;&amp;nbsp; `(when (vectorp (undo-tree-node-visualizer ,node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-visualizer-data-marker
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-visualizer ,node))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defsetf undo-tree-node-lwidth (node) (val)
&lt;br&gt;&amp;nbsp; `(let ((v (undo-tree-node-visualizer ,node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(unless (undo-tree-visualizer-data-p v)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setf (undo-tree-node-visualizer ,node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setq v (make-undo-tree-visualizer-data))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(setf (undo-tree-visualizer-data-lwidth v) ,val)))
&lt;br&gt;&lt;br&gt;(defsetf undo-tree-node-cwidth (node) (val)
&lt;br&gt;&amp;nbsp; `(let ((v (undo-tree-node-visualizer ,node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(unless (undo-tree-visualizer-data-p v)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setf (undo-tree-node-visualizer ,node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setq v (make-undo-tree-visualizer-data))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(setf (undo-tree-visualizer-data-cwidth v) ,val)))
&lt;br&gt;&lt;br&gt;(defsetf undo-tree-node-rwidth (node) (val)
&lt;br&gt;&amp;nbsp; `(let ((v (undo-tree-node-visualizer ,node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(unless (undo-tree-visualizer-data-p v)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setf (undo-tree-node-visualizer ,node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setq v (make-undo-tree-visualizer-data))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(setf (undo-tree-visualizer-data-rwidth v) ,val)))
&lt;br&gt;&lt;br&gt;(defsetf undo-tree-node-marker (node) (val)
&lt;br&gt;&amp;nbsp; `(let ((v (undo-tree-node-visualizer ,node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(unless (undo-tree-visualizer-data-p v)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setf (undo-tree-node-visualizer ,node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setq v (make-undo-tree-visualizer-data))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(setf (undo-tree-visualizer-data-marker v) ,val)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; =====================================================================
&lt;br&gt;;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Basic undo-tree data structure functions
&lt;br&gt;&lt;br&gt;(defun undo-tree-grow (undo)
&lt;br&gt;&amp;nbsp; &amp;quot;Add an UNDO node to current branch of `buffer-undo-tree'.&amp;quot;
&lt;br&gt;&amp;nbsp; (let* ((current (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(new (make-undo-tree-node current undo)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (push new (undo-tree-node-next current))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setf (undo-tree-current buffer-undo-tree) new)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-grow-backwards (node undo)
&lt;br&gt;&amp;nbsp; &amp;quot;Add an UNDO node *above* undo-tree NODE, and return new node.
&lt;br&gt;Note that this will overwrite NODE's \&amp;quot;previous\&amp;quot; link, so should
&lt;br&gt;only be used on a detached NODE, never on nodes that are already
&lt;br&gt;part of `buffer-undo-tree'.&amp;quot;
&lt;br&gt;&amp;nbsp; (let ((new (make-undo-tree-node-backwards node undo)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setf (undo-tree-node-previous node) new)
&lt;br&gt;&amp;nbsp; &amp;nbsp; new))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-compute-widths (undo-tree)
&lt;br&gt;&amp;nbsp; &amp;quot;Recursively compute widths for all UNDO-TREE's nodes.&amp;quot;
&lt;br&gt;&amp;nbsp; (let ((stack (list (undo-tree-root undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; res)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (while stack
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; try to compute widths for node at top of stack
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (if (undo-tree-node-p
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setq res (undo-tree-node-compute-widths (car stack))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; if computation fails, it returns a node whose widths still need
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; computing, which we push onto the stack
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (push res stack)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; otherwise, store widths and remove it from stack
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-lwidth (car stack)) (aref res 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-cwidth (car stack)) (aref res 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-rwidth (car stack)) (aref res 2))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (pop stack)))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-node-compute-widths (node)
&lt;br&gt;&amp;nbsp; ;; Compute NODE's left-, centre-, and right-subtree widths. Returns widths
&lt;br&gt;&amp;nbsp; ;; (in a vector) if successful. Otherwise, returns a node whose widths need
&lt;br&gt;&amp;nbsp; ;; calculating before NODE's can be calculated.
&lt;br&gt;&amp;nbsp; (let ((num-children (length (undo-tree-node-next node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (lwidth 0) (cwidth 0) (rwidth 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; p w)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (catch 'need-widths
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (cond
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; leaf nodes have 0 width
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;((= 0 num-children)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf cwidth 1
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-lwidth node) 0
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-cwidth node) 1
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-rwidth node) 0))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; odd number of children
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;((= (mod num-children 2) 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq p (undo-tree-node-next node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; compute left-width
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (dotimes (i (/ num-children 2))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (undo-tree-node-lwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf lwidth (+ (undo-tree-node-lwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-cwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-rwidth (car p))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; if child's widths haven't been computed, return that child
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (throw 'need-widths (car p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq p (cdr p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (undo-tree-node-lwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf lwidth (undo-tree-node-lwidth (car p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (throw 'need-widths (car p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; centre-width is inherited from middle child
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf cwidth (undo-tree-node-cwidth (car p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; compute right-width
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf rwidth (undo-tree-node-rwidth (car p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq p (cdr p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (dotimes (i (/ num-children 2))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (undo-tree-node-lwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf rwidth (+ (undo-tree-node-lwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-cwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-rwidth (car p))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (throw 'need-widths (car p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq p (cdr p))))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; even number of children
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(t
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq p (undo-tree-node-next node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; compute left-width
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (dotimes (i (/ num-children 2))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (undo-tree-node-lwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf lwidth (+ (undo-tree-node-lwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-cwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-rwidth (car p))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (throw 'need-widths (car p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq p (cdr p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; centre-width is 0 when number of children is even
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq cwidth 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; compute right-width
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (dotimes (i (/ num-children 2))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (undo-tree-node-lwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf rwidth (+ (undo-tree-node-lwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-cwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-rwidth (car p))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (throw 'need-widths (car p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq p (cdr p)))))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; return left-, centre- and right-widths
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (vector lwidth cwidth rwidth))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-clear-visualizer-data (undo-tree)
&lt;br&gt;&amp;nbsp; ;; Clear visualizer data from UNDO-TREE.
&lt;br&gt;&amp;nbsp; (let ((stack (list (undo-tree-root undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (while stack
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq node (pop stack))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-visualizer node) nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (dolist (n (undo-tree-node-next node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (push n stack)))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-position (node list)
&lt;br&gt;&amp;nbsp; &amp;quot;Find the first occurrence of NODE in LIST.
&lt;br&gt;Return the index of the matching item, or nil of not found.
&lt;br&gt;Comparison is done with 'eq.&amp;quot;
&lt;br&gt;&amp;nbsp; (let ((i 0))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (catch 'found
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (while (progn
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(when (eq node (car list)) (throw 'found i))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(incf i)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setq list (cdr list))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; nil)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defmacro undo-tree-num-branches ()
&lt;br&gt;&amp;nbsp; ;; Return number of branches at current undo tree node.
&lt;br&gt;&amp;nbsp; '(length (undo-tree-node-next (undo-tree-current buffer-undo-tree))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-oldest-leaf (node)
&lt;br&gt;&amp;nbsp; ;; Return oldest leaf node below NODE.
&lt;br&gt;&amp;nbsp; (while (undo-tree-node-next node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (car (sort (mapcar 'identity (undo-tree-node-next node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(lambda (a b)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(time-less-p (undo-tree-node-timestamp a)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-timestamp b)))))))
&lt;br&gt;&amp;nbsp; node)
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-discard-node (node)
&lt;br&gt;&amp;nbsp; ;; Discard NODE from `buffer-undo-tree', and return next in line for
&lt;br&gt;&amp;nbsp; ;; discarding.
&lt;br&gt;&lt;br&gt;&amp;nbsp; ;; don't discard current node
&lt;br&gt;&amp;nbsp; (unless (eq node (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (decf (undo-tree-size buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (+ (undo-list-byte-size (undo-tree-node-undo node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-list-byte-size (undo-tree-node-redo node))))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; discarding root node
&lt;br&gt;&amp;nbsp; &amp;nbsp; (if (eq node (undo-tree-root buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (cond
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; should always discard branches before root
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;((&amp;gt; (length (undo-tree-node-next node)) 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (error &amp;quot;Trying to discard undo-tree root which still\
&lt;br&gt;&amp;nbsp;has multiple branches&amp;quot;))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; don't discard root if current node is only child
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;((eq (car (undo-tree-node-next node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(t
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; make child of root into new root
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf node (setf (undo-tree-root buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(car (undo-tree-node-next node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-undo node) nil
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-redo node) nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; if new root has branches, or new root is current node, next node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; to discard is oldest leaf, otherwise it's new root
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (or (&amp;gt; (length (undo-tree-node-next node)) 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (eq (car (undo-tree-node-next node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-oldest-leaf node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; node)))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; discarding leaf node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (let* ((parent (undo-tree-node-previous node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(current (nth (undo-tree-node-branch parent)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-node-next parent))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-next parent)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (delq node (undo-tree-node-next parent))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-branch parent)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-position current (undo-tree-node-next parent)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; if parent has branches, or parent is current node, next node to
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; discard is oldest lead, otherwise it's parent
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (or (eq parent (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (and (undo-tree-node-next parent)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(or (not (eq parent (undo-tree-root buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(&amp;gt; (length (undo-tree-node-next parent)) 1))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-oldest-leaf parent)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; parent)))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-discard-history ()
&lt;br&gt;&amp;nbsp; &amp;quot;Discard undo history until we're within memory usage limits
&lt;br&gt;set by `undo-limit', `undo-strong-limit' and `undo-outer-limit'.&amp;quot;
&lt;br&gt;&lt;br&gt;&amp;nbsp; (when (&amp;gt; (undo-tree-size buffer-undo-tree) undo-limit)
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; if there are no branches off root, first node to discard is root;
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; otherwise it's leaf node at botom of oldest branch
&lt;br&gt;&amp;nbsp; &amp;nbsp; (let ((node (if (&amp;gt; (length (undo-tree-node-next
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-root buffer-undo-tree))) 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-oldest-leaf (undo-tree-root buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-root buffer-undo-tree))))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; discard nodes until memory use is within `undo-strong-limit'
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (while (and node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (&amp;gt; (undo-tree-size buffer-undo-tree) undo-strong-limit))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq node (undo-tree-discard-node node)))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; discard nodes until next node to discard would bring memory use
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; within `undo-limit'
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (while (and node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (&amp;gt; (- (undo-tree-size buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-list-byte-size (undo-tree-node-undo node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-list-byte-size (undo-tree-node-redo node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;undo-limit))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq node (undo-tree-discard-node node)))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; if we're still over the `undo-outer-limit', discard entire history
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (when (&amp;gt; (undo-tree-size buffer-undo-tree) undo-outer-limit)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; query first `undo-ask-before-discard' is set
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if undo-ask-before-discard
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (when (yes-or-no-p
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(format
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;Buffer `%s' undo info is %d bytes long; &amp;nbsp;discard it? &amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (buffer-name) (undo-tree-size buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-undo-tree nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; otherwise, discard and display warning
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (display-warning
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;'(undo discard-info)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(concat
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (format &amp;quot;Buffer `%s' undo info was %d bytes long.\n&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (buffer-name) (undo-tree-size buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;The undo info was discarded because it exceeded\
&lt;br&gt;&amp;nbsp;`undo-outer-limit'.
&lt;br&gt;&lt;br&gt;This is normal if you executed a command that made a huge change
&lt;br&gt;to the buffer. In that case, to prevent similar problems in the
&lt;br&gt;future, set `undo-outer-limit' to a value that is large enough to
&lt;br&gt;cover the maximum size of normal changes you expect a single
&lt;br&gt;command to make, but not so large that it might exceed the
&lt;br&gt;maximum memory allotted to Emacs.
&lt;br&gt;&lt;br&gt;If you did not execute any such command, the situation is
&lt;br&gt;probably due to a bug and you should report it.
&lt;br&gt;&lt;br&gt;You can disable the popping up of this buffer by adding the entry
&lt;br&gt;\(undo discard-info) to the user option `warning-suppress-types',
&lt;br&gt;which is defined in the `warnings' library.\n&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;:warning)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-undo-tree nil)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; )))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; =====================================================================
&lt;br&gt;;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Utility functions for handling `buffer-undo-list'
&lt;br&gt;&lt;br&gt;(defun undo-list-pop-changeset ()
&lt;br&gt;&amp;nbsp; ;; Pop changeset from `buffer-undo-list'.
&lt;br&gt;&amp;nbsp; ;; discard undo boundaries and marker adjustment entries at head of list
&lt;br&gt;&amp;nbsp; (while (or (null (car buffer-undo-list))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(and (consp (car buffer-undo-list))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (markerp (caar buffer-undo-list))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq buffer-undo-list (cdr buffer-undo-list)))
&lt;br&gt;&amp;nbsp; ;; pop elements up to next undo boundary
&lt;br&gt;&amp;nbsp; (unless (eq (car buffer-undo-list) 'undo-tree-canary)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (let* ((changeset (cons (pop buffer-undo-list) nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(p changeset))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (while (car buffer-undo-list)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setcdr p (cons (pop buffer-undo-list) nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; discard marker adjustment entries (see Commentary, above)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (and (consp (cadr p)) (markerp (car (cadr p))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setcdr p nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq p (cdr p))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; changeset)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-list-transfer-to-tree ()
&lt;br&gt;&amp;nbsp; ;; Transfer entries accumulated in `buffer-undo-list' to `buffer-undo-tree'.
&lt;br&gt;&amp;nbsp; (if (null buffer-undo-list)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-undo-list '(nil undo-tree-canary))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (when (not (eq (cadr buffer-undo-list) 'undo-tree-canary))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; create new node from first changeset in `buffer-undo-list', save old
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; `buffer-undo-tree' current node, and make new node the current node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (let* ((node (make-undo-tree-node nil (undo-list-pop-changeset)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(splice (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(size (undo-list-byte-size (undo-tree-node-undo node))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-current buffer-undo-tree) node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; grow tree fragment backwards using `buffer-undo-list' changesets
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (while (and buffer-undo-list
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (not (eq (cadr buffer-undo-list) 'undo-tree-canary)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-grow-backwards node (undo-list-pop-changeset)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf size (undo-list-byte-size (undo-tree-node-undo node))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; if no undo history has been discarded from `buffer-undo-list' since
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; last transfer, splice new tree fragment onto end of old
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; `buffer-undo-tree' current node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (eq (cadr buffer-undo-list) 'undo-tree-canary)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (progn
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-previous node) splice)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (push node (undo-tree-node-next splice))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-branch splice) 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf (undo-tree-size buffer-undo-tree) size))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; if undo history has been discarded, replace entire
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; `buffer-undo-tree' with new tree fragment
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq node (undo-tree-grow-backwards node nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-root buffer-undo-tree) node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-undo-list '(nil undo-tree-canary))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-size buffer-undo-tree) size))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-list-byte-size (undo-list)
&lt;br&gt;&amp;nbsp; ;; Return size (in bytes) of UNDO-LIST
&lt;br&gt;&amp;nbsp; (let ((size 0) (p undo-list))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (while p
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (incf size 8) &amp;nbsp;; cons cells use up 8 bytes
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (when (and (consp (car p)) (stringp (caar p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf size (string-bytes (caar p))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq p (cdr p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; size))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; =====================================================================
&lt;br&gt;;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Undo-tree commands
&lt;br&gt;&lt;br&gt;(define-minor-mode undo-tree-mode
&lt;br&gt;&amp;nbsp; &amp;quot;Toggle undo-tree mode.
&lt;br&gt;With no argument, this command toggles the mode.
&lt;br&gt;A positive prefix argument turns the mode on.
&lt;br&gt;A negative prefix argument turns it off.
&lt;br&gt;&lt;br&gt;Undo-tree-mode replaces Emacs' standard undo feature with a more
&lt;br&gt;powerful yet easier to use version, that treats the undo history
&lt;br&gt;as what it is: a tree.
&lt;br&gt;&lt;br&gt;The following keys are available in `undo-tree-mode':
&lt;br&gt;&lt;br&gt;&amp;nbsp; \\{undo-tree-map}
&lt;br&gt;&lt;br&gt;Within the undo-tree visualizer, the following keys are available:
&lt;br&gt;&lt;br&gt;&amp;nbsp; \\{undo-tree-visualizer-map}&amp;quot;
&lt;br&gt;&lt;br&gt;&amp;nbsp; nil &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ; init value
&lt;br&gt;&amp;nbsp; &amp;quot; Undo-Tree&amp;quot; &amp;nbsp; &amp;nbsp;; lighter
&lt;br&gt;&amp;nbsp; undo-tree-map &amp;nbsp; ; keymap
&lt;br&gt;&amp;nbsp; ;; if disabling `undo-tree-mode', remove &amp;quot;canary&amp;quot; from `buffer-undo-list'
&lt;br&gt;&amp;nbsp; (unless undo-tree-mode (setq buffer-undo-list nil)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun turn-on-undo-tree-mode ()
&lt;br&gt;&amp;nbsp; &amp;quot;Enable undo-tree-mode.&amp;quot;
&lt;br&gt;&amp;nbsp; (undo-tree-mode 1))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(define-globalized-minor-mode global-undo-tree-mode
&lt;br&gt;&amp;nbsp; undo-tree-mode turn-on-undo-tree-mode)
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-undo (&amp;optional arg)
&lt;br&gt;&amp;nbsp; &amp;quot;Undo changes. A numeric ARG serves as a repeat count.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;p&amp;quot;)
&lt;br&gt;&amp;nbsp; ;; throw error if undo is disabled in buffer
&lt;br&gt;&amp;nbsp; (when (eq buffer-undo-list t) (error &amp;quot;No undo information in this buffer&amp;quot;))
&lt;br&gt;&lt;br&gt;&amp;nbsp; (let ((undo-in-progress t))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; if `buffer-undo-tree' is empty, create initial undo-tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; (when (null buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-undo-tree (make-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; transfer entries accumulated in `buffer-undo-list' to
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; `buffer-undo-tree'
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-list-transfer-to-tree)
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; (dotimes (i (or arg 1))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; check if at top of undo tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (if (null (undo-tree-node-previous
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (error &amp;quot;No further undo information&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; undo one record from undo tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (primitive-undo 1 (undo-copy-list
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-node-undo
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-current buffer-undo-tree))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; pop redo entries that `primitive-undo' has added to
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; `buffer-undo-list' and record them in current node's redo record if
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; they're not already there
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (undo-tree-node-redo (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-list-pop-changeset)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-redo (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-list-pop-changeset))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf (undo-tree-size buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-list-byte-size
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-node-redo (undo-tree-current buffer-undo-tree)))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; rewind current node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-current buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-previous (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; update timestamp
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-timestamp (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (current-time))))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; discard undo history if necessary
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-discard-history)
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; inform user if at branch point
&lt;br&gt;&amp;nbsp; &amp;nbsp; (when (&amp;gt; (undo-tree-num-branches) 1) (message &amp;quot;Undo branch point!&amp;quot;))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-redo (&amp;optional arg)
&lt;br&gt;&amp;nbsp; &amp;quot;Redo changes. A numeric ARG serves as a repeat count.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;p&amp;quot;)
&lt;br&gt;&amp;nbsp; ;; throw error if undo is disabled in buffer
&lt;br&gt;&amp;nbsp; (when (eq buffer-undo-list t) (error &amp;quot;No undo information in this buffer&amp;quot;))
&lt;br&gt;&lt;br&gt;&amp;nbsp; (let ((undo-in-progress t))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; if `buffer-undo-tree' is empty, create initial undo-tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; (when (null buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-undo-tree (make-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; transfer entries accumulated in `buffer-undo-list' to
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; `buffer-undo-tree'
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-list-transfer-to-tree)
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; (let ((current (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (dotimes (i (or arg 1))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; check if at bottom of undo tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (null (undo-tree-node-next current))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (error &amp;quot;No further redo information&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; advance current node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq current
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-current buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (nth (undo-tree-node-branch current)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-node-next current))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; update timestamp
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-timestamp current) (current-time))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; redo one record from undo tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (primitive-undo 1 (undo-copy-list (undo-tree-node-redo current)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; discard undo entries that `primitive-undo' has added to
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; `buffer-undo-list' since we already know how to undo from here
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; (NOTE: should we instead overwrite old undo entry for safety's
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;sake?)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-undo-list '(nil undo-tree-canary)))))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; discard undo history if necessary
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-discard-history)
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; inform user if at branch point
&lt;br&gt;&amp;nbsp; &amp;nbsp; (when (&amp;gt; (undo-tree-num-branches) 1) (message &amp;quot;Undo branch point!&amp;quot;))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-switch-branch (branch)
&lt;br&gt;&amp;nbsp; &amp;quot;Switch to a different BRANCH of the undo tree.
&lt;br&gt;This will affect which branch to descend when *redoing* changes
&lt;br&gt;using `undo-tree-redo'.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive (list (or (and prefix-arg (prefix-numeric-value prefix-arg))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(and (not (eq buffer-undo-list t))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (or buffer-undo-tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (progn
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-undo-tree (make-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-list-transfer-to-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; t))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (&amp;gt; (undo-tree-num-branches) 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (read-number
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(format &amp;quot;Branch (0-%d): &amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(1- (undo-tree-num-branches))))))))
&lt;br&gt;&amp;nbsp; ;; throw error if undo is disabled in buffer
&lt;br&gt;&amp;nbsp; (when (eq buffer-undo-list t) (error &amp;quot;No undo information in this buffer&amp;quot;))
&lt;br&gt;&amp;nbsp; ;; sanity check branch number
&lt;br&gt;&amp;nbsp; (when (&amp;lt;= (undo-tree-num-branches) 1) (error &amp;quot;Not at undo branch point&amp;quot;))
&lt;br&gt;&amp;nbsp; (when (or (&amp;lt; branch 0) (&amp;gt; branch (1- (undo-tree-num-branches))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (error &amp;quot;Invalid branch number&amp;quot;)
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; if `buffer-undo-tree' is empty, create initial undo-tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; (when (null buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-undo-tree (make-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; transfer entries accumulated in `buffer-undo-list' to
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; `buffer-undo-tree'
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-list-transfer-to-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; switch branch
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setf (undo-tree-node-branch (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; branch)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-set (node)
&lt;br&gt;&amp;nbsp; ;; Set buffer to state corresponding to NODE. Returns intersection point
&lt;br&gt;&amp;nbsp; ;; between path back from current node and path back from selected NODE.
&lt;br&gt;&amp;nbsp; (let ((path (make-hash-table :test 'eq))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (n node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (puthash (undo-tree-root buffer-undo-tree) t path)
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; build list of nodes leading back from selected node to root, updating
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; branches as we go to point down to selected node
&lt;br&gt;&amp;nbsp; &amp;nbsp; (while (progn
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(puthash n t path)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(when (undo-tree-node-previous n)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setf (undo-tree-node-branch (undo-tree-node-previous n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-position
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; n (undo-tree-node-next (undo-tree-node-previous n))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setq n (undo-tree-node-previous n)))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; work backwards from current node until we intersect path back from
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; selected node
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq n (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (while (not (gethash n path))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq n (undo-tree-node-previous n)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; ascend tree until intersection node
&lt;br&gt;&amp;nbsp; &amp;nbsp; (while (not (eq (undo-tree-current buffer-undo-tree) n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-undo))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; descend tree until selected node
&lt;br&gt;&amp;nbsp; &amp;nbsp; (while (not (eq (undo-tree-current buffer-undo-tree) node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-redo))
&lt;br&gt;&amp;nbsp; &amp;nbsp; n)) &amp;nbsp;; return intersection node
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; =====================================================================
&lt;br&gt;;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Undo-tree visualizer
&lt;br&gt;&lt;br&gt;(defun undo-tree-visualize ()
&lt;br&gt;&amp;nbsp; &amp;quot;Visualize the current buffer's undo tree.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive)
&lt;br&gt;&amp;nbsp; ;; throw error if undo is disabled in buffer
&lt;br&gt;&amp;nbsp; (when (eq buffer-undo-list t) (error &amp;quot;No undo information in this buffer&amp;quot;))
&lt;br&gt;&amp;nbsp; ;; if `buffer-undo-tree' is empty, create initial undo-tree
&lt;br&gt;&amp;nbsp; (when (null buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq buffer-undo-tree (make-undo-tree)))
&lt;br&gt;&amp;nbsp; ;; transfer entries accumulated in `buffer-undo-list' to `buffer-undo-tree'
&lt;br&gt;&amp;nbsp; (undo-list-transfer-to-tree)
&lt;br&gt;&amp;nbsp; ;; add hook to kill visualizer buffer if original buffer is changed
&lt;br&gt;&amp;nbsp; (add-hook 'before-change-functions 'undo-tree-kill-visualizer nil t)
&lt;br&gt;&amp;nbsp; ;; prepare *undo-tree* buffer, then draw tree in it
&lt;br&gt;&amp;nbsp; (let ((undo-tree buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (buff (current-buffer)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (switch-to-buffer-other-window &amp;quot; *undo-tree*&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-visualizer-mode)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq undo-tree-visualizer-buffer buff)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq buffer-undo-tree undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq cursor-type nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq buffer-read-only nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-draw-tree undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq buffer-read-only t)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-kill-visualizer (&amp;rest dummy)
&lt;br&gt;&amp;nbsp; ;; Kill visualizer. Added to `before-change-functions' hook of original
&lt;br&gt;&amp;nbsp; ;; buffer when visualizer is invoked.
&lt;br&gt;&amp;nbsp; (unless undo-in-progress
&lt;br&gt;&amp;nbsp; &amp;nbsp; (unwind-protect
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (save-excursion
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (set-buffer &amp;quot; *undo-tree*&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-visualizer-quit))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; remove hook now that visualizer has been killed
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (remove-hook 'before-change-functions 'undo-tree-kill-visualizer t))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-draw-tree (undo-tree)
&lt;br&gt;&amp;nbsp; ;; Draw UNDO-TREE in current buffer.
&lt;br&gt;&amp;nbsp; (erase-buffer)
&lt;br&gt;&amp;nbsp; (undo-tree-move-down 1) &amp;nbsp; &amp;nbsp; &amp;nbsp;; top margin
&lt;br&gt;&amp;nbsp; (undo-tree-clear-visualizer-data undo-tree)
&lt;br&gt;&amp;nbsp; (undo-tree-compute-widths undo-tree)
&lt;br&gt;&amp;nbsp; (undo-tree-move-forward
&lt;br&gt;&amp;nbsp; &amp;nbsp;(max (/ (window-width) 2)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (+ (undo-tree-node-char-lwidth (undo-tree-root undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; add space for left part of left-most time-stamp
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(if undo-tree-visualizer-timestamps 4 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;2))) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;; left margin
&lt;br&gt;&amp;nbsp; ;; draw undo-tree
&lt;br&gt;&amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-default-face)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (stack (list (undo-tree-root undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (n (undo-tree-root undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; link root node to its representation in visualizer
&lt;br&gt;&amp;nbsp; &amp;nbsp; (unless (markerp (undo-tree-node-marker n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-marker n) (make-marker))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (set-marker-insertion-type (undo-tree-node-marker n) nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (move-marker (undo-tree-node-marker n) (point))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; draw nodes from stack until stack is empty
&lt;br&gt;&amp;nbsp; &amp;nbsp; (while stack
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq n (pop stack))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char (undo-tree-node-marker n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq n (undo-tree-draw-subtree n nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq stack (append stack n))))
&lt;br&gt;&amp;nbsp; ;; highlight active branch
&lt;br&gt;&amp;nbsp; (goto-char (undo-tree-node-marker (undo-tree-root undo-tree)))
&lt;br&gt;&amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-active-branch-face))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-highlight-active-branch (undo-tree-root undo-tree)))
&lt;br&gt;&amp;nbsp; ;; highlight current node
&lt;br&gt;&amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-current-face))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-draw-node (undo-tree-current undo-tree) 'current)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-highlight-active-branch (node)
&lt;br&gt;&amp;nbsp; ;; Draw highlighted active branch below NODE in current buffer.
&lt;br&gt;&amp;nbsp; (let ((stack (list node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; link node to its representation in visualizer
&lt;br&gt;&amp;nbsp; &amp;nbsp; (unless (markerp (undo-tree-node-marker node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-marker node) (make-marker))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (set-marker-insertion-type (undo-tree-node-marker node) nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (move-marker (undo-tree-node-marker node) (point))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; draw active branch
&lt;br&gt;&amp;nbsp; &amp;nbsp; (while stack
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq node (pop stack))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char (undo-tree-node-marker node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq node (undo-tree-draw-subtree node 'active))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq stack (append stack node)))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-draw-node (node &amp;optional current)
&lt;br&gt;&amp;nbsp; ;; Highlight NODE as current node.
&lt;br&gt;&amp;nbsp; (goto-char (undo-tree-node-marker node))
&lt;br&gt;&amp;nbsp; (if undo-tree-visualizer-timestamps
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (progn
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (backward-char 4)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if current (undo-tree-insert ?*) (undo-tree-insert ? ))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-insert
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-timestamp-to-string (undo-tree-node-timestamp node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (backward-char 5)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (move-marker (undo-tree-node-marker node) (point))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (put-text-property (- (point) 3) (+ (point) 5)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;'undo-tree-node node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (if current (undo-tree-insert ?x) (undo-tree-insert ?o))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (backward-char 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (put-text-property (point) (1+ (point)) 'undo-tree-node node)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-draw-subtree (node &amp;optional active-branch)
&lt;br&gt;&amp;nbsp; ;; Draw subtree rooted at NODE. The subtree will start from point.
&lt;br&gt;&amp;nbsp; ;; If ACTIVE-BRANCH is non-nil, just draw active branch below NODE.
&lt;br&gt;&amp;nbsp; ;; If TIMESTAP is non-nil, draw time-stamps instead of &amp;quot;o&amp;quot; at nodes.
&lt;br&gt;&amp;nbsp; (let ((num-children (length (undo-tree-node-next node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; node-list pos trunk-pos n)
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; draw node itself
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-draw-node node)
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; (cond
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;;; if we're at a leaf node, we're done
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;((= num-children 0))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;;; if node has only one child, draw it (not strictly necessary to deal
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;;; with this case separately, but as it's by far the most common case
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;;; this makes the code clearer and more efficient)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;((= num-children 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-insert ?|)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (backward-char 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-insert ?|)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (backward-char 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq n (car (undo-tree-node-next node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; link next node to its representation in visualizer
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (unless (markerp (undo-tree-node-marker n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-marker n) (make-marker))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (set-marker-insertion-type (undo-tree-node-marker n) nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (move-marker (undo-tree-node-marker n) (point))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; add next node to list of nodes to draw next
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (push n node-list))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;;; if node had multiple children, draw branches
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(t
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-insert ?|)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (backward-char 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq trunk-pos (point))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; left subtrees
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (backward-char
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(- (undo-tree-node-char-lwidth node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-char-lwidth
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(car (undo-tree-node-next node)))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq pos (point))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq n (cons nil (undo-tree-node-next node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (dotimes (i (/ num-children 2))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq n (cdr n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (when (or (null active-branch)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (eq (car n)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (nth (undo-tree-node-branch node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-node-next node))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-forward 2)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-insert ?_ (- trunk-pos pos 2))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char pos)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-forward 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-insert ?/)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (backward-char 2)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; link node to its representation in visualizer
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (unless (markerp (undo-tree-node-marker (car n)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-marker (car n)) (make-marker))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (set-marker-insertion-type (undo-tree-node-marker (car n)) nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (move-marker (undo-tree-node-marker (car n)) (point))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; add node to list of nodes to draw next
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (push (car n) node-list))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char pos)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-forward
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(+ (undo-tree-node-char-rwidth (car n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-char-lwidth (cadr n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; undo-tree-visualizer-spacing 1))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq pos (point)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; middle subtree (only when number of children is odd)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (when (= (mod num-children 2) 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq n (cdr n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (when (or (null active-branch)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (eq (car n)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (nth (undo-tree-node-branch node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-node-next node))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-insert ?|)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (backward-char 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; link node to its representation in visualizer
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (unless (markerp (undo-tree-node-marker (car n)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-marker (car n)) (make-marker))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (set-marker-insertion-type (undo-tree-node-marker (car n)) nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (move-marker (undo-tree-node-marker (car n)) (point))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; add node to list of nodes to draw next
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (push (car n) node-list))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char pos)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-forward
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(+ (undo-tree-node-char-rwidth (car n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (cadr n) (undo-tree-node-char-lwidth (cadr n)) 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; undo-tree-visualizer-spacing 1))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq pos (point)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; right subtrees
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (incf trunk-pos)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (dotimes (i (/ num-children 2))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq n (cdr n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (when (or (null active-branch)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (eq (car n)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (nth (undo-tree-node-branch node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-node-next node))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char trunk-pos)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-insert ?_ (- pos trunk-pos 1))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char pos)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (backward-char 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-insert ?\\)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; link node to its representation in visualizer
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (unless (markerp (undo-tree-node-marker (car n)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-marker (car n)) (make-marker))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (set-marker-insertion-type (undo-tree-node-marker (car n)) nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (move-marker (undo-tree-node-marker (car n)) (point))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; add node to list of nodes to draw next
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (push (car n) node-list))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (when (cdr n)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char pos)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-forward
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(+ (undo-tree-node-char-rwidth (car n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (cadr n) (undo-tree-node-char-lwidth (cadr n)) 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; undo-tree-visualizer-spacing 1))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq pos (point))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; return list of nodes to draw next
&lt;br&gt;&amp;nbsp; &amp;nbsp; (nreverse node-list)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-node-char-lwidth (node)
&lt;br&gt;&amp;nbsp; ;; Return left-width of NODE measured in characters.
&lt;br&gt;&amp;nbsp; (if (= (length (undo-tree-node-next node)) 0) 0
&lt;br&gt;&amp;nbsp; &amp;nbsp; (- (* (+ undo-tree-visualizer-spacing 1) (undo-tree-node-lwidth node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(if (= (undo-tree-node-cwidth node) 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(1+ (/ undo-tree-visualizer-spacing 2)) 0))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-node-char-rwidth (node)
&lt;br&gt;&amp;nbsp; ;; Return right-width of NODE measured in characters.
&lt;br&gt;&amp;nbsp; (if (= (length (undo-tree-node-next node)) 0) 0
&lt;br&gt;&amp;nbsp; &amp;nbsp; (- (* (+ undo-tree-visualizer-spacing 1) (undo-tree-node-rwidth node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(if (= (undo-tree-node-cwidth node) 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(1+ (/ undo-tree-visualizer-spacing 2)) 0))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-insert (str &amp;optional arg)
&lt;br&gt;&amp;nbsp; ;; Insert character or string STR ARG times, overwriting, and using
&lt;br&gt;&amp;nbsp; ;; `undo-tree-insert-face'.
&lt;br&gt;&amp;nbsp; (unless arg (setq arg 1))
&lt;br&gt;&amp;nbsp; (when (characterp str)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq str (make-string arg str))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq arg 1))
&lt;br&gt;&amp;nbsp; (dotimes (i arg) (insert str))
&lt;br&gt;&amp;nbsp; (setq arg (* arg (length str)))
&lt;br&gt;&amp;nbsp; (undo-tree-move-forward arg)
&lt;br&gt;&amp;nbsp; (backward-delete-char arg)
&lt;br&gt;&amp;nbsp; (when (boundp 'undo-tree-insert-face)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (put-text-property (- (point) arg) (point) 'face undo-tree-insert-face)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-move-down (&amp;optional arg)
&lt;br&gt;&amp;nbsp; ;; Move down, extending buffer if necessary.
&lt;br&gt;&amp;nbsp; (let ((row (line-number-at-pos))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (col (current-column))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; line)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (unless arg (setq arg 1))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (forward-line arg)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq line (line-number-at-pos))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; if buffer doesn't have enough lines, add some
&lt;br&gt;&amp;nbsp; &amp;nbsp; (when (/= line (+ row arg))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (insert (make-string (- arg (- line row)) ?\n)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-move-forward col)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-move-forward (&amp;optional arg)
&lt;br&gt;&amp;nbsp; ;; Move forward, extending buffer if necessary.
&lt;br&gt;&amp;nbsp; (unless arg (setq arg 1))
&lt;br&gt;&amp;nbsp; (let ((n (- (line-end-position) (point))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (if (&amp;gt; n arg)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (forward-char arg)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (end-of-line)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (insert (make-string (- arg n) ? )))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-timestamp-to-string (timestamp)
&lt;br&gt;&amp;nbsp; ;; Convert TIMESTAMP to hh:mm:ss string.
&lt;br&gt;&amp;nbsp; (let ((time (decode-time timestamp)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (format &amp;quot;%02d:%02d:%02d&amp;quot; (nth 2 time) (nth 1 time) (nth 0 time))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; =====================================================================
&lt;br&gt;;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Visualizer mode commands
&lt;br&gt;&lt;br&gt;(defun undo-tree-visualizer-mode ()
&lt;br&gt;&amp;nbsp; &amp;quot;Major mode used in undo-tree visualizer.
&lt;br&gt;&lt;br&gt;The undo-tree visualizer can only be invoked from a buffer in
&lt;br&gt;which `undo-tree-mode' is enabled. The visualizer displays the
&lt;br&gt;undo history tree graphically, and allows you to browse around
&lt;br&gt;the undo history, undoing or redoing the corresponding changes in
&lt;br&gt;the parent buffer.
&lt;br&gt;&lt;br&gt;Within the undo-tree visualizer, the following keys are available:
&lt;br&gt;&lt;br&gt;&amp;nbsp; \\{undo-tree-visualizer-map}&amp;quot;
&lt;br&gt;&amp;nbsp; (kill-all-local-variables)
&lt;br&gt;&amp;nbsp; (setq major-mode 'undo-tree-visualizer-mode)
&lt;br&gt;&amp;nbsp; (setq mode-name &amp;quot;undo-tree-visualizer-mode&amp;quot;)
&lt;br&gt;&amp;nbsp; (use-local-map undo-tree-visualizer-map)
&lt;br&gt;&amp;nbsp; (setq truncate-lines t)
&lt;br&gt;&amp;nbsp; (setq buffer-read-only t))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-visualize-undo (&amp;optional arg)
&lt;br&gt;&amp;nbsp; &amp;quot;Undo changes. A numeric ARG serves as a repeat count.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;p&amp;quot;)
&lt;br&gt;&amp;nbsp; (setq buffer-read-only nil)
&lt;br&gt;&amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-active-branch-face))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-draw-node (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; (switch-to-buffer-other-window undo-tree-visualizer-buffer)
&lt;br&gt;&amp;nbsp; (unwind-protect
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-undo arg)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (switch-to-buffer-other-window &amp;quot; *undo-tree*&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-current-face))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-draw-node (undo-tree-current buffer-undo-tree) 'current))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq buffer-read-only t)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-visualize-redo (&amp;optional arg)
&lt;br&gt;&amp;nbsp; &amp;quot;Redo changes. A numeric ARG serves as a repeat count.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;p&amp;quot;)
&lt;br&gt;&amp;nbsp; (setq buffer-read-only nil)
&lt;br&gt;&amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-active-branch-face))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-draw-node (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; (switch-to-buffer-other-window undo-tree-visualizer-buffer)
&lt;br&gt;&amp;nbsp; (unwind-protect
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-redo arg)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (switch-to-buffer-other-window &amp;quot; *undo-tree*&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (goto-char (undo-tree-node-marker (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-current-face))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-draw-node (undo-tree-current buffer-undo-tree) 'current))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq buffer-read-only t)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-visualize-switch-branch-right (arg)
&lt;br&gt;&amp;nbsp; &amp;quot;Switch to next branch of the undo tree.
&lt;br&gt;This will affect which branch to descend when *redoing* changes
&lt;br&gt;using `undo-tree-redo' or `undo-tree-visualizer-redo'.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;p&amp;quot;)
&lt;br&gt;&amp;nbsp; ;; un-highlight old active branch below current node
&lt;br&gt;&amp;nbsp; (setq buffer-read-only nil)
&lt;br&gt;&amp;nbsp; (goto-char (undo-tree-node-marker (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-default-face))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-highlight-active-branch (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; ;; increment branch
&lt;br&gt;&amp;nbsp; (let ((branch (undo-tree-node-branch (undo-tree-current buffer-undo-tree))))
&lt;br&gt;&amp;nbsp; (setf (undo-tree-node-branch (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (cond
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;((&amp;gt;= (+ branch arg) (undo-tree-num-branches))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (1- (undo-tree-num-branches)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;((&amp;lt;= (+ branch arg) 0) 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(t (+ branch arg))))
&lt;br&gt;&amp;nbsp; ;; highlight new active branch below current node
&lt;br&gt;&amp;nbsp; (goto-char (undo-tree-node-marker (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-active-branch-face))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-highlight-active-branch (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; ;; re-highlight current node
&lt;br&gt;&amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-current-face))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-draw-node (undo-tree-current buffer-undo-tree) 'current))
&lt;br&gt;&amp;nbsp; (setq buffer-read-only t)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-visualize-switch-branch-left (arg)
&lt;br&gt;&amp;nbsp; &amp;quot;Switch to previous branch of the undo tree.
&lt;br&gt;This will affect which branch to descend when *redoing* changes
&lt;br&gt;using `undo-tree-redo' or `undo-tree-visualizer-redo'.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;p&amp;quot;)
&lt;br&gt;&amp;nbsp; (undo-tree-visualize-switch-branch-right (- arg)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-visualizer-quit ()
&lt;br&gt;&amp;nbsp; &amp;quot;Quit the undo-tree visualizer.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive)
&lt;br&gt;&amp;nbsp; (undo-tree-clear-visualizer-data buffer-undo-tree)
&lt;br&gt;&amp;nbsp; (kill-buffer-and-window))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-visualizer-set (pos)
&lt;br&gt;&amp;nbsp; &amp;quot;Set buffer to state corresponding to undo tree node
&lt;br&gt;at POS.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;@e&amp;quot;)
&lt;br&gt;&amp;nbsp; (setq pos (event-start (nth 1 pos)))
&lt;br&gt;&amp;nbsp; (let ((node (get-text-property pos 'undo-tree-node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (when node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; set parent buffer to state corresponding to node at POS
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (set-buffer undo-tree-visualizer-buffer)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-set node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (set-buffer &amp;quot; *undo-tree*&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-read-only nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; re-draw undo tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-draw-tree buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-read-only t))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-visualizer-toggle-timestamps ()
&lt;br&gt;&amp;nbsp; &amp;quot;Toggle display of time-stamps.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive)
&lt;br&gt;&amp;nbsp; (setq undo-tree-visualizer-spacing
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (setq undo-tree-visualizer-timestamps
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (not undo-tree-visualizer-timestamps))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; need sufficient space if TIMESTAMP is set
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (max 9 (default-value 'undo-tree-visualizer-spacing))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (default-value 'undo-tree-visualizer-spacing)))
&lt;br&gt;&amp;nbsp; ;; redraw tree
&lt;br&gt;&amp;nbsp; (setq buffer-read-only nil)
&lt;br&gt;&amp;nbsp; (undo-tree-draw-tree buffer-undo-tree)
&lt;br&gt;&amp;nbsp; (setq buffer-read-only t))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-visualizer-scroll-left (&amp;optional arg)
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;p&amp;quot;)
&lt;br&gt;&amp;nbsp; (scroll-right (or arg 1) t))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-visualizer-scroll-right (&amp;optional arg)
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;p&amp;quot;)
&lt;br&gt;&amp;nbsp; (scroll-left (or arg 1) t))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(provide 'undo-tree)
&lt;br&gt;&lt;br&gt;;;; undo-tree.el ends here
&lt;br&gt;&lt;br /&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26564909&amp;i=1&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/undo-tree.el-tp26554347p26564909.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-26564629</id>
	<title>gtranslate.el --- google translation</title>
	<published>2009-11-29T04:46:59Z</published>
	<updated>2009-11-29T04:46:59Z</updated>
	<author>
		<name>Bruno Tavernier</name>
	</author>
	<content type="html">Dear emacs users,
&lt;br&gt;&lt;br&gt;Here is my first contribution to the open-source world, and first meaningful chunk of emacs-lisp! :-)
&lt;br&gt;&lt;br&gt;The following module (gtranslate.el) provide an interface to the google translation api.
&lt;br&gt;It should thus support any languages supported by the api (guarranty 100% not tested).
&lt;br&gt;&lt;br&gt;Api website:
&lt;br&gt;&lt;a href=&quot;http://code.google.com/apis/ajaxlanguage/&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://code.google.com/apis/ajaxlanguage/&lt;/a&gt;&lt;br&gt;&lt;br&gt;I would be glad to hear experimented hackers comments, if any.
&lt;br&gt;&lt;br&gt;&lt;br&gt;regards,
&lt;br&gt;&lt;br&gt;&lt;br&gt;Bruno Tavernier
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br /&gt; &lt;br /&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26564629&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;&lt;div class=&quot;small&quot;&gt;&lt;br/&gt;&lt;img src=&quot;http://old.nabble.com/images/icon_attachment.gif&quot; &gt; &lt;strong&gt;gtranslate.el&lt;/strong&gt; (5K) &lt;a href=&quot;http://old.nabble.com/attachment/26564629/0/gtranslate.el&quot; target=&quot;_top&quot;&gt;Download Attachment&lt;/a&gt;&lt;/div&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/gtranslate.el-----google-translation-tp26564629p26564629.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-26559143</id>
	<title>Re: undo-tree.el</title>
	<published>2009-11-28T19:43:53Z</published>
	<updated>2009-11-28T19:43:53Z</updated>
	<author>
		<name>Toby Cubitt-5</name>
	</author>
	<content type="html">Time for the first bug-fixes already...!
&lt;br&gt;&lt;br /&gt;&lt;br&gt;;;; undo-tree.el --- Treat undo history as a tree
&lt;br&gt;&lt;br&gt;&lt;br&gt;;; Copyright (C) 2009 Toby Cubitt
&lt;br&gt;&lt;br&gt;;; Author: Toby Cubitt &amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26559143&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;toby-undo-tree@...&lt;/a&gt;&amp;gt;
&lt;br&gt;;; Version: 0.1.1
&lt;br&gt;;; Keywords: undo, redo, history, tree
&lt;br&gt;;; URL: &lt;a href=&quot;http://www.dr-qubit.org/emacs.php&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.dr-qubit.org/emacs.php&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;;; This file is NOT part of Emacs.
&lt;br&gt;;;
&lt;br&gt;;; GNU Emacs is free software: you can redistribute it and/or modify it under
&lt;br&gt;;; the terms of the GNU General Public License as published by the Free
&lt;br&gt;;; Software Foundation, either version 3 of the License, or (at your option)
&lt;br&gt;;; any later version.
&lt;br&gt;&lt;br&gt;;; This program is distributed in the hope that it will be useful, but WITHOUT
&lt;br&gt;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
&lt;br&gt;;; FITNESS FOR A PARTICULAR PURPOSE. &amp;nbsp;See the GNU General Public License for
&lt;br&gt;;; more details.
&lt;br&gt;&lt;br&gt;;; You should have received a copy of the GNU General Public License along
&lt;br&gt;;; with GNU Emacs. If not, see &amp;lt;&lt;a href=&quot;http://www.gnu.org/licenses/&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.gnu.org/licenses/&lt;/a&gt;&amp;gt;.
&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; Commentary:
&lt;br&gt;;;
&lt;br&gt;;; Emacs has a powerful undo system. Unlike the standard undo/redo system in
&lt;br&gt;;; most software, it allows you to recover *any* past state of a buffer
&lt;br&gt;;; (whereas the standard undo/redo system can lose past states as soon as you
&lt;br&gt;;; redo). However, this power comes at a price: many people find Emacs' undo
&lt;br&gt;;; system confusing and difficult to use, spawning a number of packages that
&lt;br&gt;;; replace it with the less powerful but more intuitive undo/redo system.
&lt;br&gt;;;
&lt;br&gt;;; Both the loss of data with standard undo/redo, and the confusion of Emacs'
&lt;br&gt;;; undo, stem from trying to treat undo history as a linear sequence of
&lt;br&gt;;; changes. It's not. The `undo-tree-mode' provided by this package replaces
&lt;br&gt;;; Emacs' undo system with a system that treats undo history as what it is: a
&lt;br&gt;;; branching tree of changes. This simple idea allows the more intuitive
&lt;br&gt;;; behaviour of the standard undo/redo system to be combined with the power of
&lt;br&gt;;; never losing any history. An added side bonus is that undo history can in
&lt;br&gt;;; some cases be stored more efficiently, allowing more changes to accumulate
&lt;br&gt;;; before Emacs starts discarding history.
&lt;br&gt;;;
&lt;br&gt;;; The only downside to this more advanced yet simpler undo system is that it
&lt;br&gt;;; was inspired by Vim. But, after all, most successful religions steal the
&lt;br&gt;;; best ideas from their competitors!
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;; Installation
&lt;br&gt;;; ============
&lt;br&gt;;;
&lt;br&gt;;; To install `undo-tree-mode', make sure this file is saved in a directory in
&lt;br&gt;;; your `load-path', and add the line:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; (require 'undo-tree)
&lt;br&gt;;;
&lt;br&gt;;; to your .emacs file.
&lt;br&gt;;;
&lt;br&gt;;; If you want to replace the standard Emacs' undo system with the
&lt;br&gt;;; `undo-tree-mode' system in all buffers, you can enable it globally by
&lt;br&gt;;; adding:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; (global-undo-tree-mode)
&lt;br&gt;;;
&lt;br&gt;;; to your .emacs file.
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;; Quick-Start
&lt;br&gt;;; ===========
&lt;br&gt;;;
&lt;br&gt;;; If you're the kind of person who likes jump in the car and drive, without
&lt;br&gt;;; bothering to first figure out whether the button on the left dips the
&lt;br&gt;;; headlights or operates the ejector seat (after all, you'll soon figure it
&lt;br&gt;;; out when you push it), then here's the minimum you need to know:
&lt;br&gt;;;
&lt;br&gt;;; `undo-tree-mode' and `global-undo-tree-mode'
&lt;br&gt;;; &amp;nbsp; Enable undo-tree mode (either in the current buffer or globally).
&lt;br&gt;;;
&lt;br&gt;;; C-_ &amp;nbsp;C-/ &amp;nbsp;(`undo-tree-undo')
&lt;br&gt;;; &amp;nbsp; Undo changes.
&lt;br&gt;;;
&lt;br&gt;;; M-_ &amp;nbsp;C-? &amp;nbsp;(`undo-tree-redo')
&lt;br&gt;;; &amp;nbsp; Redo changes.
&lt;br&gt;;;
&lt;br&gt;;; `undo-tree-switch-branch'
&lt;br&gt;;; &amp;nbsp; Switch undo-tree branch.
&lt;br&gt;;; &amp;nbsp; (What does this mean? Better press the button and see!)
&lt;br&gt;;;
&lt;br&gt;;; C-x u &amp;nbsp;(`undo-tree-visualize')
&lt;br&gt;;; &amp;nbsp; Visualize the undo tree.
&lt;br&gt;;; &amp;nbsp; (Better try pressing this button too!)
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;; In the undo visualizer:
&lt;br&gt;;;
&lt;br&gt;;; &amp;lt;up&amp;gt; &amp;nbsp;p &amp;nbsp;C-p &amp;nbsp;(`undo-tree-visualize-undo')
&lt;br&gt;;; &amp;nbsp; Undo changes.
&lt;br&gt;;;
&lt;br&gt;;; &amp;lt;down&amp;gt; &amp;nbsp;n &amp;nbsp;C-n &amp;nbsp;(`undo-tree-visualize-undo')
&lt;br&gt;;; &amp;nbsp; Undo changes.
&lt;br&gt;;;
&lt;br&gt;;; &amp;lt;left&amp;gt; &amp;nbsp;b &amp;nbsp;C-b &amp;nbsp;(`undo-tree-visualize-switch-previous-branch')
&lt;br&gt;;; &amp;nbsp; Switch to previous undo-tree branch.
&lt;br&gt;;;
&lt;br&gt;;; &amp;lt;right&amp;gt; &amp;nbsp;f &amp;nbsp;C-f &amp;nbsp;(`undo-tree-visualize-switch-next-branch')
&lt;br&gt;;; &amp;nbsp; Switch to next undo-tree branch.
&lt;br&gt;;;
&lt;br&gt;;; t &amp;nbsp;(`undo-tree-visualizer-toggle-timestamps')
&lt;br&gt;;; &amp;nbsp; Toggle display of time-stamps.
&lt;br&gt;;;
&lt;br&gt;;; q &amp;nbsp;C-q &amp;nbsp;(`undo-tree-visualizer-quit')
&lt;br&gt;;; &amp;nbsp; Quit undo-tree-visualizer.
&lt;br&gt;;;
&lt;br&gt;;; , &amp;nbsp;&amp;lt;
&lt;br&gt;;; &amp;nbsp; Scroll left.
&lt;br&gt;;;
&lt;br&gt;;; . &amp;nbsp;&amp;gt;
&lt;br&gt;;; &amp;nbsp; Scroll right.
&lt;br&gt;;;
&lt;br&gt;;; &amp;lt;pgup&amp;gt;
&lt;br&gt;;; &amp;nbsp; Scroll up.
&lt;br&gt;;;
&lt;br&gt;;; &amp;lt;pgdown&amp;gt;
&lt;br&gt;;; &amp;nbsp; Scroll down.
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;; Explanation
&lt;br&gt;;; ===========
&lt;br&gt;;;
&lt;br&gt;;; To understand the different undo systems, it's easiest to consider an
&lt;br&gt;;; example. Imagine you make a few edits in a buffer. As you edit, you
&lt;br&gt;;; accumulate a history of changes, which we might visualize as a string of
&lt;br&gt;;; past buffer states, growing downwards:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(initial buffer state)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(first edit)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(second edit)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;x &amp;nbsp;(current buffer state)
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;; Now imagine that you undo the last two changes. We can visualize this as
&lt;br&gt;;; rewinding the current state back two steps:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(initial buffer state)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;x &amp;nbsp;(current buffer state)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;; However, this isn't a good representation of what Emacs' undo system
&lt;br&gt;;; does. Instead, it treats the undos as *new* changes to the buffer, and adds
&lt;br&gt;;; them to the history:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(initial buffer state)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(first edit)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(second edit)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;x &amp;nbsp;(buffer state before undo)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(first undo)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;x &amp;nbsp;(second undo)
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;; Actually, since the buffer returns to a previous state after an undo, a
&lt;br&gt;;; better way to visualize it is to imagine the string of changes turning back
&lt;br&gt;;; on itself:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(initial buffer state) &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(first edit) &amp;nbsp;o &amp;nbsp;x &amp;nbsp;(second undo)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (second edit) &amp;nbsp;o &amp;nbsp;o &amp;nbsp;(first undo)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| /
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|/
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(buffer state before undo)
&lt;br&gt;;;
&lt;br&gt;;; Treating undos as new changes might seem a strange thing to do. But the
&lt;br&gt;;; advantage becomes clear as soon as we imagine what happens when you edit
&lt;br&gt;;; the buffer again. Since you've undone a couple of changes, new edits will
&lt;br&gt;;; branch off from the buffer state that you've rewound to. Conceptually, it
&lt;br&gt;;; looks like this:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(initial buffer state)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|\
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;x &amp;nbsp;(new edit)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;;
&lt;br&gt;;; The standard undo/redo system only lets you go backwards and forwards
&lt;br&gt;;; linearly. So as soon as you make that new edit, it discards the old
&lt;br&gt;;; branch. Emacs' undo just keeps adding changes to the end of the string. So
&lt;br&gt;;; the undo history in the two systems now looks like this:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Undo/Redo: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Emacs' undo
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .\ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp;|\
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; . \ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| &amp;nbsp;| \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; . &amp;nbsp;x &amp;nbsp;(new edit) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp;o &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; (discarded &amp;nbsp;. &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| / &amp;nbsp; |
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; branch) &amp;nbsp; . &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|/ &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; . &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp; &amp;nbsp; |
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;x &amp;nbsp;(new edit)
&lt;br&gt;;;
&lt;br&gt;;; Now, what if you change your mind about those undos, and decide you did
&lt;br&gt;;; like those other changes you'd made after all? With the standard undo/redo
&lt;br&gt;;; system, you're stuck. There's no way to recover them, because that branch
&lt;br&gt;;; was discarded when you made the new edit.
&lt;br&gt;;;
&lt;br&gt;;; However, in Emacs' undo system, those old buffer states are still there in
&lt;br&gt;;; the undo history. You just have to rewind back through the new edit, and
&lt;br&gt;;; back through the changes made by the undos, until you reach them. Of
&lt;br&gt;;; course, since Emacs treats undos (even undos of undos!) as new changes,
&lt;br&gt;;; you're really weaving backwards and forwards through the history, all the
&lt;br&gt;;; time adding new changes to the end of the string as you go:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp;o &amp;nbsp; &amp;nbsp; o &amp;nbsp;(undo new edit)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp;|\ &amp;nbsp; &amp;nbsp;|\
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp;| \ &amp;nbsp; | \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp;o &amp;nbsp;| &amp;nbsp;| &amp;nbsp;o &amp;nbsp;(undo the undo)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | / &amp;nbsp; | &amp;nbsp;| &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |/ &amp;nbsp; &amp;nbsp;| &amp;nbsp;| &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp;(trying to get &amp;nbsp; o &amp;nbsp; &amp;nbsp; | &amp;nbsp;| &amp;nbsp;x &amp;nbsp;(undo the undo)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; to this state) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| /
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |/
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o
&lt;br&gt;;;
&lt;br&gt;;; So far, this is still reasonably intuitive to use. It doesn't behave so
&lt;br&gt;;; differently to standard undo/redo, except that by going back far enough you
&lt;br&gt;;; can access changes that would be lost in standard undo/redo.
&lt;br&gt;;;
&lt;br&gt;;; However, imagine that after undoing as just described, you decide you
&lt;br&gt;;; actually want to rewind right back to the initial state. If you're lucky,
&lt;br&gt;;; and haven't invoked any command since the last undo, you can just keep on
&lt;br&gt;;; undoing until you get back to the start:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp;(trying to get &amp;nbsp; o &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;x &amp;nbsp;(got there!)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; to this state) &amp;nbsp;| &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp;o &amp;nbsp; &amp;nbsp; o &amp;nbsp; &amp;nbsp; o &amp;nbsp;(keep undoing)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp;|\ &amp;nbsp; &amp;nbsp;|\ &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp;| \ &amp;nbsp; | \ &amp;nbsp; |
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp;o &amp;nbsp;| &amp;nbsp;| &amp;nbsp;o &amp;nbsp;o &amp;nbsp;(keep undoing)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | / &amp;nbsp; | &amp;nbsp;| &amp;nbsp;| /
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |/ &amp;nbsp; &amp;nbsp;| &amp;nbsp;| &amp;nbsp;|/
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp;(already undid &amp;nbsp; o &amp;nbsp; &amp;nbsp; | &amp;nbsp;| &amp;nbsp;o &amp;nbsp;(got this far)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; to this state) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| /
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |/
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o
&lt;br&gt;;;
&lt;br&gt;;; But if you're unlucky, you happen to have moved the point (say) after
&lt;br&gt;;; getting to the point labelled &amp;quot;got this far&amp;quot;. In that case, you've &amp;quot;broken
&lt;br&gt;;; the undo chain&amp;quot;. If you try to undo now, Emacs thinks you're trying to undo
&lt;br&gt;;; the undos! So to get back to the initial state you now have to rewind
&lt;br&gt;;; through *all* the changes, including the undos you just did:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp;(trying to get &amp;nbsp; o &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;x &amp;nbsp;(finally got there!)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; to this state) &amp;nbsp;| &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp;o &amp;nbsp; &amp;nbsp; o &amp;nbsp; &amp;nbsp; o &amp;nbsp; &amp;nbsp; o &amp;nbsp; &amp;nbsp; o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp;|\ &amp;nbsp; &amp;nbsp;|\ &amp;nbsp; &amp;nbsp;|\ &amp;nbsp; &amp;nbsp;|\ &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp;| \ &amp;nbsp; | \ &amp;nbsp; | \ &amp;nbsp; | \ &amp;nbsp; |
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp;o &amp;nbsp;| &amp;nbsp;| &amp;nbsp;o &amp;nbsp;o &amp;nbsp;o &amp;nbsp;| &amp;nbsp;o &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | / &amp;nbsp; | &amp;nbsp;| &amp;nbsp;| / &amp;nbsp; | &amp;nbsp;| &amp;nbsp;| /
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |/ &amp;nbsp; &amp;nbsp;| &amp;nbsp;| &amp;nbsp;|/ &amp;nbsp; &amp;nbsp;| &amp;nbsp;| &amp;nbsp;|/
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp;(already undid &amp;nbsp; o &amp;nbsp; &amp;nbsp; | &amp;nbsp;| &amp;nbsp;o&amp;lt;. &amp;nbsp; | &amp;nbsp;| &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; to this state) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| / &amp;nbsp; &amp;nbsp; : &amp;nbsp; | /
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |/ &amp;nbsp; &amp;nbsp; &amp;nbsp;: &amp;nbsp; |/
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp; &amp;nbsp; &amp;nbsp; : &amp;nbsp; o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; :
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (got this far, but
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;broke undo chain)
&lt;br&gt;;;
&lt;br&gt;;; Confused?
&lt;br&gt;;;
&lt;br&gt;;; In practice you can just hold down the undo key until you reach the buffer
&lt;br&gt;;; state that you want. But whatever you do, don't move around in the buffer
&lt;br&gt;;; to check you've got back to where you want! Because you'll break the undo
&lt;br&gt;;; chain, and then you'll have to traverse the entire string of undos again to
&lt;br&gt;;; get back to the point at which you broke the chain. Commands such as
&lt;br&gt;;; `undo-only', and undo in region (in transient-mark-mode), help to make
&lt;br&gt;;; using Emacs' undo a little easier, but nonetheless it remains confusing for
&lt;br&gt;;; many people.
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;; So what does undo-tree mode do? Remember the diagram we drew to represent
&lt;br&gt;;; the history we've been discussing (make a few edits, undo a couple of them,
&lt;br&gt;;; and edit again)? The diagram that conceptually represented our undo
&lt;br&gt;;; history, before we started discussing specific undo systems? It looked like
&lt;br&gt;;; this:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(initial buffer state)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|\
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;x &amp;nbsp;(current state)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;;
&lt;br&gt;;; Well, that's *exactly* what the undo history looks like to
&lt;br&gt;;; `undo-tree-mode'. &amp;nbsp;It doesn't discard the old branch (as standard undo/redo
&lt;br&gt;;; does), nor does it treat undos as new changes to be added to the end of a
&lt;br&gt;;; linear string of buffer states (as Emacs' undo does). It just keeps track
&lt;br&gt;;; of the tree of branching changes that make up the entire undo history.
&lt;br&gt;;;
&lt;br&gt;;; If you undo from this point, you'll rewind back up the tree to the previous
&lt;br&gt;;; state:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;x &amp;nbsp;(undo)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|\
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;;
&lt;br&gt;;; If you were to undo again, you'd rewind back to the initial state. If on
&lt;br&gt;;; the other hand you redo the change, you'll end up back at the bottom of the
&lt;br&gt;;; most recent branch:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(start here)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|\
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;x &amp;nbsp;(redo)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;;
&lt;br&gt;;; So far, this is just like the standard undo/redo system. But what if you
&lt;br&gt;;; want to return to a buffer state located on a previous branch of the
&lt;br&gt;;; history? Since `undo-tree-mode' keeps the entire history, you simply need
&lt;br&gt;;; to tell it to switch to a different branch, and then redo the changes you
&lt;br&gt;;; want:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(start here, but switch
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|\ &amp;nbsp;to the other branch)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(redo) &amp;nbsp;o &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(redo) &amp;nbsp;x
&lt;br&gt;;;
&lt;br&gt;;; Now you're on the other branch, and if you undo and redo changes you'll
&lt;br&gt;;; stay on that branch, moving up and down through the buffer states located
&lt;br&gt;;; on that branch. Until you decide to switch branches again, of course.
&lt;br&gt;;;
&lt;br&gt;;; Real undo trees might have multiple branches and sub-branches:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;____|______
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; / &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;____|__ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; __|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; / &amp;nbsp; &amp;nbsp;| &amp;nbsp;\ &amp;nbsp; &amp;nbsp; &amp;nbsp; / &amp;nbsp; \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp; &amp;nbsp; o &amp;nbsp; o &amp;nbsp; &amp;nbsp; o &amp;nbsp; &amp;nbsp; x
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; / \ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; / \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp; o &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp; o
&lt;br&gt;;;
&lt;br&gt;;; Trying to imagine what Emacs' undo would do as you move about such a tree
&lt;br&gt;;; will likely frazzle your brain circuits! But in `undo-tree-mode', you're
&lt;br&gt;;; just moving around this undo history tree. Most of the time, you'll
&lt;br&gt;;; probably only need to stay on the most recent branch, in which case it
&lt;br&gt;;; behaves like standard undo/redo, so is just as simple to understand. But if
&lt;br&gt;;; you ever need to recover a buffer state on a different branch, the
&lt;br&gt;;; possibility of switching between branches and accessing the full undo
&lt;br&gt;;; history is still there.
&lt;br&gt;;;
&lt;br&gt;;; Actually, it gets better. You don't have to imagine all these diagrams,
&lt;br&gt;;; because `undo-tree-mode' includes an undo-tree visualizer which draws them
&lt;br&gt;;; for you! In fact, it draws even better diagrams: it highlights the node
&lt;br&gt;;; representing the current buffer state, it highlights the current branch,
&lt;br&gt;;; and it can optionally display time-stamps for each buffer state. (There's
&lt;br&gt;;; one other tiny difference: the visualizer puts the most recent branch on
&lt;br&gt;;; the left rather than the right.)
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;; Drawbacks
&lt;br&gt;;; =========
&lt;br&gt;;;
&lt;br&gt;;; Emacs' undo system is deeply embedded in Emacs. In particular, garbage
&lt;br&gt;;; collection treats the `buffer-undo-list' specially: references to markers
&lt;br&gt;;; in `buffer-undo-list' don't count during the mark phase, and the sweep
&lt;br&gt;;; phase removes undo entries for markers that have been garbage-collected.
&lt;br&gt;;; This behaviour is implemented in C as part of the garbage collection code,
&lt;br&gt;;; and it is difficult or impossible to emulate in Elisp.
&lt;br&gt;;;
&lt;br&gt;;; To avoid dead markers being resurrected in `undo-tree-mode', and to allow
&lt;br&gt;;; them to be garbage-collected, `undo-tree-mode' doesn't record marker
&lt;br&gt;;; adjustments. Markers are rarely explicitly created by users, so the impact
&lt;br&gt;;; of this will primarily be through its effects on other features that make
&lt;br&gt;;; use of markers. Since marker adjustments haven't always been restored by
&lt;br&gt;;; undo, and even then it was buggy until recently (see Emacs bug#4803), it
&lt;br&gt;;; seems likely that relatively little code relies heavily on correct marker
&lt;br&gt;;; restoration.
&lt;br&gt;;;
&lt;br&gt;;; `undo-tree-mode' doesn't support &amp;quot;undo in region&amp;quot;, i.e. selectively undoing
&lt;br&gt;;; only the changes that affect the current region in
&lt;br&gt;;; `transient-mark-mode'). Support for this is planned for a future version.
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; Change Log:
&lt;br&gt;;;
&lt;br&gt;;; Version 0.1.1
&lt;br&gt;;; * prevented `undo-tree-kill-visualizer' from killing visualizer when
&lt;br&gt;;; &amp;nbsp; undoing/redoing from the visualizer, which completely broke the
&lt;br&gt;;; &amp;nbsp; visualizer!
&lt;br&gt;;; * changed one redo binding, so that at least one set of undo/redo bindings
&lt;br&gt;;; &amp;nbsp; works in a terminal
&lt;br&gt;;; * bound vertical scrolling commands in `undo-tree-visualizer-map', in case
&lt;br&gt;;; &amp;nbsp; they aren't bound globally
&lt;br&gt;;; * added missing :group argument to `defface's
&lt;br&gt;;;
&lt;br&gt;;; Version 0.1
&lt;br&gt;;; * initial release
&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; Code:
&lt;br&gt;&lt;br&gt;;;; =====================================================================
&lt;br&gt;;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Global variables and customization options
&lt;br&gt;&lt;br&gt;(defvar buffer-undo-tree nil
&lt;br&gt;&amp;nbsp; &amp;quot;Tree of undo entries in current buffer.&amp;quot;)
&lt;br&gt;(make-variable-buffer-local 'buffer-undo-tree)
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defgroup undo-tree nil
&lt;br&gt;&amp;nbsp; &amp;quot;Tree undo/redo.&amp;quot;
&lt;br&gt;&amp;nbsp; :group 'undo)
&lt;br&gt;&lt;br&gt;(defcustom undo-tree-visualizer-spacing 3
&lt;br&gt;&amp;nbsp; &amp;quot;Horizontal spacing in undo-tree visualization.
&lt;br&gt;Must be a postivie odd integer.&amp;quot;
&lt;br&gt;&amp;nbsp; :group 'undo-tree
&lt;br&gt;&amp;nbsp; :type '(integer
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; :match (lambda (w n) (and (integerp n) (&amp;gt; n 0) (= (mod n 2) 1)))))
&lt;br&gt;(make-variable-buffer-local 'undo-tree-visualizer-spacing)
&lt;br&gt;&lt;br&gt;(defvar undo-tree-map nil
&lt;br&gt;&amp;nbsp; &amp;quot;Keymap used in undo-tree-mode.&amp;quot;)
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defface undo-tree-visualizer-default-face
&lt;br&gt;&amp;nbsp; '((((class color)) :foreground &amp;quot;gray&amp;quot;))
&lt;br&gt;&amp;nbsp; &amp;quot;*Face used to draw undo-tree in visualizer.&amp;quot;
&lt;br&gt;&amp;nbsp; :group 'undo-tree)
&lt;br&gt;&lt;br&gt;(defface undo-tree-visualizer-current-face
&lt;br&gt;&amp;nbsp; '((((class color)) :foreground &amp;quot;red&amp;quot;))
&lt;br&gt;&amp;nbsp; &amp;quot;*Face used to highlight current undo-tree node
&lt;br&gt;in visualizer.&amp;quot;
&lt;br&gt;&amp;nbsp; :group 'undo-tree)
&lt;br&gt;&lt;br&gt;(defface undo-tree-visualizer-active-branch-face
&lt;br&gt;&amp;nbsp; '((((class color)) :foreground &amp;quot;white&amp;quot; :weight bold))
&lt;br&gt;&amp;nbsp; &amp;quot;*Face used to highlight active undo-tree branch
&lt;br&gt;in visualizer.&amp;quot;
&lt;br&gt;&amp;nbsp; :group 'undo-tree)
&lt;br&gt;&lt;br&gt;(defvar undo-tree-visualizer-map nil
&lt;br&gt;&amp;nbsp; &amp;quot;Keymap used in undo-tree visualizer.&amp;quot;)
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defvar undo-tree-visualizer-buffer nil
&lt;br&gt;&amp;nbsp; &amp;quot;Parent buffer in visualizer.&amp;quot;)
&lt;br&gt;(make-variable-buffer-local 'undo-tree-visualizer-buffer)
&lt;br&gt;&lt;br&gt;(defvar undo-tree-visualizer-timestamps nil
&lt;br&gt;&amp;nbsp; &amp;quot;Non-nil when visualizer is displaying time-stamps.&amp;quot;)
&lt;br&gt;(make-variable-buffer-local 'undo-tree-visualizer-timestamps)
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; =================================================================
&lt;br&gt;;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Setup default keymaps
&lt;br&gt;&lt;br&gt;(unless undo-tree-map
&lt;br&gt;&amp;nbsp; (setq undo-tree-map (make-sparse-keymap))
&lt;br&gt;&amp;nbsp; ;; remap `undo' to `undo-tree-undo'
&lt;br&gt;&amp;nbsp; (define-key undo-tree-map [remap undo] 'undo-tree-undo)
&lt;br&gt;&amp;nbsp; ;; bind standard undo bindings (since these match redo counterparts)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-map &amp;quot;C-/&amp;quot; 'undo-tree-undo)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-map &amp;quot;C-_&amp;quot; 'undo-tree-undo)
&lt;br&gt;&amp;nbsp; ;; redo doesn't exist normally, so define out own keybindings
&lt;br&gt;&amp;nbsp; (define-key undo-tree-map (kbd &amp;quot;C-?&amp;quot;) 'undo-tree-redo)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-map (kbd &amp;quot;M-_&amp;quot;) 'undo-tree-redo)
&lt;br&gt;&amp;nbsp; ;; just in case something has defined it...
&lt;br&gt;&amp;nbsp; (define-key undo-tree-map [remap redo] 'undo-tree-redo)
&lt;br&gt;&amp;nbsp; ;; we use &amp;quot;C-x u&amp;quot; for the undo-tree visualizer
&lt;br&gt;&amp;nbsp; (define-key undo-tree-map (kbd &amp;quot;C-x u&amp;quot;) 'undo-tree-visualize))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(unless undo-tree-visualizer-map
&lt;br&gt;&amp;nbsp; (setq undo-tree-visualizer-map (make-keymap))
&lt;br&gt;&amp;nbsp; ;; vertical motion keys undo/redo
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map [up]
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-undo)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;p&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-undo)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;\C-p&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-undo)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map [down]
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-redo)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;n&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-redo)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;\C-n&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-redo)
&lt;br&gt;&amp;nbsp; ;; horizontal motion keys switch branch
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map [right]
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-switch-next-branch)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;f&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-switch-next-branch)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;\C-f&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-undo)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map [left]
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-switch-previous-branch)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;b&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-switch-previous-branch)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;\C-b&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-switch-previous-branch)
&lt;br&gt;&amp;nbsp; ;; mouse sets buffer state to node at click
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map [mouse-1]
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualizer-set)
&lt;br&gt;&amp;nbsp; ;; toggle timestamps
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;t&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualizer-toggle-timestamps)
&lt;br&gt;&amp;nbsp; ;; horizontal scrolling may be needed if tree is very wide
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;,&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualizer-scroll-left)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;.&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualizer-scroll-right)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;&amp;lt;&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualizer-scroll-left)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;&amp;gt;&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualizer-scroll-right)
&lt;br&gt;&amp;nbsp; ;; vertical scrolling may be needed if the tree is very tall
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map [next] 'scroll-up)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map [prior] 'scroll-down)
&lt;br&gt;&amp;nbsp; ;; quit visualizer
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;q&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualizer-quit)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;\C-q&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualizer-quit))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; =====================================================================
&lt;br&gt;;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Undo-tree data structure
&lt;br&gt;&lt;br&gt;(defstruct
&lt;br&gt;&amp;nbsp; (undo-tree
&lt;br&gt;&amp;nbsp; &amp;nbsp;:named
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:constructor nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:constructor make-undo-tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(&amp;aux
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (root (make-undo-tree-node nil nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (current root)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (size 0)))
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:copier nil))
&lt;br&gt;&amp;nbsp; root current size)
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(defstruct
&lt;br&gt;&amp;nbsp; (undo-tree-node
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:type vector) &amp;nbsp; ; create unnamed struct
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:constructor nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:constructor make-undo-tree-node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(previous undo
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;aux
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (timestamp (current-time))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (branch 0)))
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:constructor make-undo-tree-node-backwards
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(next-node undo
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;aux
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (next (list next-node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (timestamp (current-time))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (branch 0)))
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:copier nil))
&lt;br&gt;&amp;nbsp; previous next undo redo timestamp branch visualizer)
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defmacro undo-tree-node-p (n)
&lt;br&gt;&amp;nbsp; (let ((len (length (make-undo-tree-node nil nil))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; `(and (vectorp ,n) (= (length ,n) ,len))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(defstruct
&lt;br&gt;&amp;nbsp; (undo-tree-visualizer-data
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:type vector) &amp;nbsp; ; create unnamed struct
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:constructor nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:constructor make-undo-tree-visualizer-data)
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:copier nil))
&lt;br&gt;&amp;nbsp; lwidth cwidth rwidth marker)
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defmacro undo-tree-visualizer-data-p (v)
&lt;br&gt;&amp;nbsp; (let ((len (length (make-undo-tree-visualizer-data))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; `(and (vectorp ,v) (= (length ,v) ,len))))
&lt;br&gt;&lt;br&gt;(defmacro undo-tree-node-lwidth (node)
&lt;br&gt;&amp;nbsp; `(when (vectorp (undo-tree-node-visualizer ,node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-visualizer-data-lwidth
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-visualizer ,node))))
&lt;br&gt;&lt;br&gt;(defmacro undo-tree-node-cwidth (node)
&lt;br&gt;&amp;nbsp; `(when (vectorp (undo-tree-node-visualizer ,node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-visualizer-data-cwidth
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-visualizer ,node))))
&lt;br&gt;&lt;br&gt;(defmacro undo-tree-node-rwidth (node)
&lt;br&gt;&amp;nbsp; `(when (vectorp (undo-tree-node-visualizer ,node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-visualizer-data-rwidth
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-visualizer ,node))))
&lt;br&gt;&lt;br&gt;(defmacro undo-tree-node-marker (node)
&lt;br&gt;&amp;nbsp; `(when (vectorp (undo-tree-node-visualizer ,node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-visualizer-data-marker
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-visualizer ,node))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defsetf undo-tree-node-lwidth (node) (val)
&lt;br&gt;&amp;nbsp; `(let ((v (undo-tree-node-visualizer ,node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(unless (undo-tree-visualizer-data-p v)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setf (undo-tree-node-visualizer ,node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setq v (make-undo-tree-visualizer-data))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(setf (undo-tree-visualizer-data-lwidth v) ,val)))
&lt;br&gt;&lt;br&gt;(defsetf undo-tree-node-cwidth (node) (val)
&lt;br&gt;&amp;nbsp; `(let ((v (undo-tree-node-visualizer ,node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(unless (undo-tree-visualizer-data-p v)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setf (undo-tree-node-visualizer ,node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setq v (make-undo-tree-visualizer-data))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(setf (undo-tree-visualizer-data-cwidth v) ,val)))
&lt;br&gt;&lt;br&gt;(defsetf undo-tree-node-rwidth (node) (val)
&lt;br&gt;&amp;nbsp; `(let ((v (undo-tree-node-visualizer ,node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(unless (undo-tree-visualizer-data-p v)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setf (undo-tree-node-visualizer ,node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setq v (make-undo-tree-visualizer-data))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(setf (undo-tree-visualizer-data-rwidth v) ,val)))
&lt;br&gt;&lt;br&gt;(defsetf undo-tree-node-marker (node) (val)
&lt;br&gt;&amp;nbsp; `(let ((v (undo-tree-node-visualizer ,node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(unless (undo-tree-visualizer-data-p v)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setf (undo-tree-node-visualizer ,node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setq v (make-undo-tree-visualizer-data))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(setf (undo-tree-visualizer-data-marker v) ,val)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; =====================================================================
&lt;br&gt;;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Basic undo-tree data structure functions
&lt;br&gt;&lt;br&gt;(defun undo-tree-grow (undo)
&lt;br&gt;&amp;nbsp; &amp;quot;Add an UNDO node to current branch of `buffer-undo-tree'.&amp;quot;
&lt;br&gt;&amp;nbsp; (let* ((current (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(new (make-undo-tree-node current undo)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (push new (undo-tree-node-next current))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setf (undo-tree-current buffer-undo-tree) new)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-grow-backwards (node undo)
&lt;br&gt;&amp;nbsp; &amp;quot;Add an UNDO node *above* undo-tree NODE, and return new node.
&lt;br&gt;Note that this will overwrite NODE's \&amp;quot;previous\&amp;quot; link, so should
&lt;br&gt;only be used on a detached NODE, never on nodes that are already
&lt;br&gt;part of `buffer-undo-tree'.&amp;quot;
&lt;br&gt;&amp;nbsp; (let ((new (make-undo-tree-node-backwards node undo)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setf (undo-tree-node-previous node) new)
&lt;br&gt;&amp;nbsp; &amp;nbsp; new))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-compute-widths (undo-tree)
&lt;br&gt;&amp;nbsp; &amp;quot;Recursively compute widths for all UNDO-TREE's nodes.&amp;quot;
&lt;br&gt;&amp;nbsp; (let ((stack (list (undo-tree-root undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; res)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (while stack
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; try to compute widths for node at top of stack
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (if (undo-tree-node-p
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setq res (undo-tree-node-compute-widths (car stack))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; if computation fails, it returns a node whose widths still need
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; computing, which we push onto the stack
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (push res stack)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; otherwise, store widths and remove it from stack
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-lwidth (car stack)) (aref res 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-cwidth (car stack)) (aref res 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-rwidth (car stack)) (aref res 2))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (pop stack)))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-node-compute-widths (node)
&lt;br&gt;&amp;nbsp; ;; Compute NODE's left-, centre-, and right-subtree widths. Returns widths
&lt;br&gt;&amp;nbsp; ;; (in a vector) if successful. Otherwise, returns a node whose widths need
&lt;br&gt;&amp;nbsp; ;; calculating before NODE's can be calculated.
&lt;br&gt;&amp;nbsp; (let ((num-children (length (undo-tree-node-next node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (lwidth 0) (cwidth 0) (rwidth 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; p w)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (catch 'need-widths
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (cond
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; leaf nodes have 0 width
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;((= 0 num-children)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf cwidth 1
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-lwidth node) 0
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-cwidth node) 1
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-rwidth node) 0))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; odd number of children
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;((= (mod num-children 2) 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq p (undo-tree-node-next node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; compute left-width
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (dotimes (i (/ num-children 2))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (undo-tree-node-lwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf lwidth (+ (undo-tree-node-lwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-cwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-rwidth (car p))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; if child's widths haven't been computed, return that child
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (throw 'need-widths (car p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq p (cdr p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (undo-tree-node-lwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf lwidth (undo-tree-node-lwidth (car p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (throw 'need-widths (car p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; centre-width is inherited from middle child
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf cwidth (undo-tree-node-cwidth (car p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; compute right-width
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf rwidth (undo-tree-node-rwidth (car p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq p (cdr p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (dotimes (i (/ num-children 2))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (undo-tree-node-lwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf rwidth (+ (undo-tree-node-lwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-cwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-rwidth (car p))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (throw 'need-widths (car p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq p (cdr p))))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; even number of children
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(t
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq p (undo-tree-node-next node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; compute left-width
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (dotimes (i (/ num-children 2))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (undo-tree-node-lwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf lwidth (+ (undo-tree-node-lwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-cwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-rwidth (car p))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (throw 'need-widths (car p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq p (cdr p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; centre-width is 0 when number of children is even
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq cwidth 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; compute right-width
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (dotimes (i (/ num-children 2))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (undo-tree-node-lwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf rwidth (+ (undo-tree-node-lwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-cwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-rwidth (car p))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (throw 'need-widths (car p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq p (cdr p)))))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; return left-, centre- and right-widths
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (vector lwidth cwidth rwidth))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-clear-visualizer-data (undo-tree)
&lt;br&gt;&amp;nbsp; ;; Clear visualizer data from UNDO-TREE.
&lt;br&gt;&amp;nbsp; (let ((stack (list (undo-tree-root undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (while stack
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq node (pop stack))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-visualizer node) nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (dolist (n (undo-tree-node-next node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (push n stack)))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-position (node list)
&lt;br&gt;&amp;nbsp; &amp;quot;Find the first occurrence of NODE in LIST.
&lt;br&gt;Return the index of the matching item, or nil of not found.
&lt;br&gt;Comparison is done with 'eq.&amp;quot;
&lt;br&gt;&amp;nbsp; (let ((i 0))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (catch 'found
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (while (progn
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(when (eq node (car list)) (throw 'found i))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(incf i)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setq list (cdr list))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; nil)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defmacro undo-tree-num-branches ()
&lt;br&gt;&amp;nbsp; ;; Return number of branches at current undo tree node.
&lt;br&gt;&amp;nbsp; '(length (undo-tree-node-next (undo-tree-current buffer-undo-tree))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-oldest-leaf (node)
&lt;br&gt;&amp;nbsp; ;; Return oldest leaf node below NODE.
&lt;br&gt;&amp;nbsp; (while (undo-tree-node-next node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (car (sort (mapcar 'identity (undo-tree-node-next node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(lambda (a b)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(time-less-p (undo-tree-node-timestamp a)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-timestamp b)))))))
&lt;br&gt;&amp;nbsp; node)
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-discard-node (node)
&lt;br&gt;&amp;nbsp; ;; Discard NODE from `buffer-undo-tree', and return next in line for
&lt;br&gt;&amp;nbsp; ;; discarding.
&lt;br&gt;&lt;br&gt;&amp;nbsp; ;; don't discard current node
&lt;br&gt;&amp;nbsp; (unless (eq node (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (decf (undo-tree-size buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (+ (undo-list-byte-size (undo-tree-node-undo node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-list-byte-size (undo-tree-node-redo node))))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; discarding root node
&lt;br&gt;&amp;nbsp; &amp;nbsp; (if (eq node (undo-tree-root buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (cond
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; should always discard branches before root
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;((&amp;gt; (length (undo-tree-node-next node)) 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (error &amp;quot;Trying to discard undo-tree root which still\
&lt;br&gt;&amp;nbsp;has multiple branches&amp;quot;))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; don't discard root if current node is only child
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;((eq (car (undo-tree-node-next node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(t
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; make child of root into new root
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf node (setf (undo-tree-root buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(car (undo-tree-node-next node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-undo node) nil
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-redo node) nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; if new root has branches, or new root is current node, next node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; to discard is oldest leaf, otherwise it's new root
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (or (&amp;gt; (length (undo-tree-node-next node)) 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (eq (car (undo-tree-node-next node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-oldest-leaf node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; node)))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; discarding leaf node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (let* ((parent (undo-tree-node-previous node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(current (nth (undo-tree-node-branch parent)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-node-next parent))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-next parent)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (delq node (undo-tree-node-next parent))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-branch parent)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-position current (undo-tree-node-next parent)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; if parent has branches, or parent is current node, next node to
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; discard is oldest lead, otherwise it's parent
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (or (eq parent (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (and (undo-tree-node-next parent)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(or (not (eq parent (undo-tree-root buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(&amp;gt; (length (undo-tree-node-next parent)) 1))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-oldest-leaf parent)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; parent)))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-discard-history ()
&lt;br&gt;&amp;nbsp; &amp;quot;Discard undo history until we're within memory usage limits
&lt;br&gt;set by `undo-limit', `undo-strong-limit' and `undo-outer-limit'.&amp;quot;
&lt;br&gt;&lt;br&gt;&amp;nbsp; (when (&amp;gt; (undo-tree-size buffer-undo-tree) undo-limit)
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; if there are no branches off root, first node to discard is root;
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; otherwise it's leaf node at botom of oldest branch
&lt;br&gt;&amp;nbsp; &amp;nbsp; (let ((node (if (&amp;gt; (length (undo-tree-node-next
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-root buffer-undo-tree))) 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-oldest-leaf (undo-tree-root buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-root buffer-undo-tree))))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; discard nodes until memory use is within `undo-strong-limit'
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (while (and node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (&amp;gt; (undo-tree-size buffer-undo-tree) undo-strong-limit))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq node (undo-tree-discard-node node)))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; discard nodes until next node to discard would bring memory use
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; within `undo-limit'
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (while (and node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (&amp;gt; (- (undo-tree-size buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-list-byte-size (undo-tree-node-undo node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-list-byte-size (undo-tree-node-redo node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;undo-limit))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq node (undo-tree-discard-node node)))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; if we're still over the `undo-outer-limit', discard entire history
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (when (&amp;gt; (undo-tree-size buffer-undo-tree) undo-outer-limit)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; query first `undo-ask-before-discard' is set
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if undo-ask-before-discard
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (when (yes-or-no-p
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(format
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;Buffer `%s' undo info is %d bytes long; &amp;nbsp;discard it? &amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (buffer-name) (undo-tree-size buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-undo-tree nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; otherwise, discard and display warning
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (display-warning
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;'(undo discard-info)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(concat
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (format &amp;quot;Buffer `%s' undo info was %d bytes long.\n&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (buffer-name) (undo-tree-size buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;The undo info was discarded because it exceeded\
&lt;br&gt;&amp;nbsp;`undo-outer-limit'.
&lt;br&gt;&lt;br&gt;This is normal if you executed a command that made a huge change
&lt;br&gt;to the buffer. In that case, to prevent similar problems in the
&lt;br&gt;future, set `undo-outer-limit' to a value that is large enough to
&lt;br&gt;cover the maximum size of normal changes you expect a single
&lt;br&gt;command to make, but not so large that it might exceed the
&lt;br&gt;maximum memory allotted to Emacs.
&lt;br&gt;&lt;br&gt;If you did not execute any such command, the situation is
&lt;br&gt;probably due to a bug and you should report it.
&lt;br&gt;&lt;br&gt;You can disable the popping up of this buffer by adding the entry
&lt;br&gt;\(undo discard-info) to the user option `warning-suppress-types',
&lt;br&gt;which is defined in the `warnings' library.\n&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;:warning)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-undo-tree nil)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; )))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; =====================================================================
&lt;br&gt;;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Utility functions for handling `buffer-undo-list'
&lt;br&gt;&lt;br&gt;(defun undo-list-pop-changeset ()
&lt;br&gt;&amp;nbsp; ;; Pop changeset from `buffer-undo-list'.
&lt;br&gt;&amp;nbsp; ;; discard undo boundaries and marker adjustment entries at head of list
&lt;br&gt;&amp;nbsp; (while (or (null (car buffer-undo-list))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(and (consp (car buffer-undo-list))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (markerp (caar buffer-undo-list))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq buffer-undo-list (cdr buffer-undo-list)))
&lt;br&gt;&amp;nbsp; ;; pop elements up to next undo boundary
&lt;br&gt;&amp;nbsp; (unless (eq (car buffer-undo-list) 'undo-tree-canary)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (let* ((changeset (cons (pop buffer-undo-list) nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(p changeset))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (while (car buffer-undo-list)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setcdr p (cons (pop buffer-undo-list) nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; discard marker adjustment entries (see Commentary, above)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (and (consp (cadr p)) (markerp (car (cadr p))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setcdr p nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq p (cdr p))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; changeset)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-list-transfer-to-tree ()
&lt;br&gt;&amp;nbsp; ;; Transfer entries accumulated in `buffer-undo-list' to `buffer-undo-tree'.
&lt;br&gt;&amp;nbsp; (if (null buffer-undo-list)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-undo-list '(nil undo-tree-canary))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (when (not (eq (cadr buffer-undo-list) 'undo-tree-canary))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; create new node from first changeset in `buffer-undo-list', save old
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; `buffer-undo-tree' current node, and make new node the current node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (let* ((node (make-undo-tree-node nil (undo-list-pop-changeset)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(splice (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(size (undo-list-byte-size (undo-tree-node-undo node))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-current buffer-undo-tree) node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; grow tree fragment backwards using `buffer-undo-list' changesets
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (while (and buffer-undo-list
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (not (eq (cadr buffer-undo-list) 'undo-tree-canary)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-grow-backwards node (undo-list-pop-changeset)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf size (undo-list-byte-size (undo-tree-node-undo node))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; if no undo history has been discarded from `buffer-undo-list' since
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; last transfer, splice new tree fragment onto end of old
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; `buffer-undo-tree' current node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (eq (cadr buffer-undo-list) 'undo-tree-canary)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (progn
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-previous node) splice)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (push node (undo-tree-node-next splice))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-branch splice) 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf (undo-tree-size buffer-undo-tree) size))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; if undo history has been discarded, replace entire
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; `buffer-undo-tree' with new tree fragment
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq node (undo-tree-grow-backwards node nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-root buffer-undo-tree) node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-undo-list '(nil undo-tree-canary))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-size buffer-undo-tree) size))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-list-byte-size (undo-list)
&lt;br&gt;&amp;nbsp; ;; Return size (in bytes) of UNDO-LIST
&lt;br&gt;&amp;nbsp; (let ((size 0) (p undo-list))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (while p
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (incf size 8) &amp;nbsp;; cons cells use up 8 bytes
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (when (and (consp (car p)) (stringp (caar p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf size (string-bytes (caar p))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq p (cdr p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; size))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; =====================================================================
&lt;br&gt;;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Undo-tree commands
&lt;br&gt;&lt;br&gt;(define-minor-mode undo-tree-mode
&lt;br&gt;&amp;nbsp; &amp;quot;Toggle undo-tree mode.
&lt;br&gt;With no argument, this command toggles the mode.
&lt;br&gt;A positive prefix argument turns the mode on.
&lt;br&gt;A negative prefix argument turns it off.
&lt;br&gt;&lt;br&gt;Undo-tree-mode replaces Emacs' standard undo feature with a more
&lt;br&gt;powerful yet easier to use version, that treats the undo history
&lt;br&gt;as what it is: a tree.
&lt;br&gt;&lt;br&gt;The following keys are available in `undo-tree-mode':
&lt;br&gt;&lt;br&gt;&amp;nbsp; \\{undo-tree-map}
&lt;br&gt;&lt;br&gt;Within the undo-tree visualizer, the following keys are available:
&lt;br&gt;&lt;br&gt;&amp;nbsp; \\{undo-tree-visualizer-map}&amp;quot;
&lt;br&gt;&lt;br&gt;&amp;nbsp; nil &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ; init value
&lt;br&gt;&amp;nbsp; &amp;quot; Undo-Tree&amp;quot; &amp;nbsp; &amp;nbsp;; lighter
&lt;br&gt;&amp;nbsp; undo-tree-map &amp;nbsp; ; keymap
&lt;br&gt;&amp;nbsp; ;; if disabling `undo-tree-mode', remove &amp;quot;canary&amp;quot; from `buffer-undo-list'
&lt;br&gt;&amp;nbsp; (unless undo-tree-mode (setq buffer-undo-list nil)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun turn-on-undo-tree-mode ()
&lt;br&gt;&amp;nbsp; &amp;quot;Enable undo-tree-mode.&amp;quot;
&lt;br&gt;&amp;nbsp; (undo-tree-mode 1))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(define-globalized-minor-mode global-undo-tree-mode
&lt;br&gt;&amp;nbsp; undo-tree-mode turn-on-undo-tree-mode)
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-undo (&amp;optional arg)
&lt;br&gt;&amp;nbsp; &amp;quot;Undo changes. A numeric ARG serves as a repeat count.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;p&amp;quot;)
&lt;br&gt;&amp;nbsp; ;; throw error if undo is disabled in buffer
&lt;br&gt;&amp;nbsp; (when (eq buffer-undo-list t) (error &amp;quot;No undo information in this buffer&amp;quot;))
&lt;br&gt;&lt;br&gt;&amp;nbsp; (let ((undo-in-progress t))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; if `buffer-undo-tree' is empty, create initial undo-tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; (when (null buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-undo-tree (make-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; transfer entries accumulated in `buffer-undo-list' to
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; `buffer-undo-tree'
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-list-transfer-to-tree)
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; (dotimes (i (or arg 1))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; check if at top of undo tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (if (null (undo-tree-node-previous
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (error &amp;quot;No further undo information&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; undo one record from undo tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (primitive-undo 1 (undo-copy-list
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-node-undo
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-current buffer-undo-tree))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; pop redo entries that `primitive-undo' has added to
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; `buffer-undo-list' and record them in current node's redo record if
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; they're not already there
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (undo-tree-node-redo (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-list-pop-changeset)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-redo (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-list-pop-changeset))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf (undo-tree-size buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-list-byte-size
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-node-redo (undo-tree-current buffer-undo-tree)))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; rewind current node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-current buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-previous (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; update timestamp
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-timestamp (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (current-time))))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; discard undo history if necessary
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-discard-history)
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; inform user if at branch point
&lt;br&gt;&amp;nbsp; &amp;nbsp; (when (&amp;gt; (undo-tree-num-branches) 1) (message &amp;quot;Undo branch point!&amp;quot;))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-redo (&amp;optional arg)
&lt;br&gt;&amp;nbsp; &amp;quot;Redo changes. A numeric ARG serves as a repeat count.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;p&amp;quot;)
&lt;br&gt;&amp;nbsp; ;; throw error if undo is disabled in buffer
&lt;br&gt;&amp;nbsp; (when (eq buffer-undo-list t) (error &amp;quot;No undo information in this buffer&amp;quot;))
&lt;br&gt;&lt;br&gt;&amp;nbsp; (let ((undo-in-progress t))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; if `buffer-undo-tree' is empty, create initial undo-tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; (when (null buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-undo-tree (make-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; transfer entries accumulated in `buffer-undo-list' to
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; `buffer-undo-tree'
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-list-transfer-to-tree)
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; (let ((current (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (dotimes (i (or arg 1))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; check if at bottom of undo tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (null (undo-tree-node-next current))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (error &amp;quot;No further redo information&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; advance current node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq current
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-current buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (nth (undo-tree-node-branch current)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-node-next current))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; update timestamp
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-timestamp current) (current-time))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; redo one record from undo tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (primitive-undo 1 (undo-copy-list (undo-tree-node-redo current)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; discard undo entries that `primitive-undo' has added to
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; `buffer-undo-list' since we already know how to undo from here
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; (NOTE: should we instead overwrite old undo entry for safety's
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;sake?)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-undo-list '(nil undo-tree-canary)))))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; discard undo history if necessary
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-discard-history)
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; inform user if at branch point
&lt;br&gt;&amp;nbsp; &amp;nbsp; (when (&amp;gt; (undo-tree-num-branches) 1) (message &amp;quot;Undo branch point!&amp;quot;))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-switch-branch (branch)
&lt;br&gt;&amp;nbsp; &amp;quot;Switch to a different BRANCH of the undo tree.
&lt;br&gt;This will affect which branch to descend when *redoing* changes
&lt;br&gt;using `undo-tree-redo'.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive (list (or (and prefix-arg (prefix-numeric-value prefix-arg))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(and (not (eq buffer-undo-list t))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (or buffer-undo-tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (progn
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-undo-tree (make-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-list-transfer-to-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; t))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (&amp;gt; (undo-tree-num-branches) 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (read-number
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(format &amp;quot;Branch (0-%d): &amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(1- (undo-tree-num-branches))))))))
&lt;br&gt;&amp;nbsp; ;; throw error if undo is disabled in buffer
&lt;br&gt;&amp;nbsp; (when (eq buffer-undo-list t) (error &amp;quot;No undo information in this buffer&amp;quot;))
&lt;br&gt;&amp;nbsp; ;; sanity check branch number
&lt;br&gt;&amp;nbsp; (when (&amp;lt;= (undo-tree-num-branches) 1) (error &amp;quot;Not at undo branch point&amp;quot;))
&lt;br&gt;&amp;nbsp; (when (or (&amp;lt; branch 0) (&amp;gt; branch (1- (undo-tree-num-branches))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (error &amp;quot;Invalid branch number&amp;quot;)
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; if `buffer-undo-tree' is empty, create initial undo-tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; (when (null buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-undo-tree (make-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; transfer entries accumulated in `buffer-undo-list' to
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; `buffer-undo-tree'
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-list-transfer-to-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; switch branch
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setf (undo-tree-node-branch (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; branch)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-set (node)
&lt;br&gt;&amp;nbsp; ;; Set buffer to state corresponding to NODE. Returns intersection point
&lt;br&gt;&amp;nbsp; ;; between path back from current node and path back from selected NODE.
&lt;br&gt;&amp;nbsp; (let ((path (make-hash-table :test 'eq))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (n node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (puthash (undo-tree-root buffer-undo-tree) t path)
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; build list of nodes leading back from selected node to root, updating
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; branches as we go to point down to selected node
&lt;br&gt;&amp;nbsp; &amp;nbsp; (while (progn
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(puthash n t path)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(when (undo-tree-node-previous n)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setf (undo-tree-node-branch (undo-tree-node-previous n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-position
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; n (undo-tree-node-next (undo-tree-node-previous n))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setq n (undo-tree-node-previous n)))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; work backwards from current node until we intersect path back from
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; selected node
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq n (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (while (not (gethash n path))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq n (undo-tree-node-previous n)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; ascend tree until intersection node
&lt;br&gt;&amp;nbsp; &amp;nbsp; (while (not (eq (undo-tree-current buffer-undo-tree) n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-undo))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; descend tree until selected node
&lt;br&gt;&amp;nbsp; &amp;nbsp; (while (not (eq (undo-tree-current buffer-undo-tree) node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-redo))
&lt;br&gt;&amp;nbsp; &amp;nbsp; n)) &amp;nbsp;; return intersection node
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; =====================================================================
&lt;br&gt;;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Undo-tree visualizer
&lt;br&gt;&lt;br&gt;(defun undo-tree-visualize ()
&lt;br&gt;&amp;nbsp; &amp;quot;Visualize the current buffer's undo tree.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive)
&lt;br&gt;&amp;nbsp; ;; throw error if undo is disabled in buffer
&lt;br&gt;&amp;nbsp; (when (eq buffer-undo-list t) (error &amp;quot;No undo information in this buffer&amp;quot;))
&lt;br&gt;&amp;nbsp; ;; if `buffer-undo-tree' is empty, create initial undo-tree
&lt;br&gt;&amp;nbsp; (when (null buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq buffer-undo-tree (make-undo-tree)))
&lt;br&gt;&amp;nbsp; ;; transfer entries accumulated in `buffer-undo-list' to `buffer-undo-tree'
&lt;br&gt;&amp;nbsp; (undo-list-transfer-to-tree)
&lt;br&gt;&amp;nbsp; ;; add hook to kill visualizer buffer if original buffer is changed
&lt;br&gt;&amp;nbsp; (add-hook 'before-change-functions 'undo-tree-kill-visualizer nil t)
&lt;br&gt;&amp;nbsp; ;; prepare *undo-tree* buffer, then draw tree in it
&lt;br&gt;&amp;nbsp; (let ((undo-tree buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (buff (current-buffer)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (switch-to-buffer-other-window &amp;quot; *undo-tree*&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-visualizer-mode)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq undo-tree-visualizer-buffer buff)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq buffer-undo-tree undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq cursor-type nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq buffer-read-only nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-draw-tree undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq buffer-read-only t)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-kill-visualizer (&amp;rest dummy)
&lt;br&gt;&amp;nbsp; ;; Kill visualizer. Added to `before-change-functions' hook of original
&lt;br&gt;&amp;nbsp; ;; buffer when visualizer is invoked.
&lt;br&gt;&amp;nbsp; (unless undo-in-progress
&lt;br&gt;&amp;nbsp; &amp;nbsp; (unwind-protect
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (save-excursion
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (set-buffer &amp;quot; *undo-tree*&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-visualizer-quit))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; remove hook now that visualizer has been killed
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (remove-hook 'before-change-functions 'undo-tree-kill-visualizer t))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-draw-tree (undo-tree)
&lt;br&gt;&amp;nbsp; ;; Draw UNDO-TREE in current buffer.
&lt;br&gt;&amp;nbsp; (erase-buffer)
&lt;br&gt;&amp;nbsp; (undo-tree-move-down 1) &amp;nbsp; &amp;nbsp; &amp;nbsp;; top margin
&lt;br&gt;&amp;nbsp; (undo-tree-clear-visualizer-data undo-tree)
&lt;br&gt;&amp;nbsp; (undo-tree-compute-widths undo-tree)
&lt;br&gt;&amp;nbsp; (undo-tree-move-forward
&lt;br&gt;&amp;nbsp; &amp;nbsp;(max (/ (window-width) 2)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (+ (undo-tree-node-char-lwidth (undo-tree-root undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; add space for left part of left-most time-stamp
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(if undo-tree-visualizer-timestamps 4 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;2))) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;; left margin
&lt;br&gt;&amp;nbsp; ;; draw undo-tree
&lt;br&gt;&amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-default-face)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (stack (list (undo-tree-root undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (n (undo-tree-root undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; link root node to its representation in visualizer
&lt;br&gt;&amp;nbsp; &amp;nbsp; (unless (markerp (undo-tree-node-marker n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-marker n) (make-marker))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (set-marker-insertion-type (undo-tree-node-marker n) nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (move-marker (undo-tree-node-marker n) (point))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; draw nodes from stack until stack is empty
&lt;br&gt;&amp;nbsp; &amp;nbsp; (while stack
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq n (pop stack))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char (undo-tree-node-marker n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq n (undo-tree-draw-subtree n nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq stack (append stack n))))
&lt;br&gt;&amp;nbsp; ;; highlight active branch
&lt;br&gt;&amp;nbsp; (goto-char (undo-tree-node-marker (undo-tree-root undo-tree)))
&lt;br&gt;&amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-active-branch-face))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-highlight-active-branch (undo-tree-root undo-tree)))
&lt;br&gt;&amp;nbsp; ;; highlight current node
&lt;br&gt;&amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-current-face))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-draw-node (undo-tree-current undo-tree) 'current)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-highlight-active-branch (node)
&lt;br&gt;&amp;nbsp; ;; Draw highlighted active branch below NODE in current buffer.
&lt;br&gt;&amp;nbsp; (let ((stack (list node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; link node to its representation in visualizer
&lt;br&gt;&amp;nbsp; &amp;nbsp; (unless (markerp (undo-tree-node-marker node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-marker node) (make-marker))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (set-marker-insertion-type (undo-tree-node-marker node) nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (move-marker (undo-tree-node-marker node) (point))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; draw active branch
&lt;br&gt;&amp;nbsp; &amp;nbsp; (while stack
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq node (pop stack))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char (undo-tree-node-marker node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq node (undo-tree-draw-subtree node 'active))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq stack (append stack node)))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-draw-node (node &amp;optional current)
&lt;br&gt;&amp;nbsp; ;; Highlight NODE as current node.
&lt;br&gt;&amp;nbsp; (goto-char (undo-tree-node-marker node))
&lt;br&gt;&amp;nbsp; (if undo-tree-visualizer-timestamps
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (progn
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (backward-char 4)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if current (undo-tree-insert ?*) (undo-tree-insert ? ))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-insert
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-timestamp-to-string (undo-tree-node-timestamp node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (backward-char 5)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (move-marker (undo-tree-node-marker node) (point))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (put-text-property (- (point) 3) (+ (point) 5)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;'undo-tree-node node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (if current (undo-tree-insert ?x) (undo-tree-insert ?o))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (backward-char 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (put-text-property (point) (1+ (point)) 'undo-tree-node node)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-draw-subtree (node &amp;optional active-branch)
&lt;br&gt;&amp;nbsp; ;; Draw subtree rooted at NODE. The subtree will start from point.
&lt;br&gt;&amp;nbsp; ;; If ACTIVE-BRANCH is non-nil, just draw active branch below NODE.
&lt;br&gt;&amp;nbsp; ;; If TIMESTAP is non-nil, draw time-stamps instead of &amp;quot;o&amp;quot; at nodes.
&lt;br&gt;&amp;nbsp; (let ((num-children (length (undo-tree-node-next node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; node-list pos trunk-pos n)
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; draw node itself
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-draw-node node)
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; (cond
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;;; if we're at a leaf node, we're done
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;((= num-children 0))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;;; if node has only one child, draw it (not strictly necessary to deal
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;;; with this case separately, but as it's by far the most common case
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;;; this makes the code clearer and more efficient)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;((= num-children 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-insert ?|)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (backward-char 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-insert ?|)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (backward-char 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq n (car (undo-tree-node-next node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; link next node to its representation in visualizer
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (unless (markerp (undo-tree-node-marker n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-marker n) (make-marker))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (set-marker-insertion-type (undo-tree-node-marker n) nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (move-marker (undo-tree-node-marker n) (point))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; add next node to list of nodes to draw next
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (push n node-list))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;;; if node had multiple children, draw branches
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(t
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-insert ?|)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (backward-char 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq trunk-pos (point))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; left subtrees
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (backward-char
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(- (undo-tree-node-char-lwidth node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-char-lwidth
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(car (undo-tree-node-next node)))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq pos (point))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq n (cons nil (undo-tree-node-next node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (dotimes (i (/ num-children 2))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq n (cdr n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (when (or (null active-branch)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (eq (car n)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (nth (undo-tree-node-branch node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-node-next node))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-forward 2)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-insert ?_ (- trunk-pos pos 2))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char pos)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-forward 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-insert ?/)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (backward-char 2)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; link node to its representation in visualizer
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (unless (markerp (undo-tree-node-marker (car n)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-marker (car n)) (make-marker))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (set-marker-insertion-type (undo-tree-node-marker (car n)) nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (move-marker (undo-tree-node-marker (car n)) (point))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; add node to list of nodes to draw next
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (push (car n) node-list))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char pos)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-forward
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(+ (undo-tree-node-char-rwidth (car n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-char-lwidth (cadr n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; undo-tree-visualizer-spacing 1))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq pos (point)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; middle subtree (only when number of children is odd)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (when (= (mod num-children 2) 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq n (cdr n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (when (or (null active-branch)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (eq (car n)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (nth (undo-tree-node-branch node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-node-next node))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-insert ?|)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (backward-char 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; link node to its representation in visualizer
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (unless (markerp (undo-tree-node-marker (car n)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-marker (car n)) (make-marker))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (set-marker-insertion-type (undo-tree-node-marker (car n)) nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (move-marker (undo-tree-node-marker (car n)) (point))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; add node to list of nodes to draw next
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (push (car n) node-list))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char pos)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-forward
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(+ (undo-tree-node-char-rwidth (car n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (cadr n) (undo-tree-node-char-lwidth (cadr n)) 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; undo-tree-visualizer-spacing 1))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq pos (point)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; right subtrees
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (incf trunk-pos)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (dotimes (i (/ num-children 2))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq n (cdr n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (when (or (null active-branch)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (eq (car n)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (nth (undo-tree-node-branch node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-node-next node))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char trunk-pos)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-insert ?_ (- pos trunk-pos 1))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char pos)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (backward-char 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-insert ?\\)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; link node to its representation in visualizer
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (unless (markerp (undo-tree-node-marker (car n)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-marker (car n)) (make-marker))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (set-marker-insertion-type (undo-tree-node-marker (car n)) nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (move-marker (undo-tree-node-marker (car n)) (point))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; add node to list of nodes to draw next
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (push (car n) node-list))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (when (cdr n)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char pos)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-forward
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(+ (undo-tree-node-char-rwidth (car n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (cadr n) (undo-tree-node-char-lwidth (cadr n)) 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; undo-tree-visualizer-spacing 1))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq pos (point))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; return list of nodes to draw next
&lt;br&gt;&amp;nbsp; &amp;nbsp; (nreverse node-list)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-node-char-lwidth (node)
&lt;br&gt;&amp;nbsp; ;; Return left-width of NODE measured in characters.
&lt;br&gt;&amp;nbsp; (if (= (length (undo-tree-node-next node)) 0) 0
&lt;br&gt;&amp;nbsp; &amp;nbsp; (- (* (+ undo-tree-visualizer-spacing 1) (undo-tree-node-lwidth node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(if (= (undo-tree-node-cwidth node) 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(1+ (/ undo-tree-visualizer-spacing 2)) 0))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-node-char-rwidth (node)
&lt;br&gt;&amp;nbsp; ;; Return right-width of NODE measured in characters.
&lt;br&gt;&amp;nbsp; (if (= (length (undo-tree-node-next node)) 0) 0
&lt;br&gt;&amp;nbsp; &amp;nbsp; (- (* (+ undo-tree-visualizer-spacing 1) (undo-tree-node-rwidth node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(if (= (undo-tree-node-cwidth node) 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(1+ (/ undo-tree-visualizer-spacing 2)) 0))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-insert (str &amp;optional arg)
&lt;br&gt;&amp;nbsp; ;; Insert character or string STR ARG times, overwriting, and using
&lt;br&gt;&amp;nbsp; ;; `undo-tree-insert-face'.
&lt;br&gt;&amp;nbsp; (unless arg (setq arg 1))
&lt;br&gt;&amp;nbsp; (when (characterp str)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq str (make-string arg str))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq arg 1))
&lt;br&gt;&amp;nbsp; (dotimes (i arg) (insert str))
&lt;br&gt;&amp;nbsp; (setq arg (* arg (length str)))
&lt;br&gt;&amp;nbsp; (undo-tree-move-forward arg)
&lt;br&gt;&amp;nbsp; (backward-delete-char arg)
&lt;br&gt;&amp;nbsp; (when (boundp 'undo-tree-insert-face)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (put-text-property (- (point) arg) (point) 'face undo-tree-insert-face)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-move-down (&amp;optional arg)
&lt;br&gt;&amp;nbsp; ;; Move down, extending buffer if necessary.
&lt;br&gt;&amp;nbsp; (let ((row (line-number-at-pos))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (col (current-column))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; line)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (unless arg (setq arg 1))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (forward-line arg)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq line (line-number-at-pos))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; if buffer doesn't have enough lines, add some
&lt;br&gt;&amp;nbsp; &amp;nbsp; (when (/= line (+ row arg))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (insert (make-string (- arg (- line row)) ?\n)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-move-forward col)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-move-forward (&amp;optional arg)
&lt;br&gt;&amp;nbsp; ;; Move forward, extending buffer if necessary.
&lt;br&gt;&amp;nbsp; (unless arg (setq arg 1))
&lt;br&gt;&amp;nbsp; (let ((n (- (line-end-position) (point))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (if (&amp;gt; n arg)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (forward-char arg)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (end-of-line)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (insert (make-string (- arg n) ? )))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-timestamp-to-string (timestamp)
&lt;br&gt;&amp;nbsp; ;; Convert TIMESTAMP to hh:mm:ss string.
&lt;br&gt;&amp;nbsp; (let ((time (decode-time timestamp)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (format &amp;quot;%02d:%02d:%02d&amp;quot; (nth 2 time) (nth 1 time) (nth 0 time))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; =====================================================================
&lt;br&gt;;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Visualizer mode commands
&lt;br&gt;&lt;br&gt;(defun undo-tree-visualizer-mode ()
&lt;br&gt;&amp;nbsp; &amp;quot;Major mode used in undo-tree visualizer.
&lt;br&gt;&lt;br&gt;The undo-tree visualizer can only be invoked from a buffer in
&lt;br&gt;which `undo-tree-mode' is enabled. The visualizer displays the
&lt;br&gt;undo history tree graphically, and allows you to browse around
&lt;br&gt;the undo history, undoing or redoing the corresponding changes in
&lt;br&gt;the parent buffer.
&lt;br&gt;&lt;br&gt;Within the undo-tree visualizer, the following keys are available:
&lt;br&gt;&lt;br&gt;&amp;nbsp; \\{undo-tree-visualizer-map}&amp;quot;
&lt;br&gt;&amp;nbsp; (kill-all-local-variables)
&lt;br&gt;&amp;nbsp; (setq major-mode 'undo-tree-visualizer-mode)
&lt;br&gt;&amp;nbsp; (setq mode-name &amp;quot;undo-tree-visualizer-mode&amp;quot;)
&lt;br&gt;&amp;nbsp; (use-local-map undo-tree-visualizer-map)
&lt;br&gt;&amp;nbsp; (setq truncate-lines t)
&lt;br&gt;&amp;nbsp; (setq buffer-read-only t))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-visualize-undo (&amp;optional arg)
&lt;br&gt;&amp;nbsp; &amp;quot;Undo changes. A numeric ARG serves as a repeat count.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;p&amp;quot;)
&lt;br&gt;&amp;nbsp; (setq buffer-read-only nil)
&lt;br&gt;&amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-active-branch-face))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-draw-node (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; (switch-to-buffer-other-window undo-tree-visualizer-buffer)
&lt;br&gt;&amp;nbsp; (unwind-protect
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-undo arg)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (switch-to-buffer-other-window &amp;quot; *undo-tree*&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-current-face))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-draw-node (undo-tree-current buffer-undo-tree) 'current))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq buffer-read-only t)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-visualize-redo (&amp;optional arg)
&lt;br&gt;&amp;nbsp; &amp;quot;Redo changes. A numeric ARG serves as a repeat count.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;p&amp;quot;)
&lt;br&gt;&amp;nbsp; (setq buffer-read-only nil)
&lt;br&gt;&amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-active-branch-face))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-draw-node (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; (switch-to-buffer-other-window undo-tree-visualizer-buffer)
&lt;br&gt;&amp;nbsp; (unwind-protect
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-redo arg)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (switch-to-buffer-other-window &amp;quot; *undo-tree*&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (goto-char (undo-tree-node-marker (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-current-face))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-draw-node (undo-tree-current buffer-undo-tree) 'current))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq buffer-read-only t)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-visualize-switch-next-branch (arg)
&lt;br&gt;&amp;nbsp; &amp;quot;Switch to next branch of the undo tree.
&lt;br&gt;This will affect which branch to descend when *redoing* changes
&lt;br&gt;using `undo-tree-redo' or `undo-tree-visualizer-redo'.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;p&amp;quot;)
&lt;br&gt;&amp;nbsp; ;; un-highlight old active branch below current node
&lt;br&gt;&amp;nbsp; (setq buffer-read-only nil)
&lt;br&gt;&amp;nbsp; (goto-char (undo-tree-node-marker (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-default-face))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-highlight-active-branch (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; ;; increment branch
&lt;br&gt;&amp;nbsp; (let ((branch (undo-tree-node-branch (undo-tree-current buffer-undo-tree))))
&lt;br&gt;&amp;nbsp; (setf (undo-tree-node-branch (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (cond
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;((&amp;gt;= (+ branch arg) (undo-tree-num-branches))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (1- (undo-tree-num-branches)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;((&amp;lt;= (+ branch arg) 0) 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(t (+ branch arg))))
&lt;br&gt;&amp;nbsp; ;; highlight new active branch below current node
&lt;br&gt;&amp;nbsp; (goto-char (undo-tree-node-marker (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-active-branch-face))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-highlight-active-branch (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; ;; re-highlight current node
&lt;br&gt;&amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-current-face))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-draw-node (undo-tree-current buffer-undo-tree) 'current))
&lt;br&gt;&amp;nbsp; (setq buffer-read-only t)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-visualize-switch-previous-branch (arg)
&lt;br&gt;&amp;nbsp; &amp;quot;Switch to previous branch of the undo tree.
&lt;br&gt;This will affect which branch to descend when *redoing* changes
&lt;br&gt;using `undo-tree-redo' or `undo-tree-visualizer-redo'.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;p&amp;quot;)
&lt;br&gt;&amp;nbsp; (undo-tree-visualize-switch-next-branch (- arg)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-visualizer-quit ()
&lt;br&gt;&amp;nbsp; &amp;quot;Quit the undo-tree visualizer.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive)
&lt;br&gt;&amp;nbsp; (undo-tree-clear-visualizer-data buffer-undo-tree)
&lt;br&gt;&amp;nbsp; (kill-buffer-and-window))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-visualizer-set (pos)
&lt;br&gt;&amp;nbsp; &amp;quot;Set buffer to state corresponding to undo tree node
&lt;br&gt;at POS.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;@e&amp;quot;)
&lt;br&gt;&amp;nbsp; (setq pos (event-start (nth 1 pos)))
&lt;br&gt;&amp;nbsp; (let ((node (get-text-property pos 'undo-tree-node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (when node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; set parent buffer to state corresponding to node at POS
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (set-buffer undo-tree-visualizer-buffer)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-set node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (set-buffer &amp;quot; *undo-tree*&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-read-only nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; re-draw undo tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-draw-tree buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-read-only t))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-visualizer-toggle-timestamps ()
&lt;br&gt;&amp;nbsp; &amp;quot;Toggle display of time-stamps.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive)
&lt;br&gt;&amp;nbsp; (setq undo-tree-visualizer-spacing
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (setq undo-tree-visualizer-timestamps
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (not undo-tree-visualizer-timestamps))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; need sufficient space if TIMESTAMP is set
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (max 9 (default-value 'undo-tree-visualizer-spacing))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (default-value 'undo-tree-visualizer-spacing)))
&lt;br&gt;&amp;nbsp; ;; redraw tree
&lt;br&gt;&amp;nbsp; (setq buffer-read-only nil)
&lt;br&gt;&amp;nbsp; (undo-tree-draw-tree buffer-undo-tree)
&lt;br&gt;&amp;nbsp; (setq buffer-read-only t))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-visualizer-scroll-left (&amp;optional arg)
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;p&amp;quot;)
&lt;br&gt;&amp;nbsp; (scroll-right (or arg 1) t))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-visualizer-scroll-right (&amp;optional arg)
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;p&amp;quot;)
&lt;br&gt;&amp;nbsp; (scroll-left (or arg 1) t))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(provide 'undo-tree)
&lt;br&gt;&lt;br&gt;;;; undo-tree.el ends here
&lt;br&gt;&lt;br /&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26559143&amp;i=1&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/undo-tree.el-tp26554347p26559143.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-26557169</id>
	<title>Re: undo-tree.el</title>
	<published>2009-11-28T13:39:16Z</published>
	<updated>2009-11-28T13:39:16Z</updated>
	<author>
		<name>Samuel Wales</name>
	</author>
	<content type="html">Hi Toby,
&lt;br&gt;&lt;br&gt;This package addresses all of my undo concerns! &amp;nbsp;(I recently posted a
&lt;br&gt;slightly humorous explanation at
&lt;br&gt;&lt;a href=&quot;http://groups.google.com/group/gnu.emacs.help/msg/b802df52522533f8&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://groups.google.com/group/gnu.emacs.help/msg/b802df52522533f8&lt;/a&gt;&amp;nbsp;.)
&lt;br&gt;I would be delighted if it were integrated into emacs!
&lt;br&gt;&lt;br&gt;FWIW, I found that characterp was not a function in Carbon Emacs
&lt;br&gt;22.2.1 . &amp;nbsp;I replaced it with char-valid-p. &amp;nbsp;Don't know if that's the
&lt;br&gt;same.
&lt;br&gt;&lt;br&gt;One type of information that would be good to store (but standard undo
&lt;br&gt;does not store it) is visibility. &amp;nbsp;If you are in org-mode, and you
&lt;br&gt;undo, you want the folding state of subtrees to be as it was, else you
&lt;br&gt;can undo stuff that is hidden etc. &amp;nbsp;I wonder if that is possible, or,
&lt;br&gt;if not, if Emacs can be made to support it for your package.
&lt;br&gt;&lt;br&gt;I would recommend making the visualization mode respect
&lt;br&gt;pop-up-windows, as currently it opens a new window even when that
&lt;br&gt;variable is nil. &amp;nbsp;It is difficult for the user to make the mode appear
&lt;br&gt;in the current window without modifying your code.
&lt;br&gt;&lt;br&gt;Mode help would be useful for that mode.
&lt;br&gt;&lt;br&gt;In that mode, up arrow for me caused &amp;quot;undo-tree-current accessing a
&lt;br&gt;non-undo-tree&amp;quot;. &amp;nbsp;The buffer's mode changed to Fundamental and the
&lt;br&gt;visualization disappeared.
&lt;br&gt;&lt;br&gt;Do you know whether org-mode uses markers in a way that would require
&lt;br&gt;it to restore them? &amp;nbsp;I know that it does use markers.
&lt;br&gt;&lt;br&gt;I will start using it all the time now and report any bugs directly to you.
&lt;br&gt;&lt;br&gt;Thanks!
&lt;br&gt;&lt;br&gt;&lt;br&gt;Samuel
&lt;br&gt;&lt;br&gt;&lt;br&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26557169&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/undo-tree.el-tp26554347p26557169.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-26556036</id>
	<title>Re: undo-tree.el</title>
	<published>2009-11-28T11:09:08Z</published>
	<updated>2009-11-28T11:09:08Z</updated>
	<author>
		<name>Stefan Monnier</name>
	</author>
	<content type="html">I like it and would be interested in integrating something along these
&lt;br&gt;lines into Emacs, but it would need to be integrated with the existing
&lt;br&gt;undo system.
&lt;br&gt;If you look at the implementation of undo-only, you'll see that the
&lt;br&gt;undo-equiv-table gives at least a large part of the data that is
&lt;br&gt;necessary to turn the linear undo-list into a tree. &amp;nbsp;If more is needed,
&lt;br&gt;we can probably cook something up for it.
&lt;br&gt;&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Stefan
&lt;br&gt;&lt;br&gt;&lt;br&gt;PS: Along the same lines, it would be neat to hook your completion-ui
&lt;br&gt;work into the new completion-in-region-functions.
&lt;br&gt;&lt;br&gt;&lt;br&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26556036&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/undo-tree.el-tp26554347p26556036.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-26554347</id>
	<title>undo-tree.el</title>
	<published>2009-11-28T07:51:06Z</published>
	<updated>2009-11-28T07:51:06Z</updated>
	<author>
		<name>Toby Cubitt-5</name>
	</author>
	<content type="html">&lt;br&gt;--
&lt;br&gt;Dr T. S. Cubitt
&lt;br&gt;Quantum Information Theory group
&lt;br&gt;Department of Mathematics
&lt;br&gt;University of Bristol
&lt;br&gt;United Kingdom
&lt;br&gt;&lt;br&gt;email: &lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26554347&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;tsc25@...&lt;/a&gt;
&lt;br&gt;web: www.dr-qubit.org
&lt;br&gt;&lt;br /&gt;&lt;br&gt;;;; undo-tree.el --- Treat undo history as a tree
&lt;br&gt;&lt;br&gt;&lt;br&gt;;; Copyright (C) 2009 Toby Cubitt
&lt;br&gt;&lt;br&gt;;; Author: Toby Cubitt &amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26554347&amp;i=1&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;toby-undo-tree@...&lt;/a&gt;&amp;gt;
&lt;br&gt;;; Version: 0.1
&lt;br&gt;;; Keywords: undo, redo, history, tree
&lt;br&gt;;; URL: &lt;a href=&quot;http://www.dr-qubit.org/emacs.php&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.dr-qubit.org/emacs.php&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;;; This file is NOT part of Emacs.
&lt;br&gt;;;
&lt;br&gt;;; GNU Emacs is free software: you can redistribute it and/or modify it under
&lt;br&gt;;; the terms of the GNU General Public License as published by the Free
&lt;br&gt;;; Software Foundation, either version 3 of the License, or (at your option)
&lt;br&gt;;; any later version.
&lt;br&gt;&lt;br&gt;;; This program is distributed in the hope that it will be useful, but WITHOUT
&lt;br&gt;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
&lt;br&gt;;; FITNESS FOR A PARTICULAR PURPOSE. &amp;nbsp;See the GNU General Public License for
&lt;br&gt;;; more details.
&lt;br&gt;&lt;br&gt;;; You should have received a copy of the GNU General Public License along
&lt;br&gt;;; with GNU Emacs. If not, see &amp;lt;&lt;a href=&quot;http://www.gnu.org/licenses/&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.gnu.org/licenses/&lt;/a&gt;&amp;gt;.
&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; Commentary:
&lt;br&gt;;;
&lt;br&gt;;; Emacs has a powerful undo system. Unlike the standard undo/redo system in
&lt;br&gt;;; most software, it allows you to recover *any* past state of a buffer
&lt;br&gt;;; (whereas the standard undo/redo system can lose past states as soon as you
&lt;br&gt;;; redo). However, this power comes at a price: many people find Emacs' undo
&lt;br&gt;;; system confusing and difficult to use, spawning a number of packages that
&lt;br&gt;;; replace it with the less powerful but more intuitive undo/redo system.
&lt;br&gt;;;
&lt;br&gt;;; Both the loss of data with standard undo/redo, and the confusion of Emacs'
&lt;br&gt;;; undo, stem from trying to treat undo history as a linear sequence of
&lt;br&gt;;; changes. It's not. The `undo-tree-mode' provided by this package replaces
&lt;br&gt;;; Emacs' undo system with a system that treats undo history as what it is: a
&lt;br&gt;;; branching tree of changes. This simple idea allows the more intuitive
&lt;br&gt;;; behaviour of the standard undo/redo system to be combined with the power of
&lt;br&gt;;; never losing any history. An added side bonus is that undo history can in
&lt;br&gt;;; some cases be stored more efficiently, allowing more changes to accumulate
&lt;br&gt;;; before Emacs starts discarding history.
&lt;br&gt;;;
&lt;br&gt;;; The only downside to this more advanced yet simpler undo system is that it
&lt;br&gt;;; was inspired by Vim. But, after all, most successful religions steal the
&lt;br&gt;;; best ideas from their competitors!
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;; Installation
&lt;br&gt;;; ============
&lt;br&gt;;;
&lt;br&gt;;; To install `undo-tree-mode', make sure this file is saved in a directory in
&lt;br&gt;;; your `load-path', and add the line:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; (require 'undo-tree)
&lt;br&gt;;;
&lt;br&gt;;; to your .emacs file.
&lt;br&gt;;;
&lt;br&gt;;; If you want to replace the standard Emacs' undo system with the
&lt;br&gt;;; `undo-tree-mode' system in all buffers, you can enable it globally by
&lt;br&gt;;; adding:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; (global-undo-tree-mode)
&lt;br&gt;;;
&lt;br&gt;;; to your .emacs file.
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;; Quick-Start
&lt;br&gt;;; ===========
&lt;br&gt;;;
&lt;br&gt;;; If you're the kind of person who likes jump in the car and drive, without
&lt;br&gt;;; bothering to first figure out whether the button on the left dips the
&lt;br&gt;;; headlights or operates the ejector seat (after all, you'll soon figure it
&lt;br&gt;;; out when you push it), then here's the minimum you need to know:
&lt;br&gt;;;
&lt;br&gt;;; `undo-tree-mode' and `global-undo-tree-mode'
&lt;br&gt;;; &amp;nbsp; Enable undo-tree mode (either in the current buffer or globally).
&lt;br&gt;;;
&lt;br&gt;;; C-_ &amp;nbsp;C-/ &amp;nbsp;(`undo-tree-undo')
&lt;br&gt;;; &amp;nbsp; Undo changes.
&lt;br&gt;;;
&lt;br&gt;;; C-+ &amp;nbsp;C-? &amp;nbsp;(`undo-tree-redo')
&lt;br&gt;;; &amp;nbsp; Redo changes.
&lt;br&gt;;;
&lt;br&gt;;; `undo-tree-switch-branch'
&lt;br&gt;;; &amp;nbsp; Switch undo-tree branch.
&lt;br&gt;;; &amp;nbsp; (What does this mean? Better press the button and see!)
&lt;br&gt;;;
&lt;br&gt;;; C-x u &amp;nbsp;(`undo-tree-visualize')
&lt;br&gt;;; &amp;nbsp; Visualize the undo tree.
&lt;br&gt;;; &amp;nbsp; (Better try pressing this button too!)
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;; In the undo visualizer:
&lt;br&gt;;;
&lt;br&gt;;; &amp;lt;up&amp;gt; &amp;nbsp;p &amp;nbsp;C-p &amp;nbsp;(`undo-tree-visualize-undo')
&lt;br&gt;;; &amp;nbsp; Undo changes.
&lt;br&gt;;;
&lt;br&gt;;; &amp;lt;down&amp;gt; &amp;nbsp;n &amp;nbsp;C-n &amp;nbsp;(`undo-tree-visualize-undo')
&lt;br&gt;;; &amp;nbsp; Undo changes.
&lt;br&gt;;;
&lt;br&gt;;; &amp;lt;left&amp;gt; &amp;nbsp;b &amp;nbsp;C-b &amp;nbsp;(`undo-tree-visualize-switch-previous-branch')
&lt;br&gt;;; &amp;nbsp; Switch to previous undo-tree branch.
&lt;br&gt;;;
&lt;br&gt;;; &amp;lt;right&amp;gt; &amp;nbsp;f &amp;nbsp;C-f &amp;nbsp;(`undo-tree-visualize-switch-next-branch')
&lt;br&gt;;; &amp;nbsp; Switch to next undo-tree branch.
&lt;br&gt;;;
&lt;br&gt;;; t &amp;nbsp;(`undo-tree-visualizer-toggle-timestamps')
&lt;br&gt;;; &amp;nbsp; Toggle display of time-stamps.
&lt;br&gt;;;
&lt;br&gt;;; q &amp;nbsp;C-q &amp;nbsp;(`undo-tree-visualizer-quit')
&lt;br&gt;;; &amp;nbsp; Quit undo-tree-visualizer.
&lt;br&gt;;;
&lt;br&gt;;; , &amp;nbsp;&amp;lt;
&lt;br&gt;;; &amp;nbsp; Scroll left.
&lt;br&gt;;;
&lt;br&gt;;; . &amp;nbsp;&amp;gt;
&lt;br&gt;;; &amp;nbsp; Scroll right.
&lt;br&gt;;;
&lt;br&gt;;; &amp;lt;pgup&amp;gt;
&lt;br&gt;;; &amp;nbsp; Scroll up.
&lt;br&gt;;;
&lt;br&gt;;; &amp;lt;pgdown&amp;gt;
&lt;br&gt;;; &amp;nbsp; Scroll down.
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;; Explanation
&lt;br&gt;;; ===========
&lt;br&gt;;;
&lt;br&gt;;; To understand the different undo systems, it's easiest to consider an
&lt;br&gt;;; example. Imagine you make a few edits in a buffer. As you edit, you
&lt;br&gt;;; accumulate a history of changes, which we might visualize as a string of
&lt;br&gt;;; past buffer states, growing downwards:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(initial buffer state)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(first edit)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(second edit)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;x &amp;nbsp;(current buffer state)
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;; Now imagine that you undo the last two changes. We can visualize this as
&lt;br&gt;;; rewinding the current state back two steps:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(initial buffer state)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;x &amp;nbsp;(current buffer state)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;; However, this isn't a good representation of what Emacs' undo system
&lt;br&gt;;; does. Instead, it treats the undos as *new* changes to the buffer, and adds
&lt;br&gt;;; them to the history:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(initial buffer state)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(first edit)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(second edit)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;x &amp;nbsp;(buffer state before undo)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(first undo)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;x &amp;nbsp;(second undo)
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;; Actually, since the buffer returns to a previous state after an undo, a
&lt;br&gt;;; better way to visualize it is to imagine the string of changes turning back
&lt;br&gt;;; on itself:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(initial buffer state) &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(first edit) &amp;nbsp;o &amp;nbsp;x &amp;nbsp;(second undo)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (second edit) &amp;nbsp;o &amp;nbsp;o &amp;nbsp;(first undo)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| /
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|/
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(buffer state before undo)
&lt;br&gt;;;
&lt;br&gt;;; Treating undos as new changes might seem a strange thing to do. But the
&lt;br&gt;;; advantage becomes clear as soon as we imagine what happens when you edit
&lt;br&gt;;; the buffer again. Since you've undone a couple of changes, new edits will
&lt;br&gt;;; branch off from the buffer state that you've rewound to. Conceptually, it
&lt;br&gt;;; looks like this:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(initial buffer state)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|\
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;x &amp;nbsp;(new edit)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;;
&lt;br&gt;;; The standard undo/redo system only lets you go backwards and forwards
&lt;br&gt;;; linearly. So as soon as you make that new edit, it discards the old
&lt;br&gt;;; branch. Emacs' undo just keeps adding changes to the end of the string. So
&lt;br&gt;;; the undo history in the two systems now looks like this:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Undo/Redo: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Emacs' undo
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .\ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp;|\
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; . \ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| &amp;nbsp;| \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; . &amp;nbsp;x &amp;nbsp;(new edit) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp;o &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; (discarded &amp;nbsp;. &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| / &amp;nbsp; |
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; branch) &amp;nbsp; . &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|/ &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; . &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp; &amp;nbsp; |
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;x &amp;nbsp;(new edit)
&lt;br&gt;;;
&lt;br&gt;;; Now, what if you change your mind about those undos, and decide you did
&lt;br&gt;;; like those other changes you'd made after all? With the standard undo/redo
&lt;br&gt;;; system, you're stuck. There's no way to recover them, because that branch
&lt;br&gt;;; was discarded when you made the new edit.
&lt;br&gt;;;
&lt;br&gt;;; However, in Emacs' undo system, those old buffer states are still there in
&lt;br&gt;;; the undo history. You just have to rewind back through the new edit, and
&lt;br&gt;;; back through the changes made by the undos, until you reach them. Of
&lt;br&gt;;; course, since Emacs treats undos (even undos of undos!) as new changes,
&lt;br&gt;;; you're really weaving backwards and forwards through the history, all the
&lt;br&gt;;; time adding new changes to the end of the string as you go:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp;o &amp;nbsp; &amp;nbsp; o &amp;nbsp;(undo new edit)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp;|\ &amp;nbsp; &amp;nbsp;|\
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp;| \ &amp;nbsp; | \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp;o &amp;nbsp;| &amp;nbsp;| &amp;nbsp;o &amp;nbsp;(undo the undo)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | / &amp;nbsp; | &amp;nbsp;| &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |/ &amp;nbsp; &amp;nbsp;| &amp;nbsp;| &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp;(trying to get &amp;nbsp; o &amp;nbsp; &amp;nbsp; | &amp;nbsp;| &amp;nbsp;x &amp;nbsp;(undo the undo)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; to this state) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| /
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |/
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o
&lt;br&gt;;;
&lt;br&gt;;; So far, this is still reasonably intuitive to use. It doesn't behave so
&lt;br&gt;;; differently to standard undo/redo, except that by going back far enough you
&lt;br&gt;;; can access changes that would be lost in standard undo/redo.
&lt;br&gt;;;
&lt;br&gt;;; However, imagine that after undoing as just described, you decide you
&lt;br&gt;;; actually want to rewind right back to the initial state. If you're lucky,
&lt;br&gt;;; and haven't invoked any command since the last undo, you can just keep on
&lt;br&gt;;; undoing until you get back to the start:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp;(trying to get &amp;nbsp; o &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;x &amp;nbsp;(got there!)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; to this state) &amp;nbsp;| &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp;o &amp;nbsp; &amp;nbsp; o &amp;nbsp; &amp;nbsp; o &amp;nbsp;(keep undoing)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp;|\ &amp;nbsp; &amp;nbsp;|\ &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp;| \ &amp;nbsp; | \ &amp;nbsp; |
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp;o &amp;nbsp;| &amp;nbsp;| &amp;nbsp;o &amp;nbsp;o &amp;nbsp;(keep undoing)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | / &amp;nbsp; | &amp;nbsp;| &amp;nbsp;| /
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |/ &amp;nbsp; &amp;nbsp;| &amp;nbsp;| &amp;nbsp;|/
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp;(already undid &amp;nbsp; o &amp;nbsp; &amp;nbsp; | &amp;nbsp;| &amp;nbsp;o &amp;nbsp;(got this far)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; to this state) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| /
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |/
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o
&lt;br&gt;;;
&lt;br&gt;;; But if you're unlucky, you happen to have moved the point (say) after
&lt;br&gt;;; getting to the point labelled &amp;quot;got this far&amp;quot;. In that case, you've &amp;quot;broken
&lt;br&gt;;; the undo chain&amp;quot;. If you try to undo now, Emacs thinks you're trying to undo
&lt;br&gt;;; the undos! So to get back to the initial state you now have to rewind
&lt;br&gt;;; through *all* the changes, including the undos you just did:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp;(trying to get &amp;nbsp; o &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;x &amp;nbsp;(finally got there!)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; to this state) &amp;nbsp;| &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp;o &amp;nbsp; &amp;nbsp; o &amp;nbsp; &amp;nbsp; o &amp;nbsp; &amp;nbsp; o &amp;nbsp; &amp;nbsp; o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp;|\ &amp;nbsp; &amp;nbsp;|\ &amp;nbsp; &amp;nbsp;|\ &amp;nbsp; &amp;nbsp;|\ &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;nbsp;| \ &amp;nbsp; | \ &amp;nbsp; | \ &amp;nbsp; | \ &amp;nbsp; |
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp;o &amp;nbsp;| &amp;nbsp;| &amp;nbsp;o &amp;nbsp;o &amp;nbsp;o &amp;nbsp;| &amp;nbsp;o &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | / &amp;nbsp; | &amp;nbsp;| &amp;nbsp;| / &amp;nbsp; | &amp;nbsp;| &amp;nbsp;| /
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |/ &amp;nbsp; &amp;nbsp;| &amp;nbsp;| &amp;nbsp;|/ &amp;nbsp; &amp;nbsp;| &amp;nbsp;| &amp;nbsp;|/
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp;(already undid &amp;nbsp; o &amp;nbsp; &amp;nbsp; | &amp;nbsp;| &amp;nbsp;o&amp;lt;. &amp;nbsp; | &amp;nbsp;| &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; to this state) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| / &amp;nbsp; &amp;nbsp; : &amp;nbsp; | /
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |/ &amp;nbsp; &amp;nbsp; &amp;nbsp;: &amp;nbsp; |/
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp; &amp;nbsp; &amp;nbsp; : &amp;nbsp; o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; :
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (got this far, but
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;broke undo chain)
&lt;br&gt;;;
&lt;br&gt;;; Confused?
&lt;br&gt;;;
&lt;br&gt;;; In practice you can just hold down the undo key until you reach the buffer
&lt;br&gt;;; state that you want. But whatever you do, don't move around in the buffer
&lt;br&gt;;; to check you've got back to where you want! Because you'll break the undo
&lt;br&gt;;; chain, and then you'll have to traverse the entire string of undos again to
&lt;br&gt;;; get back to the point at which you broke the chain. Commands such as
&lt;br&gt;;; `undo-only', and undo in region (in transient-mark-mode), help to make
&lt;br&gt;;; using Emacs' undo a little easier, but nonetheless it remains confusing for
&lt;br&gt;;; many people.
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;; So what does undo-tree mode do? Remember the diagram we drew to represent
&lt;br&gt;;; the history we've been discussing (make a few edits, undo a couple of them,
&lt;br&gt;;; and edit again)? The diagram that conceptually represented our undo
&lt;br&gt;;; history, before we started discussing specific undo systems? It looked like
&lt;br&gt;;; this:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(initial buffer state)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|\
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;x &amp;nbsp;(current state)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;;
&lt;br&gt;;; Well, that's *exactly* what the undo history looks like to
&lt;br&gt;;; `undo-tree-mode'. &amp;nbsp;It doesn't discard the old branch (as standard undo/redo
&lt;br&gt;;; does), nor does it treat undos as new changes to be added to the end of a
&lt;br&gt;;; linear string of buffer states (as Emacs' undo does). It just keeps track
&lt;br&gt;;; of the tree of branching changes that make up the entire undo history.
&lt;br&gt;;;
&lt;br&gt;;; If you undo from this point, you'll rewind back up the tree to the previous
&lt;br&gt;;; state:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;x &amp;nbsp;(undo)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|\
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;;
&lt;br&gt;;; If you were to undo again, you'd rewind back to the initial state. If on
&lt;br&gt;;; the other hand you redo the change, you'll end up back at the bottom of the
&lt;br&gt;;; most recent branch:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(start here)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|\
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;x &amp;nbsp;(redo)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;;
&lt;br&gt;;; So far, this is just like the standard undo/redo system. But what if you
&lt;br&gt;;; want to return to a buffer state located on a previous branch of the
&lt;br&gt;;; history? Since `undo-tree-mode' keeps the entire history, you simply need
&lt;br&gt;;; to tell it to switch to a different branch, and then redo the changes you
&lt;br&gt;;; want:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp;(start here, but switch
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|\ &amp;nbsp;to the other branch)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(redo) &amp;nbsp;o &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(redo) &amp;nbsp;x
&lt;br&gt;;;
&lt;br&gt;;; Now you're on the other branch, and if you undo and redo changes you'll
&lt;br&gt;;; stay on that branch, moving up and down through the buffer states located
&lt;br&gt;;; on that branch. Until you decide to switch branches again, of course.
&lt;br&gt;;;
&lt;br&gt;;; Real undo trees might have multiple branches and sub-branches:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;____|______
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; / &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;____|__ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; __|
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; / &amp;nbsp; &amp;nbsp;| &amp;nbsp;\ &amp;nbsp; &amp;nbsp; &amp;nbsp; / &amp;nbsp; \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp; &amp;nbsp; o &amp;nbsp; o &amp;nbsp; &amp;nbsp; o &amp;nbsp; &amp;nbsp; x
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;| &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; / \ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; / \
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;o &amp;nbsp; o &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; o &amp;nbsp; o
&lt;br&gt;;;
&lt;br&gt;;; Trying to imagine what Emacs' undo would do as you move about such a tree
&lt;br&gt;;; will likely frazzle your brain circuits! But in `undo-tree-mode', you're
&lt;br&gt;;; just moving around this undo history tree. Most of the time, you'll
&lt;br&gt;;; probably only need to stay on the most recent branch, in which case it
&lt;br&gt;;; behaves like standard undo/redo, so is just as simple to understand. But if
&lt;br&gt;;; you ever need to recover a buffer state on a different branch, the
&lt;br&gt;;; possibility of switching between branches and accessing the full undo
&lt;br&gt;;; history is still there.
&lt;br&gt;;;
&lt;br&gt;;; Actually, it gets better. You don't have to imagine all these diagrams,
&lt;br&gt;;; because `undo-tree-mode' includes an undo-tree visualizer which draws them
&lt;br&gt;;; for you! In fact, it draws even better diagrams: it highlights the node
&lt;br&gt;;; representing the current buffer state, it highlights the current branch,
&lt;br&gt;;; and it can optionally display time-stamps for each buffer state. (There's
&lt;br&gt;;; one other tiny difference: the visualizer puts the most recent branch on
&lt;br&gt;;; the left rather than the right.)
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;;
&lt;br&gt;;; Drawbacks
&lt;br&gt;;; =========
&lt;br&gt;;;
&lt;br&gt;;; Emacs' undo system is deeply embedded in Emacs. In particular, garbage
&lt;br&gt;;; collection treats the `buffer-undo-list' specially: references to markers
&lt;br&gt;;; in `buffer-undo-list' don't count during the mark phase, and the sweep
&lt;br&gt;;; phase removes undo entries for markers that have been garbage-collected.
&lt;br&gt;;; This behaviour is implemented in C as part of the garbage collection code,
&lt;br&gt;;; and it is difficult or impossible to emulate in Elisp.
&lt;br&gt;;;
&lt;br&gt;;; To avoid dead markers being resurrected in `undo-tree-mode', and to allow
&lt;br&gt;;; them to be garbage-collected, `undo-tree-mode' doesn't record marker
&lt;br&gt;;; adjustments. Markers are rarely explicitly created by users, so the impact
&lt;br&gt;;; of this will primarily be through its effects on other features that make
&lt;br&gt;;; use of markers. Since marker adjustments haven't always been restored by
&lt;br&gt;;; undo, and even then it was buggy until recently (see Emacs bug#4803), it
&lt;br&gt;;; seems likely that relatively little code relies heavily on correct marker
&lt;br&gt;;; restoration.
&lt;br&gt;;;
&lt;br&gt;;; `undo-tree-mode' doesn't support &amp;quot;undo in region&amp;quot;, i.e. selectively undoing
&lt;br&gt;;; only the changes that affect the current region in
&lt;br&gt;;; `transient-mark-mode'). Support for this is planned for a future version.
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; Change Log:
&lt;br&gt;;;
&lt;br&gt;;; Version 0.1
&lt;br&gt;;; * initial release
&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; Code:
&lt;br&gt;&lt;br&gt;;;; =====================================================================
&lt;br&gt;;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Global variables and customization options
&lt;br&gt;&lt;br&gt;(defvar buffer-undo-tree nil
&lt;br&gt;&amp;nbsp; &amp;quot;Tree of undo entries in current buffer.&amp;quot;)
&lt;br&gt;(make-variable-buffer-local 'buffer-undo-tree)
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defgroup undo-tree nil
&lt;br&gt;&amp;nbsp; &amp;quot;Tree undo/redo.&amp;quot;
&lt;br&gt;&amp;nbsp; :group 'undo)
&lt;br&gt;&lt;br&gt;(defcustom undo-tree-visualizer-spacing 3
&lt;br&gt;&amp;nbsp; &amp;quot;Horizontal spacing in undo-tree visualization.
&lt;br&gt;Must be a postivie odd integer.&amp;quot;
&lt;br&gt;&amp;nbsp; :group 'undo-tree
&lt;br&gt;&amp;nbsp; :type '(integer
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; :match (lambda (w n) (and (integerp n) (&amp;gt; n 0) (= (mod n 2) 1)))))
&lt;br&gt;(make-variable-buffer-local 'undo-tree-visualizer-spacing)
&lt;br&gt;&lt;br&gt;(defvar undo-tree-map nil
&lt;br&gt;&amp;nbsp; &amp;quot;Keymap used in undo-tree-mode.&amp;quot;)
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defface undo-tree-visualizer-default-face
&lt;br&gt;&amp;nbsp; '((((class color)) :foreground &amp;quot;gray&amp;quot;))
&lt;br&gt;&amp;nbsp; &amp;quot;*Face used to draw undo-tree in visualizer.&amp;quot;)
&lt;br&gt;&lt;br&gt;(defface undo-tree-visualizer-current-face
&lt;br&gt;&amp;nbsp; '((((class color)) :foreground &amp;quot;red&amp;quot;))
&lt;br&gt;&amp;nbsp; &amp;quot;*Face used to highlight current undo-tree node
&lt;br&gt;in visualizer.&amp;quot;)
&lt;br&gt;&lt;br&gt;(defface undo-tree-visualizer-active-branch-face
&lt;br&gt;&amp;nbsp; '((((class color)) :foreground &amp;quot;white&amp;quot; :weight bold))
&lt;br&gt;&amp;nbsp; &amp;quot;*Face used to highlight active undo-tree branch
&lt;br&gt;in visualizer.&amp;quot;)
&lt;br&gt;&lt;br&gt;(defvar undo-tree-visualizer-map nil
&lt;br&gt;&amp;nbsp; &amp;quot;Keymap used in undo-tree visualizer.&amp;quot;)
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defvar undo-tree-visualizer-buffer nil
&lt;br&gt;&amp;nbsp; &amp;quot;Parent buffer in visualizer.&amp;quot;)
&lt;br&gt;(make-variable-buffer-local 'undo-tree-visualizer-buffer)
&lt;br&gt;&lt;br&gt;(defvar undo-tree-visualizer-timestamps nil
&lt;br&gt;&amp;nbsp; &amp;quot;Non-nil when visualizer is displaying time-stamps.&amp;quot;)
&lt;br&gt;(make-variable-buffer-local 'undo-tree-visualizer-timestamps)
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; =================================================================
&lt;br&gt;;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Setup default keymaps
&lt;br&gt;&lt;br&gt;(unless undo-tree-map
&lt;br&gt;&amp;nbsp; (setq undo-tree-map (make-sparse-keymap))
&lt;br&gt;&amp;nbsp; ;; remap `undo' to `undo-tree-undo'
&lt;br&gt;&amp;nbsp; (define-key undo-tree-map [remap undo] 'undo-tree-undo)
&lt;br&gt;&amp;nbsp; ;; redo doesn't exist normally, so define out own keybindings
&lt;br&gt;&amp;nbsp; (define-key undo-tree-map (kbd &amp;quot;C-?&amp;quot;) 'undo-tree-redo)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-map (kbd &amp;quot;C-+&amp;quot;) 'undo-tree-redo)
&lt;br&gt;&amp;nbsp; ;; just in case something has defined it...
&lt;br&gt;&amp;nbsp; (define-key undo-tree-map [remap redo] 'undo-tree-redo)
&lt;br&gt;&amp;nbsp; ;; we use &amp;quot;C-x u&amp;quot; for the undo-tree visualizer
&lt;br&gt;&amp;nbsp; (define-key undo-tree-map (kbd &amp;quot;C-x u&amp;quot;) 'undo-tree-visualize))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(unless undo-tree-visualizer-map
&lt;br&gt;&amp;nbsp; (setq undo-tree-visualizer-map (make-keymap))
&lt;br&gt;&amp;nbsp; ;; vertical motion keys undo/redo
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map [up]
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-undo)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;p&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-undo)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;\C-p&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-undo)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map [down]
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-redo)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;n&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-redo)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;\C-n&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-redo)
&lt;br&gt;&amp;nbsp; ;; horizontal motion keys switch branch
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map [right]
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-switch-next-branch)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;f&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-switch-next-branch)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;\C-f&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-undo)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map [left]
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-switch-previous-branch)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;b&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-switch-previous-branch)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;\C-b&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualize-switch-previous-branch)
&lt;br&gt;&amp;nbsp; ;; mouse sets buffer state to node at click
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map [mouse-1]
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualizer-set)
&lt;br&gt;&amp;nbsp; ;; toggle timestamps
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;t&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualizer-toggle-timestamps)
&lt;br&gt;&amp;nbsp; ;; horizontal scrolling may be needed if tree is very wide
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;,&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualizer-scroll-left)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;.&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualizer-scroll-right)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;&amp;lt;&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualizer-scroll-left)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;&amp;gt;&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualizer-scroll-right)
&lt;br&gt;&amp;nbsp; ;; quit visualizer
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;q&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualizer-quit)
&lt;br&gt;&amp;nbsp; (define-key undo-tree-visualizer-map &amp;quot;\C-q&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; 'undo-tree-visualizer-quit))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; =====================================================================
&lt;br&gt;;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Undo-tree data structure
&lt;br&gt;&lt;br&gt;(defstruct
&lt;br&gt;&amp;nbsp; (undo-tree
&lt;br&gt;&amp;nbsp; &amp;nbsp;:named
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:constructor nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:constructor make-undo-tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(&amp;aux
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (root (make-undo-tree-node nil nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (current root)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (size 0)))
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:copier nil))
&lt;br&gt;&amp;nbsp; root current size)
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(defstruct
&lt;br&gt;&amp;nbsp; (undo-tree-node
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:type vector) &amp;nbsp; ; create unnamed struct
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:constructor nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:constructor make-undo-tree-node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(previous undo
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;aux
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (timestamp (current-time))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (branch 0)))
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:constructor make-undo-tree-node-backwards
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(next-node undo
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;aux
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (next (list next-node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (timestamp (current-time))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (branch 0)))
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:copier nil))
&lt;br&gt;&amp;nbsp; previous next undo redo timestamp branch visualizer)
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defmacro undo-tree-node-p (n)
&lt;br&gt;&amp;nbsp; (let ((len (length (make-undo-tree-node nil nil))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; `(and (vectorp ,n) (= (length ,n) ,len))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(defstruct
&lt;br&gt;&amp;nbsp; (undo-tree-visualizer-data
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:type vector) &amp;nbsp; ; create unnamed struct
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:constructor nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:constructor make-undo-tree-visualizer-data)
&lt;br&gt;&amp;nbsp; &amp;nbsp;(:copier nil))
&lt;br&gt;&amp;nbsp; lwidth cwidth rwidth marker)
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defmacro undo-tree-visualizer-data-p (v)
&lt;br&gt;&amp;nbsp; (let ((len (length (make-undo-tree-visualizer-data))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; `(and (vectorp ,v) (= (length ,v) ,len))))
&lt;br&gt;&lt;br&gt;(defmacro undo-tree-node-lwidth (node)
&lt;br&gt;&amp;nbsp; `(when (vectorp (undo-tree-node-visualizer ,node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-visualizer-data-lwidth
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-visualizer ,node))))
&lt;br&gt;&lt;br&gt;(defmacro undo-tree-node-cwidth (node)
&lt;br&gt;&amp;nbsp; `(when (vectorp (undo-tree-node-visualizer ,node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-visualizer-data-cwidth
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-visualizer ,node))))
&lt;br&gt;&lt;br&gt;(defmacro undo-tree-node-rwidth (node)
&lt;br&gt;&amp;nbsp; `(when (vectorp (undo-tree-node-visualizer ,node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-visualizer-data-rwidth
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-visualizer ,node))))
&lt;br&gt;&lt;br&gt;(defmacro undo-tree-node-marker (node)
&lt;br&gt;&amp;nbsp; `(when (vectorp (undo-tree-node-visualizer ,node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-visualizer-data-marker
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-visualizer ,node))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defsetf undo-tree-node-lwidth (node) (val)
&lt;br&gt;&amp;nbsp; `(let ((v (undo-tree-node-visualizer ,node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(unless (undo-tree-visualizer-data-p v)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setf (undo-tree-node-visualizer ,node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setq v (make-undo-tree-visualizer-data))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(setf (undo-tree-visualizer-data-lwidth v) ,val)))
&lt;br&gt;&lt;br&gt;(defsetf undo-tree-node-cwidth (node) (val)
&lt;br&gt;&amp;nbsp; `(let ((v (undo-tree-node-visualizer ,node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(unless (undo-tree-visualizer-data-p v)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setf (undo-tree-node-visualizer ,node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setq v (make-undo-tree-visualizer-data))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(setf (undo-tree-visualizer-data-cwidth v) ,val)))
&lt;br&gt;&lt;br&gt;(defsetf undo-tree-node-rwidth (node) (val)
&lt;br&gt;&amp;nbsp; `(let ((v (undo-tree-node-visualizer ,node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(unless (undo-tree-visualizer-data-p v)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setf (undo-tree-node-visualizer ,node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setq v (make-undo-tree-visualizer-data))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(setf (undo-tree-visualizer-data-rwidth v) ,val)))
&lt;br&gt;&lt;br&gt;(defsetf undo-tree-node-marker (node) (val)
&lt;br&gt;&amp;nbsp; `(let ((v (undo-tree-node-visualizer ,node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(unless (undo-tree-visualizer-data-p v)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setf (undo-tree-node-visualizer ,node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setq v (make-undo-tree-visualizer-data))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(setf (undo-tree-visualizer-data-marker v) ,val)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; =====================================================================
&lt;br&gt;;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Basic undo-tree data structure functions
&lt;br&gt;&lt;br&gt;(defun undo-tree-grow (undo)
&lt;br&gt;&amp;nbsp; &amp;quot;Add an UNDO node to current branch of `buffer-undo-tree'.&amp;quot;
&lt;br&gt;&amp;nbsp; (let* ((current (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(new (make-undo-tree-node current undo)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (push new (undo-tree-node-next current))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setf (undo-tree-current buffer-undo-tree) new)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-grow-backwards (node undo)
&lt;br&gt;&amp;nbsp; &amp;quot;Add an UNDO node *above* undo-tree NODE, and return new node.
&lt;br&gt;Note that this will overwrite NODE's \&amp;quot;previous\&amp;quot; link, so should
&lt;br&gt;only be used on a detached NODE, never on nodes that are already
&lt;br&gt;part of `buffer-undo-tree'.&amp;quot;
&lt;br&gt;&amp;nbsp; (let ((new (make-undo-tree-node-backwards node undo)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setf (undo-tree-node-previous node) new)
&lt;br&gt;&amp;nbsp; &amp;nbsp; new))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-compute-widths (undo-tree)
&lt;br&gt;&amp;nbsp; &amp;quot;Recursively compute widths for all UNDO-TREE's nodes.&amp;quot;
&lt;br&gt;&amp;nbsp; (let ((stack (list (undo-tree-root undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; res)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (while stack
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; try to compute widths for node at top of stack
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (if (undo-tree-node-p
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setq res (undo-tree-node-compute-widths (car stack))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; if computation fails, it returns a node whose widths still need
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; computing, which we push onto the stack
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (push res stack)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; otherwise, store widths and remove it from stack
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-lwidth (car stack)) (aref res 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-cwidth (car stack)) (aref res 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-rwidth (car stack)) (aref res 2))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (pop stack)))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-node-compute-widths (node)
&lt;br&gt;&amp;nbsp; ;; Compute NODE's left-, centre-, and right-subtree widths. Returns widths
&lt;br&gt;&amp;nbsp; ;; (in a vector) if successful. Otherwise, returns a node whose widths need
&lt;br&gt;&amp;nbsp; ;; calculating before NODE's can be calculated.
&lt;br&gt;&amp;nbsp; (let ((num-children (length (undo-tree-node-next node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (lwidth 0) (cwidth 0) (rwidth 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; p w)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (catch 'need-widths
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (cond
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; leaf nodes have 0 width
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;((= 0 num-children)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf cwidth 1
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-lwidth node) 0
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-cwidth node) 1
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-rwidth node) 0))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; odd number of children
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;((= (mod num-children 2) 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq p (undo-tree-node-next node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; compute left-width
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (dotimes (i (/ num-children 2))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (undo-tree-node-lwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf lwidth (+ (undo-tree-node-lwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-cwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-rwidth (car p))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; if child's widths haven't been computed, return that child
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (throw 'need-widths (car p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq p (cdr p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (undo-tree-node-lwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf lwidth (undo-tree-node-lwidth (car p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (throw 'need-widths (car p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; centre-width is inherited from middle child
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf cwidth (undo-tree-node-cwidth (car p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; compute right-width
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf rwidth (undo-tree-node-rwidth (car p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq p (cdr p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (dotimes (i (/ num-children 2))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (undo-tree-node-lwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf rwidth (+ (undo-tree-node-lwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-cwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-rwidth (car p))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (throw 'need-widths (car p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq p (cdr p))))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; even number of children
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(t
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq p (undo-tree-node-next node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; compute left-width
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (dotimes (i (/ num-children 2))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (undo-tree-node-lwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf lwidth (+ (undo-tree-node-lwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-cwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-rwidth (car p))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (throw 'need-widths (car p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq p (cdr p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; centre-width is 0 when number of children is even
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq cwidth 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; compute right-width
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (dotimes (i (/ num-children 2))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (undo-tree-node-lwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf rwidth (+ (undo-tree-node-lwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-cwidth (car p))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-rwidth (car p))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (throw 'need-widths (car p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq p (cdr p)))))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; return left-, centre- and right-widths
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (vector lwidth cwidth rwidth))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-clear-visualizer-data (undo-tree)
&lt;br&gt;&amp;nbsp; ;; Clear visualizer data from UNDO-TREE.
&lt;br&gt;&amp;nbsp; (let ((stack (list (undo-tree-root undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (while stack
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq node (pop stack))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-visualizer node) nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (dolist (n (undo-tree-node-next node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (push n stack)))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-position (node list)
&lt;br&gt;&amp;nbsp; &amp;quot;Find the first occurrence of NODE in LIST.
&lt;br&gt;Return the index of the matching item, or nil of not found.
&lt;br&gt;Comparison is done with 'eq.&amp;quot;
&lt;br&gt;&amp;nbsp; (let ((i 0))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (catch 'found
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (while (progn
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(when (eq node (car list)) (throw 'found i))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(incf i)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setq list (cdr list))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; nil)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defmacro undo-tree-num-branches ()
&lt;br&gt;&amp;nbsp; ;; Return number of branches at current undo tree node.
&lt;br&gt;&amp;nbsp; '(length (undo-tree-node-next (undo-tree-current buffer-undo-tree))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-oldest-leaf (node)
&lt;br&gt;&amp;nbsp; ;; Return oldest leaf node below NODE.
&lt;br&gt;&amp;nbsp; (while (undo-tree-node-next node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (car (sort (mapcar 'identity (undo-tree-node-next node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(lambda (a b)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(time-less-p (undo-tree-node-timestamp a)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-timestamp b)))))))
&lt;br&gt;&amp;nbsp; node)
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-discard-node (node)
&lt;br&gt;&amp;nbsp; ;; Discard NODE from `buffer-undo-tree', and return next in line for
&lt;br&gt;&amp;nbsp; ;; discarding.
&lt;br&gt;&lt;br&gt;&amp;nbsp; ;; don't discard current node
&lt;br&gt;&amp;nbsp; (unless (eq node (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (decf (undo-tree-size buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (+ (undo-list-byte-size (undo-tree-node-undo node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-list-byte-size (undo-tree-node-redo node))))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; discarding root node
&lt;br&gt;&amp;nbsp; &amp;nbsp; (if (eq node (undo-tree-root buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (cond
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; should always discard branches before root
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;((&amp;gt; (length (undo-tree-node-next node)) 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (error &amp;quot;Trying to discard undo-tree root which still\
&lt;br&gt;&amp;nbsp;has multiple branches&amp;quot;))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; don't discard root if current node is only child
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;((eq (car (undo-tree-node-next node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(t
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; make child of root into new root
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf node (setf (undo-tree-root buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(car (undo-tree-node-next node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-undo node) nil
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-redo node) nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; if new root has branches, or new root is current node, next node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; to discard is oldest leaf, otherwise it's new root
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (or (&amp;gt; (length (undo-tree-node-next node)) 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (eq (car (undo-tree-node-next node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-oldest-leaf node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; node)))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; discarding leaf node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (let* ((parent (undo-tree-node-previous node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(current (nth (undo-tree-node-branch parent)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-node-next parent))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-next parent)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (delq node (undo-tree-node-next parent))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-branch parent)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-position current (undo-tree-node-next parent)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; if parent has branches, or parent is current node, next node to
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; discard is oldest lead, otherwise it's parent
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (or (eq parent (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (and (undo-tree-node-next parent)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(or (not (eq parent (undo-tree-root buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(&amp;gt; (length (undo-tree-node-next parent)) 1))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-oldest-leaf parent)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; parent)))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-discard-history ()
&lt;br&gt;&amp;nbsp; &amp;quot;Discard undo history until we're within memory usage limits
&lt;br&gt;set by `undo-limit', `undo-strong-limit' and `undo-outer-limit'.&amp;quot;
&lt;br&gt;&lt;br&gt;&amp;nbsp; (when (&amp;gt; (undo-tree-size buffer-undo-tree) undo-limit)
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; if there are no branches off root, first node to discard is root;
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; otherwise it's leaf node at botom of oldest branch
&lt;br&gt;&amp;nbsp; &amp;nbsp; (let ((node (if (&amp;gt; (length (undo-tree-node-next
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-root buffer-undo-tree))) 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-oldest-leaf (undo-tree-root buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-root buffer-undo-tree))))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; discard nodes until memory use is within `undo-strong-limit'
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (while (and node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (&amp;gt; (undo-tree-size buffer-undo-tree) undo-strong-limit))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq node (undo-tree-discard-node node)))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; discard nodes until next node to discard would bring memory use
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; within `undo-limit'
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (while (and node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (&amp;gt; (- (undo-tree-size buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-list-byte-size (undo-tree-node-undo node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-list-byte-size (undo-tree-node-redo node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;undo-limit))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq node (undo-tree-discard-node node)))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; if we're still over the `undo-outer-limit', discard entire history
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (when (&amp;gt; (undo-tree-size buffer-undo-tree) undo-outer-limit)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; query first `undo-ask-before-discard' is set
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if undo-ask-before-discard
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (when (yes-or-no-p
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(format
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;Buffer `%s' undo info is %d bytes long; &amp;nbsp;discard it? &amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (buffer-name) (undo-tree-size buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-undo-tree nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; otherwise, discard and display warning
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (display-warning
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;'(undo discard-info)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(concat
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (format &amp;quot;Buffer `%s' undo info was %d bytes long.\n&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (buffer-name) (undo-tree-size buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;The undo info was discarded because it exceeded\
&lt;br&gt;&amp;nbsp;`undo-outer-limit'.
&lt;br&gt;&lt;br&gt;This is normal if you executed a command that made a huge change
&lt;br&gt;to the buffer. In that case, to prevent similar problems in the
&lt;br&gt;future, set `undo-outer-limit' to a value that is large enough to
&lt;br&gt;cover the maximum size of normal changes you expect a single
&lt;br&gt;command to make, but not so large that it might exceed the
&lt;br&gt;maximum memory allotted to Emacs.
&lt;br&gt;&lt;br&gt;If you did not execute any such command, the situation is
&lt;br&gt;probably due to a bug and you should report it.
&lt;br&gt;&lt;br&gt;You can disable the popping up of this buffer by adding the entry
&lt;br&gt;\(undo discard-info) to the user option `warning-suppress-types',
&lt;br&gt;which is defined in the `warnings' library.\n&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;:warning)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-undo-tree nil)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; )))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; =====================================================================
&lt;br&gt;;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Utility functions for handling `buffer-undo-list'
&lt;br&gt;&lt;br&gt;(defun undo-list-pop-changeset ()
&lt;br&gt;&amp;nbsp; ;; Pop changeset from `buffer-undo-list'.
&lt;br&gt;&amp;nbsp; ;; discard undo boundaries and marker adjustment entries at head of list
&lt;br&gt;&amp;nbsp; (while (or (null (car buffer-undo-list))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(and (consp (car buffer-undo-list))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (markerp (caar buffer-undo-list))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq buffer-undo-list (cdr buffer-undo-list)))
&lt;br&gt;&amp;nbsp; ;; pop elements up to next undo boundary
&lt;br&gt;&amp;nbsp; (unless (eq (car buffer-undo-list) 'undo-tree-canary)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (let* ((changeset (cons (pop buffer-undo-list) nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(p changeset))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (while (car buffer-undo-list)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setcdr p (cons (pop buffer-undo-list) nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; discard marker adjustment entries (see Commentary, above)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (and (consp (cadr p)) (markerp (car (cadr p))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setcdr p nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq p (cdr p))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; changeset)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-list-transfer-to-tree ()
&lt;br&gt;&amp;nbsp; ;; Transfer entries accumulated in `buffer-undo-list' to `buffer-undo-tree'.
&lt;br&gt;&amp;nbsp; (if (null buffer-undo-list)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-undo-list '(nil undo-tree-canary))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (when (not (eq (cadr buffer-undo-list) 'undo-tree-canary))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; create new node from first changeset in `buffer-undo-list', save old
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; `buffer-undo-tree' current node, and make new node the current node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (let* ((node (make-undo-tree-node nil (undo-list-pop-changeset)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(splice (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(size (undo-list-byte-size (undo-tree-node-undo node))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-current buffer-undo-tree) node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; grow tree fragment backwards using `buffer-undo-list' changesets
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (while (and buffer-undo-list
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (not (eq (cadr buffer-undo-list) 'undo-tree-canary)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-grow-backwards node (undo-list-pop-changeset)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf size (undo-list-byte-size (undo-tree-node-undo node))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; if no undo history has been discarded from `buffer-undo-list' since
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; last transfer, splice new tree fragment onto end of old
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; `buffer-undo-tree' current node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (eq (cadr buffer-undo-list) 'undo-tree-canary)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (progn
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-previous node) splice)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (push node (undo-tree-node-next splice))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-branch splice) 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf (undo-tree-size buffer-undo-tree) size))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; if undo history has been discarded, replace entire
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; `buffer-undo-tree' with new tree fragment
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq node (undo-tree-grow-backwards node nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-root buffer-undo-tree) node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-undo-list '(nil undo-tree-canary))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-size buffer-undo-tree) size))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-list-byte-size (undo-list)
&lt;br&gt;&amp;nbsp; ;; Return size (in bytes) of UNDO-LIST
&lt;br&gt;&amp;nbsp; (let ((size 0) (p undo-list))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (while p
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (incf size 8) &amp;nbsp;; cons cells use up 8 bytes
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (when (and (consp (car p)) (stringp (caar p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf size (string-bytes (caar p))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq p (cdr p)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; size))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; =====================================================================
&lt;br&gt;;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Undo-tree commands
&lt;br&gt;&lt;br&gt;(define-minor-mode undo-tree-mode
&lt;br&gt;&amp;nbsp; &amp;quot;Toggle undo-tree mode.
&lt;br&gt;With no argument, this command toggles the mode.
&lt;br&gt;A positive prefix argument turns the mode on.
&lt;br&gt;A negative prefix argument turns it off.
&lt;br&gt;&lt;br&gt;Undo-tree-mode replaces Emacs' standard undo feature with a more
&lt;br&gt;powerful yet easier to use version, that treats the undo history
&lt;br&gt;as what it is: a tree.
&lt;br&gt;&lt;br&gt;The following keys are available in `undo-tree-mode':
&lt;br&gt;&lt;br&gt;&amp;nbsp; \\{undo-tree-map}
&lt;br&gt;&lt;br&gt;Within the undo-tree visualizer, the following keys are available:
&lt;br&gt;&lt;br&gt;&amp;nbsp; \\{undo-tree-visualizer-map}&amp;quot;
&lt;br&gt;&lt;br&gt;&amp;nbsp; nil &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ; init value
&lt;br&gt;&amp;nbsp; &amp;quot; Undo-Tree&amp;quot; &amp;nbsp; &amp;nbsp;; lighter
&lt;br&gt;&amp;nbsp; undo-tree-map &amp;nbsp; ; keymap
&lt;br&gt;&amp;nbsp; ;; if disabling `undo-tree-mode', remove &amp;quot;canary&amp;quot; from `buffer-undo-list'
&lt;br&gt;&amp;nbsp; (unless undo-tree-mode (setq buffer-undo-list nil)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun turn-on-undo-tree-mode ()
&lt;br&gt;&amp;nbsp; &amp;quot;Enable undo-tree-mode.&amp;quot;
&lt;br&gt;&amp;nbsp; (undo-tree-mode 1))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(define-globalized-minor-mode global-undo-tree-mode
&lt;br&gt;&amp;nbsp; undo-tree-mode turn-on-undo-tree-mode)
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-undo (&amp;optional arg)
&lt;br&gt;&amp;nbsp; &amp;quot;Undo changes. A numeric ARG serves as a repeat count.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;p&amp;quot;)
&lt;br&gt;&amp;nbsp; ;; throw error if undo is disabled in buffer
&lt;br&gt;&amp;nbsp; (when (eq buffer-undo-list t) (error &amp;quot;No undo information in this buffer&amp;quot;))
&lt;br&gt;&lt;br&gt;&amp;nbsp; (let ((undo-in-progress t))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; if `buffer-undo-tree' is empty, create initial undo-tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; (when (null buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-undo-tree (make-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; transfer entries accumulated in `buffer-undo-list' to
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; `buffer-undo-tree'
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-list-transfer-to-tree)
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; (dotimes (i (or arg 1))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; check if at top of undo tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (if (null (undo-tree-node-previous
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (error &amp;quot;No further undo information&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; undo one record from undo tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (primitive-undo 1 (undo-copy-list
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-node-undo
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-current buffer-undo-tree))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; pop redo entries that `primitive-undo' has added to
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; `buffer-undo-list' and record them in current node's redo record if
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; they're not already there
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (undo-tree-node-redo (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-list-pop-changeset)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-redo (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-list-pop-changeset))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (incf (undo-tree-size buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-list-byte-size
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-node-redo (undo-tree-current buffer-undo-tree)))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; rewind current node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-current buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-previous (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; update timestamp
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-timestamp (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (current-time))))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; discard undo history if necessary
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-discard-history)
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; inform user if at branch point
&lt;br&gt;&amp;nbsp; &amp;nbsp; (when (&amp;gt; (undo-tree-num-branches) 1) (message &amp;quot;Undo branch point!&amp;quot;))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-redo (&amp;optional arg)
&lt;br&gt;&amp;nbsp; &amp;quot;Redo changes. A numeric ARG serves as a repeat count.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;p&amp;quot;)
&lt;br&gt;&amp;nbsp; ;; throw error if undo is disabled in buffer
&lt;br&gt;&amp;nbsp; (when (eq buffer-undo-list t) (error &amp;quot;No undo information in this buffer&amp;quot;))
&lt;br&gt;&lt;br&gt;&amp;nbsp; (let ((undo-in-progress t))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; if `buffer-undo-tree' is empty, create initial undo-tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; (when (null buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-undo-tree (make-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; transfer entries accumulated in `buffer-undo-list' to
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; `buffer-undo-tree'
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-list-transfer-to-tree)
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; (let ((current (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (dotimes (i (or arg 1))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; check if at bottom of undo tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (null (undo-tree-node-next current))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (error &amp;quot;No further redo information&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; advance current node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq current
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-current buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (nth (undo-tree-node-branch current)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-node-next current))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; update timestamp
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-timestamp current) (current-time))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; redo one record from undo tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (primitive-undo 1 (undo-copy-list (undo-tree-node-redo current)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; discard undo entries that `primitive-undo' has added to
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; `buffer-undo-list' since we already know how to undo from here
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; (NOTE: should we instead overwrite old undo entry for safety's
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;sake?)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-undo-list '(nil undo-tree-canary)))))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; discard undo history if necessary
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-discard-history)
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; inform user if at branch point
&lt;br&gt;&amp;nbsp; &amp;nbsp; (when (&amp;gt; (undo-tree-num-branches) 1) (message &amp;quot;Undo branch point!&amp;quot;))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-switch-branch (branch)
&lt;br&gt;&amp;nbsp; &amp;quot;Switch to a different BRANCH of the undo tree.
&lt;br&gt;This will affect which branch to descend when *redoing* changes
&lt;br&gt;using `undo-tree-redo'.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive (list (or (and prefix-arg (prefix-numeric-value prefix-arg))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(and (not (eq buffer-undo-list t))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (or buffer-undo-tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (progn
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-undo-tree (make-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-list-transfer-to-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; t))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (&amp;gt; (undo-tree-num-branches) 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (read-number
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(format &amp;quot;Branch (0-%d): &amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(1- (undo-tree-num-branches))))))))
&lt;br&gt;&amp;nbsp; ;; throw error if undo is disabled in buffer
&lt;br&gt;&amp;nbsp; (when (eq buffer-undo-list t) (error &amp;quot;No undo information in this buffer&amp;quot;))
&lt;br&gt;&amp;nbsp; ;; sanity check branch number
&lt;br&gt;&amp;nbsp; (when (&amp;lt;= (undo-tree-num-branches) 1) (error &amp;quot;Not at undo branch point&amp;quot;))
&lt;br&gt;&amp;nbsp; (when (or (&amp;lt; branch 0) (&amp;gt; branch (1- (undo-tree-num-branches))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (error &amp;quot;Invalid branch number&amp;quot;)
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; if `buffer-undo-tree' is empty, create initial undo-tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; (when (null buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-undo-tree (make-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; transfer entries accumulated in `buffer-undo-list' to
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; `buffer-undo-tree'
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-list-transfer-to-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; switch branch
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setf (undo-tree-node-branch (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; branch)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-set (node)
&lt;br&gt;&amp;nbsp; ;; Set buffer to state corresponding to NODE. Returns intersection point
&lt;br&gt;&amp;nbsp; ;; between path back from current node and path back from selected NODE.
&lt;br&gt;&amp;nbsp; (let ((path (make-hash-table :test 'eq))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (n node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (puthash (undo-tree-root buffer-undo-tree) t path)
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; build list of nodes leading back from selected node to root, updating
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; branches as we go to point down to selected node
&lt;br&gt;&amp;nbsp; &amp;nbsp; (while (progn
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(puthash n t path)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(when (undo-tree-node-previous n)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setf (undo-tree-node-branch (undo-tree-node-previous n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-position
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; n (undo-tree-node-next (undo-tree-node-previous n))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setq n (undo-tree-node-previous n)))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; work backwards from current node until we intersect path back from
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; selected node
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq n (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (while (not (gethash n path))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq n (undo-tree-node-previous n)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; ascend tree until intersection node
&lt;br&gt;&amp;nbsp; &amp;nbsp; (while (not (eq (undo-tree-current buffer-undo-tree) n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-undo))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; descend tree until selected node
&lt;br&gt;&amp;nbsp; &amp;nbsp; (while (not (eq (undo-tree-current buffer-undo-tree) node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-redo))
&lt;br&gt;&amp;nbsp; &amp;nbsp; n)) &amp;nbsp;; return intersection node
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; =====================================================================
&lt;br&gt;;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Undo-tree visualizer
&lt;br&gt;&lt;br&gt;(defun undo-tree-visualize ()
&lt;br&gt;&amp;nbsp; &amp;quot;Visualize the current buffer's undo tree.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive)
&lt;br&gt;&amp;nbsp; ;; throw error if undo is disabled in buffer
&lt;br&gt;&amp;nbsp; (when (eq buffer-undo-list t) (error &amp;quot;No undo information in this buffer&amp;quot;))
&lt;br&gt;&amp;nbsp; ;; if `buffer-undo-tree' is empty, create initial undo-tree
&lt;br&gt;&amp;nbsp; (when (null buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq buffer-undo-tree (make-undo-tree)))
&lt;br&gt;&amp;nbsp; ;; transfer entries accumulated in `buffer-undo-list' to `buffer-undo-tree'
&lt;br&gt;&amp;nbsp; (undo-list-transfer-to-tree)
&lt;br&gt;&amp;nbsp; ;; add hook to kill visualizer buffer if original buffer is changed
&lt;br&gt;&amp;nbsp; (add-hook 'before-change-functions 'undo-tree-kill-visualizer nil t)
&lt;br&gt;&amp;nbsp; ;; prepare *undo-tree* buffer, then draw tree in it
&lt;br&gt;&amp;nbsp; (let ((undo-tree buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (buff (current-buffer)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (switch-to-buffer-other-window &amp;quot; *undo-tree*&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-visualizer-mode)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq undo-tree-visualizer-buffer buff)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq buffer-undo-tree undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq cursor-type nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq buffer-read-only nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-draw-tree undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq buffer-read-only t)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-kill-visualizer (&amp;rest dummy)
&lt;br&gt;&amp;nbsp; ;; Kill visualizer. Added to `before-change-functions' hook of original
&lt;br&gt;&amp;nbsp; ;; buffer when visualizer is invoked.
&lt;br&gt;&amp;nbsp; (unwind-protect
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (save-excursion
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (set-buffer &amp;quot; *undo-tree*&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-visualizer-quit))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; remove hook now that visualizer has been killed
&lt;br&gt;&amp;nbsp; &amp;nbsp; (remove-hook 'before-change-functions 'undo-tree-kill-visualizer t)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-draw-tree (undo-tree)
&lt;br&gt;&amp;nbsp; ;; Draw UNDO-TREE in current buffer.
&lt;br&gt;&amp;nbsp; (erase-buffer)
&lt;br&gt;&amp;nbsp; (undo-tree-move-down 1) &amp;nbsp; &amp;nbsp; &amp;nbsp;; top margin
&lt;br&gt;&amp;nbsp; (undo-tree-clear-visualizer-data undo-tree)
&lt;br&gt;&amp;nbsp; (undo-tree-compute-widths undo-tree)
&lt;br&gt;&amp;nbsp; (undo-tree-move-forward
&lt;br&gt;&amp;nbsp; &amp;nbsp;(max (/ (window-width) 2)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (+ (undo-tree-node-char-lwidth (undo-tree-root undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; add space for left part of left-most time-stamp
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(if undo-tree-visualizer-timestamps 4 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;2))) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;; left margin
&lt;br&gt;&amp;nbsp; ;; draw undo-tree
&lt;br&gt;&amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-default-face)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (stack (list (undo-tree-root undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (n (undo-tree-root undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; link root node to its representation in visualizer
&lt;br&gt;&amp;nbsp; &amp;nbsp; (unless (markerp (undo-tree-node-marker n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-marker n) (make-marker))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (set-marker-insertion-type (undo-tree-node-marker n) nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (move-marker (undo-tree-node-marker n) (point))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; draw nodes from stack until stack is empty
&lt;br&gt;&amp;nbsp; &amp;nbsp; (while stack
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq n (pop stack))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char (undo-tree-node-marker n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq n (undo-tree-draw-subtree n nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq stack (append stack n))))
&lt;br&gt;&amp;nbsp; ;; highlight active branch
&lt;br&gt;&amp;nbsp; (goto-char (undo-tree-node-marker (undo-tree-root undo-tree)))
&lt;br&gt;&amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-active-branch-face))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-highlight-active-branch (undo-tree-root undo-tree)))
&lt;br&gt;&amp;nbsp; ;; highlight current node
&lt;br&gt;&amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-current-face))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-draw-node (undo-tree-current undo-tree) 'current)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-highlight-active-branch (node)
&lt;br&gt;&amp;nbsp; ;; Draw highlighted active branch below NODE in current buffer.
&lt;br&gt;&amp;nbsp; (let ((stack (list node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; link node to its representation in visualizer
&lt;br&gt;&amp;nbsp; &amp;nbsp; (unless (markerp (undo-tree-node-marker node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-marker node) (make-marker))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (set-marker-insertion-type (undo-tree-node-marker node) nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (move-marker (undo-tree-node-marker node) (point))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; draw active branch
&lt;br&gt;&amp;nbsp; &amp;nbsp; (while stack
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq node (pop stack))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char (undo-tree-node-marker node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq node (undo-tree-draw-subtree node 'active))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq stack (append stack node)))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-draw-node (node &amp;optional current)
&lt;br&gt;&amp;nbsp; ;; Highlight NODE as current node.
&lt;br&gt;&amp;nbsp; (goto-char (undo-tree-node-marker node))
&lt;br&gt;&amp;nbsp; (if undo-tree-visualizer-timestamps
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (progn
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (backward-char 4)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if current (undo-tree-insert ?*) (undo-tree-insert ? ))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-insert
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-timestamp-to-string (undo-tree-node-timestamp node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (backward-char 5)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (move-marker (undo-tree-node-marker node) (point))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (put-text-property (- (point) 3) (+ (point) 5)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;'undo-tree-node node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (if current (undo-tree-insert ?x) (undo-tree-insert ?o))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (backward-char 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (put-text-property (point) (1+ (point)) 'undo-tree-node node)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-draw-subtree (node &amp;optional active-branch)
&lt;br&gt;&amp;nbsp; ;; Draw subtree rooted at NODE. The subtree will start from point.
&lt;br&gt;&amp;nbsp; ;; If ACTIVE-BRANCH is non-nil, just draw active branch below NODE.
&lt;br&gt;&amp;nbsp; ;; If TIMESTAP is non-nil, draw time-stamps instead of &amp;quot;o&amp;quot; at nodes.
&lt;br&gt;&amp;nbsp; (let ((num-children (length (undo-tree-node-next node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; node-list pos trunk-pos n)
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; draw node itself
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-draw-node node)
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; (cond
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;;; if we're at a leaf node, we're done
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;((= num-children 0))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;;; if node has only one child, draw it (not strictly necessary to deal
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;;; with this case separately, but as it's by far the most common case
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;;; this makes the code clearer and more efficient)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;((= num-children 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-insert ?|)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (backward-char 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-insert ?|)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (backward-char 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq n (car (undo-tree-node-next node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; link next node to its representation in visualizer
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (unless (markerp (undo-tree-node-marker n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-marker n) (make-marker))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (set-marker-insertion-type (undo-tree-node-marker n) nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (move-marker (undo-tree-node-marker n) (point))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; add next node to list of nodes to draw next
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (push n node-list))
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;;; if node had multiple children, draw branches
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(t
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-insert ?|)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (backward-char 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq trunk-pos (point))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; left subtrees
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (backward-char
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(- (undo-tree-node-char-lwidth node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-char-lwidth
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(car (undo-tree-node-next node)))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq pos (point))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq n (cons nil (undo-tree-node-next node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (dotimes (i (/ num-children 2))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq n (cdr n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (when (or (null active-branch)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (eq (car n)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (nth (undo-tree-node-branch node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-node-next node))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-forward 2)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-insert ?_ (- trunk-pos pos 2))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char pos)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-forward 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-insert ?/)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (backward-char 2)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; link node to its representation in visualizer
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (unless (markerp (undo-tree-node-marker (car n)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-marker (car n)) (make-marker))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (set-marker-insertion-type (undo-tree-node-marker (car n)) nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (move-marker (undo-tree-node-marker (car n)) (point))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; add node to list of nodes to draw next
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (push (car n) node-list))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char pos)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-forward
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(+ (undo-tree-node-char-rwidth (car n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-node-char-lwidth (cadr n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; undo-tree-visualizer-spacing 1))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq pos (point)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; middle subtree (only when number of children is odd)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (when (= (mod num-children 2) 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq n (cdr n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (when (or (null active-branch)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (eq (car n)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (nth (undo-tree-node-branch node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-node-next node))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-insert ?|)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (backward-char 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; link node to its representation in visualizer
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (unless (markerp (undo-tree-node-marker (car n)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-marker (car n)) (make-marker))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (set-marker-insertion-type (undo-tree-node-marker (car n)) nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (move-marker (undo-tree-node-marker (car n)) (point))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; add node to list of nodes to draw next
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (push (car n) node-list))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char pos)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-forward
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(+ (undo-tree-node-char-rwidth (car n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (cadr n) (undo-tree-node-char-lwidth (cadr n)) 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; undo-tree-visualizer-spacing 1))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq pos (point)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; right subtrees
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (incf trunk-pos)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (dotimes (i (/ num-children 2))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq n (cdr n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (when (or (null active-branch)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (eq (car n)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (nth (undo-tree-node-branch node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(undo-tree-node-next node))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char trunk-pos)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-insert ?_ (- pos trunk-pos 1))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char pos)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (backward-char 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-insert ?\\)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-down 1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; link node to its representation in visualizer
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (unless (markerp (undo-tree-node-marker (car n)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setf (undo-tree-node-marker (car n)) (make-marker))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (set-marker-insertion-type (undo-tree-node-marker (car n)) nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (move-marker (undo-tree-node-marker (car n)) (point))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; add node to list of nodes to draw next
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (push (car n) node-list))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (when (cdr n)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char pos)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-move-forward
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(+ (undo-tree-node-char-rwidth (car n))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (cadr n) (undo-tree-node-char-lwidth (cadr n)) 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; undo-tree-visualizer-spacing 1))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq pos (point))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; return list of nodes to draw next
&lt;br&gt;&amp;nbsp; &amp;nbsp; (nreverse node-list)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-node-char-lwidth (node)
&lt;br&gt;&amp;nbsp; ;; Return left-width of NODE measured in characters.
&lt;br&gt;&amp;nbsp; (if (= (length (undo-tree-node-next node)) 0) 0
&lt;br&gt;&amp;nbsp; &amp;nbsp; (- (* (+ undo-tree-visualizer-spacing 1) (undo-tree-node-lwidth node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(if (= (undo-tree-node-cwidth node) 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(1+ (/ undo-tree-visualizer-spacing 2)) 0))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-node-char-rwidth (node)
&lt;br&gt;&amp;nbsp; ;; Return right-width of NODE measured in characters.
&lt;br&gt;&amp;nbsp; (if (= (length (undo-tree-node-next node)) 0) 0
&lt;br&gt;&amp;nbsp; &amp;nbsp; (- (* (+ undo-tree-visualizer-spacing 1) (undo-tree-node-rwidth node))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(if (= (undo-tree-node-cwidth node) 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(1+ (/ undo-tree-visualizer-spacing 2)) 0))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-insert (str &amp;optional arg)
&lt;br&gt;&amp;nbsp; ;; Insert character or string STR ARG times, overwriting, and using
&lt;br&gt;&amp;nbsp; ;; `undo-tree-insert-face'.
&lt;br&gt;&amp;nbsp; (unless arg (setq arg 1))
&lt;br&gt;&amp;nbsp; (when (characterp str)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq str (make-string arg str))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq arg 1))
&lt;br&gt;&amp;nbsp; (dotimes (i arg) (insert str))
&lt;br&gt;&amp;nbsp; (setq arg (* arg (length str)))
&lt;br&gt;&amp;nbsp; (undo-tree-move-forward arg)
&lt;br&gt;&amp;nbsp; (backward-delete-char arg)
&lt;br&gt;&amp;nbsp; (when (boundp 'undo-tree-insert-face)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (put-text-property (- (point) arg) (point) 'face undo-tree-insert-face)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-move-down (&amp;optional arg)
&lt;br&gt;&amp;nbsp; ;; Move down, extending buffer if necessary.
&lt;br&gt;&amp;nbsp; (let ((row (line-number-at-pos))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (col (current-column))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; line)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (unless arg (setq arg 1))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (forward-line arg)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq line (line-number-at-pos))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; if buffer doesn't have enough lines, add some
&lt;br&gt;&amp;nbsp; &amp;nbsp; (when (/= line (+ row arg))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (insert (make-string (- arg (- line row)) ?\n)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-move-forward col)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-move-forward (&amp;optional arg)
&lt;br&gt;&amp;nbsp; ;; Move forward, extending buffer if necessary.
&lt;br&gt;&amp;nbsp; (unless arg (setq arg 1))
&lt;br&gt;&amp;nbsp; (let ((n (- (line-end-position) (point))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (if (&amp;gt; n arg)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (forward-char arg)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (end-of-line)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (insert (make-string (- arg n) ? )))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-timestamp-to-string (timestamp)
&lt;br&gt;&amp;nbsp; ;; Convert TIMESTAMP to hh:mm:ss string.
&lt;br&gt;&amp;nbsp; (let ((time (decode-time timestamp)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (format &amp;quot;%02d:%02d:%02d&amp;quot; (nth 2 time) (nth 1 time) (nth 0 time))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;;;; =====================================================================
&lt;br&gt;;;; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Visualizer mode commands
&lt;br&gt;&lt;br&gt;(defun undo-tree-visualizer-mode ()
&lt;br&gt;&amp;nbsp; &amp;quot;Major mode used in undo-tree visualizer.&amp;quot;
&lt;br&gt;&amp;nbsp; (kill-all-local-variables)
&lt;br&gt;&amp;nbsp; (setq major-mode 'undo-tree-visualizer-mode)
&lt;br&gt;&amp;nbsp; (setq mode-name &amp;quot;undo-tree-visualizer-mode&amp;quot;)
&lt;br&gt;&amp;nbsp; (use-local-map undo-tree-visualizer-map)
&lt;br&gt;&amp;nbsp; (setq truncate-lines t)
&lt;br&gt;&amp;nbsp; (setq buffer-read-only t))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-visualize-undo (&amp;optional arg)
&lt;br&gt;&amp;nbsp; &amp;quot;Undo changes. A numeric ARG serves as a repeat count.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;p&amp;quot;)
&lt;br&gt;&amp;nbsp; (setq buffer-read-only nil)
&lt;br&gt;&amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-active-branch-face))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-draw-node (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; (switch-to-buffer-other-window undo-tree-visualizer-buffer)
&lt;br&gt;&amp;nbsp; (unwind-protect
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-undo arg)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (switch-to-buffer-other-window &amp;quot; *undo-tree*&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-current-face))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-draw-node (undo-tree-current buffer-undo-tree) 'current))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq buffer-read-only t)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-visualize-redo (&amp;optional arg)
&lt;br&gt;&amp;nbsp; &amp;quot;Redo changes. A numeric ARG serves as a repeat count.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;p&amp;quot;)
&lt;br&gt;&amp;nbsp; (setq buffer-read-only nil)
&lt;br&gt;&amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-active-branch-face))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-draw-node (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; (switch-to-buffer-other-window undo-tree-visualizer-buffer)
&lt;br&gt;&amp;nbsp; (unwind-protect
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-redo arg)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (switch-to-buffer-other-window &amp;quot; *undo-tree*&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (goto-char (undo-tree-node-marker (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-current-face))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-draw-node (undo-tree-current buffer-undo-tree) 'current))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq buffer-read-only t)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-visualize-switch-next-branch (arg)
&lt;br&gt;&amp;nbsp; &amp;quot;Switch to next branch of the undo tree.
&lt;br&gt;This will affect which branch to descend when *redoing* changes
&lt;br&gt;using `undo-tree-redo' or `undo-tree-visualizer-redo'.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;p&amp;quot;)
&lt;br&gt;&amp;nbsp; ;; un-highlight old active branch below current node
&lt;br&gt;&amp;nbsp; (setq buffer-read-only nil)
&lt;br&gt;&amp;nbsp; (goto-char (undo-tree-node-marker (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-default-face))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-highlight-active-branch (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; ;; increment branch
&lt;br&gt;&amp;nbsp; (let ((branch (undo-tree-node-branch (undo-tree-current buffer-undo-tree))))
&lt;br&gt;&amp;nbsp; (setf (undo-tree-node-branch (undo-tree-current buffer-undo-tree))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (cond
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;((&amp;gt;= (+ branch arg) (undo-tree-num-branches))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (1- (undo-tree-num-branches)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;((&amp;lt;= (+ branch arg) 0) 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(t (+ branch arg))))
&lt;br&gt;&amp;nbsp; ;; highlight new active branch below current node
&lt;br&gt;&amp;nbsp; (goto-char (undo-tree-node-marker (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-active-branch-face))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-highlight-active-branch (undo-tree-current buffer-undo-tree)))
&lt;br&gt;&amp;nbsp; ;; re-highlight current node
&lt;br&gt;&amp;nbsp; (let ((undo-tree-insert-face 'undo-tree-visualizer-current-face))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (undo-tree-draw-node (undo-tree-current buffer-undo-tree) 'current))
&lt;br&gt;&amp;nbsp; (setq buffer-read-only t)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-visualize-switch-previous-branch (arg)
&lt;br&gt;&amp;nbsp; &amp;quot;Switch to previous branch of the undo tree.
&lt;br&gt;This will affect which branch to descend when *redoing* changes
&lt;br&gt;using `undo-tree-redo' or `undo-tree-visualizer-redo'.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;p&amp;quot;)
&lt;br&gt;&amp;nbsp; (undo-tree-visualize-switch-next-branch (- arg)))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-visualizer-quit ()
&lt;br&gt;&amp;nbsp; &amp;quot;Quit the undo-tree visualizer.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive)
&lt;br&gt;&amp;nbsp; (undo-tree-clear-visualizer-data buffer-undo-tree)
&lt;br&gt;&amp;nbsp; (kill-buffer-and-window))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-visualizer-set (pos)
&lt;br&gt;&amp;nbsp; &amp;quot;Set buffer to state corresponding to undo tree node
&lt;br&gt;at POS.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;@e&amp;quot;)
&lt;br&gt;&amp;nbsp; (setq pos (event-start (nth 1 pos)))
&lt;br&gt;&amp;nbsp; (let ((node (get-text-property pos 'undo-tree-node)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (when node
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; set parent buffer to state corresponding to node at POS
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (set-buffer undo-tree-visualizer-buffer)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-set node)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (set-buffer &amp;quot; *undo-tree*&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-read-only nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; re-draw undo tree
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (undo-tree-draw-tree buffer-undo-tree)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-read-only t))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-visualizer-toggle-timestamps ()
&lt;br&gt;&amp;nbsp; &amp;quot;Toggle display of time-stamps.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive)
&lt;br&gt;&amp;nbsp; (setq undo-tree-visualizer-spacing
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (if (setq undo-tree-visualizer-timestamps
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (not undo-tree-visualizer-timestamps))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; need sufficient space if TIMESTAMP is set
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (max 9 (default-value 'undo-tree-visualizer-spacing))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (default-value 'undo-tree-visualizer-spacing)))
&lt;br&gt;&amp;nbsp; ;; redraw tree
&lt;br&gt;&amp;nbsp; (setq buffer-read-only nil)
&lt;br&gt;&amp;nbsp; (undo-tree-draw-tree buffer-undo-tree)
&lt;br&gt;&amp;nbsp; (setq buffer-read-only t))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-visualizer-scroll-left (&amp;optional arg)
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;p&amp;quot;)
&lt;br&gt;&amp;nbsp; (scroll-right (or arg 1) t))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun undo-tree-visualizer-scroll-right (&amp;optional arg)
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;p&amp;quot;)
&lt;br&gt;&amp;nbsp; (scroll-left (or arg 1) t))
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(provide 'undo-tree)
&lt;br&gt;&lt;br&gt;;;; undo-tree.el ends here
&lt;br&gt;&lt;br /&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26554347&amp;i=2&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/undo-tree.el-tp26554347p26554347.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-26538807</id>
	<title>Re: cal-china-x.el --- Chinese calendar extras v1.1</title>
	<published>2009-11-26T22:28:57Z</published>
	<updated>2009-11-26T22:28:57Z</updated>
	<author>
		<name>want.to.be.professer</name>
	</author>
	<content type="html">On 10月30日, 下午6时15分, William Xu &amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26538807&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;william....@...&lt;/a&gt;&amp;gt; wrote:
&lt;div class='shrinkable-quote'&gt;&lt;br&gt;&amp;gt; Would be the last version that supports emacs22, for there are quite a
&lt;br&gt;&amp;gt; few naming changes warnings introduced from 23.1.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; CHANGES SINCE 1.0
&lt;br&gt;&amp;gt; -------------------
&lt;br&gt;&amp;gt; &amp;nbsp; - Also display week number on date under cursor. &amp;nbsp;
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; WHAT IS IT?
&lt;br&gt;&amp;gt; -----------
&lt;br&gt;&amp;gt; This package adds more chinese calendar supports and others,
&lt;br&gt;&amp;gt; including:
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; &amp;nbsp; - Chinese localizations
&lt;br&gt;&amp;gt; &amp;nbsp; - Display holiday, lunar, horoscope, zodiac, solar term info on mode line
&lt;br&gt;&amp;gt; &amp;nbsp; - Can define holidays using `holiday-lunar', `holiday-solar-term'
&lt;br&gt;&amp;gt; &amp;nbsp; - Highlight holidays based on different priorities
&lt;br&gt;&amp;gt; &amp;nbsp; - Add `cal-china-x-chinese-holidays', `cal-china-x-japanese-holidays'.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; To use, add the following in your .emacs:
&lt;br&gt;&amp;gt; &amp;nbsp; &amp;nbsp; (require 'cal-china-x)
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; &amp;nbsp;cal-china-x.el
&lt;br&gt;&amp;gt; 32K查看下载
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; --
&lt;br&gt;&amp;gt; William
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; &lt;a href=&quot;http://xwl.appspot.com&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://xwl.appspot.com&lt;/a&gt;&lt;/div&gt;&lt;br&gt;perfect, that's what i need recently
&lt;br&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26538807&amp;i=1&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/Re%3A-cal-china-x.el-----Chinese-calendar-extras-v1.1-tp26538807p26538807.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-26524728</id>
	<title>ga.el v0.6 --- Generic apt alike interfaces for various package management tools</title>
	<published>2009-11-25T22:03:07Z</published>
	<updated>2009-11-25T22:03:07Z</updated>
	<author>
		<name>William Xu-2</name>
	</author>
	<content type="html">This extenstion tries to provide a generic apt(as used in Debian
&lt;br&gt;GNU/Linux) alike interface over various package management tools,
&lt;br&gt;such as: apt-get(Debian GNU/Linux), yum(redhat/fedora), emerge(Gentoo
&lt;br&gt;GNU/Linux), fink(Mac OS X), pkg-get(Solaris), etc.
&lt;br&gt;&lt;br&gt;Currently support: apt-get, fink, pkgsrc, apt-cyg(cygwin), yum. &amp;nbsp;
&lt;br&gt;&lt;br&gt;Changes since 0.5: 
&lt;br&gt;&amp;nbsp; - ga-yum.el: New backend for yum(used in Redhat, Fedora)
&lt;br&gt;&amp;nbsp; - ga-BACKEND-clean: Fix namings.
&lt;br&gt;&lt;br&gt;-- 
&lt;br&gt;William
&lt;br&gt;&lt;br&gt;&lt;a href=&quot;http://xwl.appspot.com&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://xwl.appspot.com&lt;/a&gt;&lt;br&gt;&lt;br /&gt; &lt;br /&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26524728&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;&lt;div class=&quot;small&quot;&gt;&lt;br/&gt;&lt;img src=&quot;http://old.nabble.com/images/icon_attachment.gif&quot; &gt; &lt;strong&gt;ga.zip&lt;/strong&gt; (15K) &lt;a href=&quot;http://old.nabble.com/attachment/26524728/0/ga.zip&quot; target=&quot;_top&quot;&gt;Download Attachment&lt;/a&gt;&lt;/div&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/ga.el-v0.6-----Generic-apt-alike-interfaces-for-various-package-management-tools-tp26524728p26524728.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-26522356</id>
	<title>modified cap-words.el for Emacs 23</title>
	<published>2009-11-25T15:48:03Z</published>
	<updated>2009-11-25T15:48:03Z</updated>
	<author>
		<name>Dave Love-2</name>
	</author>
	<content type="html">I found that my CapitalizedWords mode in Emacs 23 doesn't work properly.
&lt;br&gt;(I don't know whether the internals changed in the years since I wrote
&lt;br&gt;it or whether it needed changes from some old repo.) &amp;nbsp;This version works
&lt;br&gt;to the extent I've tested it in various situations. &amp;nbsp;It also changes the
&lt;br&gt;intended treatment of all-caps words to be what's probably expected, so
&lt;br&gt;it's not backwards-compatible; I doubt that's relevant given that the
&lt;br&gt;released version was broken and not documented for some reason.
&lt;br&gt;&lt;br&gt;cap-words obsoletes the various ostensibly language-specific
&lt;br&gt;&amp;quot;into-nomenclature&amp;quot;s etc. (including Emacs' cc-subword.el, which was
&lt;br&gt;meant to go). &amp;nbsp;However, it may not treat words quite the same, and
&lt;br&gt;actually affects the word primitives, not just a set of keybindings.
&lt;br&gt;This uses a Mule 6 feature, so it really requires Emacs 23.
&lt;br&gt;&lt;br&gt;&lt;br /&gt; &lt;br /&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26522356&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;&lt;div class=&quot;small&quot;&gt;&lt;br/&gt;&lt;img src=&quot;http://old.nabble.com/images/icon_attachment.gif&quot; &gt; &lt;strong&gt;cap-words.el&lt;/strong&gt; (6K) &lt;a href=&quot;http://old.nabble.com/attachment/26522356/0/cap-words.el&quot; target=&quot;_top&quot;&gt;Download Attachment&lt;/a&gt;&lt;/div&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/modified-cap-words.el-for-Emacs-23-tp26522356p26522356.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-26487098</id>
	<title>ffap-makefile-vars.el -- expand $(FOO)</title>
	<published>2009-11-23T14:21:30Z</published>
	<updated>2009-11-23T14:21:30Z</updated>
	<author>
		<name>Kevin Ryde</name>
	</author>
	<content type="html">This couple of lines gets M-x ffap to expand $(FOO) macros in makefiles
&lt;br&gt;(per the todo list in the ffap.el commentary). &amp;nbsp;The way it hooks into
&lt;br&gt;ffap is nasty (like my other ffap bits!), but the effect is good.
&lt;br&gt;&lt;br&gt;Gnu make assignment forms are recognised, but their special behaviours
&lt;br&gt;like += for concatenating aren't yet followed, since so far I only use
&lt;br&gt;it on very basic makefiles.
&lt;br&gt;&lt;br&gt;&lt;br /&gt; &lt;br /&gt;-----BEGIN PGP SIGNATURE-----
&lt;br&gt;Version: GnuPG v1.4.10 (GNU/Linux)
&lt;br&gt;&lt;br&gt;iD8DBQBLCER4LFMCIV9q3ToRAkDdAJ91YwHOxTzYKEcPkIwc/R72wo0ZuQCggnbF
&lt;br&gt;nP3yg3T4SnhULljtQX/9Sh4=
&lt;br&gt;=oDYH
&lt;br&gt;-----END PGP SIGNATURE-----
&lt;br&gt;&lt;br /&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26487098&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;&lt;div class=&quot;small&quot;&gt;&lt;br/&gt;&lt;img src=&quot;http://old.nabble.com/images/icon_attachment.gif&quot; &gt; &lt;strong&gt;ffap-makefile-vars.el&lt;/strong&gt; (7K) &lt;a href=&quot;http://old.nabble.com/attachment/26487098/0/ffap-makefile-vars.el&quot; target=&quot;_top&quot;&gt;Download Attachment&lt;/a&gt;&lt;/div&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/ffap-makefile-vars.el----expand-%24%28FOO%29-tp26487098p26487098.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-26392826</id>
	<title>windows-path.el v 0.1</title>
	<published>2009-11-16T21:50:35Z</published>
	<updated>2009-11-16T21:50:35Z</updated>
	<author>
		<name>Victor-93</name>
	</author>
	<content type="html">Hello there,
&lt;br&gt;&lt;br&gt;Sometimes Gnu Emacs within Cygwin needs to handle Windows style path
&lt;br&gt;(c:\path\ or c:/path/file). For example, drag a file into Gnu Emacs.
&lt;br&gt;&lt;br&gt;Another scenario is using distel within Cygwin Emacs. Distel needs to communicate with Windows native erlang node. Windows style path names are returns from Eralng node.
&lt;br&gt;&lt;br&gt;windows-path.el is intended to solve this problem.
&lt;br&gt;&lt;br&gt;Best Regards,
&lt;br&gt;Victor
&lt;br&gt;&lt;br&gt;&lt;br /&gt; &lt;br /&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26392826&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;&lt;div class=&quot;small&quot;&gt;&lt;br/&gt;&lt;img src=&quot;http://old.nabble.com/images/icon_attachment.gif&quot; &gt; &lt;strong&gt;windows-path.el&lt;/strong&gt; (6K) &lt;a href=&quot;http://old.nabble.com/attachment/26392826/0/windows-path.el&quot; target=&quot;_top&quot;&gt;Download Attachment&lt;/a&gt;&lt;/div&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/windows-path.el-v-0.1-tp26392826p26392826.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-26252078</id>
	<title>Tramp 2.1.17</title>
	<published>2009-11-08T00:42:34Z</published>
	<updated>2009-11-08T00:42:34Z</updated>
	<author>
		<name>Michael Albinus</name>
	</author>
	<content type="html">Hello,
&lt;br&gt;&lt;br&gt;The Tramp team is happy to announce the release of Tramp 2.1.17.
&lt;br&gt;&lt;br&gt;Tramp is a remote file editing package for GNU Emacs and XEmacs. &amp;nbsp;Tramp
&lt;br&gt;uses different methods like ssh or scp to access files on remote hosts
&lt;br&gt;as if they were local files. &amp;nbsp;Access to the remote file system for
&lt;br&gt;editing files, version control, and directory editing are transparently
&lt;br&gt;enabled.
&lt;br&gt;&lt;br&gt;Beside bug fixing, Tramp 2.1.17 introduces a new package tramp-imap.el,
&lt;br&gt;which offers the new connection methods imap and imaps. &amp;nbsp;This allows to
&lt;br&gt;save files on IMAP servers. &amp;nbsp;Due to dependencies on the new package
&lt;br&gt;imap-hash.el, tramp-imap.el is applicable with GNU Emacs 23.1.50 only.
&lt;br&gt;&lt;br&gt;The tramp-gvfs.el package has been extended by the synce method, which
&lt;br&gt;allows communication with Windows Mobile devices.
&lt;br&gt;&lt;br&gt;The GNU Emacs CVS repository is synchronized with this code. &amp;nbsp;Due to
&lt;br&gt;license problems, the XEmacs package repository is not updated.
&lt;br&gt;&lt;br&gt;The download files are located at ftp://ftp.gnu.org/gnu/tramp/
&lt;br&gt;&lt;br&gt;Tramp's homepage is &lt;a href=&quot;http://www.gnu.org/software/tramp/&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.gnu.org/software/tramp/&lt;/a&gt;&amp;nbsp;(for GNU Emacs)
&lt;br&gt;or &lt;a href=&quot;http://www.gnu.org/software/tramp/tramp-xemacs.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.gnu.org/software/tramp/tramp-xemacs.html&lt;/a&gt;&amp;nbsp;(for XEmacs),
&lt;br&gt;respectively.
&lt;br&gt;&lt;br&gt;Best regards, Michael.
&lt;br&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26252078&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/Tramp-2.1.17-tp26252078p26252078.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-26195223</id>
	<title>ELIP 0.804 available</title>
	<published>2009-11-04T04:14:08Z</published>
	<updated>2009-11-04T04:14:08Z</updated>
	<author>
		<name>Thien-Thi Nguyen-6</name>
	</author>
	<content type="html">release notes:
&lt;br&gt;&lt;br&gt;&amp;nbsp; Small doc/build/perf improvements, plus Esperanto upgrade,
&lt;br&gt;&amp;nbsp; plus &amp;quot;total item count&amp;quot; tracking.
&lt;br&gt;&lt;br&gt;&amp;nbsp; See README for new configure option `--with-edb-installation=DIR'.
&lt;br&gt;&lt;br&gt;&amp;nbsp; thi
&lt;br&gt;&lt;br&gt;README excerpt:
&lt;br&gt;&lt;br&gt;&amp;nbsp; This is ELIP, the Emacs Learning Instruction Program.
&lt;br&gt;&amp;nbsp; You can use it to improve long-term retention (memory)
&lt;br&gt;&amp;nbsp; of arbitrary sets of associated data.
&lt;br&gt;&lt;br&gt;NEWS excerpt:
&lt;br&gt;&lt;br&gt;&amp;nbsp; - 0.804 | 2009-11-04
&lt;br&gt;&amp;nbsp; &amp;nbsp; - configure script checks for EDB (required; error if not found)
&lt;br&gt;&amp;nbsp; &amp;nbsp; - new var: elip-question-face
&lt;br&gt;&amp;nbsp; &amp;nbsp; - &amp;quot;learn new&amp;quot; and &amp;quot;learn old&amp;quot; also display total item count
&lt;br&gt;&amp;nbsp; &amp;nbsp; - (internal, performance) date rep transformations faster
&lt;br&gt;&lt;br&gt;tarball, examples, etc. in dir:
&lt;br&gt;&lt;br&gt;&amp;nbsp; &lt;a href=&quot;http://www.gnuvola.org/software/elip/&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.gnuvola.org/software/elip/&lt;/a&gt;&lt;br&gt;&lt;br&gt;atom feed:
&lt;br&gt;&lt;br&gt;&amp;nbsp; &lt;a href=&quot;http://www.gnuvola.org/NEWS.atom&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.gnuvola.org/NEWS.atom&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26195223&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/ELIP-0.804-available-tp26195223p26195223.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-26195034</id>
	<title>ELIP 0.803 available</title>
	<published>2009-11-04T04:03:18Z</published>
	<updated>2009-11-04T04:03:18Z</updated>
	<author>
		<name>Thien-Thi Nguyen-6</name>
	</author>
	<content type="html">release notes:
&lt;br&gt;&lt;br&gt;&amp;nbsp; Bugfix plus user-driven improvements.
&lt;br&gt;&lt;br&gt;&amp;nbsp; thi
&lt;br&gt;&lt;br&gt;README excerpt:
&lt;br&gt;&lt;br&gt;&amp;nbsp; This is ELIP, the Emacs Learning Instruction Program.
&lt;br&gt;&amp;nbsp; You can use it to improve long-term retention (memory)
&lt;br&gt;&amp;nbsp; of arbitrary sets of associated data.
&lt;br&gt;&lt;br&gt;NEWS excerpt:
&lt;br&gt;&lt;br&gt;&amp;nbsp; - 0.803 | 2008-05-26
&lt;br&gt;&amp;nbsp; &amp;nbsp; - dependency upgrade: EDB 1.31 or later (see README)
&lt;br&gt;&amp;nbsp; &amp;nbsp; - elip-import trims leading/trailing whitespace
&lt;br&gt;&amp;nbsp; &amp;nbsp; - learning-session enhancements
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - non-&amp;quot;text mode&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - ELIP displays what you type in as &amp;quot;Your Answer&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - database-local variable `input-method' respected
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - &amp;quot;text mode&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - omitted text (and underscores) highlighted
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - before/after displays in-place
&lt;br&gt;&lt;br&gt;tarball, examples, etc. in dir:
&lt;br&gt;&lt;br&gt;&amp;nbsp; &lt;a href=&quot;http://www.gnuvola.org/software/elip/&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.gnuvola.org/software/elip/&lt;/a&gt;&lt;br&gt;&lt;br&gt;atom feed:
&lt;br&gt;&lt;br&gt;&amp;nbsp; &lt;a href=&quot;http://www.gnuvola.org/NEWS.xml.gz&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.gnuvola.org/NEWS.xml.gz&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26195034&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/ELIP-0.803-available-tp26195034p26195034.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-26186265</id>
	<title>ediprolog 0.9yb -- Emacs Does Interactive Prolog</title>
	<published>2009-11-03T11:48:38Z</published>
	<updated>2009-11-03T11:48:38Z</updated>
	<author>
		<name>Markus Triska-2</name>
	</author>
	<content type="html">&lt;br&gt;ediprolog lets you interact with SWI-Prolog in all buffers. You can
&lt;br&gt;consult Prolog programs and evaluate embedded queries.
&lt;br&gt;&lt;br&gt;New:
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp;*) program, switches and indent prefix are now localizable
&lt;br&gt;&amp;nbsp; &amp;nbsp;*) better compatibility with older Emacs versions
&lt;br&gt;&amp;nbsp; &amp;nbsp;*) many smaller improvements
&lt;br&gt;&lt;br&gt;Project page:
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp;&lt;a href=&quot;http://www.logic.at/prolog/ediprolog/ediprolog.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.logic.at/prolog/ediprolog/ediprolog.html&lt;/a&gt;&lt;br&gt;&lt;br&gt;Code:
&lt;br&gt;&lt;br&gt;;;; ediprolog.el --- Emacs Does Interactive Prolog
&lt;br&gt;&lt;br&gt;;; Copyright (C) 2006, 2007, 2008, 2009 &amp;nbsp;Markus Triska
&lt;br&gt;&lt;br&gt;;; Author: Markus Triska &amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26186265&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;markus.triska@...&lt;/a&gt;&amp;gt;
&lt;br&gt;;; Keywords: languages, processes
&lt;br&gt;&lt;br&gt;;; This file is free software; you can redistribute it and/or modify
&lt;br&gt;;; it under the terms of the GNU General Public License as published by
&lt;br&gt;;; the Free Software Foundation; either version 3, or (at your option)
&lt;br&gt;;; any later version.
&lt;br&gt;&lt;br&gt;;; This file is distributed in the hope that it will be useful,
&lt;br&gt;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
&lt;br&gt;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. &amp;nbsp;See the
&lt;br&gt;;; GNU General Public License for more details.
&lt;br&gt;&lt;br&gt;;; You should have received a copy of the GNU General Public License
&lt;br&gt;;; along with GNU Emacs; see the file COPYING. &amp;nbsp;If not, write to
&lt;br&gt;;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
&lt;br&gt;;; Boston, MA 02110-1301, USA.
&lt;br&gt;&lt;br&gt;;;; Commentary:
&lt;br&gt;&lt;br&gt;;; These definitions let you interact with SWI-Prolog in all buffers.
&lt;br&gt;;; You can consult Prolog programs and evaluate embedded queries.
&lt;br&gt;&lt;br&gt;;; Installation
&lt;br&gt;;; ============
&lt;br&gt;;;
&lt;br&gt;;; Copy ediprolog.el to your load-path and add to your .emacs:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; (require 'ediprolog)
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; (global-set-key [f10] 'ediprolog-dwim)
&lt;br&gt;;;
&lt;br&gt;;; Restart Emacs and customize ediprolog with
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; &amp;nbsp; M-x customize-group RET ediprolog RET
&lt;br&gt;;;
&lt;br&gt;&lt;br&gt;;; Usage
&lt;br&gt;;; =====
&lt;br&gt;;;
&lt;br&gt;;; The central function is `ediprolog-dwim' (Do What I Mean), which is
&lt;br&gt;;; bound to F10 by the snippet above. Depending on the content at
&lt;br&gt;;; point, `ediprolog-dwim' does the &amp;quot;appropriate&amp;quot; thing: If point is
&lt;br&gt;;; on a query, F10 sends the query to a Prolog process, and you
&lt;br&gt;;; interact with the process in the current buffer as on a terminal.
&lt;br&gt;;; Queries start with &amp;quot;?-&amp;quot; or &amp;quot;:-&amp;quot;, possibly preceded by &amp;quot;%&amp;quot; and
&lt;br&gt;;; whitespace. An example of a query is (without leading &amp;quot;;;&amp;quot;):
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; %?- member(X, [a,b,c]).
&lt;br&gt;;;
&lt;br&gt;;; If you press F10 when point is on that query, you get:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; %?- member(X, [a,b,c]).
&lt;br&gt;;; &amp;nbsp; %@ X = a ;
&lt;br&gt;;; &amp;nbsp; %@ X = b ;
&lt;br&gt;;; &amp;nbsp; %@ X = c ;
&lt;br&gt;;; &amp;nbsp; %@ false.
&lt;br&gt;;;
&lt;br&gt;;; When waiting for output of the Prolog process, you can press C-g to
&lt;br&gt;;; unblock Emacs and continue with other work. To resume interaction
&lt;br&gt;;; with the Prolog process, use M-x ediprolog-toplevel RET.
&lt;br&gt;&lt;br&gt;;; If you press F10 when point is NOT on a query, the buffer content
&lt;br&gt;;; is consulted in the Prolog process, and point is moved to the first
&lt;br&gt;;; error (if any).
&lt;br&gt;&lt;br&gt;;; For convenience, the most recent interactions with the Prolog
&lt;br&gt;;; process are logged in the buffer &amp;quot;*ediprolog-history*&amp;quot;.
&lt;br&gt;&lt;br&gt;;; Use M-x ediprolog-localize RET to make any Prolog process started
&lt;br&gt;;; in the current buffer buffer-local. This way, you can run distinct
&lt;br&gt;;; processes simultaneously. Revert with M-x ediprolog-unlocalize RET.
&lt;br&gt;&lt;br&gt;;; `ediprolog-dwim' with prefix arguments has special meanings:
&lt;br&gt;;;
&lt;br&gt;;; &amp;nbsp; C-0 F10 &amp;nbsp; &amp;nbsp; &amp;nbsp; kill Prolog process
&lt;br&gt;;; &amp;nbsp; C-1 F10 &amp;nbsp; &amp;nbsp; &amp;nbsp; always consult buffer (even when point is on a query)
&lt;br&gt;;; &amp;nbsp; C-2 F10 &amp;nbsp; &amp;nbsp; &amp;nbsp; always consult buffer, using a new process
&lt;br&gt;;; &amp;nbsp; C-7 F10 &amp;nbsp; &amp;nbsp; &amp;nbsp; equivalent to `ediprolog-toplevel'
&lt;br&gt;;; &amp;nbsp; C-u F10 &amp;nbsp; &amp;nbsp; &amp;nbsp; first consult buffer, then evaluate query (if any)
&lt;br&gt;;; &amp;nbsp; C-u C-u F10 &amp;nbsp; like C-u F10, with a new process
&lt;br&gt;&lt;br&gt;;; Tested with SWI-Prolog 5.6.55 + Emacs 21.2, 22.3 and 23.0.92.2.
&lt;br&gt;&lt;br&gt;;;; Code:
&lt;br&gt;&lt;br&gt;(defconst ediprolog-version &amp;quot;0.9yb&amp;quot;)
&lt;br&gt;&lt;br&gt;(defgroup ediprolog nil
&lt;br&gt;&amp;nbsp; &amp;quot;Transparent interaction with SWI-Prolog.&amp;quot;
&lt;br&gt;&amp;nbsp; :group 'languages
&lt;br&gt;&amp;nbsp; :group 'processes)
&lt;br&gt;&lt;br&gt;;;;###autoload
&lt;br&gt;(defcustom ediprolog-program
&lt;br&gt;&amp;nbsp; (or (executable-find &amp;quot;swipl&amp;quot;) (executable-find &amp;quot;pl&amp;quot;) &amp;quot;swipl&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;quot;Program name of the Prolog executable.&amp;quot;
&lt;br&gt;&amp;nbsp; :group 'ediprolog
&lt;br&gt;&amp;nbsp; :type 'string)
&lt;br&gt;&lt;br&gt;;;;###autoload
&lt;br&gt;(defcustom ediprolog-program-switches nil
&lt;br&gt;&amp;nbsp; &amp;quot;List of switches passed to the Prolog process. Example:
&lt;br&gt;'(\&amp;quot;-G128M\&amp;quot; \&amp;quot;-O\&amp;quot;)&amp;quot;
&lt;br&gt;&amp;nbsp; :group 'ediprolog
&lt;br&gt;&amp;nbsp; :type '(repeat string))
&lt;br&gt;&lt;br&gt;;;;###autoload
&lt;br&gt;(defcustom ediprolog-prefix &amp;quot;%@ &amp;quot;
&lt;br&gt;&amp;nbsp; &amp;quot;String to prepend when inserting output from the Prolog
&lt;br&gt;process into the buffer.&amp;quot;
&lt;br&gt;&amp;nbsp; :group 'ediprolog
&lt;br&gt;&amp;nbsp; :type 'string)
&lt;br&gt;&lt;br&gt;(defcustom ediprolog-max-history 80000
&lt;br&gt;&amp;nbsp; &amp;quot;Maximal size of history buffers storing recent interactions, or
&lt;br&gt;nil to never truncate the history.&amp;quot;
&lt;br&gt;&amp;nbsp; :group 'ediprolog
&lt;br&gt;&amp;nbsp; :type 'sexp)
&lt;br&gt;&lt;br&gt;(defvar ediprolog-process &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; nil &amp;quot;A Prolog process.&amp;quot;)
&lt;br&gt;&lt;br&gt;(defvar ediprolog-temp-buffer &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; nil
&lt;br&gt;&amp;nbsp; &amp;quot;Buffer that temporarily saves process output &amp;quot;)
&lt;br&gt;&lt;br&gt;(defvar ediprolog-seen-prompt &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; nil
&lt;br&gt;&amp;nbsp; &amp;quot;Whether a prompt was (recently) emitted by the Prolog process.&amp;quot;)
&lt;br&gt;&lt;br&gt;(defvar ediprolog-read-term &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; nil
&lt;br&gt;&amp;nbsp; &amp;quot;Whether the Prolog process waits for the user to enter a term.&amp;quot;)
&lt;br&gt;&lt;br&gt;(defvar ediprolog-indent-prefix &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;quot;&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;quot;Any whitespace occurring before the most recently executed query.&amp;quot;)
&lt;br&gt;&lt;br&gt;(defvar ediprolog-temp-file &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; nil
&lt;br&gt;&amp;nbsp; &amp;quot;File name of a temporary file used for consulting the buffer.&amp;quot;)
&lt;br&gt;&lt;br&gt;(defvar ediprolog-prompt &amp;quot;?ediprolog- &amp;quot;
&lt;br&gt;&amp;nbsp; &amp;quot;Prompt used in the Prolog session. It must differ from the
&lt;br&gt;default Prolog prompt.&amp;quot;)
&lt;br&gt;&lt;br&gt;(defvar ediprolog-consult-buffer &amp;quot;*ediprolog-consult*&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;quot;Buffer used to display consult output.&amp;quot;)
&lt;br&gt;&lt;br&gt;(defvar ediprolog-consult-window &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;nil
&lt;br&gt;&amp;nbsp; &amp;quot;Window used to show consult output.&amp;quot;)
&lt;br&gt;&lt;br&gt;(defvar ediprolog-history-buffer &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;nil
&lt;br&gt;&amp;nbsp; &amp;quot;Buffer that stores recent interactions.&amp;quot;)
&lt;br&gt;&lt;br&gt;(defvar ediprolog-interrupted &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; nil
&lt;br&gt;&amp;nbsp; &amp;quot;True iff waiting for the previous query was interrupted with C-g.&amp;quot;)
&lt;br&gt;&lt;br&gt;(defmacro ediprolog-wait-for-prompt-after (&amp;rest forms)
&lt;br&gt;&amp;nbsp; &amp;quot;Evaluate FORMS and wait for prompt.&amp;quot;
&lt;br&gt;&amp;nbsp; `(progn
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(setq ediprolog-seen-prompt nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(ediprolog-ensure-buffer &amp;quot;temp&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(with-current-buffer ediprolog-temp-buffer
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(let (buffer-read-only)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(erase-buffer)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;;; execute forms with default-directory etc. from invocation buffer
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;,@forms
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(unless (process-filter ediprolog-process)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(set-process-filter ediprolog-process 'ediprolog-wait-for-prompt-filter))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(while (not ediprolog-seen-prompt)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; Wait for output/sentinel and update consult window, if any.
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; As `accept-process-output' does not run the sentinel in
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; Emacs &amp;lt;= 23.1, we use `sit-for' to do both. However,
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; `sit-for' returns immediately if keyboard input is
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; available, so we must discard input.
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(discard-input)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(sit-for 0.1))))
&lt;br&gt;&lt;br&gt;(defmacro ediprolog-remember-interruption (form)
&lt;br&gt;&amp;nbsp; &amp;quot;Set `ediprolog-interrupted' if evaluation of FORM was interrupted.&amp;quot;
&lt;br&gt;&amp;nbsp; `(condition-case nil
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;,form
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(quit (setq ediprolog-interrupted t))))
&lt;br&gt;&lt;br&gt;;; Only the sentinel can reliably detect if no more output follows -
&lt;br&gt;;; even if process-status is 'exit, further output can still follow.
&lt;br&gt;(defun ediprolog-sentinel (proc str)
&lt;br&gt;&amp;nbsp; (when (buffer-live-p (process-buffer proc))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (with-current-buffer (process-buffer proc)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (let ((status (with-temp-buffer
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (insert str)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (while (search-backward &amp;quot;\n&amp;quot; nil t)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (replace-match &amp;quot;&amp;quot;))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (buffer-string))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (ediprolog-log
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(format &amp;quot;%s: %s.\n&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(substring (current-time-string) 4 -5) status) &amp;quot;green&amp;quot; t))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (when (string-match &amp;quot;^\\(?:finished\n\\|exited abnormally\\|killed\n\\)&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; str)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq ediprolog-seen-prompt t)))))
&lt;br&gt;&lt;br&gt;(defun ediprolog-ensure-buffer (name)
&lt;br&gt;&amp;nbsp; (let ((str (format &amp;quot;*ediprolog-%s*&amp;quot; name))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (var (intern (format &amp;quot;ediprolog-%s-buffer&amp;quot; name))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (unless (buffer-live-p (symbol-value var))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (set var (generate-new-buffer str))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (with-current-buffer (symbol-value var)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (buffer-disable-undo)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq buffer-read-only t)))))
&lt;br&gt;&lt;br&gt;(defun ediprolog-log (str &amp;optional col nl)
&lt;br&gt;&amp;nbsp; (ediprolog-ensure-buffer &amp;quot;history&amp;quot;)
&lt;br&gt;&amp;nbsp; (with-current-buffer ediprolog-history-buffer
&lt;br&gt;&amp;nbsp; &amp;nbsp; (let (buffer-read-only)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char (point-max))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (let ((s (format &amp;quot;%s%s&amp;quot; (if (and nl (not (bolp))) &amp;quot;\n&amp;quot; &amp;quot;&amp;quot;) str)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (insert (if col (propertize s 'face `(:background ,col)) s)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (let ((size (- (point-max) (point-min))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (when (and ediprolog-max-history
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(&amp;gt; size ediprolog-max-history))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; delete older half of the (possibly narrowed) history
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (delete-region (point-min) (+ (point-min) (/ size 2))))))))
&lt;br&gt;&lt;br&gt;(defun ediprolog-run-prolog ()
&lt;br&gt;&amp;nbsp; &amp;quot;Start a Prolog process.&amp;quot;
&lt;br&gt;&amp;nbsp; (let ((args (cons ediprolog-program ediprolog-program-switches)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (ediprolog-log (format &amp;quot;%s: starting: %S\n&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(substring (current-time-string) 4 -5) args)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;green&amp;quot; t)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (condition-case nil
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (ediprolog-wait-for-prompt-after
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setq ediprolog-process
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(apply #'start-process &amp;quot;ediprolog&amp;quot; (current-buffer) args))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(set-process-sentinel ediprolog-process 'ediprolog-sentinel)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(ediprolog-send-string
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (format &amp;quot;'$set_prompt'('%s').\n&amp;quot; ediprolog-prompt)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ((error quit)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(ediprolog-log &amp;quot;No prompt found.&amp;quot; &amp;quot;red&amp;quot; t)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(error &amp;quot;No prompt from: %s&amp;quot; ediprolog-program)))))
&lt;br&gt;&lt;br&gt;(defun ediprolog-kill-prolog ()
&lt;br&gt;&amp;nbsp; &amp;quot;Kill the Prolog process and run the process sentinel.&amp;quot;
&lt;br&gt;&amp;nbsp; (when (ediprolog-running)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (delete-process ediprolog-process)))
&lt;br&gt;&lt;br&gt;(defun ediprolog-show-consult-output (str)
&lt;br&gt;&amp;nbsp; (with-current-buffer (get-buffer-create ediprolog-consult-buffer)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq buffer-read-only t)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (let (buffer-read-only)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (erase-buffer)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (insert str)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char (point-min))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ;; remove normal consult status lines, which start with &amp;quot;%&amp;quot; 
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (while (re-search-forward &amp;quot;^[\t ]*%.*\n&amp;quot; nil t)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (delete-region (match-beginning 0) (match-end 0))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq str (buffer-string)))
&lt;br&gt;&amp;nbsp; ;; show consult output in a separate window unless it is a prefix of
&lt;br&gt;&amp;nbsp; ;; success (i.e., consulted without errors), or still an incomplete
&lt;br&gt;&amp;nbsp; ;; line that starts with a comment character
&lt;br&gt;&amp;nbsp; (unless (or (string-match &amp;quot;^[\t ]*\\(?:%.*\\)?\\'&amp;quot; str)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (let ((success &amp;quot;true.&amp;quot;))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (and (&amp;lt;= (length str) (length success))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(string= str (substring success 0 (length str))))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq ediprolog-consult-window (display-buffer ediprolog-consult-buffer))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (set-window-dedicated-p ediprolog-consult-window t)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (fit-window-to-buffer ediprolog-consult-window (/ (frame-height) 2))))
&lt;br&gt;&lt;br&gt;(defun ediprolog-consult-filter (proc str)
&lt;br&gt;&amp;nbsp; &amp;quot;Filter used when consulting a file, showing consult output.&amp;quot;
&lt;br&gt;&amp;nbsp; (with-current-buffer (ediprolog-temp-buffer proc)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (goto-char (point-max))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (let (buffer-read-only)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (insert str))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (with-current-buffer (process-buffer proc)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (ediprolog-log str))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (when (re-search-backward
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(format &amp;quot;^%s&amp;quot; (regexp-quote ediprolog-prompt)) nil t)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (with-current-buffer (process-buffer proc)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq ediprolog-seen-prompt t)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (skip-chars-backward &amp;quot;\n&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (ediprolog-show-consult-output (buffer-substring (point-min) (point)))))
&lt;br&gt;&lt;br&gt;(defun ediprolog-wait-for-prompt-filter (proc str)
&lt;br&gt;&amp;nbsp; &amp;quot;Filter that only waits until prompt appears.&amp;quot;
&lt;br&gt;&amp;nbsp; (with-current-buffer (ediprolog-temp-buffer proc)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (goto-char (point-max))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (let (buffer-read-only)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (insert str))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (with-current-buffer (process-buffer proc)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (ediprolog-log str))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (when (re-search-backward
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(format &amp;quot;^%s&amp;quot; (regexp-quote ediprolog-prompt)) nil t)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (with-current-buffer (process-buffer proc)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq ediprolog-seen-prompt t)))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;;;;###autoload
&lt;br&gt;(defun ediprolog-dwim (&amp;optional arg)
&lt;br&gt;&amp;nbsp; &amp;quot;Load current buffer into Prolog or post query (Do What I Mean).
&lt;br&gt;If invoked on a line starting with `:-' or `?-', possibly
&lt;br&gt;preceded by `%' and whitespace, call `ediprolog-interact' with
&lt;br&gt;the query as argument. Otherwise, call `ediprolog-consult'.
&lt;br&gt;&lt;br&gt;With prefix argument 0, kill the Prolog process. With prefix 1,
&lt;br&gt;equivalent to `ediprolog-consult'. With prefix 2, equivalent to
&lt;br&gt;`ediprolog-consult' with a new Prolog process. With prefix 7,
&lt;br&gt;equivalent to `ediprolog-toplevel'. With just C-u, first call
&lt;br&gt;`ediprolog-consult' and then, if point is on a query, call
&lt;br&gt;`ediprolog-interact' with it as argument. Analogously, C-u C-u
&lt;br&gt;for `ediprolog-consult' with a new process. With other prefix
&lt;br&gt;arguments, equivalent to `ediprolog-remove-interactions'.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive &amp;quot;P&amp;quot;)
&lt;br&gt;&amp;nbsp; (cond ((eq arg 0)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(unless (ediprolog-running)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(error &amp;quot;No Prolog process running&amp;quot;))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(ediprolog-kill-prolog)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(message &amp;quot;Prolog process killed.&amp;quot;))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ((eq arg 1) (ediprolog-consult))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ((eq arg 2) (ediprolog-consult t))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ((eq arg 7)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(unless (ediprolog-more-solutions)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(error &amp;quot;No query in progress&amp;quot;))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(ediprolog-toplevel))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ((equal arg '(4)) (ediprolog-consult) (ediprolog-query))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ((equal arg '(16)) (ediprolog-consult t) (ediprolog-query))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ((null arg) (unless (ediprolog-query) (ediprolog-consult)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (t (ediprolog-remove-interactions))))
&lt;br&gt;&lt;br&gt;(defun ediprolog-process-ready ()
&lt;br&gt;&amp;nbsp; &amp;quot;Error if the previous query is still in progress.&amp;quot;
&lt;br&gt;&amp;nbsp; (when (and ediprolog-interrupted
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(ediprolog-running)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(ediprolog-more-solutions))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (error &amp;quot;Previous query still in progress, see `ediprolog-toplevel'&amp;quot;))
&lt;br&gt;&amp;nbsp; (setq ediprolog-interrupted nil))
&lt;br&gt;&lt;br&gt;(defun ediprolog-query ()
&lt;br&gt;&amp;nbsp; &amp;quot;If point is on a query, send it to the process and start interaction.&amp;quot;
&lt;br&gt;&amp;nbsp; (ediprolog-process-ready)
&lt;br&gt;&amp;nbsp; (when (and (not (and transient-mark-mode mark-active))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(save-excursion
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(beginning-of-line)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(looking-at &amp;quot;\\([\t ]*\\)%*[\t ]*[:?]-&amp;quot;)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; whitespace preceding the query is the indentation level
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq ediprolog-indent-prefix (match-string 1))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (let* ((from (goto-char (match-end 0)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(to (if (re-search-forward &amp;quot;\\.[\t ]*\\(?:%.*\\)?$&amp;quot; nil t)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; omit trailing whitespace
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(+ (point) (skip-chars-backward &amp;quot;\t &amp;quot;))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(error &amp;quot;Missing `.' at the end of this query&amp;quot;)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(query (buffer-substring-no-properties from to)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (end-of-line)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (insert &amp;quot;\n&amp;quot; ediprolog-indent-prefix ediprolog-prefix)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (ediprolog-interact
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(format &amp;quot;%s\n&amp;quot; (mapconcat #'identity
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; `%' can precede each query line
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(split-string query &amp;quot;\n[ \t%]*&amp;quot;) &amp;quot; &amp;quot;))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; t))
&lt;br&gt;&lt;br&gt;;;;###autoload
&lt;br&gt;(defun ediprolog-interact (query)
&lt;br&gt;&amp;nbsp; &amp;quot;Send QUERY to Prolog process and interact as on a terminal.
&lt;br&gt;&lt;br&gt;You can use \\[keyboard-quit] to unblock Emacs in the case of
&lt;br&gt;longer-running queries. When the query completes and the toplevel
&lt;br&gt;asks for input, use \\[ediprolog-toplevel] to resume interaction
&lt;br&gt;with the Prolog process.&amp;quot;
&lt;br&gt;&amp;nbsp; (unless (ediprolog-running)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (ediprolog-run-prolog))
&lt;br&gt;&amp;nbsp; (set-marker (process-mark ediprolog-process) (point))
&lt;br&gt;&amp;nbsp; (set-process-buffer ediprolog-process (current-buffer))
&lt;br&gt;&amp;nbsp; (set-process-filter ediprolog-process 'ediprolog-interact-filter)
&lt;br&gt;&amp;nbsp; (ediprolog-ensure-buffer &amp;quot;temp&amp;quot;)
&lt;br&gt;&amp;nbsp; (with-current-buffer ediprolog-temp-buffer
&lt;br&gt;&amp;nbsp; &amp;nbsp; (let (buffer-read-only)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (erase-buffer)))
&lt;br&gt;&amp;nbsp; (setq ediprolog-seen-prompt nil
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ediprolog-read-term nil)
&lt;br&gt;&amp;nbsp; (ediprolog-send-string query)
&lt;br&gt;&amp;nbsp; (ediprolog-toplevel))
&lt;br&gt;&lt;br&gt;(defun ediprolog-send-string (str)
&lt;br&gt;&amp;nbsp; &amp;quot;Send string to Prolog process and log it.&amp;quot;
&lt;br&gt;&amp;nbsp; (ediprolog-log str &amp;quot;cyan&amp;quot;)
&lt;br&gt;&amp;nbsp; (process-send-string ediprolog-process str))
&lt;br&gt;&lt;br&gt;(defun ediprolog-toplevel ()
&lt;br&gt;&amp;nbsp; &amp;quot;Start or resume Prolog toplevel interaction in the buffer.
&lt;br&gt;&lt;br&gt;You can use this function if you have previously quit (with
&lt;br&gt;\\[keyboard-quit]) waiting for a longer-running query and now
&lt;br&gt;want to resume interaction with the toplevel.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive)
&lt;br&gt;&amp;nbsp; (when ediprolog-process
&lt;br&gt;&amp;nbsp; &amp;nbsp; (select-window (display-buffer (process-buffer ediprolog-process))))
&lt;br&gt;&amp;nbsp; (ediprolog-remember-interruption
&lt;br&gt;&amp;nbsp; &amp;nbsp;(while (ediprolog-more-solutions)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(let (str
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;char)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; poll for user input; meanwhile, process output can arrive
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(while (and (ediprolog-more-solutions) (null str))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(goto-char (process-mark ediprolog-process))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(if ediprolog-read-term
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(progn
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setq str (concat (read-string &amp;quot;Input: &amp;quot;) &amp;quot;\n&amp;quot;))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(ediprolog-insert-at-marker
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; str ediprolog-indent-prefix ediprolog-prefix)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setq ediprolog-read-term nil))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(condition-case nil
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(when (setq char (if (&amp;gt;= emacs-major-version 22)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (read-char nil nil 0.1)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (with-timeout (0.1 nil)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (read-char))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; char-to-string might still yield an error (C-0 etc.)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(setq str (char-to-string char)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(error
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (message &amp;quot;Non-character key&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; non-character keys must not remain in the input
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; buffer, lest `read-char' return immediately
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (discard-input)))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(when (ediprolog-more-solutions)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(if (eq char ?\C-c) &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;; char can be nil too
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;;; sending C-c directly yields strange SWI buffering
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(interrupt-process ediprolog-process)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(ediprolog-send-string str)))))))
&lt;br&gt;&lt;br&gt;;;;###autoload
&lt;br&gt;(defun ediprolog-remove-interactions ()
&lt;br&gt;&amp;nbsp; &amp;quot;Remove all lines starting with `ediprolog-prefix' from buffer.
&lt;br&gt;&lt;br&gt;In transient mark mode, the function operates on the region if it
&lt;br&gt;is active.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive)
&lt;br&gt;&amp;nbsp; (save-excursion
&lt;br&gt;&amp;nbsp; &amp;nbsp; (save-restriction
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (when (and transient-mark-mode mark-active)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (narrow-to-region (region-beginning) (region-end)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char (point-min))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (flush-lines (concat &amp;quot;^[\t ]*&amp;quot; (regexp-quote ediprolog-prefix)))))
&lt;br&gt;&amp;nbsp; (message &amp;quot;Interactions removed.&amp;quot;))
&lt;br&gt;&lt;br&gt;&lt;br&gt;;;;###autoload
&lt;br&gt;(defun ediprolog-consult (&amp;optional new-process)
&lt;br&gt;&amp;nbsp; &amp;quot;Buffer is loaded into a Prolog process. If NEW-PROCESS is
&lt;br&gt;non-nil, start a new process. Otherwise use the existing process,
&lt;br&gt;if any. In case of errors, point is moved to the position of the
&lt;br&gt;first error, and the mark is left at the previous position.
&lt;br&gt;&lt;br&gt;In transient mark mode, the function operates on the region if it
&lt;br&gt;is active.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive)
&lt;br&gt;&amp;nbsp; (when (string= (buffer-name) ediprolog-consult-buffer)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (error &amp;quot;Cannot consult the consult buffer&amp;quot;))
&lt;br&gt;&amp;nbsp; (when (window-live-p ediprolog-consult-window)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (condition-case nil
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; deleting the window can still raise an error, if the window
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; was the only window in the frame and the consult buffer was
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; killed (and it thus displays a different buffer now)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (delete-window ediprolog-consult-window)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (error nil)))
&lt;br&gt;&amp;nbsp; (when (buffer-live-p ediprolog-consult-buffer)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (bury-buffer ediprolog-consult-buffer))
&lt;br&gt;&amp;nbsp; (when new-process
&lt;br&gt;&amp;nbsp; &amp;nbsp; (ediprolog-kill-prolog))
&lt;br&gt;&amp;nbsp; (unless (ediprolog-running)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (ediprolog-run-prolog))
&lt;br&gt;&amp;nbsp; (ediprolog-process-ready)
&lt;br&gt;&amp;nbsp; (set-process-buffer ediprolog-process (current-buffer))
&lt;br&gt;&amp;nbsp; (unless ediprolog-temp-file
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq ediprolog-temp-file (make-temp-file &amp;quot;ediprolog&amp;quot;)))
&lt;br&gt;&amp;nbsp; (let ((start (if (and transient-mark-mode mark-active)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(region-beginning) (point-min)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (end (if (and transient-mark-mode mark-active)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(region-end) (point-max))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (write-region start end ediprolog-temp-file nil 'silent))
&lt;br&gt;&amp;nbsp; (set-process-filter ediprolog-process 'ediprolog-consult-filter)
&lt;br&gt;&amp;nbsp; (ediprolog-remember-interruption
&lt;br&gt;&amp;nbsp; &amp;nbsp;(ediprolog-wait-for-prompt-after
&lt;br&gt;&amp;nbsp; &amp;nbsp; (ediprolog-send-string (format &amp;quot;['%s'].\n&amp;quot; ediprolog-temp-file))))
&lt;br&gt;&amp;nbsp; (message &amp;quot;%s consulted.&amp;quot; (if (and transient-mark-mode mark-active)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;Region&amp;quot; &amp;quot;Buffer&amp;quot;))
&lt;br&gt;&amp;nbsp; ;; go to line of the first error, if any
&lt;br&gt;&amp;nbsp; (let ((line (with-current-buffer ediprolog-temp-buffer
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (when (save-excursion
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char (point-min))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (re-search-forward &amp;quot;^ERROR.*?:\\([0-9]+\\)&amp;quot; nil t))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (string-to-number (match-string 1))))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (when line
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (if (and transient-mark-mode mark-active)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (when (fboundp 'line-number-at-pos)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-line (+ (line-number-at-pos (region-beginning)) line -1)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-line line)))))
&lt;br&gt;&lt;br&gt;(defun ediprolog-running ()
&lt;br&gt;&amp;nbsp; &amp;quot;True iff `ediprolog-process' is a running process.&amp;quot;
&lt;br&gt;&amp;nbsp; (and (processp ediprolog-process)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(eq (process-status ediprolog-process) 'run)))
&lt;br&gt;&lt;br&gt;(defun ediprolog-more-solutions ()
&lt;br&gt;&amp;nbsp; &amp;quot;True iff there could be more solutions from the process.&amp;quot;
&lt;br&gt;&amp;nbsp; (not ediprolog-seen-prompt))
&lt;br&gt;&lt;br&gt;(defun ediprolog-interact-filter (proc string)
&lt;br&gt;&amp;nbsp; &amp;quot;Insert output from the process and update the state.&amp;quot;
&lt;br&gt;&amp;nbsp; (when (and (buffer-live-p (ediprolog-temp-buffer proc))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(buffer-live-p (process-buffer proc)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (let (str)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; (with-current-buffer (ediprolog-temp-buffer proc)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char (point-max))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (let (buffer-read-only)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (insert string))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (with-current-buffer (process-buffer proc)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (ediprolog-log string))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; read a term from the user?
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (when (re-search-backward &amp;quot;^|: $&amp;quot; nil t)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (with-current-buffer (process-buffer proc)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq ediprolog-read-term t))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq str (buffer-string))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (let (buffer-read-only)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (erase-buffer)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; check for prompt
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char (point-max))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (when (re-search-backward
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(format &amp;quot;^%s&amp;quot; (regexp-quote ediprolog-prompt)) nil t)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (with-current-buffer (process-buffer proc)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq ediprolog-seen-prompt t))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; ignore further output due to accidental user input (C-j,
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; C-m, etc.) while the query was running
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (set-process-filter proc 'ediprolog-ignore-filter)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (skip-chars-backward &amp;quot;\n&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq str (buffer-substring (point-min) (point))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (unless str
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char (point-max))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; delay final line if it can still be completed to prompt
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (let ((l (buffer-substring (line-beginning-position) (point))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (when (and (&amp;lt;= (length l) (length ediprolog-prompt))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(string= l (substring ediprolog-prompt 0 (length l))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char (line-beginning-position))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; delay emitting newlines until we are sure no prompt
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; follows; one or two newlines can precede a prompt
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (let ((d (abs (skip-chars-backward &amp;quot;\n&amp;quot;))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (when (&amp;gt; d 2)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (forward-char (- d 2))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq str (buffer-substring (point-min) (point)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (let (buffer-read-only)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (delete-region (point-min) (point))))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (when str
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (with-temp-buffer
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; precede each line with ediprolog prefices
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (insert str)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char (point-min))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (while (search-forward &amp;quot;\n&amp;quot; nil t)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (replace-match
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(format &amp;quot;\n%s%s&amp;quot; (with-current-buffer (process-buffer proc)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ediprolog-indent-prefix) ediprolog-prefix)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (setq str (buffer-string)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (with-current-buffer (process-buffer proc)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (let ((near (&amp;lt;= (abs (- (point) (process-mark proc))) 1)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (ediprolog-insert-at-marker str)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (when near
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ;; catch up with output if point was reasonably close
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (goto-char (process-mark proc))))))))))
&lt;br&gt;&lt;br&gt;&lt;br&gt;(defun ediprolog-insert-at-marker (&amp;rest args)
&lt;br&gt;&amp;nbsp; &amp;quot;Insert strings ARGS at marker and update the marker.&amp;quot;
&lt;br&gt;&amp;nbsp; (save-excursion
&lt;br&gt;&amp;nbsp; &amp;nbsp; (goto-char (process-mark ediprolog-process))
&lt;br&gt;&amp;nbsp; &amp;nbsp; (end-of-line)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (apply #'insert args)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (set-marker (process-mark ediprolog-process) (point))))
&lt;br&gt;&lt;br&gt;(defun ediprolog-ignore-filter (proc str)
&lt;br&gt;&amp;nbsp; &amp;quot;Log and then ignore all process output.&amp;quot;
&lt;br&gt;&amp;nbsp; (with-current-buffer (process-buffer proc)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (ediprolog-log str &amp;quot;gray&amp;quot;)))
&lt;br&gt;&lt;br&gt;(defun ediprolog-temp-buffer (proc)
&lt;br&gt;&amp;nbsp; (with-current-buffer (process-buffer proc)
&lt;br&gt;&amp;nbsp; &amp;nbsp; ;; temp buffer can be buffer local
&lt;br&gt;&amp;nbsp; &amp;nbsp; ediprolog-temp-buffer))
&lt;br&gt;&lt;br&gt;(defun ediprolog-map-variables (func)
&lt;br&gt;&amp;nbsp; &amp;quot;Call FUNC with all ediprolog variables that can become buffer-local.&amp;quot;
&lt;br&gt;&amp;nbsp; (mapc func '(ediprolog-process
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;ediprolog-program
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;ediprolog-program-switches
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;ediprolog-temp-buffer
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;ediprolog-history-buffer
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;ediprolog-seen-prompt
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;ediprolog-interrupted
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;ediprolog-read-term
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;ediprolog-indent-prefix
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;ediprolog-temp-file)))
&lt;br&gt;&lt;br&gt;;;;###autoload
&lt;br&gt;(defun ediprolog-localize ()
&lt;br&gt;&amp;nbsp; &amp;quot;After `ediprolog-localize', any Prolog process started from
&lt;br&gt;this buffer becomes buffer-local.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive)
&lt;br&gt;&amp;nbsp; (unless (local-variable-p 'ediprolog-process)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (ediprolog-map-variables #'make-local-variable)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (setq ediprolog-temp-file nil
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ediprolog-process nil
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ediprolog-history-buffer nil
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ediprolog-temp-buffer nil)))
&lt;br&gt;&lt;br&gt;(defun ediprolog-unlocalize ()
&lt;br&gt;&amp;nbsp; &amp;quot;Revert the effect of `ediprolog-localize'.&amp;quot;
&lt;br&gt;&amp;nbsp; (interactive)
&lt;br&gt;&amp;nbsp; (when (local-variable-p 'ediprolog-process)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (ediprolog-kill-prolog)
&lt;br&gt;&amp;nbsp; &amp;nbsp; (ediprolog-map-variables #'kill-local-variable)))
&lt;br&gt;&lt;br&gt;(provide 'ediprolog)
&lt;br&gt;&lt;br&gt;;;; ediprolog.el ends here
&lt;br&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26186265&amp;i=1&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/ediprolog-0.9yb----Emacs-Does-Interactive-Prolog-tp26186265p26186265.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-26127685</id>
	<title>cal-china-x.el --- Chinese calendar extras v1.1</title>
	<published>2009-10-30T03:15:46Z</published>
	<updated>2009-10-30T03:15:46Z</updated>
	<author>
		<name>William Xu-2</name>
	</author>
	<content type="html">Would be the last version that supports emacs22, for there are quite a
&lt;br&gt;few naming changes warnings introduced from 23.1.
&lt;br&gt;&lt;br&gt;CHANGES SINCE 1.0
&lt;br&gt;-------------------
&lt;br&gt;&amp;nbsp; - Also display week number on date under cursor. &amp;nbsp;
&lt;br&gt;&lt;br&gt;WHAT IS IT?
&lt;br&gt;-----------
&lt;br&gt;This package adds more chinese calendar supports and others,
&lt;br&gt;including:
&lt;br&gt;&lt;br&gt;&amp;nbsp; - Chinese localizations
&lt;br&gt;&amp;nbsp; - Display holiday, lunar, horoscope, zodiac, solar term info on mode line
&lt;br&gt;&amp;nbsp; - Can define holidays using `holiday-lunar', `holiday-solar-term'
&lt;br&gt;&amp;nbsp; - Highlight holidays based on different priorities
&lt;br&gt;&amp;nbsp; - Add `cal-china-x-chinese-holidays', `cal-china-x-japanese-holidays'.
&lt;br&gt;&lt;br&gt;To use, add the following in your .emacs:
&lt;br&gt;&amp;nbsp; &amp;nbsp; (require 'cal-china-x)
&lt;br&gt;&lt;br&gt;&lt;br /&gt; &lt;br /&gt;&lt;br&gt;-- 
&lt;br&gt;William
&lt;br&gt;&lt;br&gt;&lt;a href=&quot;http://xwl.appspot.com&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://xwl.appspot.com&lt;/a&gt;&lt;br&gt;&lt;br /&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26127685&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;&lt;div class=&quot;small&quot;&gt;&lt;br/&gt;&lt;img src=&quot;http://old.nabble.com/images/icon_attachment.gif&quot; &gt; &lt;strong&gt;cal-china-x.el&lt;/strong&gt; (32K) &lt;a href=&quot;http://old.nabble.com/attachment/26127685/0/cal-china-x.el&quot; target=&quot;_top&quot;&gt;Download Attachment&lt;/a&gt;&lt;/div&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/cal-china-x.el-----Chinese-calendar-extras-v1.1-tp26127685p26127685.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-26092400</id>
	<title>bookmark-search</title>
	<published>2009-10-28T03:26:11Z</published>
	<updated>2009-10-28T03:26:11Z</updated>
	<author>
		<name>Thierry Volpiatto-2</name>
	</author>
	<content type="html">Fix docstring in bookmark-search.el
&lt;br&gt;Use remove-if-not instead of loop.
&lt;br&gt;Find changes here also:
&lt;br&gt;&lt;a href=&quot;http://mercurial.intuxication.org/hg/bookmark-search&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://mercurial.intuxication.org/hg/bookmark-search&lt;/a&gt;&lt;br&gt;&lt;br&gt;-- 
&lt;br&gt;A + Thierry Volpiatto
&lt;br&gt;Location: Saint-Cyr-Sur-Mer - France
&lt;br&gt;&lt;br&gt;&lt;br /&gt; &lt;br /&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26092400&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;&lt;div class=&quot;small&quot;&gt;&lt;br/&gt;&lt;img src=&quot;http://old.nabble.com/images/icon_attachment.gif&quot; &gt; &lt;strong&gt;bookmark-search.el&lt;/strong&gt; (7K) &lt;a href=&quot;http://old.nabble.com/attachment/26092400/0/bookmark-search.el&quot; target=&quot;_top&quot;&gt;Download Attachment&lt;/a&gt;&lt;/div&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/bookmark-search-tp26092400p26092400.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-26085396</id>
	<title>bug fix in sbookmark-search</title>
	<published>2009-10-27T14:14:07Z</published>
	<updated>2009-10-27T14:14:07Z</updated>
	<author>
		<name>Thierry Volpiatto-2</name>
	</author>
	<content type="html">Fix error with run-with-idle-timer.
&lt;br&gt;Thanks to Uwe and Aidan.
&lt;br&gt;&lt;br&gt;The code can be found also here:
&lt;br&gt;&lt;br&gt;&lt;a href=&quot;http://mercurial.intuxication.org/hg/bookmark-search&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://mercurial.intuxication.org/hg/bookmark-search&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;-- 
&lt;br&gt;A + Thierry Volpiatto
&lt;br&gt;Location: Saint-Cyr-Sur-Mer - France
&lt;br&gt;&lt;br&gt;&lt;br /&gt; &lt;br /&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26085396&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;&lt;div class=&quot;small&quot;&gt;&lt;br/&gt;&lt;img src=&quot;http://old.nabble.com/images/icon_attachment.gif&quot; &gt; &lt;strong&gt;bookmark-search.el&lt;/strong&gt; (7K) &lt;a href=&quot;http://old.nabble.com/attachment/26085396/0/bookmark-search.el&quot; target=&quot;_top&quot;&gt;Download Attachment&lt;/a&gt;&lt;/div&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/bug-fix-in-sbookmark-search-tp26085396p26085396.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-26046162</id>
	<title>search command for bookmark</title>
	<published>2009-10-25T01:50:10Z</published>
	<updated>2009-10-25T01:50:10Z</updated>
	<author>
		<name>Thierry Volpiatto-2</name>
	</author>
	<content type="html">Hi,
&lt;br&gt;here a little file that modify implementation of bookmark-bmenu-bookmark
&lt;br&gt;in bookmark.el and provide a convenient search command for bookmarks.
&lt;br&gt;It is bound to M-g in bookmark list.
&lt;br&gt;&lt;br&gt;To use just load the file, use C-x r l as usual to get your bookmark
&lt;br&gt;list, and then just hit M-g.
&lt;br&gt;Enter characters...Remove characters... that is an incremental search
&lt;br&gt;command that will narrow your bookmark list.
&lt;br&gt;&lt;br&gt;&lt;br&gt;-- 
&lt;br&gt;A + Thierry Volpiatto
&lt;br&gt;Location: Saint-Cyr-Sur-Mer - France
&lt;br&gt;&lt;br&gt;&lt;br /&gt; &lt;br /&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26046162&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;&lt;div class=&quot;small&quot;&gt;&lt;br/&gt;&lt;img src=&quot;http://old.nabble.com/images/icon_attachment.gif&quot; &gt; &lt;strong&gt;bookmark-search.el&lt;/strong&gt; (7K) &lt;a href=&quot;http://old.nabble.com/attachment/26046162/0/bookmark-search.el&quot; target=&quot;_top&quot;&gt;Download Attachment&lt;/a&gt;&lt;/div&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/search-command-for-bookmark-tp26046162p26046162.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-26044304</id>
	<title>info-lookmore.el</title>
	<published>2009-10-24T17:28:52Z</published>
	<updated>2009-10-24T17:28:52Z</updated>
	<author>
		<name>Kevin Ryde</name>
	</author>
	<content type="html">This is a few lines I've used for a long time for extra info-look
&lt;br&gt;manuals ... worked over to a half presentable state.
&lt;br&gt;&lt;br&gt;The bit favouring the elisp manual over the user manual is may be a
&lt;br&gt;candidate for info-look.el itself, if info-lookup-symbol is mainly a
&lt;br&gt;programming tool.
&lt;br&gt;&lt;br&gt;&lt;br /&gt; &lt;br /&gt;-----BEGIN PGP SIGNATURE-----
&lt;br&gt;Version: GnuPG v1.4.10 (GNU/Linux)
&lt;br&gt;&lt;br&gt;iD8DBQBK45QNLFMCIV9q3ToRAqSAAJ0TnTUe1Ny1zFL4Lna2Q1k/Dx3oWwCeMXDt
&lt;br&gt;aBnW56Y6rQA9n+LKQs8H3Mg=
&lt;br&gt;=tRvr
&lt;br&gt;-----END PGP SIGNATURE-----
&lt;br&gt;&lt;br /&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26044304&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;&lt;div class=&quot;small&quot;&gt;&lt;br/&gt;&lt;img src=&quot;http://old.nabble.com/images/icon_attachment.gif&quot; &gt; &lt;strong&gt;info-lookmore.el&lt;/strong&gt; (11K) &lt;a href=&quot;http://old.nabble.com/attachment/26044304/0/info-lookmore.el&quot; target=&quot;_top&quot;&gt;Download Attachment&lt;/a&gt;&lt;/div&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/info-lookmore.el-tp26044304p26044304.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-26039138</id>
	<title>Sunrise Commander: Tabs Extension</title>
	<published>2009-10-24T06:17:19Z</published>
	<updated>2009-10-24T06:17:19Z</updated>
	<author>
		<name>José A. Romero L.</name>
	</author>
	<content type="html">Hello Emacs Community,
&lt;br&gt;&lt;br&gt;I'm glad to announce the first release of another add-on for the
&lt;br&gt;Sunrise Commander File Manager[1]: the Tabs extension.
&lt;br&gt;&lt;br&gt;This extension brings tab‐based navigation to the Sunrise Commander.
&lt;br&gt;It adds to the list of optional mechanisms already available in
&lt;br&gt;Sunrise for moving around the file system (like regular bookmarks,
&lt;br&gt;checkpoints, history rings, materialized virtual buffers, navigable
&lt;br&gt;paths and file‐following) another way to maintain a list of selected
&lt;br&gt;locations one wants to return later on, or to compose &amp;quot;breadcrumb
&lt;br&gt;trails&amp;quot; for complex repetitive operations. Creating, using and
&lt;br&gt;destroying tabs are fast and easy operations, either with mouse or
&lt;br&gt;keyboard.
&lt;br&gt;&lt;br&gt;The main difference between tabs and other mechanisms (besides the
&lt;br&gt;visual feedback) is that once a buffer has been assigned to a tab, it
&lt;br&gt;will not be killed automatically by Sunrise, so it’s possible to keep
&lt;br&gt;it around as long as necessary with all its marks and state untouched.
&lt;br&gt;&lt;br&gt;For this extension to work properly you need version 3R208 (or newer)
&lt;br&gt;of the Sunrise Commander. To get a copy (including installation and
&lt;br&gt;usage notes) visit: &lt;a href=&quot;http://joseito.republika.pl/sunrise-x-tabs.el.gz&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://joseito.republika.pl/sunrise-x-tabs.el.gz&lt;/a&gt;&lt;br&gt;&lt;br&gt;[1] For more information on the file manager itself and a current list
&lt;br&gt;of available extensions see: &lt;a href=&quot;http://www.emacswiki.org/emacs/Sunrise_Commander&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.emacswiki.org/emacs/Sunrise_Commander&lt;/a&gt;&lt;br&gt;&lt;br&gt;Cheers,
&lt;br&gt;--
&lt;br&gt;José A. Romero L.
&lt;br&gt;escherdragon at gmail dot com
&lt;br&gt;&amp;quot;We who cut mere stones must always be envisioning cathedrals.&amp;quot;
&lt;br&gt;(Quarry worker's creed)
&lt;br&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=26039138&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/Sunrise-Commander%3A-Tabs-Extension-tp26039138p26039138.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25986300</id>
	<title>Re: nterm a vt100 emulator</title>
	<published>2009-10-19T22:29:22Z</published>
	<updated>2009-10-19T22:29:22Z</updated>
	<author>
		<name>Ivan Kanis-45</name>
	</author>
	<content type="html">Stefan Monnier &amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25986300&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;monnier@...&lt;/a&gt;&amp;gt; wrote:
&lt;br&gt;&lt;br&gt;&amp;gt;&amp;gt; term and terminal are not meant to be full emulation. &amp;nbsp;term has
&lt;br&gt;&amp;gt;&amp;gt; a pager and line mode which nterm doesn't do. &amp;nbsp;nterm doesn't track
&lt;br&gt;&amp;gt;&amp;gt; current directory like term does.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; That makes it sound like nterm is like term but with less features.
&lt;br&gt;&amp;gt; I'm sure there's an upside to it. &amp;nbsp;Also, if you could explain how these
&lt;br&gt;&amp;gt; different design decisions affect the ability to fix the original cursor
&lt;br&gt;&amp;gt; bug, that would be great.
&lt;br&gt;&lt;br&gt;The recorder takes a trace of characters received by the
&lt;br&gt;terminal. Someone can easily reproduce a bug by replaying the trace
&lt;br&gt;both on xterm and nterm. I don't think term has that feature.
&lt;br&gt;&lt;br&gt;For now it's only a vt100 emulator, I think it can become a xterm
&lt;br&gt;emulator with a little bit of work.
&lt;br&gt;&lt;br&gt;&amp;gt; Does it adapt to a window's size or does it have a fixed size
&lt;br&gt;&amp;gt; independent from the window where the buffer is displayed?
&lt;br&gt;&lt;br&gt;It has a fixed size for now.
&lt;br&gt;-- 
&lt;br&gt;Ivan
&lt;br&gt;Kanis &lt;a href=&quot;http://kanis.fr&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://kanis.fr&lt;/a&gt;&lt;br&gt;&lt;br&gt;Wisdom is oftentimes nearer when we stoop than when we soar.
&lt;br&gt;&amp;nbsp; &amp;nbsp; -- William Wordsworth 
&lt;br&gt;&lt;br&gt;&lt;br&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25986300&amp;i=1&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/nterm-a-vt100-emulator-tp25916245p25986300.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25986297</id>
	<title>Re: nterm a vt100 emulator</title>
	<published>2009-10-19T20:37:50Z</published>
	<updated>2009-10-19T20:37:50Z</updated>
	<author>
		<name>Miles Bader-2</name>
	</author>
	<content type="html">Stefan Monnier &amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25986297&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;monnier@...&lt;/a&gt;&amp;gt; writes:
&lt;br&gt;&amp;gt;&amp;gt; I can't comment on terminal, I haven't used it.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; Neither have I. &amp;nbsp;Has someone used it? &amp;nbsp;Should we move it to `lisp/obsolete'?
&lt;br&gt;&lt;br&gt;I vaguely recall that the last time I complained about the duplication
&lt;br&gt;on this list, there was some objection to doing so, but I don't recall
&lt;br&gt;the reason. &amp;nbsp;Per's README certainly makes it sound like term.el is
&lt;br&gt;(functionally) a superset...
&lt;br&gt;&lt;br&gt;The different emulators have different methods of allowing emacs escape
&lt;br&gt;sequences to be entered while still trying to send raw keys to the
&lt;br&gt;process; maybe that was it?
&lt;br&gt;&lt;br&gt;-Miles
&lt;br&gt;&lt;br&gt;-- 
&lt;br&gt;`...the Soviet Union was sliding in to an economic collapse so comprehensive
&lt;br&gt;&amp;nbsp;that in the end its factories produced not goods but bads: finished products
&lt;br&gt;&amp;nbsp;less valuable than the raw materials they were made from.' &amp;nbsp;[The Economist]
&lt;br&gt;&lt;br&gt;&lt;br&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25986297&amp;i=1&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/nterm-a-vt100-emulator-tp25916245p25986297.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25968705</id>
	<title>Re: nterm a vt100 emulator</title>
	<published>2009-10-19T19:10:57Z</published>
	<updated>2009-10-19T19:10:57Z</updated>
	<author>
		<name>Stefan Monnier</name>
	</author>
	<content type="html">&amp;gt;&amp;gt; Could you expand a bit on it? &amp;nbsp;Mostly, how does it compare to term.el
&lt;br&gt;&amp;gt;&amp;gt; and terminal.el?
&lt;br&gt;&lt;br&gt;&amp;gt; Hi Stefan,
&lt;br&gt;&lt;br&gt;&amp;gt; I wrote it because I couldn't fix the cursor bug in term.
&lt;br&gt;&lt;br&gt;That was my guess as well ;-)
&lt;br&gt;&lt;br&gt;&amp;gt; term and terminal are not meant to be full emulation. &amp;nbsp;term has
&lt;br&gt;&amp;gt; a pager and line mode which nterm doesn't do. &amp;nbsp;nterm doesn't track
&lt;br&gt;&amp;gt; current directory like term does.
&lt;br&gt;&lt;br&gt;That makes it sound like nterm is like term but with less features.
&lt;br&gt;I'm sure there's an upside to it. &amp;nbsp;Also, if you could explain how these
&lt;br&gt;different design decisions affect the ability to fix the original cursor
&lt;br&gt;bug, that would be great.
&lt;br&gt;&lt;br&gt;&amp;gt; I can't comment on terminal, I haven't used it.
&lt;br&gt;&lt;br&gt;Neither have I. &amp;nbsp;Has someone used it? &amp;nbsp;Should we move it to `lisp/obsolete'?
&lt;br&gt;&lt;br&gt;&amp;gt; Things that remains to do:
&lt;br&gt;&amp;gt; - Double width character
&lt;br&gt;&amp;gt; - Double height character
&lt;br&gt;&amp;gt; - Sanitize keyboard map
&lt;br&gt;&amp;gt; - ANSI color
&lt;br&gt;&amp;gt; - VT52 compatibility mode
&lt;br&gt;&lt;br&gt;Does it adapt to a window's size or does it have a fixed size
&lt;br&gt;independent from the window where the buffer is displayed?
&lt;br&gt;&lt;br&gt;&amp;gt; I think nterm is easier to maintain than term. &amp;nbsp;One look at term's
&lt;br&gt;&amp;gt; term-emulate-terminal function should convince anyone that term cannot
&lt;br&gt;&amp;gt; be maintained anymore. &amp;nbsp;Compare with nterm equivalent function
&lt;br&gt;&amp;gt; nterm-emulate it is only 25 lines long.
&lt;br&gt;&lt;br&gt;term.el's maintainability is indeed a problem.
&lt;br&gt;&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Stefan
&lt;br&gt;&lt;br&gt;&lt;br&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25968705&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/nterm-a-vt100-emulator-tp25916245p25968705.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25927799</id>
	<title>Re: nterm a vt100 emulator</title>
	<published>2009-10-15T23:32:44Z</published>
	<updated>2009-10-15T23:32:44Z</updated>
	<author>
		<name>Ivan Kanis-44</name>
	</author>
	<content type="html">Stefan Monnier &amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25927799&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;monnier@...&lt;/a&gt;&amp;gt; wrote:
&lt;br&gt;&lt;br&gt;&amp;gt;&amp;gt; This a vt100 emulator for Emacs. It has a lot of rough edges. As it
&lt;br&gt;&amp;gt;&amp;gt; stands it passes the first 3 tests of vttest. I have another project
&lt;br&gt;&amp;gt;&amp;gt; coming up so I won't be able to work on nterm for a while.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; Could you expand a bit on it? &amp;nbsp;Mostly, how does it compare to term.el
&lt;br&gt;&amp;gt; and terminal.el?
&lt;br&gt;&lt;br&gt;Hi Stefan,
&lt;br&gt;&lt;br&gt;I wrote it because I couldn't fix the cursor bug in term. term and
&lt;br&gt;terminal are not meant to be full emulation. term has a pager and
&lt;br&gt;line mode which nterm doesn't do. nterm doesn't track current directory
&lt;br&gt;like term does. I can't comment on terminal, I haven't used it.
&lt;br&gt;&lt;br&gt;Nterm is meant to be a full vt100 compatible terminal emulator. It has
&lt;br&gt;the following features:
&lt;br&gt;&lt;br&gt;- G0 G1 switching with SI and SO
&lt;br&gt;- special graphics characters (used for line drawing)
&lt;br&gt;- US and UK character set.
&lt;br&gt;- blinking, bright, underline and reverse rendition
&lt;br&gt;- scroll up and down including within top and bottom margin
&lt;br&gt;- switch terminal background color
&lt;br&gt;- switch between 80 and 132 columns screen
&lt;br&gt;- tabulation set and reset
&lt;br&gt;- all VT100 escape sequences are handled
&lt;br&gt;&lt;br&gt;Things that remains to do:
&lt;br&gt;- Double width character
&lt;br&gt;- Double height character
&lt;br&gt;- Sanitize keyboard map
&lt;br&gt;- ANSI color
&lt;br&gt;- VT52 compatibility mode
&lt;br&gt;&lt;br&gt;I think nterm is easier to maintain than term. One look at term's
&lt;br&gt;term-emulate-terminal function should convince anyone that term cannot be
&lt;br&gt;maintained anymore. Compare with nterm equivalent function nterm-emulate
&lt;br&gt;it is only 25 lines long.
&lt;br&gt;&lt;br&gt;It has a recording mode (C-c r) so that you can record and replay
&lt;br&gt;traces. It has a terminal memory so that area of the terminal can be
&lt;br&gt;redrawn for blinking and changing screen background. There is a memory
&lt;br&gt;dump mode (C-c m) that allows the programmer to examine the memory.
&lt;br&gt;-- 
&lt;br&gt;Ivan
&lt;br&gt;Kanis &lt;a href=&quot;http://kanis.fr&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://kanis.fr&lt;/a&gt;&lt;br&gt;&lt;br&gt;The cause of these complaints lies in WinZip, which turns an all
&lt;br&gt;upper-case directory into an all lower case one in a fit of
&lt;br&gt;helpfulness
&lt;br&gt;&amp;nbsp; &amp;nbsp; -- Ant Documentation 
&lt;br&gt;&lt;br&gt;&lt;br&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25927799&amp;i=1&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/nterm-a-vt100-emulator-tp25916245p25927799.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25918432</id>
	<title>Re: nterm a vt100 emulator</title>
	<published>2009-10-15T16:39:00Z</published>
	<updated>2009-10-15T16:39:00Z</updated>
	<author>
		<name>Miles Bader-2</name>
	</author>
	<content type="html">Ivan Kanis &amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25918432&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;expire-by-2009-10-20@...&lt;/a&gt;&amp;gt; writes:
&lt;br&gt;&amp;gt; This a vt100 emulator for emacs. It has a lot of rough edges. As it
&lt;br&gt;&amp;gt; stands it passes the first 3 tests of vttest. I have another project
&lt;br&gt;&amp;gt; coming up so I won't be able to work on nterm for a while.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; &lt;a href=&quot;http://kanis.fr/nterm.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://kanis.fr/nterm.html&lt;/a&gt;&lt;br&gt;&lt;br&gt;We've already got two different terminal emulators in Emacs (with
&lt;br&gt;completely separate code bases); do we really want a third...?
&lt;br&gt;&lt;br&gt;-Miles
&lt;br&gt;&lt;br&gt;-- 
&lt;br&gt;Friendship, n. A ship big enough to carry two in fair weather, but only one
&lt;br&gt;in foul.
&lt;br&gt;&lt;br&gt;&lt;br&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25918432&amp;i=1&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/nterm-a-vt100-emulator-tp25916245p25918432.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25915246</id>
	<title>Re: nterm a vt100 emulator</title>
	<published>2009-10-15T13:11:52Z</published>
	<updated>2009-10-15T13:11:52Z</updated>
	<author>
		<name>Stefan Monnier</name>
	</author>
	<content type="html">&amp;gt; This a vt100 emulator for Emacs. It has a lot of rough edges. As it
&lt;br&gt;&amp;gt; stands it passes the first 3 tests of vttest. I have another project
&lt;br&gt;&amp;gt; coming up so I won't be able to work on nterm for a while.
&lt;br&gt;&lt;br&gt;Could you expand a bit on it? &amp;nbsp;Mostly, how does it compare to term.el
&lt;br&gt;and terminal.el?
&lt;br&gt;&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Stefan
&lt;br&gt;&lt;br&gt;&lt;br&gt;PS: also if anyone knows how term.el and terminal.el compare, that would
&lt;br&gt;also be useful to know (and put it in those files's commentary).
&lt;br&gt;&lt;br&gt;&lt;br&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25915246&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/nterm-a-vt100-emulator-tp25916245p25915246.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25916245</id>
	<title>nterm a vt100 emulator</title>
	<published>2009-10-15T07:45:36Z</published>
	<updated>2009-10-15T07:45:36Z</updated>
	<author>
		<name>Ivan Kanis-43</name>
	</author>
	<content type="html">Hello,
&lt;br&gt;&lt;br&gt;This a vt100 emulator for emacs. It has a lot of rough edges. As it
&lt;br&gt;stands it passes the first 3 tests of vttest. I have another project
&lt;br&gt;coming up so I won't be able to work on nterm for a while.
&lt;br&gt;&lt;br&gt;&lt;a href=&quot;http://kanis.fr/nterm.html&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://kanis.fr/nterm.html&lt;/a&gt;&lt;br&gt;&lt;br&gt;Kind regards,
&lt;br&gt;-- 
&lt;br&gt;Ivan
&lt;br&gt;Kanis &lt;a href=&quot;http://kanis.fr&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://kanis.fr&lt;/a&gt;&lt;br&gt;&lt;br&gt;Wisdom is oftentimes nearer when we stoop than when we soar.
&lt;br&gt;&amp;nbsp; &amp;nbsp; -- William Wordsworth 
&lt;br&gt;&lt;br&gt;&lt;br&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25916245&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/nterm-a-vt100-emulator-tp25916245p25916245.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25843559</id>
	<title>updated CC mode support for PHP, JavaScript, C# support</title>
	<published>2009-10-11T06:46:01Z</published>
	<updated>2009-10-11T06:46:01Z</updated>
	<author>
		<name>Dave Love-2</name>
	</author>
	<content type="html">Here's an update of support for PHP, JavaScript, and C# with CC mode. &amp;nbsp;I
&lt;br&gt;previously provided a patch, which was awkward to use, especially given
&lt;br&gt;the structure of CC mode, and was rejected as a contribution anyway.
&lt;br&gt;I've managed to convert it into an add-on which derives from CC mode,
&lt;br&gt;which I couldn't make work originally, but I haven't done much other
&lt;br&gt;than re-packaging it.
&lt;br&gt;&lt;br&gt;This doesn't suffer from some problems people complain about with other
&lt;br&gt;JavaScript and PHP modes, but could use attention from people more
&lt;br&gt;interested in these languages. &amp;nbsp;It's still somewhat inconvenient to
&lt;br&gt;build, but see the reference to a compiled version in the commentary.
&lt;br&gt;&lt;br&gt;&lt;br /&gt; &lt;br /&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25843559&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;&lt;div class=&quot;small&quot;&gt;&lt;br/&gt;&lt;img src=&quot;http://old.nabble.com/images/icon_attachment.gif&quot; &gt; &lt;strong&gt;cc-php-js-cs.el&lt;/strong&gt; (18K) &lt;a href=&quot;http://old.nabble.com/attachment/25843559/0/cc-php-js-cs.el&quot; target=&quot;_top&quot;&gt;Download Attachment&lt;/a&gt;&lt;/div&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/updated-CC-mode-support-for-PHP%2C-JavaScript%2C-C--support-tp25843559p25843559.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25843551</id>
	<title>Python 3 support in python.el</title>
	<published>2009-10-11T06:44:40Z</published>
	<updated>2009-10-11T06:44:40Z</updated>
	<author>
		<name>Dave Love-2</name>
	</author>
	<content type="html">I don't seem to have advertised the python.el support for Python 3 I did
&lt;br&gt;some time ago, but the previous implementation with separate major modes
&lt;br&gt;for the language versions turned out to be unfortunate. &amp;nbsp;In this version
&lt;br&gt;the major mode is always `python-mode', but you can still use
&lt;br&gt;`python-2-mode' and `python-3-mode' in file-local variables. &amp;nbsp;The
&lt;br&gt;support for the inferior shell works with version 2 or 3 interpreters.
&lt;br&gt;&lt;br&gt;It's often said, without good justification I've heard, that this is
&lt;br&gt;somehow bad compared with the old python-mode.el. &amp;nbsp;I'll try to address
&lt;br&gt;reports of actual bugs or missing features that aren't inappropriate to
&lt;br&gt;include, as discussed in the commentary.
&lt;br&gt;&lt;br&gt;An Emacs 21 version is at &lt;a href=&quot;http://www.loveshack.ukfsn.org/emacs/python-21.el&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://www.loveshack.ukfsn.org/emacs/python-21.el&lt;/a&gt;.
&lt;br&gt;&lt;br&gt;&lt;br /&gt; &lt;br /&gt;&lt;hr align=&quot;left&quot; width=&quot;300&quot; /&gt;&lt;tt&gt;&amp;quot;&amp;quot;&amp;quot;Definitions used by commands sent to inferior Python in python.el.&amp;quot;&amp;quot;&amp;quot;
&lt;br&gt;&lt;br&gt;# Copyright (C) 2004, 2005, 2006, 2007, 2008 &amp;nbsp;Free Software Foundation, Inc.
&lt;br&gt;# Author: Dave Love &amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25843551&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;fx@...&lt;/a&gt;&amp;gt;
&lt;br&gt;&lt;br&gt;# This file is part of GNU Emacs.
&lt;br&gt;&lt;br&gt;# This file is free software; you can redistribute it and/or modify
&lt;br&gt;# it under the terms of the GNU General Public License as published by
&lt;br&gt;# the Free Software Foundation, either version 3 of the License, or
&lt;br&gt;# (at your option) any later version.
&lt;br&gt;&lt;br&gt;# This file is distributed in the hope that it will be useful,
&lt;br&gt;# but WITHOUT ANY WARRANTY; without even the implied warranty of
&lt;br&gt;# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. &amp;nbsp;See the
&lt;br&gt;# GNU General Public License for more details.
&lt;br&gt;&lt;br&gt;# You should have received a copy of the GNU General Public License
&lt;br&gt;# along with GNU Emacs. &amp;nbsp;If not, see &amp;lt;http://www.gnu.org/licenses/&amp;gt;.
&lt;br&gt;&lt;br&gt;# $Revision: 1.17 $
&lt;br&gt;&lt;br&gt;import os, sys, traceback, inspect, keyword
&lt;br&gt;&lt;br&gt;### Python 2.3 compatibility
&lt;br&gt;&lt;br&gt;# Python 2.3 doesn't have `set'. &amp;nbsp;Avoid a warning in Python 2.6 or
&lt;br&gt;# error in 3.0. &amp;nbsp;(We can't put the import in a conditional block to
&lt;br&gt;# avoid the warning.)
&lt;br&gt;try: set
&lt;br&gt;except: from sets import Set as set # Python 2.3
&lt;br&gt;&lt;br&gt;### Python 2/3 compatibility
&lt;br&gt;&lt;br&gt;# According to the Python doc, you're meant to maintain separate
&lt;br&gt;# version 2 and version 3 files, deriving the latter from the former
&lt;br&gt;# with `2to3'. &amp;nbsp;However, we have a dynamic language, and using
&lt;br&gt;# compatibility functions like this is more maintainable once you've
&lt;br&gt;# fixed the things 2to3 complains about that aren't syntax errors.
&lt;br&gt;&lt;br&gt;# Use the Python 3 function, if available.
&lt;br&gt;&lt;br&gt;if not keyword.iskeyword (&amp;quot;print&amp;quot;): # Python 3
&lt;br&gt;&amp;nbsp; &amp;nbsp; # This avoids syntax errors in Python 2.
&lt;br&gt;&amp;nbsp; &amp;nbsp; printit = eval (&amp;quot;print&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; execit = eval (&amp;quot;exec&amp;quot;)
&lt;br&gt;else:				# Python 2
&lt;br&gt;&amp;nbsp; &amp;nbsp; # execit
&lt;br&gt;&amp;nbsp; &amp;nbsp; eval (compile (&amp;quot;&amp;quot;&amp;quot;
&lt;br&gt;def execit (string, dict = None):
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;quot;Compatibility with Python 3's `exec' for Python 2.&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; if dict:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; exec string in dict
&lt;br&gt;&amp;nbsp; &amp;nbsp; else:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; exec string
&lt;br&gt;&amp;quot;&amp;quot;&amp;quot;,'emacs.py','single'))
&lt;br&gt;&amp;nbsp; &amp;nbsp; # printit
&lt;br&gt;&amp;nbsp; &amp;nbsp; eval (compile (&amp;quot;&amp;quot;&amp;quot;
&lt;br&gt;def printit (obj, end = '\\n'):
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;quot;Partial compatibility with Python 3's `print' for Python 2.&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; if end == ' ':
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print obj,
&lt;br&gt;&amp;nbsp; &amp;nbsp; elif end == '\\n':
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print obj
&lt;br&gt;&amp;nbsp; &amp;nbsp; else:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # Not really right because of the trailing space, but not
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # called such that that matters.
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print '%s%s' % (obj, end),
&lt;br&gt;&amp;quot;&amp;quot;&amp;quot;, 'emacs.py', 'single'))
&lt;br&gt;&lt;br&gt;### main code
&lt;br&gt;&lt;br&gt;__all__ = [&amp;quot;eexecfile&amp;quot;, &amp;quot;eargs&amp;quot;, &amp;quot;complete&amp;quot;, &amp;quot;ehelp&amp;quot;, &amp;quot;eimport&amp;quot;,
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;quot;modpath&amp;quot;, &amp;quot;location_of&amp;quot;]
&lt;br&gt;&lt;br&gt;def eexecfile (file):
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;quot;&amp;quot;&amp;quot;Execute FILE and then remove it.
&lt;br&gt;&amp;nbsp; &amp;nbsp; If we get an exception, print a traceback with the top frame
&lt;br&gt;&amp;nbsp; &amp;nbsp; (ourselves) excluded.&amp;quot;&amp;quot;&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; import __main__
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; try:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; try:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # Note that the file is closed by the (quasi-?) GC since
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # there's no reference to it kept.
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; execit (open(file).read(), __main__.__dict__)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; except:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (etype, value, tb) = sys.exc_info ()
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # Lose the stack frame for this location and for execit.
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; tb = tb.tb_next.tb_next
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if tb is None: &amp;nbsp; &amp;nbsp; &amp;nbsp;# print_exception won't do it
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; printit (&amp;quot;Traceback (most recent call last):&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; traceback.print_exception (etype, value, tb)
&lt;br&gt;&amp;nbsp; &amp;nbsp; finally:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; try: os.remove (file)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; except: pass &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;# e.g. file not found, but shouldn't happen
&lt;br&gt;&lt;br&gt;def eargs (name, imports):
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;quot;&amp;quot;&amp;quot;Get arglist of NAME for Eldoc &amp;c.
&lt;br&gt;&amp;nbsp; &amp;nbsp; Exec IMPORTS first.&amp;quot;&amp;quot;&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; try:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; try: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;# don't give up if the imports fail
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if imports: execit (imports)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; parts = name.split ('.')
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if len (parts) &amp;gt; 1:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; execit ('import ' + parts[0])
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; except: pass
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; func = eval (name)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if inspect.isbuiltin (func) or inspect.isclass (func):
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; doc = func.__doc__
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if doc.find (' -&amp;gt;') != -1:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; printit ('_emacs_out ' + doc.split (' -&amp;gt;')[0])
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; elif doc.find ('\n') != -1:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; printit ('_emacs_out ' + doc.split ('\n')[0])
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; else:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; raise RuntimeError
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if inspect.ismethod (func):
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; try:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; func = func.im_func # Python 2
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; except:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; func = func.__func__ # Python 3
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if not inspect.isfunction (func):
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; raise RuntimeError
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (args, varargs, varkw, defaults) = inspect.getargspec (func)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # No space between name and arglist for consistency with builtins.
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; printit ('_emacs_out ' + \
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;func.__name__ + \
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;inspect.formatargspec (args, varargs, varkw, defaults))
&lt;br&gt;&amp;nbsp; &amp;nbsp; except: printit ('_emacs_out ')
&lt;br&gt;&lt;br&gt;def all_names (object):
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;quot;&amp;quot;&amp;quot;Return (an approximation to) a list of all possible attribute
&lt;br&gt;&amp;nbsp; &amp;nbsp; names reachable via the attributes of OBJECT, i.e. roughly the
&lt;br&gt;&amp;nbsp; &amp;nbsp; leaves of the dictionary tree under it.&amp;quot;&amp;quot;&amp;quot;
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; def do_object (object, names):
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if inspect.ismodule (object):
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; do_module (object, names)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; elif inspect.isclass (object):
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; do_class (object, names)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # Might have an object without its class in scope.
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; elif hasattr (object, '__class__'):
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; names.add ('__class__')
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; do_class (object.__class__, names)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # Probably not a good idea to try to enumerate arbitrary
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # dictionaries...
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return names
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; def do_module (module, names):
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if hasattr (module, '__all__'): # limited export list
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; names.update (module.__all__)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; for i in module.__all__:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; do_object (getattr (module, i), names)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; else: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # use all names
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; names.update (dir (module))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; for i in dir (module):
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; do_object (getattr (module, i), names)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return names
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; def do_class (object, names):
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; names.update (dir (object))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if hasattr (object, '__bases__'): # superclasses
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; for i in object.__bases__: do_object (i, names)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return names
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; return do_object (object, set ([]))
&lt;br&gt;&lt;br&gt;# Fixme: &amp;nbsp;Should do multiple dotted components -- see rlcompleter.
&lt;br&gt;def complete (name, imports):
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;quot;&amp;quot;&amp;quot;Complete NAME and print a Lisp list of completions.
&lt;br&gt;&amp;nbsp; &amp;nbsp; Exec IMPORTS first.&amp;quot;&amp;quot;&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; import __main__
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; def class_members (object):
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; names = dir (object)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if hasattr (object, '__bases__'):
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; for superc in object.__bases__:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; names = class_members (superc)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return names &amp;nbsp; &amp;nbsp;
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; names = set ([])
&lt;br&gt;&amp;nbsp; &amp;nbsp; base = None
&lt;br&gt;&amp;nbsp; &amp;nbsp; try:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; dic = __main__.__dict__.copy()
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if imports:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; try: execit (imports, dic)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; except: pass
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; l = len (name)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; dot = name.rfind ('.')
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if dot == -1:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; for elts in [__builtins__, keyword.kwlist,
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;list (dic.keys())]: # `list' for Python 3
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; for elt in elts:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if elt[:l] == name: names.add (elt)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; else:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; base = name[:dot]
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; name = name[dot+1:]
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; try:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; obj = eval (base, dic)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; names = set (dir (obj))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if hasattr (obj, '__class__'):
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; names.add ('__class__')
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; names.update (class_members (obj))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; except: names = all_names (dic)
&lt;br&gt;&amp;nbsp; &amp;nbsp; except: return []
&lt;br&gt;&amp;nbsp; &amp;nbsp; l = len (name)
&lt;br&gt;&amp;nbsp; &amp;nbsp; printit ('_emacs_out (', end=' ')
&lt;br&gt;&amp;nbsp; &amp;nbsp; for n in names:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if name == n[:l]:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if base: printit ('&amp;quot;%s.%s&amp;quot;' % (base, n), end = ' ')
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; else: printit ('&amp;quot;%s&amp;quot;' % n, end = ' ')
&lt;br&gt;&amp;nbsp; &amp;nbsp; printit (')')
&lt;br&gt;&lt;br&gt;# Fixme: &amp;nbsp;This could try to look up methods/attributes applied to
&lt;br&gt;# variables by generating possibilities like the completion code. &amp;nbsp;The
&lt;br&gt;# trouble is that could be misleading if it gets the wrong one.
&lt;br&gt;def ehelp (name, imports):
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;quot;&amp;quot;&amp;quot;Get help on string NAME.
&lt;br&gt;&amp;nbsp; &amp;nbsp; First try to eval name, e.g. for user definitions where we need
&lt;br&gt;&amp;nbsp; &amp;nbsp; the object. &amp;nbsp;Otherwise try the string form.
&lt;br&gt;&amp;nbsp; &amp;nbsp; Exec IMPORTS first.&amp;quot;&amp;quot;&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; locls = {}
&lt;br&gt;&amp;nbsp; &amp;nbsp; if imports:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; try: execit (imports, locls)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; except: pass
&lt;br&gt;&amp;nbsp; &amp;nbsp; try: help (eval (name, globals (), locls))
&lt;br&gt;&amp;nbsp; &amp;nbsp; except: help (name)
&lt;br&gt;&lt;br&gt;def eimport (mod, dir):
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;quot;&amp;quot;&amp;quot;Import module MOD with directory DIR at the head of the search path.
&lt;br&gt;&amp;nbsp; &amp;nbsp; NB doesn't load from DIR if MOD shadows a system module.&amp;quot;&amp;quot;&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; from __main__ import __dict__
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; path0 = sys.path[0] &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # will be ''
&lt;br&gt;&amp;nbsp; &amp;nbsp; sys.path[0] = dir
&lt;br&gt;&amp;nbsp; &amp;nbsp; try:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; try:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if mod in __dict__ and inspect.ismodule (__dict__[mod]):
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; reload (__dict__[mod])
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; else:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; __dict__[mod] = __import__ (mod)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; except:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (etype, value, tb) = sys.exc_info ()
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; printit (&amp;quot;Traceback (most recent call last):&amp;quot;)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; traceback.print_exception (etype, value, tb.tb_next)
&lt;br&gt;&amp;nbsp; &amp;nbsp; finally:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; sys.path[0] = path0
&lt;br&gt;&lt;br&gt;def modpath (module):
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;quot;&amp;quot;&amp;quot;Get the source file for the given MODULE (or nil).&amp;quot;&amp;quot;&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; locls = {}
&lt;br&gt;&amp;nbsp; &amp;nbsp; try:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; __import__ (module)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; printit (&amp;quot;_emacs_out &amp;quot; + \
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; inspect.getsourcefile (eval (module, globals (), locls)))
&lt;br&gt;&amp;nbsp; &amp;nbsp; except:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; printit (&amp;quot;_emacs_out ()&amp;quot;)
&lt;br&gt;&lt;br&gt;def location_of (name, imports):
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;quot;&amp;quot;&amp;quot;Get location at which NAME is defined (or nil).
&lt;br&gt;&amp;nbsp; &amp;nbsp; Provides a pair (PATH, LINE), where LINE is the start of the definition
&lt;br&gt;&amp;nbsp; &amp;nbsp; in path name PATH.
&lt;br&gt;&amp;nbsp; &amp;nbsp; Exec IMPORTS first.&amp;quot;&amp;quot;&amp;quot;
&lt;br&gt;&amp;nbsp; &amp;nbsp; locls = {}
&lt;br&gt;&amp;nbsp; &amp;nbsp; if imports:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; try: execit (imports, locls)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; except: pass
&lt;br&gt;&amp;nbsp; &amp;nbsp; try:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; obj = eval (name, globals (), locls)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # Bug: (in Python 2.5) `getsourcefile' only works with modules,
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # hence the `getmodule' here.
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; srcfile = inspect.getsourcefile (inspect.getmodule (obj))
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; _, line = inspect.getsourcelines (obj)
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; printit ('_emacs_out (&amp;quot;%s&amp;quot; . %d)' % (srcfile, line))
&lt;br&gt;&amp;nbsp; &amp;nbsp; except:
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; printit (&amp;quot;_emacs_out ()&amp;quot;)
&lt;br&gt;&lt;br&gt;# print '_emacs_ok' &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # ready for input and can call continuation
&lt;br&gt;&lt;br&gt;# arch-tag: d90408f3-90e2-4de4-99c2-6eb9c7b9ca46
&lt;br&gt;&lt;/tt&gt;&lt;hr align=&quot;left&quot; width=&quot;300&quot; /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; -*-text-*-
&lt;br&gt;* Revision 1.29 (emacs.py 1.17, python-21.el 1.77)
&lt;br&gt;&lt;br&gt;&amp;nbsp; * Change the mechanism for Python2/Python3: &amp;nbsp;`python-2-mode' and
&lt;br&gt;&amp;nbsp; &amp;nbsp; `python-3-mode' are no longer proper major modes, but just invoke
&lt;br&gt;&amp;nbsp; &amp;nbsp; `python-mode' with `python-default-version' bound appropriately.
&lt;br&gt;&amp;nbsp; &amp;nbsp; Thus you can use, say, python-3-mode in file-local variables, but
&lt;br&gt;&amp;nbsp; &amp;nbsp; `major-mode' is always `python-mode' to avoid breaking things
&lt;br&gt;&amp;nbsp; &amp;nbsp; which test `major-mode'.
&lt;br&gt;&lt;br&gt;&amp;nbsp; * Bug fixes:
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; * Allow trailing comments on outline headings.
&lt;br&gt;&amp;nbsp; &amp;nbsp; * `python-load-file' produces a stack trace with the file name.
&lt;br&gt;&lt;br&gt;* Revision 1.25 (emacs.py 1.16, python-21.el 1.73)
&lt;br&gt;&lt;br&gt;&amp;nbsp; * Fix hideshow to work with the new major modes, and make it
&lt;br&gt;&amp;nbsp; &amp;nbsp; consistent with outlining.
&lt;br&gt;&lt;br&gt;* Revision 1.24 (emacs.py 1.16, python-21.el 1.72)
&lt;br&gt;&lt;br&gt;&amp;nbsp; * Flymake support (via `python-check-command').
&lt;br&gt;&lt;br&gt;&amp;nbsp; * Bug/infelicity fixes:
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; * Error with backslash-continued line inside parens.
&lt;br&gt;&amp;nbsp; &amp;nbsp; * Allow &amp;quot;else&amp;quot; after &amp;quot;finally&amp;quot;.
&lt;br&gt;&amp;nbsp; &amp;nbsp; * Set `comment-start-skip', `local-abbrev-table'.
&lt;br&gt;&amp;nbsp; &amp;nbsp; * Allow non-ASCII ids with Eldoc.
&lt;br&gt;&amp;nbsp; &amp;nbsp; * `python-process-kill-without-query' allows silent killing of
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; inferior process.
&lt;br&gt;&amp;nbsp; &amp;nbsp; * Avoid possible bad indentation of try block clauses.
&lt;br&gt;&lt;br&gt;* Revision 1.18 (emacs.py 1.16, python-21.el 1.66)
&lt;br&gt;&lt;br&gt;&amp;nbsp; * Support for Python 3:
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; * New modes, `python-3-mode' and `python-2-mode'. &amp;nbsp;`python-mode'
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; changed just to invoke the one determined by
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; `python-default-version'.
&lt;br&gt;&amp;nbsp; &amp;nbsp; * emacs.py should work with python 2.3 up. &amp;nbsp;(Only 2.5 and 3.0
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; tested.)
&lt;br&gt;&lt;br&gt;&amp;nbsp; * Bug fixes:
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; * Completion works again in python 2.4 up.
&lt;br&gt;&amp;nbsp; &amp;nbsp; * `python-beginning-of-block' moves to the beginning properly when
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; point is in the first statement of an outer block.
&lt;br&gt;&amp;nbsp; &amp;nbsp; * `python-mark-block' is more sensible because of the above.
&lt;br&gt;&amp;nbsp; &amp;nbsp; * `python-mark-block' doesn't push marks or deactivate the region
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; if it doesn't find a block.
&lt;br&gt;&amp;nbsp; &amp;nbsp; * `indent-tabs-mode' is now normally nil -- Python 3 objects to
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; typical mixed tab/space indentation otherwise. &amp;nbsp;The indentation
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; isn't guessed if it's set file-locally.
&lt;br&gt;&amp;nbsp; &amp;nbsp; * Avoid error in `python-find-function'.
&lt;br&gt;&amp;nbsp; &amp;nbsp; * Try harder to find Info files for info-look.
&lt;br&gt;&amp;nbsp; &amp;nbsp; * Customizing `python-python-command' updates things which depend
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; on it.
&lt;br&gt;&amp;nbsp; &amp;nbsp; * Fix Imenu finding nested definitions.
&lt;br&gt;&amp;nbsp; &amp;nbsp; * Fix python-beginning-of-defun with nested definitions.
&lt;br&gt;&lt;br&gt;&amp;nbsp; * Other changes
&lt;br&gt;&amp;nbsp; 
&lt;br&gt;&amp;nbsp; &amp;nbsp; * Imenu generation is sanitized: &amp;nbsp;class names are indicated by a
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; suffix, not a prefix; sorting is sorted; the default
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; `imenu-sort-function' gives an overall order of module variables,
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; class definitions, and function definitions.
&lt;br&gt;&amp;nbsp; &amp;nbsp; * In Emacs 21, bind C-M-h and C-x n d usefully to work around
&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; problems with normal bindings.
&lt;br&gt;&lt;br /&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25843551&amp;i=1&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;&lt;div class=&quot;small&quot;&gt;&lt;br/&gt;&lt;img src=&quot;http://old.nabble.com/images/icon_attachment.gif&quot; &gt; &lt;strong&gt;python.el.gz&lt;/strong&gt; (41K) &lt;a href=&quot;http://old.nabble.com/attachment/25843551/0/python.el.gz&quot; target=&quot;_top&quot;&gt;Download Attachment&lt;/a&gt;&lt;/div&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/Python-3-support-in-python.el-tp25843551p25843551.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25830504</id>
	<title>Re: facebook.el v 0.0.3</title>
	<published>2009-10-09T19:46:29Z</published>
	<updated>2009-10-09T19:46:29Z</updated>
	<author>
		<name>Richard Stallman</name>
	</author>
	<content type="html">&amp;nbsp; &amp;nbsp; On Facebook &amp;quot;Apps&amp;quot; are essentially just existing applications that you
&lt;br&gt;&amp;nbsp; &amp;nbsp; configure to use with your account. &amp;nbsp;Adding the &amp;quot;Developers App&amp;quot; is
&lt;br&gt;&amp;nbsp; &amp;nbsp; essentially clicking a checkbox which enables their API for use and
&lt;br&gt;&amp;nbsp; &amp;nbsp; gives you an API key, so no more net proprietary software in the world
&lt;br&gt;&amp;nbsp; &amp;nbsp; is installed on any computers anywhere.
&lt;br&gt;&lt;br&gt;It seems misleading to call this an &amp;quot;app&amp;quot;, but now that I understand
&lt;br&gt;the meaning, I agree this is not a bad thing.
&lt;br&gt;&lt;br&gt;&lt;br&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25830504&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/facebook.el-v-0.0.3-tp25788968p25830504.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25815762</id>
	<title>Re: facebook.el v 0.0.3</title>
	<published>2009-10-08T22:30:05Z</published>
	<updated>2009-10-08T22:30:05Z</updated>
	<author>
		<name>Daniel Bastos-2</name>
	</author>
	<content type="html">In article &amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25815762&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;87hbu9pz2m.fsf@...&lt;/a&gt;&amp;gt;,
&lt;br&gt;Maurizio Vitale wrote:
&lt;br&gt;&lt;br&gt;&amp;gt; [A] lot of webservices (Amazon S3 storage for instance) require you
&lt;br&gt;&amp;gt; to register and obtain a secret key which is used for authentication
&lt;br&gt;&amp;gt; and (sometimes) traffic encription. Registration is typically free
&lt;br&gt;&amp;gt; (for S3 you pay for the service, but this is a separate matter).
&lt;br&gt;&lt;br&gt;In my view, that's very proprietary. I don't know if the definition
&lt;br&gt;that says that ``proprietary software is computer software which is
&lt;br&gt;the legal property of one party'' is sufficient, but it probably is a
&lt;br&gt;necessary part.
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25815762&amp;i=1&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/facebook.el-v-0.0.3-tp25788968p25815762.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25815230</id>
	<title>Re: facebook.el v 0.0.3</title>
	<published>2009-10-08T10:36:49Z</published>
	<updated>2009-10-08T10:36:49Z</updated>
	<author>
		<name>Maurizio Vitale-5</name>
	</author>
	<content type="html">&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; &amp;quot;rms&amp;quot; == Richard Stallman &amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25815230&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;rms@...&lt;/a&gt;&amp;gt; writes:
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; rms&amp;gt; &amp;nbsp; &amp;nbsp; ;;; First pass at interfacing with facebook. &amp;nbsp;You must add
&lt;br&gt;&amp;nbsp; &amp;nbsp; rms&amp;gt; the &amp;quot;developers ;;; app&amp;quot; and get your own application api-key
&lt;br&gt;&amp;nbsp; &amp;nbsp; rms&amp;gt; and application secret key to ;;; use this.
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; rms&amp;gt; What is the &amp;quot;developers app&amp;quot;? &amp;nbsp;Is that a proprietary program?
&lt;br&gt;&amp;nbsp; &amp;nbsp; rms&amp;gt; It looks that way, but I cannot tell for certain.
&lt;br&gt;&lt;br&gt;I'm not familiar with the facebook situation, but lot of webservices
&lt;br&gt;(Amazon S3 storage for instance) require you to register and obtain a
&lt;br&gt;secret key which is used for authentication and (sometimes) traffic
&lt;br&gt;encription. Registration is typically free (for S3 you pay
&lt;br&gt;for the service, but this is a separate matter).
&lt;br&gt;&lt;br&gt;In the S3 case you don't have to install any proprietary program, but
&lt;br&gt;you still need two secret keys. Think of it as ssh where the other side
&lt;br&gt;tells you the password to use.
&lt;br&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; rms&amp;gt; Please do not make postings here that are likely to induce
&lt;br&gt;&amp;nbsp; &amp;nbsp; rms&amp;gt; people to install proprietary software.
&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;-- 
&lt;br&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25815230&amp;i=1&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/facebook.el-v-0.0.3-tp25788968p25815230.html" />
</entry>

<entry>
	<id>tag:old.nabble.com,2006:post-25815227</id>
	<title>Re: facebook.el v 0.0.3</title>
	<published>2009-10-08T07:41:37Z</published>
	<updated>2009-10-08T07:41:37Z</updated>
	<author>
		<name>paul.huff</name>
	</author>
	<content type="html">Hey Richard,
&lt;br&gt;&lt;br&gt;On Facebook &amp;quot;Apps&amp;quot; are essentially just existing applications that you
&lt;br&gt;configure to use with your account. &amp;nbsp;Adding the &amp;quot;Developers App&amp;quot; is
&lt;br&gt;essentially clicking a checkbox which enables their API for use and
&lt;br&gt;gives you an API key, so no more net proprietary software in the world
&lt;br&gt;is installed on any computers anywhere.
&lt;br&gt;&lt;br&gt;-Paul
&lt;br&gt;&lt;br&gt;On Thu, Oct 8, 2009 at 3:36 AM, Richard Stallman &amp;lt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25815227&amp;i=0&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;rms@...&lt;/a&gt;&amp;gt; wrote:
&lt;div class='shrinkable-quote'&gt;&lt;br&gt;&amp;gt;    ;;;   First pass at interfacing with facebook.  You must add the &amp;quot;developers
&lt;br&gt;&amp;gt;    ;;;   app&amp;quot; and get your own application api-key and application secret key to
&lt;br&gt;&amp;gt;    ;;;   use this.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; What is the &amp;quot;developers app&amp;quot;?  Is that a proprietary program?
&lt;br&gt;&amp;gt; It looks that way, but I cannot tell for certain.
&lt;br&gt;&amp;gt;
&lt;br&gt;&amp;gt; Please do not make postings here that are likely to
&lt;br&gt;&amp;gt; induce people to install proprietary software.
&lt;br&gt;&amp;gt;
&lt;/div&gt;&lt;br&gt;&lt;br&gt;_______________________________________________
&lt;br&gt;gnu-emacs-sources mailing list
&lt;br&gt;&lt;a href=&quot;http://old.nabble.com/user/SendEmail.jtp?type=post&amp;post=25815227&amp;i=1&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;gnu-emacs-sources@...&lt;/a&gt;
&lt;br&gt;&lt;a href=&quot;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&quot; target=&quot;_top&quot; rel=&quot;nofollow&quot;&gt;http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources&lt;/a&gt;&lt;br&gt;</content>
	<link rel="alternate" type="text/html" href="http://old.nabble.com/facebook.el-v-0.0.3-tp25788968p25815227.html" />
</entry>

</feed>
