;; 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.
;;;###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
: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
"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 `[...]'."
;;;###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
(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)))
(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.
(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 *$"))
(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
(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 "):")
;;;###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))))
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
((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