(display-time-event-handler): Fix previous change.
[bpt/emacs.git] / lisp / time-stamp.el
CommitLineData
9565745a 1;;; time-stamp.el --- Maintain last change time stamps in files edited by Emacs
9565745a 2
b578f267
EN
3;; Copyright 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
4
03d7856a 5;; Maintainer's Time-stamp: <1996-08-13 14:03:17 gildea>
9565745a 6;; Maintainer: Stephen Gildea <gildea@lcs.mit.edu>
9565745a
RS
7;; Keywords: tools
8
9;; This file is free software; you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
11;; the Free Software Foundation; either version 2, or (at your option)
12;; any later version.
13
14;; This file is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
b578f267
EN
20;; along with GNU Emacs; see the file COPYING. If not, write to the
21;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22;; Boston, MA 02111-1307, USA.
9565745a
RS
23
24;;; Commentary:
25
03d7856a
KH
26;; A template in a file can be updated with a new time stamp when
27;; you save the file. For example:
28;; static char *ts = "sdmain.c Time-stamp: <1996-08-13 10:20:51 gildea>";
29;; See the top of `time-stamp.el' for another example.
30
31;; To use time-stamping, add this line to your .emacs file:
32;; (add-hook 'write-file-hooks 'time-stamp)
33;; Now any time-stamp templates in your files will be updated automatically.
34
35;; See the documentation for the functions `time-stamp'
36;; and `time-stamp-toggle-active' for details.
b578f267 37
717e06e5 38;;; Change Log:
b578f267
EN
39
40;; Originally based on the 19 Dec 88 version of
41;; date.el by John Sturdy <mcvax!harlqn.co.uk!jcgs@uunet.uu.net>
03d7856a 42;; Version 2, January 1995: replaced functions with %-escapes
c9c0e4bb 43;; $Id: time-stamp.el,v 1.20 1996/11/05 18:27:41 rms Exp rms $
9565745a
RS
44
45;;; Code:
46
47(defvar time-stamp-active t
f8d35bf3 48 "*Non-nil to enable time-stamping of buffers by \\[time-stamp].
b1defad2 49Can be toggled by \\[time-stamp-toggle-active].
03d7856a 50See also the variable `time-stamp-warn-inactive'.")
b1defad2
RS
51
52(defvar time-stamp-warn-inactive t
03d7856a
KH
53 "Non-nil to have \\[time-stamp] warn if a buffer did not get time-stamped.
54A warning is printed if `time-stamp-active' is nil and the buffer contains
f8d35bf3 55a time stamp template that would otherwise have been updated.")
b1defad2 56
03d7856a
KH
57(defvar time-stamp-old-format-warn 'ask
58 "Action to take if `time-stamp-format' is an old-style list.
c9c0e4bb
RS
59If `error', the format is not used. If `ask', the user is queried about
60using the time-stamp-format. If `warn', a warning is displayed.
03d7856a
KH
61If nil, no notification is given.")
62
c9c0e4bb 63(defvar time-stamp-format "%y-%m-%d %H:%M:%S %u"
03d7856a 64 "*Format of the string inserted by \\[time-stamp].
c9c0e4bb
RS
65The value may be a string or a list. Lists are supported only for
66backward compatibility; see variable `time-stamp-old-format-warn'.
f8d35bf3 67
c9c0e4bb 68A string is used with `format-time-string'.
f8d35bf3 69For example, to get the format used by the `date' command,
c9c0e4bb 70use \"%3a %3b %2d %H:%M:%S %Z %y\"")
03d7856a 71
9565745a
RS
72;;; Do not change time-stamp-line-limit, time-stamp-start, or
73;;; time-stamp-end in your .emacs or you will be incompatible
74;;; with other people's files! If you must change them,
75;;; do so only in the local variables section of the file itself.
76
03d7856a 77
e1f40b28 78(defvar time-stamp-line-limit 8 ;Do not change!
c7c4ddd4 79 "Lines of a file searched; positive counts from start, negative from end.
e1f40b28 80The patterns `time-stamp-start' and `time-stamp-end' must be found on one
c7c4ddd4
KH
81of the first (last) `time-stamp-line-limit' lines of the file for the
82file to be time-stamped by \\[time-stamp].
e1f40b28
RS
83
84Do not change `time-stamp-line-limit', `time-stamp-start', or
85`time-stamp-end' for yourself or you will be incompatible
86with other people's files! If you must change them for some application,
87do so in the local variables section of the time-stamped file itself.")
88
9565745a 89
36081614 90(defvar time-stamp-start "Time-stamp:[ \t]+\\\\?[\"<]+" ;Do not change!
9565745a 91 "Regexp after which the time stamp is written by \\[time-stamp].
e1f40b28 92See also the variables `time-stamp-end' and `time-stamp-line-limit'.
9565745a 93
e1f40b28
RS
94Do not change `time-stamp-line-limit', `time-stamp-start', or
95`time-stamp-end' for yourself or you will be incompatible
9565745a
RS
96with other people's files! If you must change them for some application,
97do so in the local variables section of the time-stamped file itself.")
98
99
e1f40b28 100(defvar time-stamp-end "\\\\?[\">]" ;Do not change!
9565745a 101 "Regexp marking the text after the time stamp.
e1f40b28
RS
102\\[time-stamp] deletes the text between the first match of `time-stamp-start'
103and the following match of `time-stamp-end' on the same line,
104then writes the time stamp specified by `time-stamp-format' between them.
105
106Do not change `time-stamp-line-limit', `time-stamp-start', or
107`time-stamp-end' for yourself or you will be incompatible
108with other people's files! If you must change them for some application,
109do so in the local variables section of the time-stamped file itself.")
110
9565745a 111
03d7856a 112
59b644e8 113;;;###autoload
9565745a
RS
114(defun time-stamp ()
115 "Update the time stamp string in the buffer.
03d7856a
KH
116A template in a file can be automatically updated with a new time stamp
117every time you save the file. Add this line to your .emacs file:
118 (add-hook 'write-file-hooks 'time-stamp)
119Normally the template must appear in the first 8 lines of a file and
120look like one of the following:
121 Time-stamp: <>
122 Time-stamp: \" \"
123The time stamp is written between the brackets or quotes:
124 Time-stamp: <1996-07-18 10:20:51 gildea>
125Only updates the time stamp if the variable `time-stamp-active' is non-nil.
126The format of the time stamp is set by the variable `time-stamp-format'.
127The variables `time-stamp-line-limit', `time-stamp-start',
128and `time-stamp-end' control finding the template."
9565745a 129 (interactive)
fe8287c6 130 (let ((case-fold-search nil)
03d7856a
KH
131 (start nil)
132 (end nil)
133 search-limit)
fe8287c6
KH
134 (save-excursion
135 (save-restriction
136 (widen)
03d7856a
KH
137 (cond ((> time-stamp-line-limit 0)
138 (goto-char (setq start (point-min)))
139 (forward-line time-stamp-line-limit)
140 (setq search-limit (point)))
141 (t
142 (goto-char (setq search-limit (point-max)))
143 (forward-line time-stamp-line-limit)
144 (setq start (point))))
c7c4ddd4 145 (goto-char start)
03d7856a
KH
146 (while (and (< (point) search-limit)
147 (not end)
148 (re-search-forward time-stamp-start search-limit 'move))
c7c4ddd4
KH
149 (setq start (point))
150 (end-of-line)
151 (let ((line-end (point)))
152 (goto-char start)
153 (if (re-search-forward time-stamp-end line-end 'move)
03d7856a
KH
154 (setq end (match-beginning 0)))))))
155 (if end
156 (progn
157 ;; do all warnings outside save-excursion
158 (cond
159 ((not time-stamp-active)
160 (if time-stamp-warn-inactive
161 ;; don't signal an error in a write-file-hook
c7c4ddd4 162 (progn
03d7856a
KH
163 (message "Warning: time-stamp-active is off; did not time-stamp buffer.")
164 (sit-for 1))))
165 ((not (and (stringp time-stamp-start)
166 (stringp time-stamp-end)))
167 (message "time-stamp-start or time-stamp-end is not a string")
168 (sit-for 1))
169 (t
170 (let ((new-time-stamp (time-stamp-string)))
171 (if (stringp new-time-stamp)
172 (save-excursion
173 (save-restriction
174 (widen)
175 (delete-region start end)
176 (goto-char start)
177 (insert new-time-stamp)
178 (setq end (point))
179 ;; remove any tabs used to format time stamp
180 (goto-char start)
181 (if (search-forward "\t" end t)
182 (untabify start end)))))))))))
9565745a
RS
183 ;; be sure to return nil so can be used on write-file-hooks
184 nil)
185
b1defad2
RS
186;;;###autoload
187(defun time-stamp-toggle-active (&optional arg)
03d7856a 188 "Toggle `time-stamp-active', setting whether \\[time-stamp] updates a buffer.
b1defad2
RS
189With arg, turn time stamping on if and only if arg is positive."
190 (interactive "P")
191 (setq time-stamp-active
192 (if (null arg)
193 (not time-stamp-active)
194 (> (prefix-numeric-value arg) 0)))
195 (message "time-stamp is now %s." (if time-stamp-active "active" "off")))
03d7856a 196
b1defad2 197
9565745a
RS
198(defun time-stamp-string ()
199 "Generate the new string to be inserted by \\[time-stamp]."
b1defad2 200 (if (stringp time-stamp-format)
c9c0e4bb 201 (format-time-string time-stamp-format (current-time))
03d7856a
KH
202 ;; handle version 1 compatibility
203 (cond ((or (eq time-stamp-old-format-warn 'error)
204 (and (eq time-stamp-old-format-warn 'ask)
205 (not (y-or-n-p "Use non-string time-stamp-format? "))))
206 (message "Warning: no time-stamp: time-stamp-format not a string")
207 (sit-for 1)
208 nil)
209 (t
210 (cond ((eq time-stamp-old-format-warn 'warn)
211 (message "Obsolescent time-stamp-format type; should be string")
212 (sit-for 1)))
213 (time-stamp-fconcat time-stamp-format " ")))))
b1defad2 214
1f92d7ef
KH
215(defconst time-stamp-month-numbers
216 '(("Jan" . 1) ("Feb" . 2) ("Mar" . 3) ("Apr" . 4) ("May" . 5) ("Jun" . 6)
217 ("Jul" . 7) ("Aug" . 8) ("Sep" . 9) ("Oct" . 10) ("Nov" . 11) ("Dec" . 12))
218 "Alist of months and their number.")
219
220(defconst time-stamp-month-full-names
221 ["(zero)" "January" "February" "March" "April" "May" "June"
222 "July" "August" "September" "October" "November" "December"])
223
c7c4ddd4
KH
224(defconst time-stamp-no-file "(no file)"
225 "String to use when the buffer is not associated with a file.")
226
b1defad2
RS
227(defun time-stamp-mail-host-name ()
228 "Return the name of the host where the user receives mail.
229This is the value of `mail-host-address' if bound and a string,
230otherwise the value of `time-stamp-mail-host' (for versions of Emacs
c7c4ddd4 231before 19.29) otherwise the value of the function system-name."
b1defad2
RS
232 (or (and (boundp 'mail-host-address)
233 (stringp mail-host-address)
234 mail-host-address)
235 (and (boundp 'time-stamp-mail-host) ;for backward compatibility
236 (stringp time-stamp-mail-host)
237 time-stamp-mail-host)
238 (system-name)))
239
240;;; the rest of this file is for version 1 compatibility
9565745a
RS
241
242(defun time-stamp-fconcat (list sep)
e1f40b28 243 "Similar to (mapconcat 'funcall LIST SEP) but LIST allows literals.
9565745a
RS
244If an element of LIST is a symbol, it is funcalled to get the string to use;
245the separator SEP is used between two strings obtained by funcalling a
246symbol. Otherwise the element itself is inserted; no separator is used
247around literals."
248 (let ((return-string "")
249 (insert-sep-p nil))
250 (while list
251 (cond ((symbolp (car list))
252 (if insert-sep-p
253 (setq return-string (concat return-string sep)))
254 (setq return-string (concat return-string (funcall (car list))))
255 (setq insert-sep-p t))
256 (t
257 (setq return-string (concat return-string (car list)))
258 (setq insert-sep-p nil)))
259 (setq list (cdr list)))
260 return-string))
261
03d7856a 262;;; Some functions used in time-stamp-format
9565745a
RS
263
264;;; Could generate most of a message-id with
e1f40b28 265;;; '(time-stamp-yymmdd "" time-stamp-hhmm "@" time-stamp-mail-host-name)
9565745a 266
9565745a
RS
267;;; pretty form, suitable for a title page
268
269(defun time-stamp-month-dd-yyyy ()
e1f40b28 270 "Return the current date as a string in \"Month DD, YYYY\" form."
9565745a 271 (let ((date (current-time-string)))
579cc01c 272 (format "%s %d, %s"
9565745a
RS
273 (aref time-stamp-month-full-names
274 (cdr (assoc (substring date 4 7) time-stamp-month-numbers)))
275 (string-to-int (substring date 8 10))
276 (substring date -4))))
277
b24173f7
RS
278(defun time-stamp-dd/mm/yyyy ()
279 "Return the current date as a string in \"DD/MM/YYYY\" form."
280 (let ((date (current-time-string)))
281 (format "%02d/%02d/%s"
282 (string-to-int (substring date 8 10))
283 (cdr (assoc (substring date 4 7) time-stamp-month-numbers))
284 (substring date -4) )))
285
9565745a
RS
286;;; same as __DATE__ in ANSI C
287
288(defun time-stamp-mon-dd-yyyy ()
e1f40b28
RS
289 "Return the current date as a string in \"Mon DD YYYY\" form.
290The first character of DD is space if the value is less than 10."
9565745a
RS
291 (let ((date (current-time-string)))
292 (format "%s %2d %s"
293 (substring date 4 7)
294 (string-to-int (substring date 8 10))
295 (substring date -4))))
296
297;;; RFC 822 date
298
299(defun time-stamp-dd-mon-yy ()
e1f40b28 300 "Return the current date as a string in \"DD Mon YY\" form."
9565745a
RS
301 (let ((date (current-time-string)))
302 (format "%02d %s %s"
303 (string-to-int (substring date 8 10))
304 (substring date 4 7)
305 (substring date -2))))
306
307;;; RCS 3 date
308
309(defun time-stamp-yy/mm/dd ()
e1f40b28 310 "Return the current date as a string in \"YY/MM/DD\" form."
9565745a
RS
311 (let ((date (current-time-string)))
312 (format "%s/%02d/%02d"
313 (substring date -2)
314 (cdr (assoc (substring date 4 7) time-stamp-month-numbers))
315 (string-to-int (substring date 8 10)))))
316
317;;; RCS 5 date
318
319(defun time-stamp-yyyy/mm/dd ()
e1f40b28 320 "Return the current date as a string in \"YYYY/MM/DD\" form."
9565745a
RS
321 (let ((date (current-time-string)))
322 (format "%s/%02d/%02d"
323 (substring date -4)
324 (cdr (assoc (substring date 4 7) time-stamp-month-numbers))
325 (string-to-int (substring date 8 10)))))
326
e1f40b28 327;;; ISO 8601 date
9565745a 328
e1f40b28
RS
329(defun time-stamp-yyyy-mm-dd ()
330 "Return the current date as a string in \"YYYY-MM-DD\" form."
9565745a 331 (let ((date (current-time-string)))
e1f40b28
RS
332 (format "%s-%02d-%02d"
333 (substring date -4)
9565745a 334 (cdr (assoc (substring date 4 7) time-stamp-month-numbers))
e1f40b28 335 (string-to-int (substring date 8 10)))))
9565745a 336
e1f40b28
RS
337(defun time-stamp-yymmdd ()
338 "Return the current date as a string in \"YYMMDD\" form."
9565745a 339 (let ((date (current-time-string)))
e1f40b28
RS
340 (format "%s%02d%02d"
341 (substring date -2)
9565745a 342 (cdr (assoc (substring date 4 7) time-stamp-month-numbers))
e1f40b28 343 (string-to-int (substring date 8 10)))))
9565745a
RS
344
345(defun time-stamp-hh:mm:ss ()
e1f40b28 346 "Return the current time as a string in \"HH:MM:SS\" form."
9565745a
RS
347 (substring (current-time-string) 11 19))
348
9565745a 349(defun time-stamp-hhmm ()
e1f40b28 350 "Return the current time as a string in \"HHMM\" form."
9565745a
RS
351 (let ((date (current-time-string)))
352 (concat (substring date 11 13)
353 (substring date 14 16))))
354
355(provide 'time-stamp)
356
357;;; time-stamp.el ends here