aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlenn Morris2011-01-25 00:36:34 -0800
committerGlenn Morris2011-01-25 00:36:34 -0800
commit0fe719e691955e8e4a7f5bc74ed981b2e8ca17ce (patch)
treee51b35f061a107899cfb14205c424067f53d846e
parentd0cb866238b3a7ab811ed666d21e8bd97f6f3b41 (diff)
downloademacs-0fe719e691955e8e4a7f5bc74ed981b2e8ca17ce.tar.gz
emacs-0fe719e691955e8e4a7f5bc74ed981b2e8ca17ce.zip
copyright.el updates.
* 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.
-rw-r--r--etc/NEWS5
-rw-r--r--lisp/ChangeLog14
-rw-r--r--lisp/emacs-lisp/copyright.el137
3 files changed, 120 insertions, 36 deletions
diff --git a/etc/NEWS b/etc/NEWS
index f301dc8509d..0a12a122d27 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -607,6 +607,11 @@ means to prompt the user for command specifics, e.g. a merge location.
607 607
608**** Currently supported by Bzr. 608**** Currently supported by Bzr.
609 609
610** Miscellaneous
611
612---
613*** `copyright-fix-years' can optionally convert consecutive years to ranges.
614
610 615
611* New Modes and Packages in Emacs 24.1 616* New Modes and Packages in Emacs 24.1
612 617
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 5b4b0dcc2d3..4d758d4bb18 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,17 @@
12011-01-25 Glenn Morris <rgm@gnu.org>
2
3 * emacs-lisp/copyright.el (copyright-at-end-flag)
4 (copyright-names-regexp): Add safety properties.
5 (copyright-year-ranges): New option.
6 (copyright-find-end): New function, split from copyright-update-year.
7 (copyright-update-year): Use copyright-find-end.
8 (copyright-fix-years): Optionally, convert years to ranges.
9 Handle years continued over comment lines.
10 Do not mess with the fill-prefix.
11 Do not call copyright-update.
12 (copyright-update-directory): Optionally, fix years rather than update.
13 Skip directories. Find files literally, with only safe local vars.
14
12011-01-25 Stefan Monnier <monnier@iro.umontreal.ca> 152011-01-25 Stefan Monnier <monnier@iro.umontreal.ca>
2 16
3 * files.el (file-name-non-special): Only change buffer-file-name after 17 * files.el (file-name-non-special): Only change buffer-file-name after
diff --git a/lisp/emacs-lisp/copyright.el b/lisp/emacs-lisp/copyright.el
index 54a9437e649..cf5a48b5a29 100644
--- a/lisp/emacs-lisp/copyright.el
+++ b/lisp/emacs-lisp/copyright.el
@@ -1,7 +1,6 @@
1;;; copyright.el --- update the copyright notice in current buffer 1;;; copyright.el --- update the copyright notice in current buffer
2 2
3;; Copyright (C) 1991-1995, 1998, 2001-2011 3;; Copyright (C) 1991-1995, 1998, 2001-2011 Free Software Foundation, Inc.
4;; Free Software Foundation, Inc.
5 4
6;; Author: Daniel Pfeiffer <occitan@esperanto.org> 5;; Author: Daniel Pfeiffer <occitan@esperanto.org>
7;; Keywords: maint, tools 6;; Keywords: maint, tools
@@ -47,6 +46,7 @@ This is useful for ChangeLogs."
47 :group 'copyright 46 :group 'copyright
48 :type 'boolean 47 :type 'boolean
49 :version "23.1") 48 :version "23.1")
49;;;###autoload(put 'copyright-at-end-flag 'safe-local-variable 'booleanp)
50 50
51(defcustom copyright-regexp 51(defcustom copyright-regexp
52 "\\(©\\|@copyright{}\\|[Cc]opyright\\s *:?\\s *\\(?:(C)\\)?\ 52 "\\(©\\|@copyright{}\\|[Cc]opyright\\s *:?\\s *\\(?:(C)\\)?\
@@ -66,6 +66,11 @@ someone else or to a group for which you do not work."
66 :group 'copyright 66 :group 'copyright
67 :type 'regexp) 67 :type 'regexp)
68 68
69;; The worst that can happen is a malicious regexp that overflows in
70;; the regexp matcher, a minor nuisance. It's a pain to be always
71;; prompted if you want to put this in a dir-locals.el.
72;;;###autoload(put 'copyright-names-regexp 'safe-local-variable 'stringp)
73
69(defcustom copyright-years-regexp 74(defcustom copyright-years-regexp
70 "\\(\\s *\\)\\([1-9]\\([-0-9, ';/*%#\n\t]\\|\\s<\\|\\s>\\)*[0-9]+\\)" 75 "\\(\\s *\\)\\([1-9]\\([-0-9, ';/*%#\n\t]\\|\\s<\\|\\s>\\)*[0-9]+\\)"
71 "Match additional copyright notice years. 76 "Match additional copyright notice years.
@@ -73,6 +78,19 @@ The second \\( \\) construct must match the years."
73 :group 'copyright 78 :group 'copyright
74 :type 'regexp) 79 :type 'regexp)
75 80
81;; See "Copyright Notices" in maintain.info.
82;; TODO? 'end only for ranges at the end, other for all ranges.
83;; Minimum limit on the size of a range?
84(defcustom copyright-year-ranges nil
85 "Non-nil if individual consecutive years should be replaced with a range.
86For example: 2005, 2006, 2007, 2008 might be replaced with 2005-2008.
87If you use ranges, you should add an explanatory note in a README file.
88The function `copyright-fix-year' respects this variable."
89 :group 'copyright
90 :type 'boolean
91 :version "24.1")
92
93;;;###autoload(put 'copyright-year-ranges 'safe-local-variable 'booleanp)
76 94
77(defcustom copyright-query 'function 95(defcustom copyright-query 'function
78 "If non-nil, ask user before changing copyright. 96 "If non-nil, ask user before changing copyright.
@@ -139,11 +157,10 @@ This function sets the match-data that `copyright-update-year' uses."
139 ;; such an error is very inconvenient for the user. 157 ;; such an error is very inconvenient for the user.
140 (error (message "Can't update copyright: %s" err) nil))) 158 (error (message "Can't update copyright: %s" err) nil)))
141 159
142(defun copyright-update-year (replace noquery) 160(defun copyright-find-end ()
143 ;; This uses the match-data from copyright-find-copyright. 161 "Possibly adjust the search performed by `copyright-find-copyright'.
144 (goto-char (match-end 1)) 162If the years continue onto multiple lines that are marked as comments,
145 ;; If the years are continued onto multiple lines 163skips to the end of all the years."
146 ;; that are marked as comments, skip to the end of the years anyway.
147 (while (save-excursion 164 (while (save-excursion
148 (and (eq (following-char) ?,) 165 (and (eq (following-char) ?,)
149 (progn (forward-char 1) t) 166 (progn (forward-char 1) t)
@@ -158,8 +175,12 @@ This function sets the match-data that `copyright-update-year' uses."
158 (re-search-forward comment-start-skip) 175 (re-search-forward comment-start-skip)
159 ;; (2) Need the extra \\( \\) so that the years are subexp 3, as 176 ;; (2) Need the extra \\( \\) so that the years are subexp 3, as
160 ;; they are at note (1) above. 177 ;; they are at note (1) above.
161 (re-search-forward (format "\\(%s\\)" copyright-years-regexp))) 178 (re-search-forward (format "\\(%s\\)" copyright-years-regexp))))
162 179
180(defun copyright-update-year (replace noquery)
181 ;; This uses the match-data from copyright-find-copyright/end.
182 (goto-char (match-end 1))
183 (copyright-find-end)
163 ;; Note that `current-time-string' isn't locale-sensitive. 184 ;; Note that `current-time-string' isn't locale-sensitive.
164 (setq copyright-current-year (substring (current-time-string) -4)) 185 (setq copyright-current-year (substring (current-time-string) -4))
165 (unless (string= (buffer-substring (- (match-end 3) 2) (match-end 3)) 186 (unless (string= (buffer-substring (- (match-end 3) 2) (match-end 3))
@@ -217,6 +238,7 @@ interactively."
217 (save-restriction 238 (save-restriction
218 ;; If names-regexp doesn't match, we should not mess with 239 ;; If names-regexp doesn't match, we should not mess with
219 ;; the years _or_ the GPL version. 240 ;; the years _or_ the GPL version.
241 ;; TODO there may be multiple copyrights we should update.
220 (when (copyright-find-copyright) 242 (when (copyright-find-copyright)
221 (copyright-update-year arg noquery) 243 (copyright-update-year arg noquery)
222 (goto-char (copyright-start-point)) 244 (goto-char (copyright-start-point))
@@ -246,42 +268,78 @@ interactively."
246 nil)) 268 nil))
247 269
248 270
249;; FIXME should be within 50 years of present (cf calendar). 271;; FIXME heuristic should be within 50 years of present (cf calendar).
250;;;###autoload 272;;;###autoload
251(defun copyright-fix-years () 273(defun copyright-fix-years ()
252 "Convert 2 digit years to 4 digit years. 274 "Convert 2 digit years to 4 digit years.
253Uses heuristic: year >= 50 means 19xx, < 50 means 20xx." 275Uses heuristic: year >= 50 means 19xx, < 50 means 20xx.
276If `copyright-year-ranges' (which see) is non-nil, also
277independently replaces consecutive years with a range."
254 (interactive) 278 (interactive)
279 ;; TODO there may be multiple copyrights we should fix.
255 (if (copyright-find-copyright) 280 (if (copyright-find-copyright)
256 (let ((s (match-beginning 2)) 281 (let ((s (match-beginning 3))
257 (e (copy-marker (1+ (match-end 2))))
258 (p (make-marker)) 282 (p (make-marker))
259 last) 283 ;; Not line-beg-pos, so we don't mess up leading whitespace.
284 (copystart (match-beginning 0))
285 e last sep year prev-year first-year range-start range-end)
286 ;; In case years are continued over multiple, commented lines.
287 (goto-char (match-end 1))
288 (copyright-find-end)
289 (setq e (copy-marker (1+ (match-end 3))))
260 (goto-char s) 290 (goto-char s)
261 (while (re-search-forward "[0-9]+" e t) 291 (while (re-search-forward "[0-9]+" e t)
262 (set-marker p (point)) 292 (set-marker p (point))
263 (goto-char (match-beginning 0)) 293 (goto-char (match-beginning 0))
264 (let ((sep (char-before)) 294 (setq year (string-to-number (match-string 0)))
265 (year (string-to-number (match-string 0)))) 295 (and (setq sep (char-before))
266 (when (and sep 296 (/= (char-syntax sep) ?\s)
267 (/= (char-syntax sep) ?\s) 297 (/= sep ?-)
268 (/= sep ?-)) 298 (insert " "))
269 (insert " ")) 299 (when (< year 100)
270 (when (< year 100) 300 (insert (if (>= year 50) "19" "20"))
271 (insert (if (>= year 50) "19" "20")))) 301 (setq year (+ year (if (>= year 50) 1900 2000))))
272 (goto-char p) 302 (goto-char p)
273 (setq last p)) 303 (when copyright-year-ranges
304 ;; If the previous thing was a range, don't try to tack more on.
305 ;; Ie not 2000-2005 -> 2000-2005-2007
306 ;; TODO should merge into existing range if possible.
307 (if (eq sep ?-)
308 (setq prev-year nil
309 year nil)
310 (if (and prev-year (= year (1+ prev-year)))
311 (setq range-end (point))
312 (when (and first-year prev-year
313 (> prev-year first-year))
314 (goto-char range-end)
315 (delete-region range-start range-end)
316 (insert (format "-%d" prev-year))
317 (goto-char p))
318 (setq first-year year
319 range-start (point)))))
320 (setq prev-year year
321 last p))
274 (when last 322 (when last
323 (when (and copyright-year-ranges
324 first-year prev-year
325 (> prev-year first-year))
326 (goto-char range-end)
327 (delete-region range-start range-end)
328 (insert (format "-%d" prev-year)))
275 (goto-char last) 329 (goto-char last)
276 ;; Don't mess up whitespace after the years. 330 ;; Don't mess up whitespace after the years.
277 (skip-chars-backward " \t") 331 (skip-chars-backward " \t")
278 (save-restriction 332 (save-restriction
279 (narrow-to-region (copyright-start-point) (point)) 333 (narrow-to-region copystart (point))
280 (let ((fill-prefix " ")) 334 ;; This is clearly wrong, eg what about comment markers?
281 (fill-region s last)))) 335 ;;; (let ((fill-prefix " "))
336 ;; TODO do not break copyright owner over lines.
337 (fill-region (point-min) (point-max))))
282 (set-marker e nil) 338 (set-marker e nil)
283 (set-marker p nil) 339 (set-marker p nil))
284 (copyright-update nil t)) 340 ;; Simply reformatting the years is not copyrightable, so it does
341 ;; not seem right to call this. Also it messes with ranges.
342;;; (copyright-update nil t))
285 (message "No copyright message"))) 343 (message "No copyright message")))
286 344
287;;;###autoload 345;;;###autoload
@@ -296,17 +354,24 @@ Uses heuristic: year >= 50 means 19xx, < 50 means 20xx."
296 (message "Copyright extends beyond `copyright-limit' and won't be updated automatically.")) 354 (message "Copyright extends beyond `copyright-limit' and won't be updated automatically."))
297 comment-end \n) 355 comment-end \n)
298 356
357;; TODO: recurse, exclude COPYING etc.
299;;;###autoload 358;;;###autoload
300(defun copyright-update-directory (directory match) 359(defun copyright-update-directory (directory match &optional fix)
301 "Update copyright notice for all files in DIRECTORY matching MATCH." 360 "Update copyright notice for all files in DIRECTORY matching MATCH.
361If FIX is non-nil, run `copyright-fix-years' instead."
302 (interactive "DDirectory: \nMFilenames matching (regexp): ") 362 (interactive "DDirectory: \nMFilenames matching (regexp): ")
303 (dolist (file (directory-files directory t match nil)) 363 (dolist (file (directory-files directory t match nil))
304 (message "Updating file `%s'" file) 364 (unless (file-directory-p file)
305 (find-file file) 365 (message "Updating file `%s'" file)
306 (let ((copyright-query nil)) 366 (find-file-literally file)
307 (copyright-update)) 367 (let ((inhibit-read-only t)
308 (save-buffer) 368 (enable-local-variables :safe)
309 (kill-buffer (current-buffer)))) 369 copyright-query)
370 (if fix
371 (copyright-fix-years)
372 (copyright-update)))
373 (save-buffer)
374 (kill-buffer (current-buffer)))))
310 375
311(provide 'copyright) 376(provide 'copyright)
312 377