diff options
Diffstat (limited to 'lisp/emacs-lisp/copyright.el')
-rw-r--r-- | lisp/emacs-lisp/copyright.el | 113 |
1 files changed, 88 insertions, 25 deletions
diff --git a/lisp/emacs-lisp/copyright.el b/lisp/emacs-lisp/copyright.el index 96c846d912a..5ab50847f8c 100644 --- a/lisp/emacs-lisp/copyright.el +++ b/lisp/emacs-lisp/copyright.el @@ -43,17 +43,30 @@ A value of nil means to search whole buffer." :type '(choice (integer :tag "Limit") (const :tag "No limit"))) -;; The character classes have the Latin-1 version and the Latin-9 -;; version, which is probably enough. +(defcustom copyright-at-end-flag nil + "Non-nil means to search backwards from the end of the buffer for copyright. +This is useful for ChangeLogs." + :group 'copyright + :type 'boolean + :version "23.1") + (defcustom copyright-regexp - "\\([]\\|@copyright{}\\|[Cc]opyright\\s *:?\\s *\\(?:(C)\\)?\ -\\|[Cc]opyright\\s *:?\\s *[]\\)\ + "\\(©\\|@copyright{}\\|[Cc]opyright\\s *:?\\s *\\(?:(C)\\)?\ +\\|[Cc]opyright\\s *:?\\s *©\\)\ \\s *\\([1-9]\\([-0-9, ';/*%#\n\t]\\|\\s<\\|\\s>\\)*[0-9]+\\)" "What your copyright notice looks like. The second \\( \\) construct must match the years." :group 'copyright :type 'regexp) +(defcustom copyright-names-regexp "" + "Regexp matching the names which correspond to the user. +Only copyright lines where the name matches this regexp will be updated. +This allows you to avoid adding years to a copyright notice belonging to +someone else or to a group for which you do not work." + :group 'copyright + :type 'regexp) + (defcustom copyright-years-regexp "\\(\\s *\\)\\([1-9]\\([-0-9, ';/*%#\n\t]\\|\\s<\\|\\s>\\)*[0-9]+\\)" "Match additional copyright notice years. @@ -82,10 +95,47 @@ When this is `function', only ask when called non-interactively." (defvar copyright-current-year (substring (current-time-string) -4) "String representing the current year.") +(defsubst copyright-limit () ; re-search-forward BOUND + (and copyright-limit + (if copyright-at-end-flag + (- (point) copyright-limit) + (+ (point) copyright-limit)))) + +(defun copyright-re-search (regexp &optional bound noerror count) + "Re-search forward or backward depending on `copyright-at-end-flag'." + (if copyright-at-end-flag + (re-search-backward regexp bound noerror count) + (re-search-forward regexp bound noerror count))) + +(defun copyright-start-point () + "Return point-min or point-max, depending on `copyright-at-end-flag'." + (if copyright-at-end-flag + (point-max) + (point-min))) + +(defun copyright-offset-too-large-p () + "Return non-nil if point is too far from the edge of the buffer." + (when copyright-limit + (if copyright-at-end-flag + (< (point) (- (point-max) copyright-limit)) + (> (point) (+ (point-min) copyright-limit))))) + (defun copyright-update-year (replace noquery) - (when (re-search-forward copyright-regexp - (if copyright-limit (+ (point) copyright-limit)) t) - ;; If the years are continued onto multiple lined + (when + (condition-case err + ;; (1) Need the extra \\( \\) around copyright-regexp because we + ;; goto (match-end 1) below. See note (2) below. + (copyright-re-search (concat "\\(" copyright-regexp + "\\)\\([ \t]*\n\\)?.*\\(?:" + copyright-names-regexp "\\)") + (copyright-limit) + t) + ;; In case the regexp is rejected. This is useful because + ;; copyright-update is typically called from before-save-hook where + ;; such an error is very inconvenient for the user. + (error (message "Can't update copyright: %s" err) nil)) + (goto-char (match-end 1)) + ;; If the years are continued onto multiple lines ;; that are marked as comments, skip to the end of the years anyway. (while (save-excursion (and (eq (following-char) ?,) @@ -96,15 +146,16 @@ When this is `function', only ask when called non-interactively." (forward-line 1) (and (looking-at comment-start-skip) (goto-char (match-end 0)))) - (save-match-data - (looking-at copyright-years-regexp)))) + (looking-at-p copyright-years-regexp))) (forward-line 1) (re-search-forward comment-start-skip) - (re-search-forward copyright-years-regexp)) + ;; (2) Need the extra \\( \\) so that the years are subexp 3, as + ;; they are at note (1) above. + (re-search-forward (format "\\(%s\\)" copyright-years-regexp))) ;; Note that `current-time-string' isn't locale-sensitive. (setq copyright-current-year (substring (current-time-string) -4)) - (unless (string= (buffer-substring (- (match-end 2) 2) (match-end 2)) + (unless (string= (buffer-substring (- (match-end 3) 2) (match-end 3)) (substring copyright-current-year -2)) (if (or noquery (y-or-n-p (if replace @@ -113,7 +164,7 @@ When this is `function', only ask when called non-interactively." (concat "Add " copyright-current-year " to copyright? ")))) (if replace - (replace-match copyright-current-year t t nil 2) + (replace-match copyright-current-year t t nil 3) (let ((size (save-excursion (skip-chars-backward "0-9")))) (if (and (eq (% (- (string-to-number copyright-current-year) (string-to-number (buffer-substring @@ -154,21 +205,24 @@ interactively." (save-excursion (save-restriction (widen) - (goto-char (point-min)) + (goto-char (copyright-start-point)) (copyright-update-year arg noquery) - (goto-char (point-min)) + (goto-char (copyright-start-point)) (and copyright-current-gpl-version ;; match the GPL version comment in .el files, including the ;; bilingual Esperanto one in two-column, and in texinfo.tex - (re-search-forward + (copyright-re-search "\\(the Free Software Foundation;\ either \\|; a\\^u eldono \\([0-9]+\\)a, ? a\\^u (la\\^u via \\)\ version \\([0-9]+\\), or (at" - (if copyright-limit (+ (point) copyright-limit)) t) - (not (string= (match-string 3) copyright-current-gpl-version)) + (copyright-limit) t) + ;; Don't update if the file is already using a more recent + ;; version than the "current" one. + (< (string-to-number (match-string 3)) + (string-to-number copyright-current-gpl-version)) (or noquery - (y-or-n-p (concat "Replace GPL version by " - copyright-current-gpl-version "? "))) + (y-or-n-p (format "Replace GPL version by %s? " + copyright-current-gpl-version))) (progn (if (match-end 2) ;; Esperanto bilingual comment in two-column.el @@ -185,9 +239,8 @@ version \\([0-9]+\\), or (at" Uses heuristic: year >= 50 means 19xx, < 50 means 20xx." (interactive) (widen) - (goto-char (point-min)) - (if (re-search-forward copyright-regexp - (if copyright-limit (+ (point) copyright-limit)) t) + (goto-char (copyright-start-point)) + (if (copyright-re-search copyright-regexp (copyright-limit) t) (let ((s (match-beginning 2)) (e (copy-marker (1+ (match-end 2)))) (p (make-marker)) @@ -211,7 +264,7 @@ Uses heuristic: year >= 50 means 19xx, < 50 means 20xx." ;; Don't mess up whitespace after the years. (skip-chars-backward " \t") (save-restriction - (narrow-to-region (point-min) (point)) + (narrow-to-region (copyright-start-point) (point)) (let ((fill-prefix " ")) (fill-region s last)))) (set-marker e nil) @@ -227,15 +280,25 @@ Uses heuristic: year >= 50 means 19xx, < 50 means 20xx." "Copyright (C) " `(substring (current-time-string) -4) " by " (or (getenv "ORGANIZATION") str) - '(if (and copyright-limit (> (point) (+ (point-min) copyright-limit))) + '(if (copyright-offset-too-large-p) (message "Copyright extends beyond `copyright-limit' and won't be updated automatically.")) comment-end \n) +(defun copyright-update-directory (directory match) + "Update copyright notice for all files in DIRECTORY matching MATCH." + (interactive "DDirectory: \nMFilenames matching: ") + (dolist (file (directory-files directory t match nil)) + (find-file file) + (let ((copyright-query nil)) + (copyright-update)) + (save-buffer) + (kill-buffer (current-buffer)))) + (provide 'copyright) ;; For the copyright sign: ;; Local Variables: -;; coding: emacs-mule +;; coding: utf-8 ;; End: ;; arch-tag: b4991afb-b6b1-4590-bebe-e076d9d4aee8 |