29041
|
1 ;;; log-view.el --- Major mode for browsing RCS/CVS/SCCS log output
|
28088
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
2
|
40954
|
3 ;; Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
|
28088
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
4
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
5 ;; Author: Stefan Monnier <monnier@cs.yale.edu>
|
29041
|
6 ;; Keywords: rcs sccs cvs log version-control
|
28088
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
7
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
8 ;; This file is part of GNU Emacs.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
9
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
10 ;; GNU Emacs is free software; you can redistribute it and/or modify
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
11 ;; it under the terms of the GNU General Public License as published by
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
12 ;; the Free Software Foundation; either version 2, or (at your option)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
13 ;; any later version.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
14
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
15 ;; GNU Emacs is distributed in the hope that it will be useful,
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
18 ;; GNU General Public License for more details.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
19
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
20 ;; You should have received a copy of the GNU General Public License
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
21 ;; along with GNU Emacs; see the file COPYING. If not, write to the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
23 ;; Boston, MA 02111-1307, USA.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
24
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
25 ;;; Commentary:
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
26
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
27 ;; Todo:
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
28
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
29 ;; - add compatibility with cvs-log.el
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
30 ;; - add ability to modify a log-entry (via cvs-mode-admin ;-)
|
29041
|
31 ;; - remove references to cvs-*
|
28088
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
32
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
33 ;;; Code:
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
34
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
35 (eval-when-compile (require 'cl))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
36 (require 'pcvs-util)
|
40958
|
37 (autoload 'vc-version-diff "vc")
|
28088
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
38
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
39 (defgroup log-view nil
|
29041
|
40 "Major mode for browsing log output of RCS/CVS/SCCS."
|
28088
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
41 :group 'pcl-cvs
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
42 :prefix "log-view-")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
43
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
44 (easy-mmode-defmap log-view-mode-map
|
40958
|
45 '(("q" . quit-window)
|
|
46 ("z" . kill-this-buffer)
|
|
47 ("m" . set-mark-command)
|
49236
|
48 ;; ("e" . cvs-mode-edit-log)
|
40958
|
49 ("d" . log-view-diff)
|
41557
|
50 ("f" . log-view-find-version)
|
40958
|
51 ("n" . log-view-msg-next)
|
28251
|
52 ("p" . log-view-msg-prev)
|
|
53 ("N" . log-view-file-next)
|
|
54 ("P" . log-view-file-prev)
|
40450
|
55 ("\M-n" . log-view-file-next)
|
|
56 ("\M-p" . log-view-file-prev))
|
28088
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
57 "Log-View's keymap."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
58 :group 'log-view
|
29041
|
59 ;; Here I really need either buffer-local keymap-inheritance
|
|
60 ;; or a minor-mode-map with lower precedence than the local map.
|
|
61 :inherit (if (boundp 'cvs-mode-map) cvs-mode-map))
|
28088
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
62
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
63 (defvar log-view-mode-hook nil
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
64 "Hook run at the end of `log-view-mode'.")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
65
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
66 (defface log-view-file-face
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
67 '((((class color) (background light))
|
42456
|
68 (:background "grey70" :weight bold))
|
|
69 (t (:weight bold)))
|
28088
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
70 "Face for the file header line in `log-view-mode'."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
71 :group 'log-view)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
72 (defvar log-view-file-face 'log-view-file-face)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
73
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
74 (defface log-view-message-face
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
75 '((((class color) (background light))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
76 (:background "grey85"))
|
42456
|
77 (t (:weight bold)))
|
28088
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
78 "Face for the message header line in `log-view-mode'."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
79 :group 'log-view)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
80 (defvar log-view-message-face 'log-view-message-face)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
81
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
82 (defconst log-view-file-re
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
83 (concat "^\\("
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
84 "Working file: \\(.+\\)"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
85 "\\|SCCS/s\\.\\(.+\\):"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
86 "\\)\n"))
|
49236
|
87 ;; In RCS, a locked revision will look like "revision N.M\tlocked by: FOO".
|
|
88 (defconst log-view-message-re "^\\(revision \\([.0-9]+\\)\\(?:\t.*\\)?\\|rev \\([0-9]+\\): .*\\|D \\([.0-9]+\\) .*\\)$")
|
28088
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
89
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
90 (defconst log-view-font-lock-keywords
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
91 `((,log-view-file-re
|
29041
|
92 (2 (if (boundp 'cvs-filename-face) cvs-filename-face) nil t)
|
|
93 (3 (if (boundp 'cvs-filename-face) cvs-filename-face) nil t)
|
|
94 (0 log-view-file-face append))
|
28088
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
95 (,log-view-message-re . log-view-message-face)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
96 (defconst log-view-font-lock-defaults
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
97 '(log-view-font-lock-keywords t nil nil nil))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
98
|
40954
|
99 ;;;;
|
28088
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
100 ;;;; Actual code
|
40954
|
101 ;;;;
|
28088
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
102
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
103 ;;;###autoload
|
28251
|
104 (define-derived-mode log-view-mode fundamental-mode "Log-View"
|
28088
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
105 "Major mode for browsing CVS log output."
|
40958
|
106 (setq buffer-read-only t)
|
28088
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
107 (set (make-local-variable 'font-lock-defaults) log-view-font-lock-defaults)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
108 (set (make-local-variable 'cvs-minor-wrap-function) 'log-view-minor-wrap))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
109
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
110 ;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
111 ;;;; Navigation
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
112 ;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
113
|
28251
|
114 ;; define log-view-{msg,file}-{next,prev}
|
|
115 (easy-mmode-define-navigation log-view-msg log-view-message-re "log message")
|
|
116 (easy-mmode-define-navigation log-view-file log-view-file-re "file")
|
28088
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
117
|
28861
|
118 (defun log-view-goto-rev (rev)
|
|
119 (goto-char (point-min))
|
|
120 (ignore-errors
|
|
121 (while (not (equal rev (log-view-current-tag)))
|
|
122 (log-view-msg-next))
|
|
123 t))
|
|
124
|
28088
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
125 ;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
126 ;;;; Linkage to PCL-CVS (mostly copied from cvs-status.el)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
127 ;;;;
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
128
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
129 (defconst log-view-dir-re "^cvs[.ex]* [a-z]+: Logging \\(.+\\)$")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
130
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
131 (defun log-view-current-file ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
132 (save-excursion
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
133 (forward-line 1)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
134 (or (re-search-backward log-view-file-re nil t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
135 (re-search-forward log-view-file-re))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
136 (let* ((file (or (match-string 2) (match-string 3)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
137 (cvsdir (and (re-search-backward log-view-dir-re nil t)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
138 (match-string 1)))
|
29041
|
139 (pcldir (and (boundp 'cvs-pcl-cvs-dirchange-re)
|
|
140 (re-search-backward cvs-pcl-cvs-dirchange-re nil t)
|
28088
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
141 (match-string 1)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
142 (dir ""))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
143 (let ((default-directory ""))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
144 (when pcldir (setq dir (expand-file-name pcldir dir)))
|
40958
|
145 (when cvsdir (setq dir (expand-file-name cvsdir dir))))
|
|
146 (expand-file-name file dir))))
|
28088
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
147
|
40958
|
148 (defun log-view-current-tag (&optional where)
|
28251
|
149 (save-excursion
|
40958
|
150 (when where (goto-char where))
|
28251
|
151 (forward-line 1)
|
|
152 (let ((pt (point)))
|
|
153 (when (re-search-backward log-view-message-re nil t)
|
42074
|
154 (let ((rev (or (match-string 2) (match-string 3) (match-string 4))))
|
28251
|
155 (unless (re-search-forward log-view-file-re pt t)
|
|
156 rev))))))
|
28088
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
157
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
158 (defun log-view-minor-wrap (buf f)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
159 (let ((data (with-current-buffer buf
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
160 (cons
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
161 (cons (log-view-current-file)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
162 (log-view-current-tag))
|
28861
|
163 (when mark-active
|
28088
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
164 (save-excursion
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
165 (goto-char (mark))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
166 (cons (log-view-current-file)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
167 (log-view-current-tag))))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
168 (let ((cvs-branch-prefix (cdar data))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
169 (cvs-secondary-branch-prefix (and (cdar data) (cddr data)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
170 (cvs-minor-current-files
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
171 (cons (caar data)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
172 (when (and (cadr data) (not (equal (caar data) (cadr data))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
173 (list (cadr data)))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
174 ;; FIXME: I need to force because the fileinfos are UNKNOWN
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
175 (cvs-force-command "/F"))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
176 (funcall f))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
177
|
41557
|
178 (defun log-view-find-version (pos)
|
|
179 "Visit the version at point."
|
|
180 (interactive "d")
|
|
181 (save-excursion
|
|
182 (goto-char pos)
|
49597
|
183 (switch-to-buffer (vc-find-version (log-view-current-file)
|
41557
|
184 (log-view-current-tag)))))
|
|
185
|
42074
|
186 ;;
|
|
187 ;; diff
|
|
188 ;;
|
40958
|
189
|
|
190 (defun log-view-diff (beg end)
|
|
191 "Get the diff for several revisions.
|
|
192 If the point is the same as the mark, get the diff for this revision.
|
|
193 Otherwise, get the diff between the revisions
|
55175
|
194 were the region starts and ends."
|
|
195 (interactive
|
|
196 (list (if mark-active (region-beginning) (point))
|
|
197 (if mark-active (region-end) (point))))
|
40958
|
198 (let ((fr (log-view-current-tag beg))
|
|
199 (to (log-view-current-tag end)))
|
|
200 (when (string-equal fr to)
|
|
201 (save-excursion
|
|
202 (goto-char end)
|
|
203 (log-view-msg-next)
|
|
204 (setq to (log-view-current-tag))))
|
|
205 (vc-version-diff (log-view-current-file) to fr)))
|
|
206
|
28088
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
207 (provide 'log-view)
|
28251
|
208
|
52401
|
209 ;;; arch-tag: 0d64220b-ce7e-4f62-9c2a-6b04c2f81f4f
|
28088
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
210 ;;; log-view.el ends here
|