;;; log-view.el --- Major mode for browsing RCS/CVS/SCCS log output
;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-;; 2006, 2007 Free Software Foundation, Inc.
+;; 2006, 2007, 2008 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords: rcs sccs cvs log version-control
;; GNU Emacs 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, or (at your option)
+;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;;;; Subversion:
+;; ------------------------------------------------------------------------
+;; r4622 | ckuethe | 2007-12-23 18:18:01 -0500 (Sun, 23 Dec 2007) | 2 lines
+;;
+;; uBlox AEK-4T in binary mode. Added to unstable because it breaks gpsfake
+;;
+;; ------------------------------------------------------------------------
+;; r4621 | ckuethe | 2007-12-23 16:48:11 -0500 (Sun, 23 Dec 2007) | 3 lines
+;;
+;; Add a note about requiring usbfs to use the garmin gps18 (usb)
+;; Mention firmware testing the AC12 with firmware BQ00 and BQ04
+;;
+;; ------------------------------------------------------------------------
+;; r4620 | ckuethe | 2007-12-23 15:52:34 -0500 (Sun, 23 Dec 2007) | 1 line
+;;
+;; add link to latest hardware reference
+;; ------------------------------------------------------------------------
+;; r4619 | ckuethe | 2007-12-23 14:37:31 -0500 (Sun, 23 Dec 2007) | 1 line
+;;
+;; there is now a regression test for AC12 without raw data output
+
;;;; Darcs:
;; Changes to darcsum.el:
;; Add trailing-whitespace option to mode hook and fix
;; darcsum-display-changeset not to use trailing whitespace.
+;;;; Mercurial
+
+;; changeset: 11:8ff1a4166444
+;; tag: tip
+;; user: Eric S. Raymond <esr@thyrsus.com>
+;; date: Wed Dec 26 12:18:58 2007 -0500
+;; summary: Explain keywords. Add markup fixes.
+;;
+;; changeset: 10:20abc7ab09c3
+;; user: Eric S. Raymond <esr@thyrsus.com>
+;; date: Wed Dec 26 11:37:28 2007 -0500
+;; summary: Typo fixes.
+;;
+;; changeset: 9:ada9f4da88aa
+;; user: Eric S. Raymond <esr@thyrsus.com>
+;; date: Wed Dec 26 11:23:00 2007 -0500
+;; summary: Add RCS example session.
+
;;; Todo:
;; - add ability to modify a log-entry (via cvs-mode-admin ;-)
(eval-when-compile (require 'cl))
(require 'pcvs-util)
-(autoload 'vc-find-version "vc")
+(autoload 'vc-find-revision "vc")
(autoload 'vc-version-diff "vc")
(defvar cvs-minor-wrap-function)
(easy-mmode-defmap log-view-mode-map
'(("q" . quit-window)
("z" . kill-this-buffer)
- ("m" . set-mark-command)
- ;; ("e" . cvs-mode-edit-log)
+ ("m" . log-view-toggle-mark-entry)
+ ("e" . log-view-modify-change-comment)
("d" . log-view-diff)
- ("f" . log-view-find-version)
+ ("a" . log-view-annotate-version)
+ ("f" . log-view-find-revision)
("n" . log-view-msg-next)
("p" . log-view-msg-prev)
+ ("\t" . log-view-msg-next)
+ ([backtab] . log-view-msg-prev)
("N" . log-view-file-next)
("P" . log-view-file-prev)
("\M-n" . log-view-file-next)
;; XXX Do we need menu entries for these?
;; ["Quit" quit-window]
;; ["Kill This Buffer" kill-this-buffer]
- ["Mark Log Entry for Diff" set-mark-command]
- ["Diff Revisions" log-view-diff]
- ["Visit Version" log-view-find-version]
- ["Next Log Entry" log-view-msg-next]
- ["Previous Log Entry" log-view-msg-prev]
- ["Next File" log-view-file-next]
- ["Previous File" log-view-file-prev]))
+ ["Mark Log Entry for Diff" set-mark-command
+ :help ""]
+ ["Diff Revisions" log-view-diff
+ :help "Get the diff between two revisions"]
+ ["Visit Version" log-view-find-revision
+ :help "Visit the version at point"]
+ ["Annotate Version" log-view-annotate-version
+ :help "Annotate the version at point"]
+ ["Modify Log Comment" log-view-modify-change-comment
+ :help "Edit the change comment displayed at point"]
+ "-----"
+ ["Next Log Entry" log-view-msg-next
+ :help "Go to the next count'th log message"]
+ ["Previous Log Entry" log-view-msg-prev
+ :help "Go to the previous count'th log message"]
+ ["Next File" log-view-file-next
+ :help "Go to the next count'th file"]
+ ["Previous File" log-view-file-prev
+ :help "Go to the previous count'th file"]))
(defvar log-view-mode-hook nil
"Hook run at the end of `log-view-mode'.")
(1 (if (boundp 'cvs-filename-face) cvs-filename-face))
(0 log-view-file-face append)))
(eval . `(,log-view-message-re . log-view-message-face))))
+
(defconst log-view-font-lock-defaults
'(log-view-font-lock-keywords t nil nil nil))
"Major mode for browsing CVS log output."
(setq buffer-read-only t)
(set (make-local-variable 'font-lock-defaults) log-view-font-lock-defaults)
+ (set (make-local-variable 'beginning-of-defun-function)
+ 'log-view-beginning-of-defun)
+ (set (make-local-variable 'end-of-defun-function)
+ 'log-view-end-of-defun)
(set (make-local-variable 'cvs-minor-wrap-function) 'log-view-minor-wrap))
;;;;
(save-excursion
(forward-line 1)
(or (re-search-backward log-view-file-re nil t)
- (re-search-forward log-view-file-re))
+ (re-search-forward log-view-file-re nil t)
+ (error "Unable to determine the current file"))
(let* ((file (match-string 1))
(cvsdir (and (re-search-backward log-view-dir-re nil t)
(match-string 1)))
(forward-line 1)
(let ((pt (point)))
(when (re-search-backward log-view-message-re nil t)
- (let ((rev (match-string 1)))
+ (let ((rev (match-string-no-properties 1)))
(unless (re-search-forward log-view-file-re pt t)
rev))))))
+(defun log-view-toggle-mark-entry ()
+ "Toggle the marked state for the log entry at point.
+Individual log entries can be marked and unmarked. The marked
+entries are denoted by changing their background color.
+`log-view-get-marked' returns the list of tags for the marked
+log entries."
+ (interactive)
+ (save-excursion
+ (forward-line 1)
+ (let ((pt (point)))
+ (when (re-search-backward log-view-message-re nil t)
+ (let ((beg (match-beginning 0))
+ end ov ovlist found tag)
+ (unless (re-search-forward log-view-file-re pt t)
+ ;; Look to see if the current entry is marked.
+ (setq found (get-char-property (point) 'log-view-self))
+ (if found
+ (delete-overlay found)
+ ;; Create an overlay that covers this entry and change
+ ;; its color.
+ (setq tag (log-view-current-tag (point)))
+ (forward-line 1)
+ (setq end
+ (if (re-search-forward log-view-message-re nil t)
+ (match-beginning 0)
+ (point-max)))
+ (setq ov (make-overlay beg end))
+ (overlay-put ov 'face 'log-view-file)
+ ;; This is used to check if the overlay is present.
+ (overlay-put ov 'log-view-self ov)
+ (overlay-put ov 'log-view-marked tag))))))))
+
+(defun log-view-get-marked ()
+ "Return the list of tags for the marked log entries."
+ (save-excursion
+ (let ((pos (point-min))
+ marked-list ov)
+ (while (setq pos (next-single-property-change pos 'face))
+ (when (setq ov (get-char-property pos 'log-view-self))
+ (push (overlay-get ov 'log-view-marked) marked-list)
+ (setq pos (overlay-end ov))))
+ marked-list)))
+
+(defun log-view-beginning-of-defun ()
+ ;; This assumes that a log entry starts with a line matching
+ ;; `log-view-message-re'. Modes that derive from `log-view-mode'
+ ;; for which this assumption is not valid will have to provide
+ ;; another implementation of this function. `log-view-msg-prev'
+ ;; does a similar job to this function, we can't use it here
+ ;; directly because it prints messages that are not appropriate in
+ ;; this context and it does not move to the beginning of the buffer
+ ;; when the point is before the first log entry.
+
+ ;; `log-view-beginning-of-defun' and `log-view-end-of-defun' have
+ ;; been checked to work with logs produced by RCS, CVS, git,
+ ;; mercurial and subversion.
+
+ (re-search-backward log-view-message-re nil 'move))
+
+(defun log-view-end-of-defun ()
+ ;; The idea in this function is to search for the beginning of the
+ ;; next log entry using `log-view-message-re' and then go back one
+ ;; line when finding it. Modes that derive from `log-view-mode' for
+ ;; which this assumption is not valid will have to provide another
+ ;; implementation of this function.
+
+ ;; Look back and if there is no entry there it means we are before
+ ;; the first log entry, so go forward until finding one.
+ (unless (save-excursion (re-search-backward log-view-message-re nil t))
+ (re-search-forward log-view-message-re nil t))
+
+ ;; In case we are at the end of log entry going forward a line will
+ ;; make us find the next entry when searching. If we are inside of
+ ;; an entry going forward a line will still keep the point inside
+ ;; the same entry.
+ (forward-line 1)
+
+ ;; In case we are at the beginning of an entry, move past it.
+ (when (looking-at log-view-message-re)
+ (goto-char (match-end 0))
+ (forward-line 1))
+
+ ;; Search for the start of the next log entry. Go to the end of the
+ ;; buffer if we could not find a next entry.
+ (when (re-search-forward log-view-message-re nil 'move)
+ (goto-char (match-beginning 0))
+ (forward-line -1)))
+
(defvar cvs-minor-current-files)
(defvar cvs-branch-prefix)
(defvar cvs-secondary-branch-prefix)
(cvs-force-command "/F"))
(funcall f))))
-(defun log-view-find-version (pos)
+(defun log-view-find-revision (pos)
"Visit the version at point."
(interactive "d")
(save-excursion
(goto-char pos)
- (switch-to-buffer (vc-find-version (log-view-current-file)
+ (switch-to-buffer (vc-find-revision (log-view-current-file)
(log-view-current-tag)))))
+
+(defun log-view-extract-comment ()
+ "Parse comment from around the current point in the log."
+ (save-excursion
+ (let (st en (backend (vc-backend (log-view-current-file))))
+ (log-view-end-of-defun)
+ (cond ((eq backend 'SVN)
+ (forward-line -1)))
+ (setq en (point))
+ (log-view-beginning-of-defun)
+ (cond ((memq backend '(SCCS RCS CVS MCVS SVN))
+ (forward-line 2))
+ ((eq backend 'Hg)
+ (forward-line 4)
+ (re-search-forward "summary: *" nil t)))
+ (setq st (point))
+ (buffer-substring st en))))
+
+(declare-function vc-modify-change-comment "vc" (files rev oldcomment))
+
+(defun log-view-modify-change-comment ()
+ "Edit the change comment displayed at point."
+ (interactive)
+ (vc-modify-change-comment (list (log-view-current-file))
+ (log-view-current-tag)
+ (log-view-extract-comment)))
+
+(defun log-view-annotate-version (pos)
+ "Annotate the version at point."
+ (interactive "d")
+ (save-excursion
+ (goto-char pos)
+ (switch-to-buffer (vc-annotate (log-view-current-file)
+ (log-view-current-tag)))))
+
;;
;; diff
;;
(goto-char end)
(log-view-msg-next)
(setq to (log-view-current-tag))))
- (vc-version-diff (log-view-current-file) to fr)))
+ (vc-version-diff (list (log-view-current-file)) to fr)))
(provide 'log-view)