]> code.delx.au - gnu-emacs/blobdiff - lisp/add-log.el
(set-register): Use push.
[gnu-emacs] / lisp / add-log.el
index ce8130c4a43b4ecc23e33ce316582bdc3e2977fd..1c3f70a9b7714cd3f873a549dae69c4ba9f1eacd 100644 (file)
@@ -2,6 +2,7 @@
 
 ;; Copyright (C) 1985, 86, 88, 93, 94, 97, 98, 2000 Free Software Foundation, Inc.
 
+;; Maintainer: FSF
 ;; Keywords: tools
 
 ;; This file is part of GNU Emacs.
@@ -66,10 +67,14 @@ This defaults to the value returned by the function `user-full-name'."
 
 ;;;###autoload
 (defcustom add-log-mailing-address nil
-  "*Electronic mail address of user, for inclusion in ChangeLog daily headers.
-This defaults to the value of `user-mail-address'."
+  "*Electronic mail addresses of user, for inclusion in ChangeLog headers.
+This defaults to the value of `user-mail-address'.  In addition to
+being a simple string, this value can also be a list.  All elements
+will be recognized as referring to the same user; when creating a new
+ChangeLog entry, one element will be chosen at random."
   :type '(choice (const :tag "Default" nil)
-                string)
+                (string :tag "String")
+                (repeat :tag "List of Strings" string))
   :group 'change-log)
 
 (defcustom add-log-time-format 'add-log-iso8601-time-string
@@ -116,6 +121,12 @@ this variable."
   :type 'boolean
   :group 'change-log)
 
+(defcustom add-log-always-start-new-record nil
+  "*If non-nil, `add-change-log-entry' will always start a new record."
+  :version "21.4"
+  :type 'boolean
+  :group 'change-log)
+
 (defcustom add-log-buffer-file-name-function nil
   "*If non-nil, function to call to identify the full filename of a buffer.
 This function is called with no argument.  If this is nil, the default is to
@@ -181,7 +192,7 @@ Note: The search is conducted only within 10%, at the beginning of the file."
   "Face for highlighting parenthesized lists of functions or variables."
   :version "21.1"
   :group 'change-log)
-  
+
 (defface change-log-conditionals-face
   '((t (:inherit font-lock-variable-name-face)))
   "Face for highlighting conditionals of the form `[...]'."
@@ -401,16 +412,27 @@ Optional arg BUFFER-FILE overrides `buffer-file-name'."
 
 ;;;###autoload
 (defun add-change-log-entry (&optional whoami file-name other-window new-entry)
-  "Find change log file and add an entry for today.
+  "Find change log file, and add an entry for today and an item for this file.
 Optional arg WHOAMI (interactive prefix) non-nil means prompt for user
 name and site.
 
-Second arg is FILE-NAME of change log.  If nil, uses `change-log-default-name'.
+Second arg FILE-NAME is file name of the change log.
+If nil, use the value of `change-log-default-name'.
+
 Third arg OTHER-WINDOW non-nil means visit in other window.
+
 Fourth arg NEW-ENTRY non-nil means always create a new entry at the front;
 never append to an existing entry.  Option `add-log-keep-changes-together'
 otherwise affects whether a new entry is created.
 
+Option `add-log-always-start-new-record' non-nil means always create a
+new record, even when the last record was made on the same date and by
+the same person.
+
+The change log file can start with a copyright notice and a copying
+permission notice.  The first blank line indicates the end of these
+notices.
+
 Today's date is calculated according to `change-log-time-zone-rule' if
 non-nil, otherwise in local time."
   (interactive (list current-prefix-arg
@@ -438,8 +460,8 @@ non-nil, otherwise in local time."
         (buffer-file (if buf-file-name (expand-file-name buf-file-name)))
         (file-name (expand-file-name
                     (or file-name (find-change-log file-name buffer-file))))
-        ;; Set ENTRY to the file name to use in the new entry.
-        (entry (add-log-file-name buffer-file file-name))
+        ;; Set ITEM to the file name to use in the new item.
+        (item (add-log-file-name buffer-file file-name))
         bound)
 
     (if (or (and other-window (not (equal file-name buffer-file-name)))
@@ -450,36 +472,57 @@ non-nil, otherwise in local time."
        (change-log-mode))
     (undo-boundary)
     (goto-char (point-min))
-    (let ((new-entry (concat (funcall add-log-time-format)
-                            "  " add-log-full-name
-                            "  <" add-log-mailing-address ">")))
-      (if (looking-at (regexp-quote new-entry))
+
+    ;; If file starts with a copyright and permission notice, skip them.
+    ;; Assume they end at first blank line.
+    (when (looking-at "Copyright")
+      (search-forward "\n\n")
+      (skip-chars-forward "\n"))
+
+    ;; Advance into first entry if it is usable; else make new one.
+    (let ((new-entries (mapcar (lambda (addr)
+                                (concat (funcall add-log-time-format)
+                                        "  " add-log-full-name
+                                        "  <" addr ">"))
+                              (if (consp add-log-mailing-address)
+                                  add-log-mailing-address
+                                (list add-log-mailing-address)))))
+      (if (and (not add-log-always-start-new-record)
+               (let ((hit nil))
+                (dolist (entry new-entries hit)
+                  (when (looking-at (regexp-quote entry))
+                    (setq hit t)))))
          (forward-line 1)
-       (insert new-entry "\n\n")))
+       (insert (nth (random (length new-entries))
+                    new-entries)
+               "\n\n")
+       (forward-line -1)))
 
+    ;; Determine where we should stop searching for a usable
+    ;; item to add to, within this entry.
     (setq bound
-         (progn
+         (save-excursion
             (if (looking-at "\n*[^\n* \t]")
                 (skip-chars-forward "\n")
              (if add-log-keep-changes-together
                  (forward-page)        ; page delimits entries for date
                (forward-paragraph)))   ; paragraph delimits entries for file
            (point)))
-    (goto-char (point-min))
-    ;; Now insert the new line for this entry.
+
+    ;; Now insert the new line for this item.
     (cond ((re-search-forward "^\\s *\\*\\s *$" bound t)
-          ;; Put this file name into the existing empty entry.
-          (if entry
-              (insert entry)))
+          ;; Put this file name into the existing empty item.
+          (if item
+              (insert item)))
          ((and (not new-entry)
                (let (case-fold-search)
                  (re-search-forward
-                  (concat (regexp-quote (concat "* " entry))
+                  (concat (regexp-quote (concat "* " item))
                           ;; Don't accept `foo.bar' when
                           ;; looking for `foo':
                           "\\(\\s \\|[(),:]\\)")
                   bound t)))
-          ;; Add to the existing entry for the same file.
+          ;; Add to the existing item for the same file.
           (re-search-forward "^\\s *$\\|^\\s \\*")
           (goto-char (match-beginning 0))
           ;; Delete excess empty lines; make just 2.
@@ -489,8 +532,7 @@ non-nil, otherwise in local time."
           (forward-line -2)
           (indent-relative-maybe))
          (t
-          ;; Make a new entry.
-          (forward-line 1)
+          ;; Make a new item.
           (while (looking-at "\\sW")
             (forward-line 1))
           (while (and (not (eobp)) (looking-at "^\\s *$"))
@@ -499,9 +541,9 @@ non-nil, otherwise in local time."
           (forward-line -2)
           (indent-to left-margin)
           (insert "* ")
-          (if entry (insert entry))))
+          (if item (insert item))))
     ;; Now insert the function name, if we have one.
-    ;; Point is at the entry for this file,
+    ;; Point is at the item for this file,
     ;; either at the end of the line or at the first blank line.
     (if defun
        (progn
@@ -511,8 +553,8 @@ non-nil, otherwise in local time."
                    (beginning-of-line 1)
                    (looking-at "\\s *$"))
            (insert ?\ ))
-         ;; See if the prev function name has a message yet or not
-         ;; If not, merge the two entries.
+         ;; See if the prev function name has a message yet or not.
+         ;; If not, merge the two items.
          (let ((pos (point-marker)))
            (if (and (skip-syntax-backward " ")
                     (skip-chars-backward "):")
@@ -536,13 +578,9 @@ non-nil, otherwise in local time."
 
 ;;;###autoload
 (defun add-change-log-entry-other-window (&optional whoami file-name)
-  "Find change log file in other window and add an entry for today.
-Optional arg WHOAMI (interactive prefix) non-nil means prompt for user
-name and site.
-Second optional arg FILE-NAME is file name of change log.
-If nil, use `change-log-default-name'.
-
-Affected by the same options as `add-change-log-entry'."
+  "Find change log file in other window and add entry and item.
+This is just like `add-change-log-entry' except that it displays
+the change log file in another window."
   (interactive (if current-prefix-arg
                   (list current-prefix-arg
                         (prompt-for-change-log-name))))
@@ -629,7 +667,7 @@ Other modes are handled by a heuristic that looks in the 10K before
 point for uppercase headings starting in the first column or
 identifiers followed by `:' or `='.  See variables
 `add-log-current-defun-header-regexp' and
-`add-log-current-defun-function'
+`add-log-current-defun-function'.
 
 Has a preference of looking backwards."
   (condition-case nil
@@ -794,7 +832,7 @@ Has a preference of looking backwards."
                ((eq major-mode 'texinfo-mode)
                 (if (re-search-backward "^@node[ \t]+\\([^,\n]+\\)" nil t)
                     (match-string-no-properties 1)))
-               ((eq major-mode 'perl-mode)
+               ((memq major-mode '(perl-mode cperl-mode))
                 (if (re-search-backward "^sub[ \t]+\\([^ \t\n]+\\)" nil t)
                     (match-string-no-properties 1)))
                ;; Emacs's autoconf-mode installs its own