]> git.eshelyaron.com Git - emacs.git/commitdiff
copyright.el updates.
authorGlenn Morris <rgm@gnu.org>
Tue, 25 Jan 2011 08:36:34 +0000 (00:36 -0800)
committerGlenn Morris <rgm@gnu.org>
Tue, 25 Jan 2011 08:36:34 +0000 (00:36 -0800)
* lisp/emacs-lisp/copyright.el (copyright-at-end-flag)
(copyright-names-regexp): Add safety properties.
(copyright-year-ranges): New option.
(copyright-find-end): New function, split from copyright-update-year.
(copyright-update-year): Use copyright-find-end.
(copyright-fix-years): Optionally, convert years to ranges.
Handle years continued over comment lines.
Do not mess with the fill-prefix.
Do not call copyright-update.
(copyright-update-directory): Optionally, fix years rather than update.
Skip directories.  Find files literally, with only safe local vars.

* etc/NEWS: Mention copyright-fix-years and ranges.

etc/NEWS
lisp/ChangeLog
lisp/emacs-lisp/copyright.el

index f301dc8509da8349f48ca33a267cc3b8eb18181f..0a12a122d278960c1fd6576ef630ddf6ccb4b94b 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -607,6 +607,11 @@ means to prompt the user for command specifics, e.g. a merge location.
 
 **** Currently supported by Bzr.
 
+** Miscellaneous
+
+---
+*** `copyright-fix-years' can optionally convert consecutive years to ranges.
+
 \f
 * New Modes and Packages in Emacs 24.1
 
index 5b4b0dcc2d35720a832040a2a8f7dba61a9db402..4d758d4bb18c539dbba328b88b5d9fcd4763aed5 100644 (file)
@@ -1,3 +1,17 @@
+2011-01-25  Glenn Morris  <rgm@gnu.org>
+
+       * emacs-lisp/copyright.el (copyright-at-end-flag)
+       (copyright-names-regexp): Add safety properties.
+       (copyright-year-ranges): New option.
+       (copyright-find-end): New function, split from copyright-update-year.
+       (copyright-update-year): Use copyright-find-end.
+       (copyright-fix-years): Optionally, convert years to ranges.
+       Handle years continued over comment lines.
+       Do not mess with the fill-prefix.
+       Do not call copyright-update.
+       (copyright-update-directory): Optionally, fix years rather than update.
+       Skip directories.  Find files literally, with only safe local vars.
+
 2011-01-25  Stefan Monnier  <monnier@iro.umontreal.ca>
 
        * files.el (file-name-non-special): Only change buffer-file-name after
index 54a9437e64990dd379d0240e9b350d2a21562535..cf5a48b5a292f3b9d627933bc16fa703130ff593 100644 (file)
@@ -1,7 +1,6 @@
 ;;; copyright.el --- update the copyright notice in current buffer
 
-;; Copyright (C) 1991-1995, 1998, 2001-2011
-;;   Free Software Foundation, Inc.
+;; Copyright (C) 1991-1995, 1998, 2001-2011  Free Software Foundation, Inc.
 
 ;; Author: Daniel Pfeiffer <occitan@esperanto.org>
 ;; Keywords: maint, tools
@@ -47,6 +46,7 @@ This is useful for ChangeLogs."
   :group 'copyright
   :type 'boolean
   :version "23.1")
+;;;###autoload(put 'copyright-at-end-flag 'safe-local-variable 'booleanp)
 
 (defcustom copyright-regexp
  "\\(©\\|@copyright{}\\|[Cc]opyright\\s *:?\\s *\\(?:(C)\\)?\
@@ -66,6 +66,11 @@ someone else or to a group for which you do not work."
   :group 'copyright
   :type 'regexp)
 
+;; The worst that can happen is a malicious regexp that overflows in
+;; the regexp matcher, a minor nuisance.  It's a pain to be always
+;; prompted if you want to put this in a dir-locals.el.
+;;;###autoload(put 'copyright-names-regexp 'safe-local-variable 'stringp)
+
 (defcustom copyright-years-regexp
  "\\(\\s *\\)\\([1-9]\\([-0-9, ';/*%#\n\t]\\|\\s<\\|\\s>\\)*[0-9]+\\)"
   "Match additional copyright notice years.
@@ -73,6 +78,19 @@ The second \\( \\) construct must match the years."
   :group 'copyright
   :type 'regexp)
 
+;; See "Copyright Notices" in maintain.info.
+;; TODO? 'end only for ranges at the end, other for all ranges.
+;; Minimum limit on the size of a range?
+(defcustom copyright-year-ranges nil
+  "Non-nil if individual consecutive years should be replaced with a range.
+For example: 2005, 2006, 2007, 2008 might be replaced with 2005-2008.
+If you use ranges, you should add an explanatory note in a README file.
+The function `copyright-fix-year' respects this variable."
+  :group 'copyright
+  :type 'boolean
+  :version "24.1")
+
+;;;###autoload(put 'copyright-year-ranges 'safe-local-variable 'booleanp)
 
 (defcustom copyright-query 'function
   "If non-nil, ask user before changing copyright.
@@ -139,11 +157,10 @@ This function sets the match-data that `copyright-update-year' uses."
     ;; such an error is very inconvenient for the user.
     (error (message "Can't update copyright: %s" err) nil)))
 
-(defun copyright-update-year (replace noquery)
-  ;; This uses the match-data from copyright-find-copyright.
-  (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.
+(defun copyright-find-end ()
+  "Possibly adjust the search performed by `copyright-find-copyright'.
+If the years continue onto multiple lines that are marked as comments,
+skips to the end of all the years."
   (while (save-excursion
           (and (eq (following-char) ?,)
                (progn (forward-char 1) t)
@@ -158,8 +175,12 @@ This function sets the match-data that `copyright-update-year' uses."
     (re-search-forward comment-start-skip)
     ;; (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)))
+    (re-search-forward (format "\\(%s\\)" copyright-years-regexp))))
 
+(defun copyright-update-year (replace noquery)
+  ;; This uses the match-data from copyright-find-copyright/end.
+  (goto-char (match-end 1))
+  (copyright-find-end)
   ;; Note that `current-time-string' isn't locale-sensitive.
   (setq copyright-current-year (substring (current-time-string) -4))
   (unless (string= (buffer-substring (- (match-end 3) 2) (match-end 3))
@@ -217,6 +238,7 @@ interactively."
        (save-restriction
          ;; If names-regexp doesn't match, we should not mess with
          ;; the years _or_ the GPL version.
+         ;; TODO there may be multiple copyrights we should update.
          (when (copyright-find-copyright)
            (copyright-update-year arg noquery)
            (goto-char (copyright-start-point))
@@ -246,42 +268,78 @@ interactively."
     nil))
 
 
-;; FIXME should be within 50 years of present (cf calendar).
+;; FIXME heuristic should be within 50 years of present (cf calendar).
 ;;;###autoload
 (defun copyright-fix-years ()
   "Convert 2 digit years to 4 digit years.
-Uses heuristic: year >= 50 means 19xx, < 50 means 20xx."
+Uses heuristic: year >= 50 means 19xx, < 50 means 20xx.
+If `copyright-year-ranges' (which see) is non-nil, also
+independently replaces consecutive years with a range."
   (interactive)
+  ;; TODO there may be multiple copyrights we should fix.
   (if (copyright-find-copyright)
-      (let ((s (match-beginning 2))
-           (e (copy-marker (1+ (match-end 2))))
+      (let ((s (match-beginning 3))
            (p (make-marker))
-           last)
+           ;; Not line-beg-pos, so we don't mess up leading whitespace.
+           (copystart (match-beginning 0))
+           e last sep year prev-year first-year range-start range-end)
+       ;; In case years are continued over multiple, commented lines.
+       (goto-char (match-end 1))
+       (copyright-find-end)
+       (setq e (copy-marker (1+ (match-end 3))))
        (goto-char s)
        (while (re-search-forward "[0-9]+" e t)
          (set-marker p (point))
          (goto-char (match-beginning 0))
-         (let ((sep (char-before))
-               (year (string-to-number (match-string 0))))
-           (when (and sep
-                      (/= (char-syntax sep) ?\s)
-                      (/= sep ?-))
-             (insert " "))
-           (when (< year 100)
-             (insert (if (>= year 50) "19" "20"))))
+         (setq year (string-to-number (match-string 0)))
+         (and (setq sep (char-before))
+              (/= (char-syntax sep) ?\s)
+              (/= sep ?-)
+              (insert " "))
+         (when (< year 100)
+           (insert (if (>= year 50) "19" "20"))
+           (setq year (+ year (if (>= year 50) 1900 2000))))
          (goto-char p)
-         (setq last p))
+         (when copyright-year-ranges
+           ;; If the previous thing was a range, don't try to tack more on.
+           ;; Ie not 2000-2005 -> 2000-2005-2007
+           ;; TODO should merge into existing range if possible.
+           (if (eq sep ?-)
+               (setq prev-year nil
+                     year nil)
+             (if (and prev-year (= year (1+ prev-year)))
+                 (setq range-end (point))
+               (when (and first-year prev-year
+                          (> prev-year first-year))
+                 (goto-char range-end)
+                 (delete-region range-start range-end)
+                 (insert (format "-%d" prev-year))
+                 (goto-char p))
+               (setq first-year year
+                     range-start (point)))))
+         (setq prev-year year
+               last p))
        (when last
+         (when (and copyright-year-ranges
+                    first-year prev-year
+                    (> prev-year first-year))
+           (goto-char range-end)
+           (delete-region range-start range-end)
+           (insert (format "-%d" prev-year)))
          (goto-char last)
          ;; Don't mess up whitespace after the years.
          (skip-chars-backward " \t")
-         (save-restriction
-           (narrow-to-region (copyright-start-point) (point))
-           (let ((fill-prefix "     "))
-             (fill-region s last))))
+          (save-restriction
+            (narrow-to-region copystart (point))
+            ;; This is clearly wrong, eg what about comment markers?
+ ;;;       (let ((fill-prefix "     "))
+            ;; TODO do not break copyright owner over lines.
+            (fill-region (point-min) (point-max))))
        (set-marker e nil)
-       (set-marker p nil)
-       (copyright-update nil t))
+       (set-marker p nil))
+    ;; Simply reformatting the years is not copyrightable, so it does
+    ;; not seem right to call this.  Also it messes with ranges.
+;;;    (copyright-update nil t))
     (message "No copyright message")))
 
 ;;;###autoload
@@ -296,17 +354,24 @@ Uses heuristic: year >= 50 means 19xx, < 50 means 20xx."
        (message "Copyright extends beyond `copyright-limit' and won't be updated automatically."))
   comment-end \n)
 
+;; TODO: recurse, exclude COPYING etc.
 ;;;###autoload
-(defun copyright-update-directory (directory match)
-  "Update copyright notice for all files in DIRECTORY matching MATCH."
+(defun copyright-update-directory (directory match &optional fix)
+  "Update copyright notice for all files in DIRECTORY matching MATCH.
+If FIX is non-nil, run `copyright-fix-years' instead."
   (interactive "DDirectory: \nMFilenames matching (regexp): ")
   (dolist (file (directory-files directory t match nil))
-    (message "Updating file `%s'" file)
-    (find-file file)
-    (let ((copyright-query nil))
-      (copyright-update))
-    (save-buffer)
-    (kill-buffer (current-buffer))))
+    (unless (file-directory-p file)
+      (message "Updating file `%s'" file)
+      (find-file-literally file)
+      (let ((inhibit-read-only t)
+           (enable-local-variables :safe)
+           copyright-query)
+       (if fix
+           (copyright-fix-years)
+         (copyright-update)))
+      (save-buffer)
+      (kill-buffer (current-buffer)))))
 
 (provide 'copyright)