[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[ELPA-diffs] /srv/bzr/emacs/elpa r229: updated undo-tree package to vers
From: |
Toby S. Cubitt |
Subject: |
[ELPA-diffs] /srv/bzr/emacs/elpa r229: updated undo-tree package to version 0.5.2 |
Date: |
Thu, 24 May 2012 11:49:41 +0300 |
User-agent: |
Bazaar (2.5.0) |
------------------------------------------------------------
revno: 229
committer: Toby S. Cubitt <address@hidden>
branch nick: elpa
timestamp: Thu 2012-05-24 11:49:41 +0300
message:
updated undo-tree package to version 0.5.2
* undo-tree.el: add diff view feature in undo-tree visualizer.
modified:
packages/undo-tree/undo-tree.el
=== modified file 'packages/undo-tree/undo-tree.el'
--- a/packages/undo-tree/undo-tree.el 2012-05-02 20:20:08 +0000
+++ b/packages/undo-tree/undo-tree.el 2012-05-24 08:49:41 +0000
@@ -3,7 +3,7 @@
;; Copyright (C) 2009-2012 Free Software Foundation, Inc
;; Author: Toby Cubitt <address@hidden>
-;; Version: 0.4
+;; Version: 0.5.2
;; Keywords: convenience, files, undo, redo, history, tree
;; URL: http://www.dr-qubit.org/emacs.php
;; Repository: http://www.dr-qubit.org/git/undo-tree.git
@@ -103,6 +103,7 @@
;; Restore buffer state from register.
;;
;;
+;;
;; In the undo-tree visualizer:
;;
;; <up> p C-p (`undo-tree-visualize-undo')
@@ -117,12 +118,24 @@
;; <right> f C-f (`undo-tree-visualize-switch-branch-right')
;; Switch to next undo-tree branch.
;;
+;; <mouse-1> (`undo-tree-visualizer-mouse-set')
+;; Set state to node at mouse click.
+;;
;; t (`undo-tree-visualizer-toggle-timestamps')
;; Toggle display of time-stamps.
;;
-;; q C-q (`undo-tree-visualizer-quit')
+;; d (`undo-tree-visualizer-toggle-diff')
+;; Toggle diff display.
+;;
+;; s (`undo-tree-visualizer-selection-mode')
+;; Toggle keyboard selection mode.
+;;
+;; q (`undo-tree-visualizer-quit')
;; Quit undo-tree-visualizer.
;;
+;; C-q (`undo-tree-visualizer-abort')
+;; Abort undo-tree-visualizer.
+;;
;; , <
;; Scroll left.
;;
@@ -137,6 +150,53 @@
;;
;;
;;
+;; In visualizer selection mode:
+;;
+;; <up> p C-p (`undo-tree-visualizer-select-previous')
+;; Select previous node.
+;;
+;; <down> n C-n (`undo-tree-visualizer-select-next')
+;; Select next node.
+;;
+;; <left> b C-b (`undo-tree-visualizer-select-left')
+;; Select left sibling node.
+;;
+;; <right> f C-f (`undo-tree-visualizer-select-right')
+;; Select right sibling node.
+;;
+;; <pgup> M-v
+;; Select node 10 above.
+;;
+;; <pgdown> C-v
+;; Select node 10 below.
+;;
+;; <enter> (`undo-tree-visualizer-set')
+;; Set state to selected node and exit selection mode.
+;;
+;; s (`undo-tree-visualizer-mode')
+;; Exit selection mode.
+;;
+;; t (`undo-tree-visualizer-toggle-timestamps')
+;; Toggle display of time-stamps.
+;;
+;; d (`undo-tree-visualizer-toggle-diff')
+;; Toggle diff display.
+;;
+;; q (`undo-tree-visualizer-quit')
+;; Quit undo-tree-visualizer.
+;;
+;; C-q (`undo-tree-visualizer-abort')
+;; Abort undo-tree-visualizer.
+;;
+;; , <
+;; Scroll left.
+;;
+;; . >
+;; Scroll right.
+;;
+;;
+;;
+;;
;; Undo Systems
;; ============
;;
@@ -436,9 +496,12 @@
;; 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, it highlights the current
-;; branch, and (by hitting "t") you can toggle the display of
-;; time-stamps. (There's one other tiny difference: the visualizer puts the
-;; most recent branch on the left rather than the right.)
+;; branch, and you can toggle the display of time-stamps (by hitting "t") and
+;; a diff of the undo changes (by hitting "d"). (There's one other tiny
+;; difference: the visualizer puts the most recent branch on the left rather
+;; than the right.)
+;;
+;; Bring up the undo tree visualizer whenever you want by hitting "C-x u".
;;
;; In the visualizer, the usual keys for moving up and down a buffer instead
;; move up and down the undo history tree (e.g. the up and down arrow keys, or
@@ -446,10 +509,17 @@
;; history you are visualizing) is updated as you move around the undo tree in
;; the visualizer. If you reach a branch point in the visualizer, the usual
;; keys for moving forward and backward in a buffer instead switch branch
-;; (e.g. the left and right arrow keys, or "C-f" and "C-b"). And clicking with
-;; the mouse on any node in the visualizer will take you directly to that
-;; node, resetting the state of the parent buffer to the state represented by
-;; that node.
+;; (e.g. the left and right arrow keys, or "C-f" and "C-b").
+;;
+;; Clicking with the mouse on any node in the visualizer will take you
+;; directly to that node, resetting the state of the parent buffer to the
+;; state represented by that node.
+;;
+;; You can also select nodes directly using the keyboard, by hitting "s" to
+;; toggle selection mode. The usual motion keys now allow you to move around
+;; the tree without changing the parent buffer. Hitting <enter> will reset the
+;; state of the parent buffer to the state represented by the currently
+;; selected node.
;;
;; It can be useful to see how long ago the parent buffer was in the state
;; represented by a particular node in the visualizer. Hitting "t" in the
@@ -458,8 +528,24 @@
;; somewhat later than the true times, especially if it's been a long time
;; since you last undid any changes.)
;;
+;; To get some idea of what changes are represented by a given node in the
+;; tree, it can be useful to see a diff of the changes. Hit "d" in the
+;; visualizer to toggle a diff display. This normally displays a diff between
+;; the current state and the previous one, i.e. it shows you the changes that
+;; will be applied if you undo (move up the tree). However, the diff display
+;; really comes into its own in the visualizer's selection mode (see above),
+;; where it instead shows a diff between the current state and the currently
+;; selected state, i.e. it shows you the changes that will be applied if you
+;; reset to the selected state.
+;;
+;; (Note that the diff is generated by the Emacs `diff' command, and is
+;; displayed using `diff-mode'. See the corresponding customization groups if
+;; you want to customize the diff display.)
+;;
;; Finally, hitting "q" will quit the visualizer, leaving the parent buffer in
-;; whatever state you ended at.
+;; whatever state you ended at. Hitting "C-q" will abort the visualizer,
+;; returning the parent buffer to whatever state it was originally in when the
+;; visualizer was .
;;
;;
;;
@@ -604,6 +690,47 @@
;;; Change Log:
;;
+;; Version 0.5.2
+;; * added `~' to end of default history save-file name
+;; * avoid error in `undo-tree-save-history' when undo is disabled in buffer
+;; or buffer has no undo information to save
+;;
+;; Version 0.5.1
+;; * remove now unnecessary compatibility hack for `called-interactively-p'
+;;
+;; Version 0.5
+;; * implemented diff display in visualizer, toggled on and off using
+;; `undo-tree-visualizer-toggle-diff'
+;; * added `undo-tree-visualizer-diff' customization option, to display diff
+;; by default
+;; * added `called-interactively-p', `registerv-make', `registerv-data',
+;; `diff-no-select' and `diff-file-local-copy' compatibility hacks for
+;; older Emacsen
+;; * split out core of `undo-tree-undo' and `undo-tree-redo' into internal
+;; `undo-tree-undo-1' and `undo-tree-redo-1' functions, which now take an
+;; additional optional argument to preserve timestamps
+;; * preserve timestamps when generating diff for visualizer diff view
+;; * fixed bug in `undo-tree-visualizer-select-left' and
+;; `undo-tree-visualizer-select-right' when using selection mode whilst
+;; timestamps are displayed
+;; * fixed bug in `undo-tree-draw-node' caused by new registerv structure,
+;; which prevented registers from being displayed in visualizer
+;; * added `undo-tree-visualizer-relative-timestamps' option to make
+;; visualizer display timestamps relative to current time
+;; * use a function `undo-tree-make-history-save-file-name' function to
+;; generate history save filename, allowing save file to be customized by
+;; overriding this function
+;; * clear visualizer data / kill visualizer in `undo-tree-save-history'
+;; before saving history to file, otherwise markers in visualizer meta-data
+;; cause read errors in `undo-tree-load-history'
+;; * make `undo-tree-visualizer-timestamps' into defcustom, to allow
+;; timestamps to be displayed by default
+;; * use `undo-tree-visualizer-selected-node' to store currently selected node
+;; in visualizer selection mode, instead of relying on point location, to
+;; avoid errors if point was moved manually
+;; * added `undo-tree-visualizer-abort' command to quit visualizer and return
+;; to original state, stored in `undo-tree-visualizer-initial-node'
+;;
;; Version 0.4
;; * implemented persistent history storage: `undo-tree-save-history' and
;; `undo-tree-load-history' save and restore an undo tree to file, enabling
@@ -744,16 +871,101 @@
;;; Code:
(eval-when-compile (require 'cl))
-
-;; `characterp' isn't defined in Emacs versions <= 22
+(require 'diff)
+
+
+
+;;; =====================================================================
+;;; Compatibility hacks for older Emacsen
+
+;; `characterp' isn't defined in Emacs versions < 23
(unless (fboundp 'characterp)
(defalias 'characterp 'char-valid-p))
-;; `region-active-p' isn't defined in Emacs versions <= 22
+;; `region-active-p' isn't defined in Emacs versions < 23
(unless (fboundp 'region-active-p)
(defun region-active-p () (and transient-mark-mode mark-active)))
+;; `registerv' defstruct isn't defined in Emacs versions < 24
+(unless (fboundp 'registerv-make)
+ (defmacro registerv-make (data &rest dummy) data))
+
+(unless (fboundp 'registerv-data)
+ (defmacro registerv-data (data) data))
+
+
+;; `diff-no-select' and `diff-file-local-copy' aren't defined in Emacs
+;; versions < 24 (copied and adapted from Emacs 24)
+(unless (fboundp 'diff-no-select)
+ (defun diff-no-select (old new &optional switches no-async buf)
+ ;; Noninteractive helper for creating and reverting diff buffers
+ (unless (bufferp new) (setq new (expand-file-name new)))
+ (unless (bufferp old) (setq old (expand-file-name old)))
+ (or switches (setq switches diff-switches)) ; If not specified, use
default.
+ (unless (listp switches) (setq switches (list switches)))
+ (or buf (setq buf (get-buffer-create "*Diff*")))
+ (let* ((old-alt (diff-file-local-copy old))
+ (new-alt (diff-file-local-copy new))
+ (command
+ (mapconcat 'identity
+ `(,diff-command
+ ;; Use explicitly specified switches
+ ,@switches
+ ,@(mapcar #'shell-quote-argument
+ (nconc
+ (when (or old-alt new-alt)
+ (list "-L" (if (stringp old)
+ old (prin1-to-string old))
+ "-L" (if (stringp new)
+ new (prin1-to-string
new))))
+ (list (or old-alt old)
+ (or new-alt new)))))
+ " "))
+ (thisdir default-directory))
+ (with-current-buffer buf
+ (setq buffer-read-only t)
+ (buffer-disable-undo (current-buffer))
+ (let ((inhibit-read-only t))
+ (erase-buffer))
+ (buffer-enable-undo (current-buffer))
+ (diff-mode)
+ (set (make-local-variable 'revert-buffer-function)
+ (lambda (_ignore-auto _noconfirm)
+ (diff-no-select old new switches no-async (current-buffer))))
+ (setq default-directory thisdir)
+ (let ((inhibit-read-only t))
+ (insert command "\n"))
+ (if (and (not no-async) (fboundp 'start-process))
+ (let ((proc (start-process "Diff" buf shell-file-name
+ shell-command-switch command)))
+ (set-process-filter proc 'diff-process-filter)
+ (set-process-sentinel
+ proc (lambda (proc _msg)
+ (with-current-buffer (process-buffer proc)
+ (diff-sentinel (process-exit-status proc))
+ (if old-alt (delete-file old-alt))
+ (if new-alt (delete-file new-alt))))))
+ ;; Async processes aren't available.
+ (let ((inhibit-read-only t))
+ (diff-sentinel
+ (call-process shell-file-name nil buf nil
+ shell-command-switch command))
+ (if old-alt (delete-file old-alt))
+ (if new-alt (delete-file new-alt)))))
+ buf)))
+
+(unless (fboundp 'diff-file-local-copy)
+ (defun diff-file-local-copy (file-or-buf)
+ (if (bufferp file-or-buf)
+ (with-current-buffer file-or-buf
+ (let ((tempfile (make-temp-file "buffer-content-")))
+ (write-region nil nil tempfile nil 'nomessage)
+ tempfile))
+ (file-local-copy file-or-buf))))
+
+
+
;;; =====================================================================
;;; Global variables and customization options
@@ -774,15 +986,6 @@
:group 'undo-tree
:type 'string)
-(defcustom undo-tree-enable-undo-in-region t
- "When non-nil, enable undo-in-region.
-
-When undo-in-region is enabled, undoing or redoing when the
-region is active (in `transient-mark-mode') or with a prefix
-argument (not in `transient-mark-mode') only undoes changes
-within the current region."
- :group 'undo-tree
- :type 'boolean)
(defcustom undo-tree-auto-save-history nil
"When non-nil, `undo-tree-mode' will save undo history to file
@@ -806,32 +1009,65 @@
'(choice (const :tag "<disabled>" nil))
'boolean))
+
+(defcustom undo-tree-visualizer-relative-timestamps t
+ "When non-nil, display times relative to current time
+when displaying time stamps in visualizer.
+
+Otherwise, display absolute times."
+ :group 'undo-tree
+ :type 'boolean)
+
+
+(defcustom undo-tree-visualizer-timestamps nil
+ "When non-nil, display time-stamps by default
+in undo-tree visualizer.
+
+\\<undo-tree-visualizer-map>You can always toggle time-stamps on and off \
+using \\[undo-tree-visualizer-toggle-timestamps], regardless of the
+setting of this variable."
+ :group 'undo-tree
+ :type 'boolean)
+(make-variable-buffer-local 'undo-tree-visualizer-timestamps)
+
+
+(defcustom undo-tree-visualizer-diff nil
+ "When non-nil, display diff by default in undo-tree visualizer.
+
+\\<undo-tree-visualizer-map>You can always toggle the diff display \
+using \\[undo-tree-visualizer-toggle-diff], regardless of the
+setting of this variable."
+ :group 'undo-tree
+ :type 'boolean)
+(make-variable-buffer-local 'undo-tree-visualizer-diff)
+
+
(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
:type '(repeat symbol))
-(defcustom undo-tree-visualizer-spacing 3
- "Horizontal spacing in undo-tree visualization.
-Must be a postivie odd integer."
+
+(defcustom undo-tree-enable-undo-in-region t
+ "When non-nil, enable undo-in-region.
+
+When undo-in-region is enabled, undoing or redoing when the
+region is active (in `transient-mark-mode') or with a prefix
+argument (not in `transient-mark-mode') only undoes changes
+within the current region."
:group 'undo-tree
- :type '(integer
- :match (lambda (w n) (and (integerp n) (> n 0) (= (mod n 2) 1)))))
-(make-variable-buffer-local 'undo-tree-visualizer-spacing)
-
-(defvar undo-tree-map nil
- "Keymap used in undo-tree-mode.")
+ :type 'boolean)
(defface undo-tree-visualizer-default-face
'((((class color)) :foreground "gray"))
- "*Face used to draw undo-tree in visualizer."
+ "Face used to draw undo-tree in visualizer."
:group 'undo-tree)
(defface undo-tree-visualizer-current-face
'((((class color)) :foreground "red"))
- "*Face used to highlight current undo-tree node in visualizer."
+ "Face used to highlight current undo-tree node in visualizer."
:group 'undo-tree)
(defface undo-tree-visualizer-active-branch-face
@@ -839,37 +1075,47 @@
(:foreground "white" :weight bold))
(((class color) (background light))
(:foreground "black" :weight bold)))
- "*Face used to highlight active undo-tree branch
-in visualizer."
+ "Face used to highlight active undo-tree branch in visualizer."
:group 'undo-tree)
(defface undo-tree-visualizer-register-face
'((((class color)) :foreground "yellow"))
- "*Face used to highlight undo-tree nodes saved to a register
+ "Face used to highlight undo-tree nodes saved to a register
in visualizer."
:group 'undo-tree)
-(defvar undo-tree-visualizer-map nil
- "Keymap used in undo-tree visualizer.")
-
-(defvar undo-tree-visualizer-selection-map nil
- "Keymap used in undo-tree visualizer selection mode.")
-
(defvar undo-tree-visualizer-parent-buffer nil
"Parent buffer in visualizer.")
(make-variable-buffer-local 'undo-tree-visualizer-parent-buffer)
-(defvar undo-tree-visualizer-timestamps nil
- "Non-nil when visualizer is displaying time-stamps.")
-(make-variable-buffer-local 'undo-tree-visualizer-timestamps)
-
-(defconst undo-tree-visualizer-buffer-name " *undo-tree*")
+;; stores current horizontal spacing needed for drawing undo-tree
+(defvar undo-tree-visualizer-spacing nil)
+(make-variable-buffer-local 'undo-tree-visualizer-spacing)
+
+;; calculate horizontal spacing required for drawing undo-tree with current
+;; settings
+(defsubst undo-tree-visualizer-calculate-spacing ()
+ (if undo-tree-visualizer-timestamps
+ (if undo-tree-visualizer-relative-timestamps 9 13)
+ 3))
+
+;; holds node that was current when visualizer was invoked
+(defvar undo-tree-visualizer-initial-node nil)
+(make-variable-buffer-local 'undo-tree-visualizer-initial-node)
+
+;; holds currently selected node in visualizer selection mode
+(defvar undo-tree-visualizer-selected-node nil)
+(make-variable-buffer-local 'undo-tree-visualizer-selected)
;; dynamically bound to t when undoing from visualizer, to inhibit
;; `undo-tree-kill-visualizer' hook function in parent buffer
(defvar undo-tree-inhibit-kill-visualizer nil)
+
+(defconst undo-tree-visualizer-buffer-name " *undo-tree*")
+(defconst undo-tree-diff-buffer-name "*undo-tree Diff*")
+
;; prevent debugger being called on "No further redo information"
(add-to-list 'debug-ignored-errors "^No further redo information")
@@ -879,158 +1125,132 @@
;;; =================================================================
;;; Setup default keymaps
+(defvar undo-tree-map nil
+ "Keymap used in undo-tree-mode.")
+
(unless undo-tree-map
- (setq undo-tree-map (make-sparse-keymap))
- ;; remap `undo' and `undo-only' to `undo-tree-undo'
- (define-key undo-tree-map [remap undo] 'undo-tree-undo)
- (define-key undo-tree-map [remap undo-only] 'undo-tree-undo)
- ;; bind standard undo bindings (since these match redo counterparts)
- (define-key undo-tree-map (kbd "C-/") 'undo-tree-undo)
- (define-key undo-tree-map "\C-_" 'undo-tree-undo)
- ;; redo doesn't exist normally, so define our own keybindings
- (define-key undo-tree-map (kbd "C-?") 'undo-tree-redo)
- (define-key undo-tree-map (kbd "M-_") 'undo-tree-redo)
- ;; just in case something has defined `redo'...
- (define-key undo-tree-map [remap redo] 'undo-tree-redo)
- ;; we use "C-x u" for the undo-tree visualizer
- (define-key undo-tree-map (kbd "\C-x u") 'undo-tree-visualize)
- ;; bind register commands
- (define-key undo-tree-map (kbd "C-x r u")
- 'undo-tree-save-state-to-register)
- (define-key undo-tree-map (kbd "C-x r U")
- 'undo-tree-restore-state-from-register))
-
+ (let ((map (make-sparse-keymap)))
+ ;; remap `undo' and `undo-only' to `undo-tree-undo'
+ (define-key map [remap undo] 'undo-tree-undo)
+ (define-key map [remap undo-only] 'undo-tree-undo)
+ ;; bind standard undo bindings (since these match redo counterparts)
+ (define-key map (kbd "C-/") 'undo-tree-undo)
+ (define-key map "\C-_" 'undo-tree-undo)
+ ;; redo doesn't exist normally, so define our own keybindings
+ (define-key map (kbd "C-?") 'undo-tree-redo)
+ (define-key map (kbd "M-_") 'undo-tree-redo)
+ ;; just in case something has defined `redo'...
+ (define-key map [remap redo] 'undo-tree-redo)
+ ;; we use "C-x u" for the undo-tree visualizer
+ (define-key map (kbd "\C-x u") 'undo-tree-visualize)
+ ;; bind register commands
+ (define-key map (kbd "C-x r u") 'undo-tree-save-state-to-register)
+ (define-key map (kbd "C-x r U") 'undo-tree-restore-state-from-register)
+ ;; set keymap
+ (setq undo-tree-map map)))
+
+
+(defvar undo-tree-visualizer-map nil
+ "Keymap used in undo-tree visualizer.")
(unless undo-tree-visualizer-map
- (setq undo-tree-visualizer-map (make-keymap))
- ;; vertical motion keys undo/redo
- (define-key undo-tree-visualizer-map [remap previous-line]
- 'undo-tree-visualize-undo)
- (define-key undo-tree-visualizer-map [remap next-line]
- 'undo-tree-visualize-redo)
- (define-key undo-tree-visualizer-map [up]
- 'undo-tree-visualize-undo)
- (define-key undo-tree-visualizer-map "p"
- 'undo-tree-visualize-undo)
- (define-key undo-tree-visualizer-map "\C-p"
- 'undo-tree-visualize-undo)
- (define-key undo-tree-visualizer-map [down]
- 'undo-tree-visualize-redo)
- (define-key undo-tree-visualizer-map "n"
- 'undo-tree-visualize-redo)
- (define-key undo-tree-visualizer-map "\C-n"
- 'undo-tree-visualize-redo)
- ;; horizontal motion keys switch branch
- (define-key undo-tree-visualizer-map [remap forward-char]
- 'undo-tree-visualize-switch-branch-right)
- (define-key undo-tree-visualizer-map [remap backward-char]
- 'undo-tree-visualize-switch-branch-left)
- (define-key undo-tree-visualizer-map [right]
- 'undo-tree-visualize-switch-branch-right)
- (define-key undo-tree-visualizer-map "f"
- 'undo-tree-visualize-switch-branch-right)
- (define-key undo-tree-visualizer-map "\C-f"
- 'undo-tree-visualize-switch-branch-right)
- (define-key undo-tree-visualizer-map [left]
- 'undo-tree-visualize-switch-branch-left)
- (define-key undo-tree-visualizer-map "b"
- 'undo-tree-visualize-switch-branch-left)
- (define-key undo-tree-visualizer-map "\C-b"
- 'undo-tree-visualize-switch-branch-left)
- ;; mouse sets buffer state to node at click
- (define-key undo-tree-visualizer-map [mouse-1]
- 'undo-tree-visualizer-mouse-set)
- ;; toggle timestamps
- (define-key undo-tree-visualizer-map "t"
- 'undo-tree-visualizer-toggle-timestamps)
- ;; selection mode
- (define-key undo-tree-visualizer-map "s"
- 'undo-tree-visualizer-selection-mode)
- ;; horizontal scrolling may be needed if the tree is very wide
- (define-key undo-tree-visualizer-map ","
- 'undo-tree-visualizer-scroll-left)
- (define-key undo-tree-visualizer-map "."
- 'undo-tree-visualizer-scroll-right)
- (define-key undo-tree-visualizer-map "<"
- 'undo-tree-visualizer-scroll-left)
- (define-key undo-tree-visualizer-map ">"
- 'undo-tree-visualizer-scroll-right)
- ;; vertical scrolling may be needed if the tree is very tall
- (define-key undo-tree-visualizer-map [next] 'scroll-up)
- (define-key undo-tree-visualizer-map [prior] 'scroll-down)
- ;; quit visualizer
- (define-key undo-tree-visualizer-map "q"
- 'undo-tree-visualizer-quit)
- (define-key undo-tree-visualizer-map "\C-q"
- 'undo-tree-visualizer-quit))
-
+ (let ((map (make-sparse-keymap)))
+ ;; vertical motion keys undo/redo
+ (define-key map [remap previous-line] 'undo-tree-visualize-undo)
+ (define-key map [remap next-line] 'undo-tree-visualize-redo)
+ (define-key map [up] 'undo-tree-visualize-undo)
+ (define-key map "p" 'undo-tree-visualize-undo)
+ (define-key map "\C-p" 'undo-tree-visualize-undo)
+ (define-key map [down] 'undo-tree-visualize-redo)
+ (define-key map "n" 'undo-tree-visualize-redo)
+ (define-key map "\C-n" 'undo-tree-visualize-redo)
+ ;; horizontal motion keys switch branch
+ (define-key map [remap forward-char]
+ 'undo-tree-visualize-switch-branch-right)
+ (define-key map [remap backward-char]
+ 'undo-tree-visualize-switch-branch-left)
+ (define-key map [right] 'undo-tree-visualize-switch-branch-right)
+ (define-key map "f" 'undo-tree-visualize-switch-branch-right)
+ (define-key map "\C-f" 'undo-tree-visualize-switch-branch-right)
+ (define-key map [left] 'undo-tree-visualize-switch-branch-left)
+ (define-key map "b" 'undo-tree-visualize-switch-branch-left)
+ (define-key map "\C-b" 'undo-tree-visualize-switch-branch-left)
+ ;; mouse sets buffer state to node at click
+ (define-key map [mouse-1] 'undo-tree-visualizer-mouse-set)
+ ;; toggle timestamps
+ (define-key map "t" 'undo-tree-visualizer-toggle-timestamps)
+ ;; toggle diff
+ (define-key map "d" 'undo-tree-visualizer-toggle-diff)
+ ;; selection mode
+ (define-key map "s" 'undo-tree-visualizer-selection-mode)
+ ;; horizontal scrolling may be needed if the tree is very wide
+ (define-key map "," 'undo-tree-visualizer-scroll-left)
+ (define-key map "." 'undo-tree-visualizer-scroll-right)
+ (define-key map "<" 'undo-tree-visualizer-scroll-left)
+ (define-key map ">" 'undo-tree-visualizer-scroll-right)
+ ;; vertical scrolling may be needed if the tree is very tall
+ (define-key map [next] 'scroll-up)
+ (define-key map [prior] 'scroll-down)
+ ;; quit/abort visualizer
+ (define-key map "q" 'undo-tree-visualizer-quit)
+ (define-key map "\C-q" 'undo-tree-visualizer-abort)
+ ;; set keymap
+ (setq undo-tree-visualizer-map map)))
+
+
+(defvar undo-tree-visualizer-selection-map nil
+ "Keymap used in undo-tree visualizer selection mode.")
(unless undo-tree-visualizer-selection-map
- (setq undo-tree-visualizer-selection-map (make-keymap))
- ;; vertical motion keys move up and down tree
- (define-key undo-tree-visualizer-selection-map [remap previous-line]
- 'undo-tree-visualizer-select-previous)
- (define-key undo-tree-visualizer-selection-map [remap next-line]
- 'undo-tree-visualizer-select-next)
- (define-key undo-tree-visualizer-selection-map [up]
- 'undo-tree-visualizer-select-previous)
- (define-key undo-tree-visualizer-selection-map "p"
- 'undo-tree-visualizer-select-previous)
- (define-key undo-tree-visualizer-selection-map "\C-p"
- 'undo-tree-visualizer-select-previous)
- (define-key undo-tree-visualizer-selection-map [down]
- 'undo-tree-visualizer-select-next)
- (define-key undo-tree-visualizer-selection-map "n"
- 'undo-tree-visualizer-select-next)
- (define-key undo-tree-visualizer-selection-map "\C-n"
- 'undo-tree-visualizer-select-next)
- ;; vertical scroll keys move up and down quickly
- (define-key undo-tree-visualizer-selection-map [next]
- (lambda () (interactive) (undo-tree-visualizer-select-next 10)))
- (define-key undo-tree-visualizer-selection-map [prior]
- (lambda () (interactive) (undo-tree-visualizer-select-previous 10)))
- ;; horizontal motion keys move to left and right siblings
- (define-key undo-tree-visualizer-selection-map [remap forward-char]
- 'undo-tree-visualizer-select-right)
- (define-key undo-tree-visualizer-selection-map [remap backward-char]
- 'undo-tree-visualizer-select-left)
- (define-key undo-tree-visualizer-selection-map [right]
- 'undo-tree-visualizer-select-right)
- (define-key undo-tree-visualizer-selection-map "f"
- 'undo-tree-visualizer-select-right)
- (define-key undo-tree-visualizer-selection-map "\C-f"
- 'undo-tree-visualizer-select-right)
- (define-key undo-tree-visualizer-selection-map [left]
- 'undo-tree-visualizer-select-left)
- (define-key undo-tree-visualizer-selection-map "b"
- 'undo-tree-visualizer-select-left)
- (define-key undo-tree-visualizer-selection-map "\C-b"
- 'undo-tree-visualizer-select-left)
- ;; horizontal scroll keys move left or right quickly
- (define-key undo-tree-visualizer-selection-map ","
- (lambda () (interactive) (undo-tree-visualizer-select-left 10)))
- (define-key undo-tree-visualizer-selection-map "."
- (lambda () (interactive) (undo-tree-visualizer-select-right 10)))
- (define-key undo-tree-visualizer-selection-map "<"
- (lambda () (interactive) (undo-tree-visualizer-select-left 10)))
- (define-key undo-tree-visualizer-selection-map ">"
- (lambda () (interactive) (undo-tree-visualizer-select-right 10)))
- ;; mouse or <enter> sets buffer state to node at point/click
- (define-key undo-tree-visualizer-selection-map "\r"
- 'undo-tree-visualizer-set)
- (define-key undo-tree-visualizer-selection-map [mouse-1]
- 'undo-tree-visualizer-mouse-set)
- ;; toggle timestamps
- (define-key undo-tree-visualizer-selection-map "t"
- 'undo-tree-visualizer-toggle-timestamps)
- ;; quit visualizer selection mode
- (define-key undo-tree-visualizer-selection-map "s"
- 'undo-tree-visualizer-mode)
- ;; quit visualizer
- (define-key undo-tree-visualizer-selection-map "q"
- 'undo-tree-visualizer-quit)
- (define-key undo-tree-visualizer-selection-map "\C-q"
- 'undo-tree-visualizer-quit))
+ (let ((map (make-sparse-keymap)))
+ ;; vertical motion keys move up and down tree
+ (define-key map [remap previous-line]
+ 'undo-tree-visualizer-select-previous)
+ (define-key map [remap next-line]
+ 'undo-tree-visualizer-select-next)
+ (define-key map [up] 'undo-tree-visualizer-select-previous)
+ (define-key map "p" 'undo-tree-visualizer-select-previous)
+ (define-key map "\C-p" 'undo-tree-visualizer-select-previous)
+ (define-key map [down] 'undo-tree-visualizer-select-next)
+ (define-key map "n" 'undo-tree-visualizer-select-next)
+ (define-key map "\C-n" 'undo-tree-visualizer-select-next)
+ ;; vertical scroll keys move up and down quickly
+ (define-key map [next]
+ (lambda () (interactive) (undo-tree-visualizer-select-next 10)))
+ (define-key map [prior]
+ (lambda () (interactive) (undo-tree-visualizer-select-previous 10)))
+ ;; horizontal motion keys move to left and right siblings
+ (define-key map [remap forward-char] 'undo-tree-visualizer-select-right)
+ (define-key map [remap backward-char] 'undo-tree-visualizer-select-left)
+ (define-key map [right] 'undo-tree-visualizer-select-right)
+ (define-key map "f" 'undo-tree-visualizer-select-right)
+ (define-key map "\C-f" 'undo-tree-visualizer-select-right)
+ (define-key map [left] 'undo-tree-visualizer-select-left)
+ (define-key map "b" 'undo-tree-visualizer-select-left)
+ (define-key map "\C-b" 'undo-tree-visualizer-select-left)
+ ;; horizontal scroll keys move left or right quickly
+ (define-key map ","
+ (lambda () (interactive) (undo-tree-visualizer-select-left 10)))
+ (define-key map "."
+ (lambda () (interactive) (undo-tree-visualizer-select-right 10)))
+ (define-key map "<"
+ (lambda () (interactive) (undo-tree-visualizer-select-left 10)))
+ (define-key map ">"
+ (lambda () (interactive) (undo-tree-visualizer-select-right 10)))
+ ;; mouse or <enter> sets buffer state to node at point/click
+ (define-key map "\r" 'undo-tree-visualizer-set)
+ (define-key map [mouse-1] 'undo-tree-visualizer-mouse-set)
+ ;; toggle timestamps
+ (define-key map "t" 'undo-tree-visualizer-toggle-timestamps)
+ ;; toggle diff
+ (define-key map "d" 'undo-tree-visualizer-selection-toggle-diff)
+ ;; quit visualizer selection mode
+ (define-key map "s" 'undo-tree-visualizer-mode)
+ ;; quit visualizer
+ (define-key map "q" 'undo-tree-visualizer-quit)
+ (define-key map "\C-q" 'undo-tree-visualizer-abort)
+ ;; set keymap
+ (setq undo-tree-visualizer-selection-map map)))
@@ -1889,7 +2109,7 @@
;; (recognizable as first node with more than one branch)
(let ((mark-active nil))
(while (= (length (undo-tree-node-next node)) 1)
- (undo-tree-undo)
+ (undo-tree-undo-1)
(setq fragment node
node (undo-tree-current buffer-undo-tree))))
(when (eq splice node) (setq splice nil))
@@ -2006,7 +2226,7 @@
(let ((mark-active nil))
(while (not (eq (undo-tree-current buffer-undo-tree)
original-current))
- (undo-tree-redo)))
+ (undo-tree-redo-1)))
nil) ; return nil to indicate failure
;; otherwise...
@@ -2016,9 +2236,9 @@
(let ((mark-active nil)
(current (undo-tree-current buffer-undo-tree)))
(while (not (eq (undo-tree-current buffer-undo-tree) node))
- (undo-tree-undo))
+ (undo-tree-undo-1))
(while (not (eq (undo-tree-current buffer-undo-tree) current))
- (undo-tree-redo)))
+ (undo-tree-redo-1)))
(cond
;; if there's no remaining fragment, just create undo-in-region node
@@ -2057,7 +2277,7 @@
(undo-tree-node-previous original-fragment))
(let ((mark-active nil))
(while (not (eq (undo-tree-current buffer-undo-tree) splice))
- (undo-tree-redo nil 'preserve-undo))))
+ (undo-tree-redo-1 nil 'preserve-undo))))
;; splice new undo-in-region node into fragment
(setq node (undo-tree-make-node nil region-changeset))
(undo-tree-splice-node node splice)
@@ -2428,7 +2648,7 @@
-(defun undo-tree-undo (&optional arg preserve-redo)
+(defun undo-tree-undo (&optional arg)
"Undo changes.
Repeat this command to undo more changes.
A numeric ARG serves as a repeat count.
@@ -2436,15 +2656,24 @@
In Transient Mark mode when the mark is active, only undo changes
within the current region. Similarly, when not in Transient Mark
mode, just \\[universal-argument] as an argument limits undo to
-changes within the current region.
-
-A non-nil PRESERVE-REDO causes the existing redo record to be
-preserved, rather than replacing it with the new one generated by
-undoing."
+changes within the current region."
(interactive "*P")
;; throw error if undo is disabled in buffer
(when (eq buffer-undo-list t) (error "No undo information in this buffer"))
-
+ (undo-tree-undo-1 arg)
+ ;; inform user if at branch point
+ (when (> (undo-tree-num-branches) 1) (message "Undo branch point!")))
+
+
+(defun undo-tree-undo-1 (&optional arg preserve-redo preserve-timestamps)
+ ;; Internal undo function. An active mark in `transient-mark-mode', or
+ ;; non-nil ARG otherwise, enables undo-in-region. Non-nil PRESERVE-REDO
+ ;; causes the existing redo record to be preserved, rather than replacing it
+ ;; with the new one generated by undoing. Non-nil PRESERVE-TIMESTAMPS
+ ;; disables updating of timestamps in visited undo-tree nodes. (This latter
+ ;; should *only* be used when temporarily visiting another undo state and
+ ;; immediately returning to the original state afterwards. Otherwise, it
+ ;; could cause history-discarding errors.)
(let ((undo-in-progress t)
(undo-in-region (and undo-tree-enable-undo-in-region
(or (region-active-p)
@@ -2506,9 +2735,10 @@
;; rewind current node and update timestamp
(setf (undo-tree-current buffer-undo-tree)
- (undo-tree-node-previous (undo-tree-current buffer-undo-tree))
- (undo-tree-node-timestamp (undo-tree-current buffer-undo-tree))
- (current-time))
+ (undo-tree-node-previous (undo-tree-current buffer-undo-tree)))
+ (unless preserve-timestamps
+ (setf (undo-tree-node-timestamp (undo-tree-current buffer-undo-tree))
+ (current-time)))
;; if undoing-in-region, record current node, region and direction so we
;; can tell if undo-in-region is repeated, and re-activate mark if in
@@ -2523,29 +2753,34 @@
(set-marker pos nil)))
;; undo deactivates mark unless undoing-in-region
- (setq deactivate-mark (not undo-in-region))
- ;; inform user if at branch point
- (when (and (called-interactively-p 'interactive)
- (> (undo-tree-num-branches) 1))
- (message "Undo branch point!"))))
-
-
-
-(defun undo-tree-redo (&optional arg preserve-undo)
+ (setq deactivate-mark (not undo-in-region))))
+
+
+
+(defun undo-tree-redo (&optional arg)
"Redo changes. A numeric ARG serves as a repeat count.
In Transient Mark mode when the mark is active, only redo changes
within the current region. Similarly, when not in Transient Mark
mode, just \\[universal-argument] as an argument limits redo to
-changes within the current region.
-
-A non-nil PRESERVE-UNDO causes the existing undo record to be
-preserved, rather than replacing it with the new one generated by
-redoing."
+changes within the current region."
(interactive "*P")
;; throw error if undo is disabled in buffer
(when (eq buffer-undo-list t) (error "No undo information in this buffer"))
-
+ (undo-tree-redo-1 arg)
+ ;; inform user if at branch point
+ (when (> (undo-tree-num-branches) 1) (message "Undo branch point!")))
+
+
+(defun undo-tree-redo-1 (&optional arg preserve-undo preserve-timestamps)
+ ;; Internal redo function. An active mark in `transient-mark-mode', or
+ ;; non-nil ARG otherwise, enables undo-in-region. Non-nil PRESERVE-UNDO
+ ;; causes the existing redo record to be preserved, rather than replacing it
+ ;; with the new one generated by undoing. Non-nil PRESERVE-TIMESTAMPS
+ ;; disables updating of timestamps in visited undo-tree nodes. (This latter
+ ;; should *only* be used when temporarily visiting another undo state and
+ ;; immediately returning to the original state afterwards. Otherwise, it
+ ;; could cause history-discarding errors.)
(let ((undo-in-progress t)
(redo-in-region (and undo-tree-enable-undo-in-region
(or (region-active-p)
@@ -2610,7 +2845,8 @@
(undo-list-byte-size (undo-tree-node-undo current))))
;; update timestamp
- (setf (undo-tree-node-timestamp current) (current-time))
+ (unless preserve-timestamps
+ (setf (undo-tree-node-timestamp current) (current-time)))
;; if redoing-in-region, record current node, region and direction so we
;; can tell if redo-in-region is repeated, and re-activate mark if in
@@ -2623,11 +2859,7 @@
(set-marker pos nil)))
;; redo deactivates the mark unless redoing-in-region
- (setq deactivate-mark (not redo-in-region))
- ;; inform user if at branch point
- (when (and (called-interactively-p 'interactive)
- (> (undo-tree-num-branches) 1))
- (message "Undo branch point!"))))
+ (setq deactivate-mark (not redo-in-region))))
@@ -2664,9 +2896,13 @@
(message "Switched to branch %d" branch))
-(defun undo-tree-set (node)
+(defun undo-tree-set (node &optional preserve-timestamps)
;; Set buffer to state corresponding to NODE. Returns intersection point
;; between path back from current node and path back from selected NODE.
+ ;; Non-nil PRESERVE-TIMESTAMPS disables updating of timestamps in visited
+ ;; undo-tree nodes. (This should *only* be used when temporarily visiting
+ ;; another undo state and immediately returning to the original state
+ ;; afterwards. Otherwise, it could cause history-discarding errors.)
(let ((path (make-hash-table :test 'eq))
(n node))
(puthash (undo-tree-root buffer-undo-tree) t path)
@@ -2686,10 +2922,10 @@
(setq n (undo-tree-node-previous n)))
;; ascend tree until intersection node
(while (not (eq (undo-tree-current buffer-undo-tree) n))
- (undo-tree-undo))
+ (undo-tree-undo-1))
;; descend tree until selected node
(while (not (eq (undo-tree-current buffer-undo-tree) node))
- (undo-tree-redo))
+ (undo-tree-redo-1))
n)) ; return intersection node
@@ -2738,10 +2974,9 @@
-(defmacro undo-tree-history-save-file (file)
- `(concat (file-name-directory ,file)
- "." (file-name-nondirectory ,file)
- ".~undo-tree"))
+(defun undo-tree-make-history-save-file-name ()
+ (concat (file-name-directory (buffer-file-name))
+ "." (file-name-nondirectory (buffer-file-name)) ".~undo-tree~"))
(defun undo-tree-save-history (&optional filename overwrite)
@@ -2755,24 +2990,28 @@
without asking for confirmation."
(interactive)
(undo-list-transfer-to-tree)
- (let ((buff (current-buffer))
- (tree (copy-undo-tree buffer-undo-tree)))
- ;; get filename
- (unless filename
- (setq filename
- (if buffer-file-name
- (undo-tree-history-save-file buffer-file-name)
- (expand-file-name (read-file-name "File to save in: ") nil))))
- (when (or (not (file-exists-p filename))
- overwrite
- (yes-or-no-p (format "Overwrite \"%s\"? " filename)))
- ;; discard undo-tree object pool before saving
- (setf (undo-tree-object-pool tree) nil)
- ;; print undo-tree to file
- (with-temp-file filename
- (prin1 (sha1 buff) (current-buffer))
- (terpri (current-buffer))
- (let ((print-circle t)) (prin1 tree (current-buffer)))))))
+ (when (and buffer-undo-tree (not (eq buffer-undo-tree t)))
+ (condition-case nil
+ (undo-tree-kill-visualizer)
+ (error (undo-tree-clear-visualizer-data buffer-undo-tree)))
+ (let ((buff (current-buffer))
+ (tree (copy-undo-tree buffer-undo-tree)))
+ ;; get filename
+ (unless filename
+ (setq filename
+ (if buffer-file-name
+ (undo-tree-make-history-save-file-name)
+ (expand-file-name (read-file-name "File to save in: ") nil))))
+ (when (or (not (file-exists-p filename))
+ overwrite
+ (yes-or-no-p (format "Overwrite \"%s\"? " filename)))
+ ;; discard undo-tree object pool before saving
+ (setf (undo-tree-object-pool tree) nil)
+ ;; print undo-tree to file
+ (with-temp-file filename
+ (prin1 (sha1 buff) (current-buffer))
+ (terpri (current-buffer))
+ (let ((print-circle t)) (prin1 tree (current-buffer))))))))
@@ -2790,7 +3029,7 @@
(unless filename
(setq filename
(if buffer-file-name
- (undo-tree-history-save-file buffer-file-name)
+ (undo-tree-make-history-save-file-name)
(expand-file-name (read-file-name "File to load from: ") nil))))
;; attempt to read undo-tree from FILENAME
@@ -2861,9 +3100,13 @@
(display-buffer-mark-dedicated 'soft))
(switch-to-buffer-other-window
(get-buffer-create undo-tree-visualizer-buffer-name))
- (undo-tree-visualizer-mode)
(setq undo-tree-visualizer-parent-buffer buff)
(setq buffer-undo-tree undo-tree)
+ (setq undo-tree-visualizer-initial-node (undo-tree-current undo-tree))
+ (setq undo-tree-visualizer-spacing
+ (undo-tree-visualizer-calculate-spacing))
+ (when undo-tree-visualizer-diff (undo-tree-visualizer-show-diff))
+ (undo-tree-visualizer-mode)
(let ((inhibit-read-only t)) (undo-tree-draw-tree undo-tree))))
@@ -2887,8 +3130,10 @@
(max (/ (window-width) 2)
(+ (undo-tree-node-char-lwidth (undo-tree-root undo-tree))
;; add space for left part of left-most time-stamp
- (if undo-tree-visualizer-timestamps 4 0)
- 2))) ; left margin
+ (if undo-tree-visualizer-timestamps
+ (/ (- undo-tree-visualizer-spacing 4) 2)
+ 0)
+ 2))) ; left margin
;; draw undo-tree
(let ((undo-tree-insert-face 'undo-tree-visualizer-default-face)
(stack (list (undo-tree-root undo-tree)))
@@ -2931,26 +3176,27 @@
(defun undo-tree-draw-node (node &optional current)
;; Draw symbol representing NODE in visualizer.
(goto-char (undo-tree-node-marker node))
- (when undo-tree-visualizer-timestamps (backward-char 5))
+ (when undo-tree-visualizer-timestamps
+ (backward-char (/ undo-tree-visualizer-spacing 2)))
(let ((register (undo-tree-node-register node))
node-string)
- (unless (and register (eq node (get-register register)))
+ (unless (and register
+ (eq node (undo-tree-register-data-node
+ (registerv-data (get-register register)))))
(setq register nil))
;; represent node by differentl symbols, depending on whether it's the
;; current node or is saved in a register
(setq node-string
(cond
(undo-tree-visualizer-timestamps
- (undo-tree-timestamp-to-string (undo-tree-node-timestamp node)))
+ (undo-tree-timestamp-to-string
+ (undo-tree-node-timestamp node)
+ undo-tree-visualizer-relative-timestamps
+ current register))
(current "x")
(register (char-to-string register))
(t "o")))
- (when undo-tree-visualizer-timestamps
- (setq node-string
- (concat (if current "*" " ") node-string
- (if register (concat "(" (char-to-string register) ")")
- " "))))
(cond
(current
@@ -2971,11 +3217,11 @@
(undo-tree-insert node-string)))
(t (undo-tree-insert node-string)))
- (backward-char (if undo-tree-visualizer-timestamps 7 1))
+ (backward-char (if undo-tree-visualizer-timestamps
+ (1+ (/ undo-tree-visualizer-spacing 2))
+ 1))
(move-marker (undo-tree-node-marker node) (point))
- (put-text-property (- (point) (if undo-tree-visualizer-timestamps 3 0))
- (+ (point) (if undo-tree-visualizer-timestamps 5 1))
- 'undo-tree-node node)))
+ (put-text-property (point) (1+ (point)) 'undo-tree-node node)))
(defun undo-tree-draw-subtree (node &optional active-branch)
@@ -3168,10 +3414,48 @@
(insert (make-string (- arg n) ? )))))
-(defun undo-tree-timestamp-to-string (timestamp)
- ;; Convert TIMESTAMP to hh:mm:ss string.
- (let ((time (decode-time timestamp)))
- (format "%02d:%02d:%02d" (nth 2 time) (nth 1 time) (nth 0 time))))
+(defun undo-tree-timestamp-to-string
+ (timestamp &optional relative current register)
+ ;; Convert TIMESTAMP to string (either absolute or RELATVE time), indicating
+ ;; if it's the CURRENT node and/or has an associated REGISTER.
+ (if relative
+ ;; relative time
+ (let ((time (floor (float-time
+ (subtract-time (current-time) timestamp))))
+ n)
+ (setq time
+ ;; years
+ (if (> (setq n (/ time 315360000)) 0)
+ (if (> n 999) "-ages" (format "-%dy" n))
+ (setq time (% time 315360000))
+ ;; days
+ (if (> (setq n (/ time 86400)) 0)
+ (format "-%dd" n)
+ (setq time (% time 86400))
+ ;; hours
+ (if (> (setq n (/ time 3600)) 0)
+ (format "-%dh" n)
+ (setq time (% time 3600))
+ ;; mins
+ (if (> (setq n (/ time 60)) 0)
+ (format "-%dm" n)
+ ;; secs
+ (format "-%ds" (% time 60)))))))
+ (setq time (concat
+ (if current "*" " ")
+ time
+ (if register (concat "[" (char-to-string register) "]")
+ " ")))
+ (setq n (length time))
+ (if (< n 9)
+ (concat (make-string (- 9 n) ? ) time)
+ time))
+ ;; absolute time
+ (concat (if current "*" " ")
+ (format-time-string "%H:%M:%S" timestamp)
+ (if register
+ (concat "[" (char-to-string register) "]")
+ " "))))
@@ -3197,7 +3481,9 @@
(use-local-map undo-tree-visualizer-map)
(setq truncate-lines t)
(setq cursor-type nil)
- (setq buffer-read-only t))
+ (setq buffer-read-only t)
+ (setq undo-tree-visualizer-selected-node nil)
+ (when undo-tree-visualizer-diff (undo-tree-visualizer-update-diff)))
@@ -3213,7 +3499,8 @@
(let ((undo-tree-inhibit-kill-visualizer t)) (undo-tree-undo arg))
(switch-to-buffer-other-window undo-tree-visualizer-buffer-name)
(let ((inhibit-read-only t))
- (undo-tree-draw-node (undo-tree-current buffer-undo-tree) 'current))))
+ (undo-tree-draw-node (undo-tree-current buffer-undo-tree) 'current))
+ (when undo-tree-visualizer-diff (undo-tree-visualizer-update-diff))))
(defun undo-tree-visualize-redo (&optional arg)
@@ -3229,7 +3516,8 @@
(switch-to-buffer-other-window undo-tree-visualizer-buffer-name)
(goto-char (undo-tree-node-marker (undo-tree-current buffer-undo-tree)))
(let ((inhibit-read-only t))
- (undo-tree-draw-node (undo-tree-current buffer-undo-tree) 'current))))
+ (undo-tree-draw-node (undo-tree-current buffer-undo-tree) 'current))
+ (when undo-tree-visualizer-diff (undo-tree-visualizer-update-diff))))
(defun undo-tree-visualize-switch-branch-right (arg)
@@ -3275,12 +3563,25 @@
(unwind-protect
(with-current-buffer undo-tree-visualizer-parent-buffer
(remove-hook 'before-change-functions 'undo-tree-kill-visualizer t))
+ ;; kill diff buffer, if any
+ (when undo-tree-visualizer-diff (undo-tree-visualizer-hide-diff))
(let ((parent undo-tree-visualizer-parent-buffer)
window)
+ ;; kill visualizer buffer
(kill-buffer nil)
- (if (setq window (get-buffer-window parent))
- (select-window window)
- (switch-to-buffer parent)))))
+ ;; switch back to parent buffer
+ (unwind-protect
+ (if (setq window (get-buffer-window parent))
+ (select-window window)
+ (switch-to-buffer parent))))))
+
+
+(defun undo-tree-visualizer-abort ()
+ "Quit the undo-tree visualizer and return buffer to original state."
+ (interactive)
+ (let ((node undo-tree-visualizer-initial-node))
+ (undo-tree-visualizer-quit)
+ (undo-tree-set node)))
(defun undo-tree-visualizer-set (&optional pos)
@@ -3291,11 +3592,12 @@
(let ((node (get-text-property pos 'undo-tree-node)))
(when node
;; set parent buffer to state corresponding to node at POS
- (set-buffer undo-tree-visualizer-parent-buffer)
+ (switch-to-buffer-other-window undo-tree-visualizer-parent-buffer)
(let ((undo-tree-inhibit-kill-visualizer t)) (undo-tree-set node))
- (set-buffer undo-tree-visualizer-buffer-name)
+ (switch-to-buffer-other-window undo-tree-visualizer-buffer-name)
;; re-draw undo tree
- (let ((inhibit-read-only t)) (undo-tree-draw-tree buffer-undo-tree)))))
+ (let ((inhibit-read-only t)) (undo-tree-draw-tree buffer-undo-tree))
+ (when undo-tree-visualizer-diff (undo-tree-visualizer-update-diff)))))
(defun undo-tree-visualizer-mouse-set (pos)
@@ -3308,12 +3610,8 @@
(defun undo-tree-visualizer-toggle-timestamps ()
"Toggle display of time-stamps."
(interactive)
- (setq undo-tree-visualizer-spacing
- (if (setq undo-tree-visualizer-timestamps
- (not undo-tree-visualizer-timestamps))
- ;; need sufficient space if displaying timestamps
- (max 13 (default-value 'undo-tree-visualizer-spacing))
- (default-value 'undo-tree-visualizer-spacing)))
+ (setq undo-tree-visualizer-timestamps (not undo-tree-visualizer-timestamps))
+ (setq undo-tree-visualizer-spacing (undo-tree-visualizer-calculate-spacing))
;; redraw tree
(let ((inhibit-read-only t)) (undo-tree-draw-tree buffer-undo-tree)))
@@ -3339,61 +3637,165 @@
(setq major-mode 'undo-tree-visualizer-selection-mode)
(setq mode-name "undo-tree-visualizer-selection-mode")
(use-local-map undo-tree-visualizer-selection-map)
- (setq cursor-type 'box))
+ (setq cursor-type 'box)
+ (setq undo-tree-visualizer-selected-node
+ (undo-tree-current buffer-undo-tree))
+ ;; erase diff (if any), as initially selected node is identical to current
+ (when undo-tree-visualizer-diff
+ (let ((buff (get-buffer undo-tree-diff-buffer-name))
+ (inhibit-read-only t))
+ (when buff (with-current-buffer buff (erase-buffer))))))
(defun undo-tree-visualizer-select-previous (&optional arg)
"Move to previous node."
(interactive "p")
- (let ((node (get-text-property (point) 'undo-tree-node)))
+ (let ((node undo-tree-visualizer-selected-node))
(catch 'top
(dotimes (i arg)
(unless (undo-tree-node-previous node) (throw 'top t))
(setq node (undo-tree-node-previous node))))
- (goto-char (undo-tree-node-marker node))))
+ (goto-char (undo-tree-node-marker node))
+ (when (and undo-tree-visualizer-diff
+ (not (eq node undo-tree-visualizer-selected-node)))
+ (undo-tree-visualizer-update-diff node))
+ (setq undo-tree-visualizer-selected-node node)))
(defun undo-tree-visualizer-select-next (&optional arg)
"Move to next node."
(interactive "p")
- (let ((node (get-text-property (point) 'undo-tree-node)))
+ (let ((node undo-tree-visualizer-selected-node))
(catch 'bottom
(dotimes (i arg)
(unless (nth (undo-tree-node-branch node) (undo-tree-node-next node))
(throw 'bottom t))
(setq node
(nth (undo-tree-node-branch node) (undo-tree-node-next node)))))
- (goto-char (undo-tree-node-marker node))))
+ (goto-char (undo-tree-node-marker node))
+ (when (and undo-tree-visualizer-diff
+ (not (eq node undo-tree-visualizer-selected-node)))
+ (undo-tree-visualizer-update-diff node))
+ (setq undo-tree-visualizer-selected-node node)))
(defun undo-tree-visualizer-select-right (&optional arg)
"Move right to a sibling node."
(interactive "p")
- (let ((pos (point))
- (end (line-end-position))
- node)
+ (let ((node undo-tree-visualizer-selected-node)
+ end)
+ (goto-char (undo-tree-node-marker undo-tree-visualizer-selected-node))
+ (setq end (line-end-position))
(catch 'end
(dotimes (i arg)
- (while (not node)
+ (while (or (null node) (eq node undo-tree-visualizer-selected-node))
(forward-char)
(setq node (get-text-property (point) 'undo-tree-node))
(when (= (point) end) (throw 'end t)))))
- (goto-char (if node (undo-tree-node-marker node) pos))))
+ (goto-char (undo-tree-node-marker
+ (or node undo-tree-visualizer-selected-node)))
+ (when (and undo-tree-visualizer-diff node
+ (not (eq node undo-tree-visualizer-selected-node)))
+ (undo-tree-visualizer-update-diff node))
+ (setq undo-tree-visualizer-selected-node node)))
(defun undo-tree-visualizer-select-left (&optional arg)
"Move left to a sibling node."
(interactive "p")
- (let ((pos (point))
- (beg (line-beginning-position))
- node)
+ (let ((node (get-text-property (point) 'undo-tree-node))
+ beg)
+ (goto-char (undo-tree-node-marker undo-tree-visualizer-selected-node))
+ (setq beg (line-beginning-position))
(catch 'beg
(dotimes (i arg)
- (while (not node)
+ (while (or (null node) (eq node undo-tree-visualizer-selected-node))
(backward-char)
(setq node (get-text-property (point) 'undo-tree-node))
(when (= (point) beg) (throw 'beg t)))))
- (goto-char (if node (undo-tree-node-marker node) pos))))
+ (goto-char (undo-tree-node-marker
+ (or node undo-tree-visualizer-selected-node)))
+ (when (and undo-tree-visualizer-diff node
+ (not (eq node undo-tree-visualizer-selected-node)))
+ (undo-tree-visualizer-update-diff node))
+ (setq undo-tree-visualizer-selected-node node)))
+
+
+
+;;; =====================================================================
+;;; Visualizer diff display
+
+(defun undo-tree-visualizer-toggle-diff ()
+ "Toggle diff display in undo-tree visualizer."
+ (interactive)
+ (if undo-tree-visualizer-diff
+ (undo-tree-visualizer-hide-diff)
+ (undo-tree-visualizer-show-diff)))
+
+
+(defun undo-tree-visualizer-selection-toggle-diff ()
+ "Toggle diff display in undo-tree visualizer selection mode."
+ (interactive)
+ (if undo-tree-visualizer-diff
+ (undo-tree-visualizer-hide-diff)
+ (let ((node (get-text-property (point) 'undo-tree-node)))
+ (when node (undo-tree-visualizer-show-diff node)))))
+
+
+(defun undo-tree-visualizer-show-diff (&optional node)
+ ;; show visualizer diff display
+ (setq undo-tree-visualizer-diff t)
+ (let ((buff (with-current-buffer undo-tree-visualizer-parent-buffer
+ (undo-tree-diff node)))
+ (display-buffer-mark-dedicated 'soft)
+ win)
+ (setq win (split-window))
+ (set-window-buffer win buff)
+ (shrink-window-if-larger-than-buffer win)))
+
+
+(defun undo-tree-visualizer-hide-diff ()
+ ;; hide visualizer diff display
+ (setq undo-tree-visualizer-diff nil)
+ (let ((win (get-buffer-window undo-tree-diff-buffer-name)))
+ (when win (with-selected-window win (kill-buffer-and-window)))))
+
+
+(defun undo-tree-diff (&optional node)
+ ;; Create diff between current state and NODE (or previous state, if NODE is
+ ;; null). Returns buffer containing diff.
+ (let (tmpfile buff)
+ ;; generate diff
+ (let ((undo-tree-inhibit-kill-visualizer t)
+ (current (undo-tree-current buffer-undo-tree)))
+ (undo-tree-set (or node (undo-tree-node-previous current) current)
+ 'preserve-timestamps)
+ (setq tmpfile (diff-file-local-copy (current-buffer)))
+ (undo-tree-set current 'preserve-timestamps))
+ (setq buff (diff-no-select
+ (current-buffer) tmpfile nil 'noasync
+ (get-buffer-create undo-tree-diff-buffer-name)))
+ ;; delete process messages and useless headers from diff buffer
+ (with-current-buffer buff
+ (goto-char (point-min))
+ (delete-region (point) (1+ (line-end-position 3)))
+ (goto-char (point-max))
+ (forward-line -2)
+ (delete-region (point) (point-max))
+ (setq cursor-type nil)
+ (setq buffer-read-only t))
+ buff))
+
+
+(defun undo-tree-visualizer-update-diff (&optional node)
+ ;; update visualizer diff display to show diff between current state and
+ ;; NODE (or previous state, if NODE is null)
+ (with-current-buffer undo-tree-visualizer-parent-buffer
+ (undo-tree-diff node))
+ (let ((win (get-buffer-window undo-tree-diff-buffer-name)))
+ (when win
+ (balance-windows)
+ (shrink-window-if-larger-than-buffer win))))
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [ELPA-diffs] /srv/bzr/emacs/elpa r229: updated undo-tree package to version 0.5.2,
Toby S. Cubitt <=