;;; undo-tree.el --- Treat undo history as a tree
-;; Copyright (C) 2009-2011 Free Software Foundation, Inc
+
+;; Copyright (C) 2009-2012 Toby Cubitt
;; Author: Toby Cubitt <toby-undo-tree@dr-qubit.org>
-;; Version: 0.3.1
+;; Version: 0.3.3
;; Keywords: convenience, files, undo, redo, history, tree
;; URL: http://www.dr-qubit.org/emacs.php
;; Git Repository: http://www.dr-qubit.org/git/undo-tree.git
-;; This file is part of Emacs.
+;; This file is NOT part of Emacs.
;;
-;; Emacs is free software: you can redistribute it and/or modify it under
+;; This file 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 3 of the License, or (at your option)
;; any later version.
;;
-;; Emacs is distributed in the hope that it will be useful, but WITHOUT
+;; 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.
;; 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 operates the ejector seat (after all, you'll soon figure it
-;; out when you push it), then here's the minimum you need to know:
+;; If you're the kind of person who likes to jump in the car and drive,
+;; without bothering to first figure out whether the button on the left dips
+;; the headlights or operates the ejector seat (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).
;; . >
;; Scroll right.
;;
-;; <pgup>
+;; <pgup> M-v
;; Scroll up.
;;
-;; <pgdown>
+;; <pgdown> C-v
;; Scroll down.
;;
;;
;;
;; Emacs allows a very useful and powerful method of undoing only selected
;; changes: when a region is active, only changes that affect the text within
-;; that region will are undone. With the standard Emacs undo system, changes
+;; that region will be undone. With the standard Emacs undo system, changes
;; produced by undoing-in-region naturally get added onto the end of the
;; linear undo history:
;;
;;; Change Log:
;;
+;; Version 0.3.3;
+;; * added `term-mode' to `undo-tree-incompatible-major-modes'
+;;
+;; Version 0.3.2
+;; * added additional check in `undo-list-GCd-marker-elt-p' to guard against
+;; undo elements being mis-identified as marker elements.
+;; * fixed bug in `undo-list-transfer-to-tree'
+;;
;; Version 0.3.1
;; * use `get-buffer-create' when creating the visualizer buffer in
;; `undo-tree-visualize', to fix bug caused by `global-undo-tree-mode' being
:group 'undo-tree
:type 'string)
-(defcustom undo-tree-incompatible-major-modes nil
+(defcustom undo-tree-incompatible-major-modes '(term-mode)
"List of major-modes in which `undo-tree-mode' should not be enabled.
\(See `turn-on-undo-tree-mode'.\)"
:group 'undo-tree
`(markerp (car-safe ,elt)))
(defmacro undo-list-GCd-marker-elt-p (elt)
- `(and (symbolp (car-safe ,elt)) (numberp (cdr-safe ,elt))))
+ ;; Return t if ELT is a marker element whose marker has been moved to the
+ ;; object-pool, so may potentially have been garbage-collected.
+ ;; Note: Valid marker undo elements should be uniquely identified as cons
+ ;; cells with a symbol in the car (replacing the marker), and a number in
+ ;; the cdr. However, to guard against future changes to undo element
+ ;; formats, we perform an additional redundant check on the symbol name.
+ `(and (car-safe ,elt)
+ (symbolp (car ,elt))
+ (let ((str (symbol-name (car ,elt))))
+ (and (> (length str) 12)
+ (string= (substring str 0 12) "undo-tree-id")))
+ (numberp (cdr-safe ,elt))))
(defun undo-tree-move-GC-elts-to-pool (elt)
;; if `buffer-undo-tree' is empty, create initial undo-tree
(when (null buffer-undo-tree) (setq buffer-undo-tree (make-undo-tree)))
;; make sure there's a canary at end of `buffer-undo-list'
- (if (null buffer-undo-list)
- (setq buffer-undo-list '(nil undo-tree-canary))
- (let ((elt (last buffer-undo-list)))
- (unless (eq (car elt) 'undo-tree-canary)
- (setcdr elt '(nil undo-tree-canary)))))
+ (when (null buffer-undo-list)
+ (setq buffer-undo-list '(nil undo-tree-canary)))
(unless (eq (cadr buffer-undo-list) 'undo-tree-canary)
;; create new node from first changeset in `buffer-undo-list', save old
(setq node (undo-tree-grow-backwards node nil))
(setf (undo-tree-root buffer-undo-tree) node)
(setq buffer-undo-list '(nil undo-tree-canary))
- (setf (undo-tree-size buffer-undo-tree) size)))
+ (setf (undo-tree-size buffer-undo-tree) size)
+ (setq buffer-undo-list '(nil undo-tree-canary))))
;; discard undo history if necessary
(undo-tree-discard-history)))
nil)
;; discard root
(t
+ ;; clear any register referring to root
+ (let ((r (undo-tree-node-register node)))
+ (when (and r (eq (get-register r) node))
+ (set-register r nil)))
;; make child of root into new root
(setq node (setf (undo-tree-root buffer-undo-tree)
(car (undo-tree-node-next node))))
(let* ((parent (undo-tree-node-previous node))
(current (nth (undo-tree-node-branch parent)
(undo-tree-node-next parent))))
+ ;; clear any register referring to the discarded node
+ (let ((r (undo-tree-node-register node)))
+ (when (and r (eq (get-register r) node))
+ (set-register r nil)))
;; update undo-tree size
(decf (undo-tree-size buffer-undo-tree)
(+ (undo-list-byte-size (undo-tree-node-undo node))