Commit | Line | Data |
---|---|---|
3f61a2e7 | 1 | ;;; copyright.el --- update the copyright notice in current buffer |
d501f516 | 2 | |
6b61353c | 3 | ;; Copyright (C) 1991, 92, 93, 94, 95, 1998, 2001, 2003, 2004 |
f47f5302 | 4 | ;; Free Software Foundation, Inc. |
58142744 | 5 | |
3e910376 | 6 | ;; Author: Daniel Pfeiffer <occitan@esperanto.org> |
3f61a2e7 KH |
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 | |
b578f267 EN |
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. | |
3f61a2e7 KH |
25 | |
26 | ;;; Commentary: | |
27 | ||
28 | ;; Allows updating the copyright year and above mentioned GPL version manually | |
f47f5302 | 29 | ;; or when saving a file. |
6b61353c KH |
30 | ;; Do (add-hook 'before-save-hook 'copyright-update), or use |
31 | ;; M-x customize-variable RET before-save-hook RET. | |
0343b087 | 32 | |
d46bac56 ER |
33 | ;;; Code: |
34 | ||
3f251fcd AS |
35 | (defgroup copyright nil |
36 | "Update the copyright notice in current buffer." | |
37 | :group 'tools) | |
38 | ||
39 | (defcustom copyright-limit 2000 | |
3f61a2e7 | 40 | "*Don't try to update copyright beyond this position unless interactive. |
9c05459c | 41 | A value of nil means to search whole buffer." |
3f251fcd AS |
42 | :group 'copyright |
43 | :type '(choice (integer :tag "Limit") | |
44 | (const :tag "No limit"))) | |
3f61a2e7 | 45 | |
3f251fcd | 46 | (defcustom copyright-regexp |
8f924df7 | 47 | "\\(©\|@copyright{}\\|[Cc]opyright\\s *:?\\s *\\(?:(C)\\)?\ |
d260b218 | 48 | \\|[Cc]opyright\\s *:?\\s *©\\)\ |
9c05459c | 49 | \\s *\\([1-9]\\([-0-9, ';\n\t]\\|\\s<\\|\\s>\\)*[0-9]+\\)" |
3f61a2e7 | 50 | "*What your copyright notice looks like. |
3f251fcd AS |
51 | The second \\( \\) construct must match the years." |
52 | :group 'copyright | |
53 | :type 'regexp) | |
3f61a2e7 KH |
54 | |
55 | ||
3f251fcd | 56 | (defcustom copyright-query 'function |
9c05459c | 57 | "*If non-nil, ask user before changing copyright. |
3f251fcd AS |
58 | When this is `function', only ask when called non-interactively." |
59 | :group 'copyright | |
60 | :type '(choice (const :tag "Do not ask") | |
e4f0bdfa AS |
61 | (const :tag "Ask unless interactive" function) |
62 | (other :tag "Ask" t))) | |
3f61a2e7 KH |
63 | |
64 | ||
a7acbbe4 | 65 | ;; when modifying this, also modify the comment generated by autoinsert.el |
3f61a2e7 | 66 | (defconst copyright-current-gpl-version "2" |
9c05459c | 67 | "String representing the current version of the GPL or nil.") |
0343b087 | 68 | |
3f61a2e7 | 69 | (defvar copyright-update t) |
9cfd2eeb | 70 | |
b7812d30 EZ |
71 | ;; This is a defvar rather than a defconst, because the year can |
72 | ;; change during the Emacs session. | |
9c05459c | 73 | (defvar copyright-current-year (substring (current-time-string) -4) |
b7812d30 EZ |
74 | "String representing the current year.") |
75 | ||
f47f5302 SM |
76 | (defun copyright-update-year (replace noquery) |
77 | (when (re-search-forward copyright-regexp (+ (point) copyright-limit) t) | |
78 | ;; Note that `current-time-string' isn't locale-sensitive. | |
79 | (setq copyright-current-year (substring (current-time-string) -4)) | |
80 | (unless (string= (buffer-substring (- (match-end 2) 2) (match-end 2)) | |
81 | (substring copyright-current-year -2)) | |
82 | (if (or noquery | |
83 | (y-or-n-p (if replace | |
84 | (concat "Replace copyright year(s) by " | |
85 | copyright-current-year "? ") | |
86 | (concat "Add " copyright-current-year | |
87 | " to copyright? ")))) | |
88 | (if replace | |
89 | (replace-match copyright-current-year t t nil 1) | |
90 | (let ((size (save-excursion (skip-chars-backward "0-9")))) | |
91 | (if (and (eq (% (- (string-to-number copyright-current-year) | |
92 | (string-to-number (buffer-substring | |
93 | (+ (point) size) | |
94 | (point)))) | |
95 | 100) | |
96 | 1) | |
97 | (or (eq (char-after (+ (point) size -1)) ?-) | |
98 | (eq (char-after (+ (point) size -2)) ?-))) | |
99 | ;; This is a range so just replace the end part. | |
100 | (delete-char size) | |
101 | ;; Detect if this is using the following shorthand: | |
102 | ;; (C) 1993, 94, 95, 1998, 2000, 01, 02, 2003 | |
103 | (if (and | |
104 | ;; Check that the last year was 4-chars and same century. | |
105 | (eq size -4) | |
106 | (equal (buffer-substring (- (point) 4) (- (point) 2)) | |
107 | (substring copyright-current-year 0 2)) | |
108 | ;; Check that there are 2-char years as well. | |
109 | (save-excursion | |
110 | (re-search-backward "[^0-9][0-9][0-9][^0-9]" | |
111 | (line-beginning-position) t)) | |
112 | ;; Make sure we don't remove the first century marker. | |
113 | (save-excursion | |
114 | (forward-char size) | |
115 | (re-search-backward | |
116 | (concat (buffer-substring (point) (+ (point) 2)) | |
117 | "[0-9][0-9]") | |
118 | (line-beginning-position) t))) | |
119 | ;; Remove the century marker of the last entry. | |
120 | (delete-region (- (point) 4) (- (point) 2))) | |
121 | ;; Insert a comma with the preferred number of spaces. | |
122 | (insert | |
123 | (save-excursion | |
124 | (if (re-search-backward "[0-9]\\( *, *\\)[0-9]" | |
125 | (line-beginning-position) t) | |
126 | (match-string 1) | |
127 | ", "))) | |
128 | ;; If people use the '91 '92 '93 scheme, do that as well. | |
129 | (if (eq (char-after (+ (point) size -3)) ?') | |
130 | (insert ?'))) | |
131 | ;; Finally insert the new year. | |
132 | (insert (substring copyright-current-year size)))))))) | |
b7812d30 | 133 | |
0343b087 | 134 | ;;;###autoload |
f47f5302 | 135 | (defun copyright-update (&optional arg interactivep) |
9c05459c RS |
136 | "Update copyright notice at beginning of buffer to indicate the current year. |
137 | With prefix ARG, replace the years in the notice rather than adding | |
138 | the current year after them. If necessary, and | |
139 | `copyright-current-gpl-version' is set, any copying permissions | |
f47f5302 SM |
140 | following the copyright are updated as well. |
141 | If non-nil, INTERACTIVEP tells the function to behave as when it's called | |
142 | interactively." | |
143 | (interactive "*P\nd") | |
144 | (when (or copyright-update interactivep) | |
145 | (let ((noquery (or (not copyright-query) | |
146 | (and (eq copyright-query 'function) interactivep)))) | |
3f61a2e7 KH |
147 | (save-excursion |
148 | (save-restriction | |
149 | (widen) | |
150 | (goto-char (point-min)) | |
f47f5302 | 151 | (copyright-update-year arg noquery) |
3f61a2e7 KH |
152 | (goto-char (point-min)) |
153 | (and copyright-current-gpl-version | |
154 | ;; match the GPL version comment in .el files, including the | |
155 | ;; bilingual Esperanto one in two-column, and in texinfo.tex | |
9c05459c RS |
156 | (re-search-forward "\\(the Free Software Foundation;\ |
157 | either \\|; a\\^u eldono \\([0-9]+\\)a, ? a\\^u (la\\^u via \\)\ | |
158 | version \\([0-9]+\\), or (at" | |
f47f5302 | 159 | (+ (point) copyright-limit) t) |
9c05459c | 160 | (not (string= (match-string 3) copyright-current-gpl-version)) |
f47f5302 | 161 | (or noquery |
3f61a2e7 KH |
162 | (y-or-n-p (concat "Replace GPL version by " |
163 | copyright-current-gpl-version "? "))) | |
164 | (progn | |
165 | (if (match-end 2) | |
166 | ;; Esperanto bilingual comment in two-column.el | |
f47f5302 SM |
167 | (replace-match copyright-current-gpl-version t t nil 2)) |
168 | (replace-match copyright-current-gpl-version t t nil 3)))) | |
3f61a2e7 | 169 | (set (make-local-variable 'copyright-update) nil))) |
f47f5302 SM |
170 | ;; If a write-file-hook returns non-nil, the file is presumed to be written. |
171 | nil)) | |
0343b087 | 172 | |
d501f516 | 173 | |
3f61a2e7 KH |
174 | ;;;###autoload |
175 | (define-skeleton copyright | |
176 | "Insert a copyright by $ORGANIZATION notice at cursor." | |
177 | "Company: " | |
178 | comment-start | |
b7812d30 | 179 | "Copyright (C) " `(substring (current-time-string) -4) " by " |
3f61a2e7 KH |
180 | (or (getenv "ORGANIZATION") |
181 | str) | |
f47f5302 | 182 | '(if (> (point) (+ (point-min) copyright-limit)) |
3f61a2e7 | 183 | (message "Copyright extends beyond `copyright-limit' and won't be updated automatically.")) |
48a96f51 | 184 | comment-end \n) |
3f61a2e7 | 185 | |
896546cd RS |
186 | (provide 'copyright) |
187 | ||
bf5f1abd DL |
188 | ;; For the copyright sign: |
189 | ;; Local Variables: | |
d260b218 | 190 | ;; coding: utf-8 |
bf5f1abd DL |
191 | ;; End: |
192 | ||
6b61353c | 193 | ;;; arch-tag: b4991afb-b6b1-4590-bebe-e076d9d4aee8 |
e8af40ee | 194 | ;;; copyright.el ends here |