]> code.delx.au - gnu-emacs/blobdiff - lisp/log-edit.el
* term/x-win.el (x-gtk-stock-map):
[gnu-emacs] / lisp / log-edit.el
index 5c2cf989f625b3cd0485f6c3760eec15f992f7d5..c7ecac22ae752daf6d34a9656488871bdd881fd0 100644 (file)
@@ -1,17 +1,17 @@
 ;;; log-edit.el --- Major mode for editing CVS commit messages
 
 ;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004,
-;;   2005, 2006, 2007 Free Software Foundation, Inc.
+;;   2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords: pcl-cvs cvs commit log
 
 ;; This file is part of GNU Emacs.
 
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; 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 3, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -19,9 +19,7 @@
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
@@ -57,6 +55,7 @@
 (easy-mmode-defmap log-edit-mode-map
   `(("\C-c\C-c" . log-edit-done)
     ("\C-c\C-a" . log-edit-insert-changelog)
+    ("\C-c\C-d" . log-edit-show-diff)
     ("\C-c\C-f" . log-edit-show-files)
     ("\M-n"    . log-edit-next-comment)
     ("\M-p"    . log-edit-previous-comment)
     ["Done" log-edit-done
      :help "Exit log-edit and proceed with the actual action."]
     "--"
-    ["Insert ChangeLog" log-edit-insert-changelog]
-    ["Add to ChangeLog" log-edit-add-to-changelog]
+    ["Insert ChangeLog" log-edit-insert-changelog
+     :help "Insert a log message by looking at the ChangeLog"]
+    ["Add to ChangeLog" log-edit-add-to-changelog
+     :help "Insert this log message into the appropriate ChangeLog file"]
     "--"
+    ["Show diff" log-edit-show-diff
+     :help "Show the diff for the files to be committed."]
     ["List files" log-edit-show-files
      :help "Show the list of relevant files."]
     "--"
-    ["Previous comment"                log-edit-previous-comment]
-    ["Next comment"            log-edit-next-comment]
-    ["Search comment forward"  log-edit-comment-search-forward]
-    ["Search comment backward" log-edit-comment-search-backward]))
+    ["Previous comment"                log-edit-previous-comment
+     :help "Cycle backwards through comment history"]
+    ["Next comment"            log-edit-next-comment
+     :help "Cycle forwards through comment history."]
+    ["Search comment forward"  log-edit-comment-search-forward
+     :help "Search forwards through comment history for a substring match of str"]
+    ["Search comment backward" log-edit-comment-search-backward
+     :help "Search backwards through comment history for substring match of str"]))
 
 (defcustom log-edit-confirm 'changed
-  "*If non-nil, `log-edit-done' will request confirmation.
+  "If non-nil, `log-edit-done' will request confirmation.
 If 'changed, only request confirmation if the list of files has
   changed since the beginning of the log-edit session."
   :group 'log-edit
   :type '(choice (const changed) (const t) (const nil)))
 
 (defcustom log-edit-keep-buffer nil
-  "*If non-nil, don't hide the buffer after `log-edit-done'."
+  "If non-nil, don't hide the buffer after `log-edit-done'."
   :group 'log-edit
   :type 'boolean)
 
 (defvar cvs-commit-buffer-require-final-newline t)
 (make-obsolete-variable 'cvs-commit-buffer-require-final-newline
-                        'log-edit-require-final-newline)
+                        'log-edit-require-final-newline
+                       "21.1")
 
 (defcustom log-edit-require-final-newline
   cvs-commit-buffer-require-final-newline
-  "*Enforce a newline at the end of commit log messages.
+  "Enforce a newline at the end of commit log messages.
 Enforce it silently if t, query if non-nil and don't do anything if nil."
   :group 'log-edit
   :type '(choice (const ask) (const t) (const nil)))
 
 (defcustom log-edit-setup-invert nil
-  "*Non-nil means `log-edit' should invert the meaning of its SETUP arg.
+  "Non-nil means `log-edit' should invert the meaning of its SETUP arg.
 If SETUP is 'force, this variable has no effect."
   :group 'log-edit
   :type 'boolean)
 
 (defcustom log-edit-hook '(log-edit-insert-cvs-template
                           log-edit-insert-changelog)
-  "*Hook run at the end of `log-edit'."
+  "Hook run at the end of `log-edit'."
   :group 'log-edit
   :type '(hook :options (log-edit-insert-changelog
                          log-edit-insert-cvs-rcstemplate
@@ -126,12 +134,12 @@ If SETUP is 'force, this variable has no effect."
                         log-edit-insert-filenames)))
 
 (defcustom log-edit-mode-hook (if (boundp 'vc-log-mode-hook) vc-log-mode-hook)
-  "*Hook run when entering `log-edit-mode'."
+  "Hook run when entering `log-edit-mode'."
   :group 'log-edit
   :type 'hook)
 
 (defcustom log-edit-done-hook nil
-  "*Hook run before doing the actual commit.
+  "Hook run before doing the actual commit.
 This hook can be used to cleanup the message, enforce various
 conventions, or to allow recording the message in some other database,
 such as a bug-tracking system.  The list of files about to be committed
@@ -140,9 +148,14 @@ can be obtained from `log-edit-files'."
   :type '(hook :options (log-edit-set-common-indentation
                         log-edit-add-to-changelog)))
 
+(defcustom log-edit-strip-single-file-name t
+  "If non-nil, remove file name from single-file log entries."
+  :type 'boolean)
+
 (defvar cvs-changelog-full-paragraphs t)
 (make-obsolete-variable 'cvs-changelog-full-paragraphs
-                        'log-edit-changelog-full-paragraphs)
+                        'log-edit-changelog-full-paragraphs
+                       "21.1")
 
 (defvar log-edit-changelog-full-paragraphs cvs-changelog-full-paragraphs
   "*If non-nil, include full ChangeLog paragraphs in the log.
@@ -170,6 +183,7 @@ when this variable is set to nil.")
 (defconst log-edit-files-buf "*log-edit-files*")
 (defvar log-edit-initial-files nil)
 (defvar log-edit-callback nil)
+(defvar log-edit-diff-function nil)
 (defvar log-edit-listfun nil)
 (defvar log-edit-parent-buffer nil)
 
@@ -301,19 +315,24 @@ automatically."
      (2 font-lock-function-name-face))))
 
 ;;;###autoload
-(defun log-edit (callback &optional setup listfun buffer &rest ignore)
+(defun log-edit (callback &optional setup params buffer &rest ignore)
   "Setup a buffer to enter a log message.
 \\<log-edit-mode-map>The buffer will be put in `log-edit-mode'.
 If SETUP is non-nil, the buffer is then erased and `log-edit-hook' is run.
-Mark and point will be set around the entire contents of the
-buffer so that it is easy to kill the contents of the buffer with \\[kill-region].
+Mark and point will be set around the entire contents of the buffer so
+that it is easy to kill the contents of the buffer with \\[kill-region].
 Once you're done editing the message, pressing \\[log-edit-done] will call
 `log-edit-done' which will end up calling CALLBACK to do the actual commit.
-LISTFUN if non-nil is a function of no arguments returning the list of files
-  that are concerned by the current operation (using relative names).
+
+PARAMS if non-nil is an alist.  Possible keys and associated values:
+ `log-edit-listfun' -- function taking no arguments that returns the list of
+ files that are concerned by the current operation (using relative names);
+ `log-edit-diff-function' -- function taking no arguments that
+ displays a diff of the files concerned by the current operation.
+
 If BUFFER is non-nil `log-edit' will jump to that buffer, use it to edit the
-  log message and go back to the current buffer when done.  Otherwise, it
-  uses the current buffer."
+log message and go back to the current buffer when done.  Otherwise, it
+uses the current buffer."
   (let ((parent (current-buffer)))
     (if buffer (pop-to-buffer buffer))
     (when (and log-edit-setup-invert (not (eq setup 'force)))
@@ -321,7 +340,13 @@ If BUFFER is non-nil `log-edit' will jump to that buffer, use it to edit the
     (when setup (erase-buffer))
     (log-edit-mode)
     (set (make-local-variable 'log-edit-callback) callback)
-    (set (make-local-variable 'log-edit-listfun) listfun)
+    (if (listp params)
+       (dolist (crt params)
+         (set (make-local-variable (car crt)) (cdr crt)))
+      ;; For backward compatibility with log-edit up to version 22.2
+      ;; accept non-list PARAMS to mean `log-edit-list'.
+      (set (make-local-variable 'log-edit-listfun) params))
+
     (if buffer (set (make-local-variable 'log-edit-parent-buffer) parent))
     (set (make-local-variable 'log-edit-initial-files) (log-edit-files))
     (when setup (run-hooks 'log-edit-hook))
@@ -417,6 +442,13 @@ If you want to abort the commit, simply delete the buffer."
       (indent-rigidly (point-min) (point-max)
                      (- log-edit-common-indent common)))))
 
+(defun log-edit-show-diff ()
+  "Show the diff for the files to be committed."
+  (interactive)
+  (if (functionp log-edit-diff-function)
+      (funcall log-edit-diff-function)
+    (error "Diff functionality has not been setup")))
+
 (defun log-edit-show-files ()
   "Show the list of files to be committed."
   (interactive)
@@ -438,7 +470,8 @@ If you want to abort the commit, simply delete the buffer."
   "Insert the template specified by the CVS administrator, if any.
 This simply uses the local CVS/Template file."
   (interactive)
-  (when (or (interactive-p) (= (point-min) (point-max)))
+  (when (or (called-interactively-p 'interactive)
+           (= (point-min) (point-max)))
     (when (file-readable-p "CVS/Template")
       (insert-file-contents "CVS/Template"))))
 
@@ -447,7 +480,8 @@ This simply uses the local CVS/Template file."
 This contacts the repository to get the rcstemplate file and
 can thus take some time."
   (interactive)
-  (when (or (interactive-p) (= (point-min) (point-max)))
+  (when (or (called-interactively-p 'interactive)
+           (= (point-min) (point-max)))
     (when (file-readable-p "CVS/Root")
       ;; Ignore the stderr stuff, even if it's an error.
       (call-process "cvs" nil '(t nil) nil
@@ -493,7 +527,7 @@ regardless of user name or time."
     (log-edit-insert-changelog-entries (log-edit-files)))
   (log-edit-set-common-indentation)
   (goto-char (point-min))
-  (when (looking-at "\\*\\s-+")
+  (when (and log-edit-strip-single-file-name (looking-at "\\*\\s-+"))
     (forward-line 1)
     (when (not (re-search-forward "^\\*\\s-+" nil t))
       (goto-char (point-min))
@@ -528,23 +562,21 @@ A \"page\" in a ChangeLog file is the area between two dates."
 (defun log-edit-changelog-paragraph ()
   "Return the bounds of the ChangeLog paragraph containing point.
 If we are between paragraphs, return the previous paragraph."
-  (save-excursion
-    (beginning-of-line)
-    (if (looking-at "^[ \t]*$")
-        (skip-chars-backward " \t\n" (point-min)))
-    (list (progn
-            (if (re-search-backward "^[ \t]*\n" nil 'or-to-limit)
-                (goto-char (match-end 0)))
-            (point))
-          (if (re-search-forward "^[ \t\n]*$" nil t)
-              (match-beginning 0)
-            (point-max)))))
+  (beginning-of-line)
+  (if (looking-at "^[ \t]*$")
+      (skip-chars-backward " \t\n" (point-min)))
+  (list (progn
+          (if (re-search-backward "^[ \t]*\n" nil 'or-to-limit)
+              (goto-char (match-end 0)))
+          (point))
+        (if (re-search-forward "^[ \t\n]*$" nil t)
+            (match-beginning 0)
+          (point-max))))
 
 (defun log-edit-changelog-subparagraph ()
   "Return the bounds of the ChangeLog subparagraph containing point.
 A subparagraph is a block of non-blank lines beginning with an asterisk.
 If we are between sub-paragraphs, return the previous subparagraph."
-  (save-excursion
     (end-of-line)
     (if (search-backward "*" nil t)
         (list (progn (beginning-of-line) (point))
@@ -553,16 +585,17 @@ If we are between sub-paragraphs, return the previous subparagraph."
                 (if (re-search-forward "^[ \t]*[\n*]" nil t)
                     (match-beginning 0)
                   (point-max))))
-      (list (point) (point)))))
+    (list (point) (point))))
 
 (defun log-edit-changelog-entry ()
   "Return the bounds of the ChangeLog entry containing point.
 The variable `log-edit-changelog-full-paragraphs' decides whether an
 \"entry\" is a paragraph or a subparagraph; see its documentation string
 for more details."
-  (if log-edit-changelog-full-paragraphs
-      (log-edit-changelog-paragraph)
-    (log-edit-changelog-subparagraph)))
+  (save-excursion
+    (if log-edit-changelog-full-paragraphs
+        (log-edit-changelog-paragraph)
+      (log-edit-changelog-subparagraph))))
 
 (defvar user-full-name)
 (defvar user-mail-address)
@@ -631,11 +664,17 @@ where LOGBUFFER is the name of the ChangeLog buffer, and each
                                   pattern
                                   "\\($\\|[^[:alnum:]]\\)"))
 
-           (let (texts)
-             (while (re-search-forward pattern nil t)
+           (let (texts
+                  (pos (point)))
+             (while (and (not (eobp)) (re-search-forward pattern nil t))
                (let ((entry (log-edit-changelog-entry)))
-                 (push entry texts)
-                 (goto-char (elt entry 1))))
+                  (if (< (elt entry 1) (max (1+ pos) (point)))
+                      ;; This is not relevant, actually.
+                      nil
+                    (push entry texts))
+                  ;; Make sure we make progress.
+                  (setq pos (max (1+ pos) (elt entry 1)))
+                 (goto-char pos)))
 
              (cons (current-buffer) texts))))))))