;;; add-log.el --- change log maintenance commands for Emacs
;; Copyright (C) 1985, 1986, 1988, 1993, 1994, 1997, 1998, 2000, 2001,
-;; 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+;; 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+;; Free Software Foundation, Inc.
;; Maintainer: FSF
;; Keywords: tools
:group 'change-log)
(defcustom change-log-version-number-regexp-list
- (let ((re "\\([0-9]+\.[0-9.]+\\)"))
+ (let ((re "\\([0-9]+\.[0-9.]+\\)"))
(list
;; (defconst ad-version "2.15"
(concat "^(def[^ \t\n]+[ \t]+[^ \t\n][ \t]\"" re)
"Face used to highlight dates in date lines."
:version "21.1"
:group 'change-log)
-;; backward-compatibility alias
-(put 'change-log-date-face 'face-alias 'change-log-date)
+(define-obsolete-face-alias 'change-log-date-face 'change-log-date "22.1")
(defface change-log-name
'((t (:inherit font-lock-constant-face)))
"Face for highlighting author names."
:version "21.1"
:group 'change-log)
-;; backward-compatibility alias
-(put 'change-log-name-face 'face-alias 'change-log-name)
+(define-obsolete-face-alias 'change-log-name-face 'change-log-name "22.1")
(defface change-log-email
'((t (:inherit font-lock-variable-name-face)))
"Face for highlighting author email addresses."
:version "21.1"
:group 'change-log)
-;; backward-compatibility alias
-(put 'change-log-email-face 'face-alias 'change-log-email)
+(define-obsolete-face-alias 'change-log-email-face 'change-log-email "22.1")
(defface change-log-file
'((t (:inherit font-lock-function-name-face)))
"Face for highlighting file names."
:version "21.1"
:group 'change-log)
-;; backward-compatibility alias
-(put 'change-log-file-face 'face-alias 'change-log-file)
+(define-obsolete-face-alias 'change-log-file-face 'change-log-file "22.1")
(defface change-log-list
'((t (:inherit font-lock-keyword-face)))
"Face for highlighting parenthesized lists of functions or variables."
:version "21.1"
:group 'change-log)
-;; backward-compatibility alias
-(put 'change-log-list-face 'face-alias 'change-log-list)
+(define-obsolete-face-alias 'change-log-list-face 'change-log-list "22.1")
(defface change-log-conditionals
'((t (:inherit font-lock-variable-name-face)))
"Face for highlighting conditionals of the form `[...]'."
:version "21.1"
:group 'change-log)
-;; backward-compatibility alias
-(put 'change-log-conditionals-face 'face-alias 'change-log-conditionals)
+(define-obsolete-face-alias 'change-log-conditionals-face
+ 'change-log-conditionals "22.1")
(defface change-log-function
'((t (:inherit font-lock-variable-name-face)))
"Face for highlighting items of the form `<....>'."
:version "21.1"
:group 'change-log)
-;; backward-compatibility alias
-(put 'change-log-function-face 'face-alias 'change-log-function)
+(define-obsolete-face-alias 'change-log-function-face
+ 'change-log-function "22.1")
(defface change-log-acknowledgement
'((t (:inherit font-lock-comment-face)))
"Face for highlighting acknowledgments."
:version "21.1"
:group 'change-log)
-;; backward-compatibility alias
-(put 'change-log-acknowledgement-face 'face-alias 'change-log-acknowledgement)
+(define-obsolete-face-alias 'change-log-acknowledgement-face
+ 'change-log-acknowledgement "22.1")
(defconst change-log-file-names-re "^\\( +\\|\t\\)\\* \\([^ ,:([\n]+\\)")
(defconst change-log-start-entry-re "^\\sw.........[0-9:+ ]*")
(match-string-no-properties 2)
;; Look backwards for either a file name or the log entry start.
(if (re-search-backward
- (concat "\\(" change-log-start-entry-re
+ (concat "\\(" change-log-start-entry-re
"\\)\\|\\("
change-log-file-names-re "\\)") nil t)
(if (match-beginning 1)
(defun change-log-search-tag-name (&optional at)
"Search for a tag name near `point'.
-Optional argument AT non-nil means search near buffer position
-AT. Return value is a cons whose car is the string representing
+Optional argument AT non-nil means search near buffer position AT.
+Return value is a cons whose car is the string representing
the tag and whose cdr is the position where the tag was found."
(save-excursion
(goto-char (setq at (or at (point))))
(defvar change-log-find-head nil)
(defvar change-log-find-tail nil)
+(defvar change-log-find-window nil)
(defun change-log-goto-source-1 (tag regexp file buffer
&optional window first last)
;; Record this as first match when there's none.
(unless first (setq first last)))))))
(if (or last first)
- (with-selected-window (or window (display-buffer buffer))
+ (with-selected-window
+ (setq change-log-find-window (or window (display-buffer buffer)))
(if last
(progn
(when (or (< last (point-min)) (> last (point-max)))
;; We either have not found a suitable file name or `file-2'
;; provides a "better" file name wrt `point'. Go to the
;; buffer of `file-2' instead.
- (display-buffer (find-file-noselect file-2)))
+ (setq change-log-find-window
+ (display-buffer (find-file-noselect file-2))))
(t
(setq change-log-find-head
(list tag (concat "\\_<" (regexp-quote tag) "\\_>")
tag file)))))))))
(defun change-log-next-error (&optional argp reset)
- "Move to the Nth (default 1) next match in an Occur mode buffer.
+ "Move to the Nth (default 1) next match in a ChangeLog buffer.
Compatibility function for \\[next-error] invocations."
(interactive "p")
(let* ((argp (or argp 0))
(beginning-of-line)
;; if we found a place to visit...
(when (looking-at change-log-file-names-re)
- (change-log-goto-source)
- ;; go to the file itself
- (let ((file (nth 2 change-log-find-head)))
- (when file (pop-to-buffer (find-file-noselect file))))))
+ (let (change-log-find-window)
+ (change-log-goto-source)
+ (when change-log-find-window
+ ;; Select window displaying source file.
+ (select-window change-log-find-window)))))
(defvar change-log-mode-map
- (let ((map (make-sparse-keymap)))
+ (let ((map (make-sparse-keymap))
+ (menu-map (make-sparse-keymap)))
(define-key map [?\C-c ?\C-p] 'add-log-edit-prev-comment)
(define-key map [?\C-c ?\C-n] 'add-log-edit-next-comment)
(define-key map [?\C-c ?\C-f] 'change-log-find-file)
(define-key map [?\C-c ?\C-c] 'change-log-goto-source)
+ (define-key map [menu-bar changelog] (cons "ChangeLog" menu-map))
+ (define-key menu-map [gs]
+ '(menu-item "Go To Source" change-log-goto-source
+ :help "Go to source location of ChangeLog tag near point"))
+ (define-key menu-map [ff]
+ '(menu-item "Find File" change-log-find-file
+ :help "Visit the file for the change under point"))
+ (define-key menu-map [sep] '("--"))
+ (define-key menu-map [nx]
+ '(menu-item "Next Log-Edit Comment" add-log-edit-next-comment
+ :help "Cycle forward through Log-Edit mode comment history"))
+ (define-key menu-map [pr]
+ '(menu-item "Previous Log-Edit Comment" add-log-edit-prev-comment
+ :help "Cycle backward through Log-Edit mode comment history"))
map)
"Keymap for Change Log major mode.")
version)))))
(declare-function diff-find-source-location "diff-mode"
- (&optional other-file reverse))
+ (&optional other-file reverse noprompt))
;;;###autoload
(defun find-change-log (&optional file-name buffer-file)
Optional arg BUFFER-FILE overrides `buffer-file-name'."
;; If we are called from a diff, first switch to the source buffer;
;; in order to respect buffer-local settings of change-log-default-name, etc.
- (let ((buff (if (eq major-mode 'diff-mode)
- (car (ignore-errors (diff-find-source-location))))))
- (with-current-buffer (if (buffer-live-p buff) buff
- (current-buffer))
+ (with-current-buffer (let ((buff (if (eq major-mode 'diff-mode)
+ (car (ignore-errors
+ (diff-find-source-location))))))
+ (if (buffer-live-p buff) buff
+ (current-buffer)))
;; If user specified a file name or if this buffer knows which one to use,
;; just use that.
- (or file-name
- (setq file-name (and change-log-default-name
- (file-name-directory change-log-default-name)
- change-log-default-name)))
- (progn
- ;; Chase links in the source file
- ;; and use the change log in the dir where it points.
- (setq file-name (or (and (or buffer-file buffer-file-name)
- (file-name-directory
- (file-chase-links
- (or buffer-file buffer-file-name))))
- default-directory))
- (if (file-directory-p file-name)
- (setq file-name (expand-file-name (change-log-name) file-name)))
- ;; Chase links before visiting the file.
- ;; This makes it easier to use a single change log file
- ;; for several related directories.
- (setq file-name (file-chase-links file-name))
- (setq file-name (expand-file-name file-name))
- ;; Move up in the dir hierarchy till we find a change log file.
- (let ((file1 file-name)
- parent-dir)
- (while (and (not (or (get-file-buffer file1) (file-exists-p file1)))
- (progn (setq parent-dir
+ (or file-name
+ (setq file-name (and change-log-default-name
+ (file-name-directory change-log-default-name)
+ change-log-default-name))
+ (progn
+ ;; Chase links in the source file
+ ;; and use the change log in the dir where it points.
+ (setq file-name (or (and (or buffer-file buffer-file-name)
(file-name-directory
- (directory-file-name
- (file-name-directory file1))))
- ;; Give up if we are already at the root dir.
- (not (string= (file-name-directory file1)
- parent-dir))))
- ;; Move up to the parent dir and try again.
- (setq file1 (expand-file-name
- (file-name-nondirectory (change-log-name))
- parent-dir)))
- ;; If we found a change log in a parent, use that.
- (if (or (get-file-buffer file1) (file-exists-p file1))
- (setq file-name file1))))
- ;; Make a local variable in this buffer so we needn't search again.
- (set (make-local-variable 'change-log-default-name) file-name)))
+ (file-chase-links
+ (or buffer-file buffer-file-name))))
+ default-directory))
+ (if (file-directory-p file-name)
+ (setq file-name (expand-file-name (change-log-name) file-name)))
+ ;; Chase links before visiting the file.
+ ;; This makes it easier to use a single change log file
+ ;; for several related directories.
+ (setq file-name (file-chase-links file-name))
+ (setq file-name (expand-file-name file-name))
+ ;; Move up in the dir hierarchy till we find a change log file.
+ (let ((file1 file-name)
+ parent-dir)
+ (while (and (not (or (get-file-buffer file1) (file-exists-p file1)))
+ (progn (setq parent-dir
+ (file-name-directory
+ (directory-file-name
+ (file-name-directory file1))))
+ ;; Give up if we are already at the root dir.
+ (not (string= (file-name-directory file1)
+ parent-dir))))
+ ;; Move up to the parent dir and try again.
+ (setq file1 (expand-file-name
+ (file-name-nondirectory (change-log-name))
+ parent-dir)))
+ ;; If we found a change log in a parent, use that.
+ (if (or (get-file-buffer file1) (file-exists-p file1))
+ (setq file-name file1)))))
+ ;; Make a local variable in this buffer so we needn't search again.
+ (set (make-local-variable 'change-log-default-name) file-name))
file-name)
(defun add-log-file-name (buffer-file log-file)
(item (add-log-file-name buffer-file file-name)))
(unless (equal file-name buffer-file-name)
- (if (or other-window (window-dedicated-p (selected-window)))
- (find-file-other-window file-name)
- (find-file file-name)))
+ (cond
+ ((equal file-name (buffer-file-name (window-buffer (selected-window))))
+ ;; If the selected window already shows the desired buffer don't show
+ ;; it again (particularly important if other-window is true).
+ ;; This is important for diff-add-change-log-entries-other-window.
+ (set-buffer (window-buffer (selected-window))))
+ ((or other-window (window-dedicated-p (selected-window)))
+ (find-file-other-window file-name))
+ (t (find-file file-name))))
(or (derived-mode-p 'change-log-mode)
(change-log-mode))
(undo-boundary)
;;;###autoload
(define-derived-mode change-log-mode text-mode "Change Log"
- "Major mode for editing change logs; like Indented Text Mode.
+ "Major mode for editing change logs; like Indented Text mode.
Prevents numeric backups and sets `left-margin' to 8 and `fill-column' to 74.
New log entries are usually made with \\[add-change-log-entry] or \\[add-change-log-entry-other-window].
Each entry behaves as a paragraph, and the entries for one day as a page.
Runs `change-log-mode-hook'.
-\\{change-log-mode-map}"
+\n\\{change-log-mode-map}"
(setq left-margin 8
fill-column 74
indent-tabs-mode t
tab-width 8
show-trailing-whitespace t)
- (set (make-local-variable 'fill-paragraph-function)
- 'change-log-fill-paragraph)
+ (set (make-local-variable 'fill-forward-paragraph-function)
+ 'change-log-fill-forward-paragraph)
+ ;; Make sure we call `change-log-indent' when filling.
+ (set (make-local-variable 'fill-indent-according-to-mode) t)
;; Avoid that filling leaves behind a single "*" on a line.
(add-hook 'fill-nobreak-predicate
'(lambda ()
'(change-log-font-lock-keywords t nil nil backward-paragraph))
(set (make-local-variable 'multi-isearch-next-buffer-function)
'change-log-next-buffer)
- (set (make-local-variable 'beginning-of-defun-function)
+ (set (make-local-variable 'beginning-of-defun-function)
'change-log-beginning-of-defun)
- (set (make-local-variable 'end-of-defun-function)
+ (set (make-local-variable 'end-of-defun-function)
'change-log-end-of-defun)
;; next-error function glue
(setq next-error-function 'change-log-next-error)
(cadr (member (file-name-nondirectory (buffer-file-name buffer))
files))))))
-;; It might be nice to have a general feature to replace this. The idea I
-;; have is a variable giving a regexp matching text which should not be
-;; moved from bol by filling. change-log-mode would set this to "^\\s *\\s(".
-;; But I don't feel up to implementing that today.
-(defun change-log-fill-paragraph (&optional justify)
- "Fill the paragraph, but preserve open parentheses at beginning of lines.
-Prefix arg means justify as well."
- (interactive "P")
- (let ((end (progn (forward-paragraph) (point)))
- (beg (progn (backward-paragraph) (point)))
- ;; Add lines starting with whitespace followed by a left paren or an
+(defun change-log-fill-forward-paragraph (n)
+ "Cut paragraphs so filling preserves open parentheses at beginning of lines."
+ (let (;; Add lines starting with whitespace followed by a left paren or an
;; asterisk.
- (paragraph-start (concat paragraph-start "\\|\\s *\\(?:\\s(\\|\\*\\)"))
- ;; Make sure we call `change-log-indent'.
- (fill-indent-according-to-mode t))
- (fill-region beg end justify)
- t))
+ (paragraph-start (concat paragraph-start "\\|\\s *\\(?:\\s(\\|\\*\\)")))
+ (forward-paragraph n)))
\f
(defcustom add-log-current-defun-header-regexp
"^\\([[:upper:]][[:upper:]_ ]*[[:upper:]_]\\|[-_[:alpha:]]+\\)[ \t]*[:=]"
- "Heuristic regexp used by `add-log-current-defun' for unknown major modes."
+ "Heuristic regexp used by `add-log-current-defun' for unknown major modes.
+The regexp's first submatch is placed in the ChangeLog entry, in
+parentheses."
:type 'regexp
:group 'change-log)