entered into RCS
[bpt/emacs.git] / lisp / time-stamp.el
CommitLineData
9565745a 1;;; time-stamp.el --- Maintain last change time stamps in files edited by Emacs
9565745a
RS
2;;; Copyright 1989, 1993 Free Software Foundation, Inc.
3
4;; Maintainer: Stephen Gildea <gildea@lcs.mit.edu>
e1f40b28 5;; Time-stamp: <93/12/19 14:50:59 gildea>
9565745a
RS
6;; Keywords: tools
7
8;; This file is free software; you can redistribute it and/or modify
9;; it under the terms of the GNU General Public License as published by
10;; the Free Software Foundation; either version 2, or (at your option)
11;; any later version.
12
13;; This file is distributed in the hope that it will be useful,
14;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16;; GNU General Public License for more details.
17
18;; You should have received a copy of the GNU General Public License
19;; along with GNU Emacs; see the file COPYING. If not, write to
20;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21
22;;; Commentary:
23
24;;; If you put a time stamp template anywhere in the first 8 lines of a file,
25;;; it can be updated every time you save the file. See the top of
26;;; time-stamp.el for a sample. The template looks like one of the following:
27;;; Time-stamp: <>
08cb6a9f 28;;; Time-stamp: " "
9565745a
RS
29;;; The time stamp is written between the brackets or quotes, resulting in
30;;; Time-stamp: <93/06/18 10:26:51 gildea>
31;;; Here is an example which puts the file name and time stamp in the binary:
32;;; static char *time_stamp = "sdmain.c Time-stamp: <>";
33
34;;; To activate automatic time stamping, add this code to your .emacs file:
35;;;
9565745a
RS
36;;; (if (not (memq 'time-stamp write-file-hooks))
37;;; (setq write-file-hooks
38;;; (cons 'time-stamp write-file-hooks)))
75ee4bfe
RS
39;;;
40;;; In Emacs 18 you will also need
41;;; (autoload 'time-stamp "time-stamp" "Update the time stamp in a buffer." t)
9565745a
RS
42
43;;; Change Log:
44
45;;; Originally based on the 19 Dec 88 version of
46;;; date.el by John Sturdy <mcvax!harlqn.co.uk!jcgs@uunet.uu.net>
47
48;;; Code:
49
50(defvar time-stamp-active t
51 "*Non-nil to enable time-stamping of files. See the function time-stamp.")
52
53(defvar time-stamp-format
54 '(time-stamp-yy/mm/dd time-stamp-hh:mm:ss user-login-name)
55 "*A list of functions to call to generate the time stamp string.
56Each element of the list is called as a function and the results are
57concatenated together separated by spaces. Elements may also be strings,
58which are included verbatim. Spaces are not inserted around literal strings.")
59
60;;; Do not change time-stamp-line-limit, time-stamp-start, or
61;;; time-stamp-end in your .emacs or you will be incompatible
62;;; with other people's files! If you must change them,
63;;; do so only in the local variables section of the file itself.
64
e1f40b28 65(defvar time-stamp-line-limit 8 ;Do not change!
9565745a 66 "Number of lines at the beginning of a file that are searched.
e1f40b28
RS
67The patterns `time-stamp-start' and `time-stamp-end' must be found on one
68of the first `time-stamp-line-limit' lines of the file for the file to
69be time-stamped by \\[time-stamp].
70
71Do not change `time-stamp-line-limit', `time-stamp-start', or
72`time-stamp-end' for yourself or you will be incompatible
73with other people's files! If you must change them for some application,
74do so in the local variables section of the time-stamped file itself.")
75
9565745a
RS
76
77(defvar time-stamp-start "Time-stamp: \\\\?[\"<]+" ;Do not change!
78 "Regexp after which the time stamp is written by \\[time-stamp].
e1f40b28 79See also the variables `time-stamp-end' and `time-stamp-line-limit'.
9565745a 80
e1f40b28
RS
81Do not change `time-stamp-line-limit', `time-stamp-start', or
82`time-stamp-end' for yourself or you will be incompatible
9565745a
RS
83with other people's files! If you must change them for some application,
84do so in the local variables section of the time-stamped file itself.")
85
86
e1f40b28 87(defvar time-stamp-end "\\\\?[\">]" ;Do not change!
9565745a 88 "Regexp marking the text after the time stamp.
e1f40b28
RS
89\\[time-stamp] deletes the text between the first match of `time-stamp-start'
90and the following match of `time-stamp-end' on the same line,
91then writes the time stamp specified by `time-stamp-format' between them.
92
93Do not change `time-stamp-line-limit', `time-stamp-start', or
94`time-stamp-end' for yourself or you will be incompatible
95with other people's files! If you must change them for some application,
96do so in the local variables section of the time-stamped file itself.")
97
9565745a 98
59b644e8 99;;;###autoload
9565745a
RS
100(defun time-stamp ()
101 "Update the time stamp string in the buffer.
e1f40b28
RS
102If you put a time stamp template anywhere in the first 8 lines of a file,
103it can be updated every time you save the file. See the top of
104`time-stamp.el' for a sample. The template looks like one of the following:
105 Time-stamp: <>
106 Time-stamp: \" \"
107The time stamp is written between the brackets or quotes, resulting in
108 Time-stamp: <93/06/18 10:26:51 gildea>
9565745a
RS
109Only does its thing if the variable time-stamp-active is non-nil.
110Typically used on write-file-hooks for automatic time-stamping.
e1f40b28
RS
111The format of the time stamp is determined by the variable time-stamp-format.
112The variables time-stamp-line-limit, time-stamp-start, and time-stamp-end
113control finding the template."
9565745a
RS
114 (interactive)
115 (if time-stamp-active
116 (let ((case-fold-search nil))
117 (if (and (stringp time-stamp-start)
118 (stringp time-stamp-end))
119 (save-excursion
120 (goto-char (point-min))
121 (if (re-search-forward time-stamp-start
122 (save-excursion
123 (forward-line time-stamp-line-limit)
124 (point))
125 t)
126 (let ((start (point)))
127 (if (re-search-forward time-stamp-end
128 (save-excursion (end-of-line) (point))
129 t)
130 (let ((end (match-beginning 0)))
131 (delete-region start end)
132 (goto-char start)
133 (insert (time-stamp-string))
134 (setq end (point))
135 ;; remove any tabs used to format the time stamp
136 (goto-char start)
137 (if (search-forward "\t" end t)
138 (untabify start end)))))))
139 ;; don't signal an error in a write-file-hook
140 (message "time-stamp-start or time-stamp-end is not a string"))))
141 ;; be sure to return nil so can be used on write-file-hooks
142 nil)
143
144(defun time-stamp-string ()
145 "Generate the new string to be inserted by \\[time-stamp]."
146 (time-stamp-fconcat time-stamp-format " "))
147
148(defun time-stamp-fconcat (list sep)
e1f40b28 149 "Similar to (mapconcat 'funcall LIST SEP) but LIST allows literals.
9565745a
RS
150If an element of LIST is a symbol, it is funcalled to get the string to use;
151the separator SEP is used between two strings obtained by funcalling a
152symbol. Otherwise the element itself is inserted; no separator is used
153around literals."
154 (let ((return-string "")
155 (insert-sep-p nil))
156 (while list
157 (cond ((symbolp (car list))
158 (if insert-sep-p
159 (setq return-string (concat return-string sep)))
160 (setq return-string (concat return-string (funcall (car list))))
161 (setq insert-sep-p t))
162 (t
163 (setq return-string (concat return-string (car list)))
164 (setq insert-sep-p nil)))
165 (setq list (cdr list)))
166 return-string))
167
168
169(defconst time-stamp-month-numbers
170 '(("Jan" . 1) ("Feb" . 2) ("Mar" . 3) ("Apr" . 4) ("May" . 5) ("Jun" . 6)
171 ("Jul" . 7) ("Aug" . 8) ("Sep" . 9) ("Oct" . 10) ("Nov" . 11) ("Dec" . 12))
e1f40b28 172 "Alist of months and their number.")
9565745a
RS
173
174(defconst time-stamp-month-full-names
175 ["(zero)" "January" "February" "March" "April" "May" "June"
176 "July" "August" "September" "October" "November" "December"])
177
178(defvar time-stamp-mail-host nil
e1f40b28
RS
179 "*Name of the host where the user receives mail.
180See the function `time-stamp-mail-host-name'.")
9565745a
RS
181
182;;; Some useful functions to use in time-stamp-format
183
184;;; Could generate most of a message-id with
e1f40b28 185;;; '(time-stamp-yymmdd "" time-stamp-hhmm "@" time-stamp-mail-host-name)
9565745a
RS
186
187(defun time-stamp-mail-host-name ()
188 "Return the name of the host where the user receives mail.
e1f40b28
RS
189This is the value of `time-stamp-mail-host' if bound and a string,
190otherwise the value of the function system-name.
191This function may be usefully referenced by `time-stamp-format'."
9565745a
RS
192 (or (and (boundp 'time-stamp-mail-host)
193 (stringp time-stamp-mail-host)
194 time-stamp-mail-host)
195 (system-name)))
196
9565745a
RS
197;;; pretty form, suitable for a title page
198
199(defun time-stamp-month-dd-yyyy ()
e1f40b28 200 "Return the current date as a string in \"Month DD, YYYY\" form."
9565745a 201 (let ((date (current-time-string)))
579cc01c 202 (format "%s %d, %s"
9565745a
RS
203 (aref time-stamp-month-full-names
204 (cdr (assoc (substring date 4 7) time-stamp-month-numbers)))
205 (string-to-int (substring date 8 10))
206 (substring date -4))))
207
208;;; same as __DATE__ in ANSI C
209
210(defun time-stamp-mon-dd-yyyy ()
e1f40b28
RS
211 "Return the current date as a string in \"Mon DD YYYY\" form.
212The first character of DD is space if the value is less than 10."
9565745a
RS
213 (let ((date (current-time-string)))
214 (format "%s %2d %s"
215 (substring date 4 7)
216 (string-to-int (substring date 8 10))
217 (substring date -4))))
218
219;;; RFC 822 date
220
221(defun time-stamp-dd-mon-yy ()
e1f40b28 222 "Return the current date as a string in \"DD Mon YY\" form."
9565745a
RS
223 (let ((date (current-time-string)))
224 (format "%02d %s %s"
225 (string-to-int (substring date 8 10))
226 (substring date 4 7)
227 (substring date -2))))
228
229;;; RCS 3 date
230
231(defun time-stamp-yy/mm/dd ()
e1f40b28 232 "Return the current date as a string in \"YY/MM/DD\" form."
9565745a
RS
233 (let ((date (current-time-string)))
234 (format "%s/%02d/%02d"
235 (substring date -2)
236 (cdr (assoc (substring date 4 7) time-stamp-month-numbers))
237 (string-to-int (substring date 8 10)))))
238
239;;; RCS 5 date
240
241(defun time-stamp-yyyy/mm/dd ()
e1f40b28 242 "Return the current date as a string in \"YYYY/MM/DD\" form."
9565745a
RS
243 (let ((date (current-time-string)))
244 (format "%s/%02d/%02d"
245 (substring date -4)
246 (cdr (assoc (substring date 4 7) time-stamp-month-numbers))
247 (string-to-int (substring date 8 10)))))
248
e1f40b28 249;;; ISO 8601 date
9565745a 250
e1f40b28
RS
251(defun time-stamp-yyyy-mm-dd ()
252 "Return the current date as a string in \"YYYY-MM-DD\" form."
9565745a 253 (let ((date (current-time-string)))
e1f40b28
RS
254 (format "%s-%02d-%02d"
255 (substring date -4)
9565745a 256 (cdr (assoc (substring date 4 7) time-stamp-month-numbers))
e1f40b28 257 (string-to-int (substring date 8 10)))))
9565745a 258
e1f40b28
RS
259(defun time-stamp-yymmdd ()
260 "Return the current date as a string in \"YYMMDD\" form."
9565745a 261 (let ((date (current-time-string)))
e1f40b28
RS
262 (format "%s%02d%02d"
263 (substring date -2)
9565745a 264 (cdr (assoc (substring date 4 7) time-stamp-month-numbers))
e1f40b28 265 (string-to-int (substring date 8 10)))))
9565745a
RS
266
267(defun time-stamp-hh:mm:ss ()
e1f40b28 268 "Return the current time as a string in \"HH:MM:SS\" form."
9565745a
RS
269 (substring (current-time-string) 11 19))
270
9565745a 271(defun time-stamp-hhmm ()
e1f40b28 272 "Return the current time as a string in \"HHMM\" form."
9565745a
RS
273 (let ((date (current-time-string)))
274 (concat (substring date 11 13)
275 (substring date 14 16))))
276
277(provide 'time-stamp)
278
279;;; time-stamp.el ends here