]> code.delx.au - gnu-emacs/blob - lisp/emacs-lisp/copyright.el
*** empty log message ***
[gnu-emacs] / lisp / emacs-lisp / copyright.el
1 ;;; copyright.el --- update the copyright notice in current buffer
2
3 ;; Copyright (C) 1991, 92, 93, 94, 95, 1998, 2001, 2003
4 ;; Free Software Foundation, Inc.
5
6 ;; Author: Daniel Pfeiffer <occitan@esperanto.org>
7 ;; Keywords: maint, tools
8
9 ;; This file is part of GNU Emacs.
10
11 ;; GNU Emacs is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
14 ;; any later version.
15
16 ;; GNU Emacs is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING. If not, write to the
23 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 ;; Boston, MA 02111-1307, USA.
25
26 ;;; Commentary:
27
28 ;; Allows updating the copyright year and above mentioned GPL version manually
29 ;; or when saving a file.
30 ;; Do (add-hook 'write-file-functions 'copyright-update).
31
32 ;;; Code:
33
34 (defgroup copyright nil
35 "Update the copyright notice in current buffer."
36 :group 'tools)
37
38 (defcustom copyright-limit 2000
39 "*Don't try to update copyright beyond this position unless interactive.
40 A value of nil means to search whole buffer."
41 :group 'copyright
42 :type '(choice (integer :tag "Limit")
43 (const :tag "No limit")))
44
45 (defcustom copyright-regexp
46 "\\(©\|@copyright{}\\|[Cc]opyright\\s *:?\\s *\\(?:(C)\\)?\
47 \\|[Cc]opyright\\s *:?\\s *©\\)\
48 \\s *\\([1-9]\\([-0-9, ';\n\t]\\|\\s<\\|\\s>\\)*[0-9]+\\)"
49 "*What your copyright notice looks like.
50 The second \\( \\) construct must match the years."
51 :group 'copyright
52 :type 'regexp)
53
54
55 (defcustom copyright-query 'function
56 "*If non-nil, ask user before changing copyright.
57 When this is `function', only ask when called non-interactively."
58 :group 'copyright
59 :type '(choice (const :tag "Do not ask")
60 (const :tag "Ask unless interactive" function)
61 (other :tag "Ask" t)))
62
63
64 ;; when modifying this, also modify the comment generated by autoinsert.el
65 (defconst copyright-current-gpl-version "2"
66 "String representing the current version of the GPL or nil.")
67
68 (defvar copyright-update t)
69
70 ;; This is a defvar rather than a defconst, because the year can
71 ;; change during the Emacs session.
72 (defvar copyright-current-year (substring (current-time-string) -4)
73 "String representing the current year.")
74
75 (defun copyright-update-year (replace noquery)
76 (when (re-search-forward copyright-regexp (+ (point) copyright-limit) t)
77 ;; Note that `current-time-string' isn't locale-sensitive.
78 (setq copyright-current-year (substring (current-time-string) -4))
79 (unless (string= (buffer-substring (- (match-end 2) 2) (match-end 2))
80 (substring copyright-current-year -2))
81 (if (or noquery
82 (y-or-n-p (if replace
83 (concat "Replace copyright year(s) by "
84 copyright-current-year "? ")
85 (concat "Add " copyright-current-year
86 " to copyright? "))))
87 (if replace
88 (replace-match copyright-current-year t t nil 1)
89 (let ((size (save-excursion (skip-chars-backward "0-9"))))
90 (if (and (eq (% (- (string-to-number copyright-current-year)
91 (string-to-number (buffer-substring
92 (+ (point) size)
93 (point))))
94 100)
95 1)
96 (or (eq (char-after (+ (point) size -1)) ?-)
97 (eq (char-after (+ (point) size -2)) ?-)))
98 ;; This is a range so just replace the end part.
99 (delete-char size)
100 ;; Detect if this is using the following shorthand:
101 ;; (C) 1993, 94, 95, 1998, 2000, 01, 02, 2003
102 (if (and
103 ;; Check that the last year was 4-chars and same century.
104 (eq size -4)
105 (equal (buffer-substring (- (point) 4) (- (point) 2))
106 (substring copyright-current-year 0 2))
107 ;; Check that there are 2-char years as well.
108 (save-excursion
109 (re-search-backward "[^0-9][0-9][0-9][^0-9]"
110 (line-beginning-position) t))
111 ;; Make sure we don't remove the first century marker.
112 (save-excursion
113 (forward-char size)
114 (re-search-backward
115 (concat (buffer-substring (point) (+ (point) 2))
116 "[0-9][0-9]")
117 (line-beginning-position) t)))
118 ;; Remove the century marker of the last entry.
119 (delete-region (- (point) 4) (- (point) 2)))
120 ;; Insert a comma with the preferred number of spaces.
121 (insert
122 (save-excursion
123 (if (re-search-backward "[0-9]\\( *, *\\)[0-9]"
124 (line-beginning-position) t)
125 (match-string 1)
126 ", ")))
127 ;; If people use the '91 '92 '93 scheme, do that as well.
128 (if (eq (char-after (+ (point) size -3)) ?')
129 (insert ?')))
130 ;; Finally insert the new year.
131 (insert (substring copyright-current-year size))))))))
132
133 ;;;###autoload
134 (defun copyright-update (&optional arg interactivep)
135 "Update copyright notice at beginning of buffer to indicate the current year.
136 With prefix ARG, replace the years in the notice rather than adding
137 the current year after them. If necessary, and
138 `copyright-current-gpl-version' is set, any copying permissions
139 following the copyright are updated as well.
140 If non-nil, INTERACTIVEP tells the function to behave as when it's called
141 interactively."
142 (interactive "*P\nd")
143 (when (or copyright-update interactivep)
144 (let ((noquery (or (not copyright-query)
145 (and (eq copyright-query 'function) interactivep))))
146 (save-excursion
147 (save-restriction
148 (widen)
149 (goto-char (point-min))
150 (copyright-update-year arg noquery)
151 (goto-char (point-min))
152 (and copyright-current-gpl-version
153 ;; match the GPL version comment in .el files, including the
154 ;; bilingual Esperanto one in two-column, and in texinfo.tex
155 (re-search-forward "\\(the Free Software Foundation;\
156 either \\|; a\\^u eldono \\([0-9]+\\)a, ? a\\^u (la\\^u via \\)\
157 version \\([0-9]+\\), or (at"
158 (+ (point) copyright-limit) t)
159 (not (string= (match-string 3) copyright-current-gpl-version))
160 (or noquery
161 (y-or-n-p (concat "Replace GPL version by "
162 copyright-current-gpl-version "? ")))
163 (progn
164 (if (match-end 2)
165 ;; Esperanto bilingual comment in two-column.el
166 (replace-match copyright-current-gpl-version t t nil 2))
167 (replace-match copyright-current-gpl-version t t nil 3))))
168 (set (make-local-variable 'copyright-update) nil)))
169 ;; If a write-file-hook returns non-nil, the file is presumed to be written.
170 nil))
171
172
173 ;;;###autoload
174 (define-skeleton copyright
175 "Insert a copyright by $ORGANIZATION notice at cursor."
176 "Company: "
177 comment-start
178 "Copyright (C) " `(substring (current-time-string) -4) " by "
179 (or (getenv "ORGANIZATION")
180 str)
181 '(if (> (point) (+ (point-min) copyright-limit))
182 (message "Copyright extends beyond `copyright-limit' and won't be updated automatically."))
183 comment-end \n)
184
185 (provide 'copyright)
186
187 ;; For the copyright sign:
188 ;; Local Variables:
189 ;; coding: utf-8
190 ;; End:
191
192 ;;; copyright.el ends here