additional global bindings, goto-last-change, nxml config updates
[emacs-init.git] / auto-install / goto-last-change.el
1 ;;; goto-last-change.el --- Move point through buffer-undo-list positions -*-unibyte: t; coding: iso-8859-1;-*-
2
3 ;; Copyright © 2003 Kevin Rodgers
4
5 ;; Author: Kevin Rodgers <ihs_4664@yahoo.com>
6 ;; Created: 17 Jun 2003
7 ;; Version: $Revision: 1.2 $
8 ;; Keywords: convenience
9 ;; RCS: $Id: goto-last-change.el,v 1.2 2003/07/30 17:43:47 kevinr Exp kevinr $
10
11 ;; Contributors:
12 ;;   Attila Lendvai <attila.lendvai@gmail.com> (line distance and auto marks)
13
14 ;; This program is free software; you can redistribute it and/or
15 ;; modify it under the terms of the GNU General Public License as
16 ;; published by the Free Software Foundation; either version 2 of
17 ;; the License, or (at your option) any later version.
18
19 ;; This program is distributed in the hope that it will be
20 ;; useful, but WITHOUT ANY WARRANTY; without even the implied
21 ;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
22 ;; PURPOSE.  See the GNU General Public License for more details.
23
24 ;; You should have received a copy of the GNU General Public
25 ;; License along with this program; if not, write to the Free
26 ;; Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
27 ;; MA 02111-1307 USA
28
29 ;;; Commentary:
30
31 ;; After installing goto-last-change.el in a `load-path' directory and
32 ;; compiling it with `M-x byte-compile-file', load it with
33 ;;      (require 'goto-last-change)
34 ;; or autoload it with
35 ;;      (autoload 'goto-last-change "goto-last-change"
36 ;;        "Set point to the position of the last change." t)
37 ;; 
38 ;; You may also want to bind a key to `M-x goto-last-change', e.g.
39 ;;      (global-set-key "\C-x\C-\\" 'goto-last-change)
40
41 ;; goto-last-change.el was written in response to to the following:
42 ;; 
43 ;; From: Dan Jacobson <jidanni@jidanni.org>
44 ;; Newsgroups: gnu.emacs.bug
45 ;; Subject: function to go to spot of last change
46 ;; Date: Sun, 15 Jun 2003 00:15:08 +0000 (UTC)
47 ;; Sender: news <news@main.gmane.org>
48 ;; Message-ID: <mailman.7910.1055637181.21513.bug-gnu-emacs@gnu.org>
49 ;; NNTP-Posting-Host: monty-python.gnu.org
50 ;; 
51 ;; 
52 ;; Why of course, a function to get the user to the spot of last changes
53 ;; in the current buffer(s?), that's what emacs must lack.
54 ;; 
55 ;; How many times have you found yourself mosying [<-not in spell
56 ;; checker!?] thru a file when you wonder, where the heck was I just
57 ;; editing?  Well, the best you can do is hit undo, ^F, and undo again,
58 ;; to get back.  Hence the "burning need" for the additional function,
59 ;; which you might name the-jacobson-memorial-function, due to its brilliance.
60 ;; -- 
61 ;; http://jidanni.org/ Taiwan(04)25854780
62
63 ;;; Code:
64 (provide 'goto-last-change)
65
66 (or (fboundp 'last)                     ; Emacs 20
67     (require 'cl))                      ; Emacs 19
68
69 (defvar goto-last-change-undo nil
70   "The `buffer-undo-list' entry of the previous \\[goto-last-change] command.")
71 (make-variable-buffer-local 'goto-last-change-undo)
72
73 ;;;###autoload
74 (defun goto-last-change (&optional mark-point minimal-line-distance)
75   "Set point to the position of the last change.
76 Consecutive calls set point to the position of the previous change.
77 With a prefix arg (optional arg MARK-POINT non-nil), set mark so \
78 \\[exchange-point-and-mark]
79 will return point to the current position."
80   (interactive "P")
81   ;; (unless (buffer-modified-p)
82   ;;   (error "Buffer not modified"))
83   (when (eq buffer-undo-list t)
84     (error "No undo information in this buffer"))
85   (when mark-point
86     (push-mark))
87   (unless minimal-line-distance
88     (setq minimal-line-distance 10))
89   (let ((position nil)
90         (undo-list (if (and (eq this-command last-command)
91                             goto-last-change-undo)
92                        (cdr (memq goto-last-change-undo buffer-undo-list))
93                      buffer-undo-list))
94         undo)
95     (while (and undo-list
96                 (or (not position)
97                     (eql position (point))
98                     (and minimal-line-distance
99                          ;; The first invocation always goes to the last change, subsequent ones skip
100                          ;; changes closer to (point) then minimal-line-distance.
101                          (memq last-command '(goto-last-change
102                                               goto-last-change-with-auto-marks))
103                          (< (count-lines (min position (point-max)) (point))
104                             minimal-line-distance))))
105       (setq undo (car undo-list))
106       (cond ((and (consp undo) (integerp (car undo)) (integerp (cdr undo)))
107              ;; (BEG . END)
108              (setq position (cdr undo)))
109             ((and (consp undo) (stringp (car undo))) ; (TEXT . POSITION)
110              (setq position (abs (cdr undo))))
111             ((and (consp undo) (eq (car undo) t))) ; (t HIGH . LOW)
112             ((and (consp undo) (null (car undo)))
113              ;; (nil PROPERTY VALUE BEG . END)
114              (setq position (cdr (last undo))))
115             ((and (consp undo) (markerp (car undo)))) ; (MARKER . DISTANCE)
116             ((integerp undo))           ; POSITION
117             ((null undo))               ; nil
118             (t (error "Invalid undo entry: %s" undo)))
119       (setq undo-list (cdr undo-list)))
120     (cond (position
121            (setq goto-last-change-undo undo)
122            (goto-char (min position (point-max))))
123           ((and (eq this-command last-command)
124                 goto-last-change-undo)
125            (setq goto-last-change-undo nil)
126            (error "No further undo information"))
127           (t
128            (setq goto-last-change-undo nil)
129            (error "Buffer not modified")))))
130
131 (defun goto-last-change-with-auto-marks (&optional minimal-line-distance)
132   "Calls goto-last-change and sets the mark at only the first invocations
133 in a sequence of invocations."
134   (interactive "P")
135   (goto-last-change (not (or (eq last-command 'goto-last-change-with-auto-marks)
136                              (eq last-command t)))
137                     minimal-line-distance))
138
139 ;; (global-set-key "\C-x\C-\\" 'goto-last-change)
140
141 ;;; goto-last-change.el ends here