[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/undo-tree 5a1ba84 017/195: Added standard Elisp package
From: |
Stefan Monnier |
Subject: |
[elpa] externals/undo-tree 5a1ba84 017/195: Added standard Elisp package headers, including an extensive Commentary. |
Date: |
Sat, 28 Nov 2020 13:41:11 -0500 (EST) |
branch: externals/undo-tree
commit 5a1ba848ad8aa04179aa12efeddf324345fd0478
Author: tsc25 <tsc25@cantab.net>
Commit: tsc25 <tsc25@cantab.net>
Added standard Elisp package headers, including an extensive Commentary.
---
undo-tree.el | 420 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 419 insertions(+), 1 deletion(-)
diff --git a/undo-tree.el b/undo-tree.el
index c960c30..6e95df5 100644
--- a/undo-tree.el
+++ b/undo-tree.el
@@ -1,5 +1,420 @@
-
+;;; undo-tree.el --- Treat undo history as a tree
+
+
+;; Copyright (C) 2009 Toby Cubitt
+
+;; Author: Toby Cubitt <toby-undo-tree@dr-qubit.org>
+;; Version: 0.1
+;; Keywords: undo, redo, history, tree
+;; URL: http://www.dr-qubit.org/emacs.php
+
+
+;; This file is NOT part of Emacs.
+;;
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License
+;; as published by the Free Software Foundation; either version 2
+;; of the License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, write to the Free Software
+;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
+
+
+;;; Commentary:
+;;
+;; Emacs has a powerful undo-system. Unlike the standard undo/redo system in
+;; most software, it allows you to recover *any* past state of a buffer
+;; (whereas the standard undo/redo system loses past states as soon as you
+;; redo). However, this power comes at a price: people can find Emacs' undo
+;; confusing and difficult to use, spawning a number of packages that replace
+;; it with the less powerful but more intuitive undo/redo system.
+;;
+;; Both the loss of data with standard undo/redo, and the confusion of Emacs'
+;; undo, stem from trying to treat undo history as a linear sequence of
+;; changes. It's not. Undo-tree-mode replaces Emacs' undo system with a system
+;; that treats undo history as what it is: a branching tree of changes. This
+;; simple idea allows the more intuitive behaviour of the standard undo/redo
+;; system to be combined with the power of never losing any history. An added
+;; side bonus is that undo history can be stored more efficiently, allowing
+;; more changes to accumulate before Emacs starts discarding history.
+;;
+;; The only downside to this more advanced yet simpler undo system is that it
+;; was inspired by Vim. But, after all, successful religions always steal the
+;; best ideas from other religions.
+;;
+;;
+;; Quick-Start
+;; ===========
+;;
+;; If you're the kind of person who likes jump in the car and drive, without
+;; bothering to first figure out whether the button on the left dips the
+;; headlights or opens sun-roof (after all, you'll soon figure it out when you
+;; push it), then here's the minimum you need to know:
+;;
+;; `undo-tree-mode' and `global-undo-tree-mode'
+;; Enable undo-tree mode (either in the current buffer or globally).
+;;
+;; C-_ C-/ (`undo-tree-undo')
+;; Undo changes.
+;;
+;; C-+ C-? (`undo-tree-redo')
+;; Redo changes.
+;;
+;; `undo-tree-switch-branch'
+;; Switch undo-tree branch.
+;; (What does this mean? Better press that button and see!)
+;;
+;; C-x u (`undo-tree-visualize')
+;; Visualize undo tree.
+;; (Better press this button too!)
+;;
+;;
+;; In the undo visualizer:
+;;
+;; <up> p C-p (`undo-tree-visualize-undo')
+;; Undo changes.
+;;
+;; <down> n C-n (`undo-tree-visualize-undo')
+;; Undo changes.
+;;
+;; <left> b C-b (`undo-tree-visualize-switch-previous-branch')
+;; Switch to previous undo-tree branch.
+;;
+;; <right> f C-f (`undo-tree-visualize-switch-next-branch')
+;; Switch to next undo-tree branch.
+;;
+;; q C-q
+;; Quit undo-tree-visualizer.
+;;
+;; , <
+;; Scroll left.
+;;
+;; . >
+;; Scroll right.
+;;
+;; <pgup>
+;; Scroll up.
+;;
+;; <pgdown>
+;; Scroll down.
+;;
+;;
+;;
+;; Explanation
+;; ===========
+;;
+;; To understand the different undo systems, it's easiest to consider an
+;; example. Imagine you make a few edits in a buffer. As you edit, you
+;; accumulate a history of changes, which we might visualize as a string of
+;; past buffer states, growing downwards:
+;;
+;; o (initial buffer state)
+;; |
+;; |
+;; o (first edit)
+;; |
+;; |
+;; o (second edit)
+;; |
+;; |
+;; x (current buffer state)
+;;
+;;
+;; Now imagine that you undo the last two changes. We can visualize this as
+;; rewinding the current state back two steps:
+;;
+;; o (initial buffer state)
+;; |
+;; |
+;; x (current buffer state)
+;; |
+;; |
+;; o
+;; |
+;; |
+;; o
+;;
+;;
+;; However, this isn't a good representation of what Emacs' undo system
+;; does. Instead, it treats the undos as *new* changes to the buffer, and adds
+;; them to the history:
+;;
+;; o (initial buffer state)
+;; |
+;; |
+;; o (first edit)
+;; |
+;; |
+;; o (second edit)
+;; |
+;; |
+;; x (buffer state before undo)
+;; |
+;; |
+;; o (first undo)
+;; |
+;; |
+;; x (second undo)
+;;
+;;
+;; Actually, since the buffer returns to a previous state after an undo, a
+;; better way to visualize it is to imagine the string of changes turning back
+;; on itself:
+;;
+;; (initial buffer state) o
+;; |
+;; |
+;; (first edit) o x (second undo)
+;; | |
+;; | |
+;; (second edit) o o (first undo)
+;; | /
+;; |/
+;; o (buffer state before undo)
+;;
+;; Treating undos as new changes might seem a strange thing to do. But the
+;; advantage becomes clear as soon as we imagine what happens when you edit
+;; the buffer again. Since you've undone a couple of changes, new edits will
+;; branch off from the buffer state that you've rewound to:
+;;
+;; o (initial buffer state)
+;; |
+;; |
+;; o
+;; |\
+;; | \
+;; o x (new edit)
+;; |
+;; |
+;; o
+;;
+;; The standard undo/redo system only lets you go backwards and forwards
+;; linearly. So as soon as you make that new edit, it discards the old
+;; branch. Emacs' undo just keeps adding changes to the end of the string. So
+;; the undo history in the two systems now looks like this:
+;;
+;; Undo/Redo: Emacs' undo
+;;
+;; o o
+;; | |
+;; | |
+;; o o o
+;; .\ | |\
+;; . \ | | \
+;; . x (new edit) o o |
+;; (discarded . | / |
+;; branch) . |/ |
+;; . o |
+;; |
+;; |
+;; x (new edit)
+;;
+;; Now, what if you change your mind about those undos, and decide you did
+;; like those other changes you'd made after all? With the standard undo/redo
+;; system, you're dead. There's no way to recover them, because that branch
+;; was discarded when you made the new edit.
+;;
+;; However, in Emacs' undo system, those old buffer states are still there in
+;; the undo history. You just have to rewind back through the new edit, and
+;; back through the changes made by the undos, until you reach them. Of
+;; course, since Emacs treats undos (even undos of undos!) as new changes,
+;; you're really weaving backwards and forwards through the history, adding
+;; new changes to the end of the string as you go:
+;;
+;; o
+;; |
+;; |
+;; o o o (undo new edit)
+;; | |\ |\
+;; | | \ | \
+;; o o | | o (undo the undo)
+;; | / | | |
+;; |/ | | |
+;; (trying to get o | | x (undo the undo)
+;; to this state) | /
+;; |/
+;; o
+;;
+;; So far, this is still reasonably intuitive to use. It doesn't behave so
+;; differently to standard undo/redo, except that by going back far enough you
+;; can access changes that would be lost in standard undo/redo.
+;;
+;; However, imagine that after undoing as just described, you decide you
+;; actually want to rewind right back to the initial state. If you're lucky,
+;; and haven't invoked any command since the last undo, you can just keep on
+;; undoing until you get back to the start:
+;;
+;; (trying to get o x (got there!)
+;; to this state) | |
+;; | |
+;; o o o o (keep undoing)
+;; | |\ |\ |
+;; | | \ | \ |
+;; o o | | o o (keep undoing)
+;; | / | | | /
+;; |/ | | |/
+;; (already undid o | | o (got this far)
+;; to this state) | /
+;; |/
+;; o
+;;
+;; But if you're unlucky, you've moved the point (say) after getting to the
+;; point labelled "got this far". In that case, you've "broken the undo
+;; chain". If you try to undo now, Emacs thinks you're trying to undo the
+;; undos. So to get back to the initial state you now have to rewind through
+;; *all* the changes, including the undos you just did:
+;;
+;; (trying to get o x (finally got there!)
+;; to this state) | |
+;; | |
+;; o o o o o o
+;; | |\ |\ |\ |\ |
+;; | | \ | \ | \ | \ |
+;; o o | | o o o | o o
+;; | / | | | / | | | /
+;; |/ | | |/ | | |/
+;; (already undid o | | o<. | | o
+;; to this state) | / : | /
+;; |/ : |/
+;; o : o
+;; :
+;; (got this far, but
+;; broke undo chain)
+;;
+;; Confused?
+;;
+;; In practice you can just hold down the undo key until you reach the buffer
+;; state that you want. But whatever you do, don't move around in the buffer
+;; to check! Because you'll break the undo chain, and then you'll have to
+;; traverse the entire string of undos again to get back to the point at which
+;; you broke the chain. Commands such as `undo-only', and undo in region (in
+;; transient-mark-mode), help make using Emacs' undo a little easier, but
+;; nonetheless it remains confusing.
+;;
+;;
+;; So what does undo-tree mode do? Remember the diagram we drew to represent
+;; the history we've been discussing (make a few edits, undo a couple of
+;; times, and edit again)? The diagram that conceptually represented our undo
+;; history, before we started discussing specific undo systems? It looked like
+;; this:
+;;
+;; o (initial buffer state)
+;; |
+;; |
+;; o
+;; |\
+;; | \
+;; o x (current state)
+;; |
+;; |
+;; o
+;;
+;; Well, that's *exactly* what the undo history looks like to undo-tree-mode.
+;; It doesn't discard the old branch (as standard undo/redo does), nor does it
+;; treat undos as new changes to be added to the end of a linear string of
+;; buffer states (as Emacs' undo does). It just keeps track of the tree of
+;; branching changes that make up the entire undo history.
+;;
+;; If you undo from this point, you'll rewind back up the tree to the previous
+;; state:
+;;
+;; o
+;; |
+;; |
+;; x (undo)
+;; |\
+;; | \
+;; o o
+;; |
+;; |
+;; o
+;;
+;; If you were to undo again, you'd rewind back to the initial state. If on
+;; the other hand you redo the change, you'll end up back at the bottom of the
+;; most recent branch:
+;;
+;; o
+;; |
+;; |
+;; o (start here)
+;; |\
+;; | \
+;; o x (redo)
+;; |
+;; |
+;; o
+;;
+;; So far, this is just like the standard undo/redo system. But what if you
+;; want to return to a buffer state located on a previous branch of the
+;; history? Since undo-tree-mode keeps the entire history, you simply need to
+;; tell it to switch to a different branch, and then redo the changes you
+;; want:
+;;
+;; o
+;; |
+;; |
+;; o (start here, but switch
+;; |\ to the other branch)
+;; | \
+;; (redo) o o
+;; |
+;; |
+;; (redo) x
+;;
+;; Now you're on the other branch, and if you undo and redo changes you'll
+;; stay on that branch, moving up and down through the buffer states located
+;; on that branch. Until you decide to switch branches again, of course.
+;;
+;; Real undo trees might have multiple branches and sub-branches:
+;;
+;; o
+;; ____|______
+;; / \
+;; o o
+;; ____|__ __|
+;; / | \ / \
+;; o o o o x
+;; | |
+;; / \ / \
+;; o o o o
+;;
+;; Trying to imagine what Emacs' undo is doing as you move about such a tree
+;; will likely frazzle your brain circuits! But in undo-tree-mode, you're just
+;; moving up and down this undo history tree. Most of the time, you'll
+;; probably only need to stay on the most recent branch, in which case it
+;; behaves like standard undo/redo, so is just as simple to understand. But if
+;; you ever need to recover a buffer state on a different branch, the
+;; possibility of switching between branches and accessing the full undo
+;; history is still there.
+;;
+;;
+;; Actually, it gets better. You don't have to imagine all these diagrams,
+;; because undo-tree-mode includes an undo-tree visualizer which draws them
+;; for you. In fact, it draws even better diagrams: it highlights the node
+;; representing the current buffer state, and it also highlights the current
+;; branch. (There's one other tiny difference: the visualizer puts the most
+;; recent branch on the left rather than the right, because it's slightly more
+;; convenient for really big trees.)
+
+
+
+;;; Change Log:
+;;
+;; Version 0.1
+;; * initial release
+
+
+;;; Code:
+
+(provide 'undo-tree)
;;; =====================================================================
@@ -817,3 +1232,6 @@ at POS."
(setq buffer-read-only nil)
(undo-tree-draw-tree buffer-undo-tree)
(setq buffer-read-only t))))
+
+
+;;; undo-tree.el ends here
- [elpa] externals/undo-tree 270bc25 110/195: Added `~' to end of default history save-file name., (continued)
- [elpa] externals/undo-tree 270bc25 110/195: Added `~' to end of default history save-file name., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree d5a6148 120/195: Don't try to auto-save undo history if undo is disabled in buffer., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree cfc036a 133/195: Fix undo-tree-redo to avoid corrupting undo-tree state if redoing fails., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree bdfd73f 132/195: Ignore bogus buffer modification entries in undo changesets., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree 6e0775d 139/195: Use define-derived-mode and define-minor-mode for undo-tree visualizer., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree d6fa2e7 152/195: Reinstate accidentally deleted file header., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree 8afead1 162/195: Add Maintainer line to package headers., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree e9a9102 164/195: Throw error if interactive commands called outside undo-tree-mode., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree ffd18cd 175/195: Refactor undo-list-transfer-to-tree again in attempt to mitigate GC races., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree 941bfe5 190/195: Don't attempt to save undo history if history file is unwritable., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree 5a1ba84 017/195: Added standard Elisp package headers, including an extensive Commentary.,
Stefan Monnier <=
- [elpa] externals/undo-tree 62e6097 044/195: Added undo-tree-save/restore-state-to/from-register commands and keybindings, Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree c638cbd 051/195: General code tidying and reorganisation., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree caa3bd0 082/195: Added new customization option to allow undo-in-region to be disabled., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree 8972e4d 069/195: Use get-buffer-create when creating the visualizer buffer in undo-tree-visualize., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree d7c1b2c 118/195: "De-circle" undo-tree when saving to file, restore when loading., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree 121cab9 136/195: Trivial typo fixes in comments., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree 18754c1 114/195: Use with-temp-buffer instead of with-temp-file when saving undo history., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree c9f78c3 137/195: Use new user-error instead of error for expected undo errors., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree 1114679 135/195: Fix bugs in binding of undo-tree-insert-face., Stefan Monnier, 2020/11/28
- [elpa] externals/undo-tree 5d19d4e 155/195: Bump version number and copyright year., Stefan Monnier, 2020/11/28