(bcopy) Use memmove instead of memcpy.
[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>
579cc01c 5;; Time-stamp: <93/12/07 07:38:54 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
65(defvar time-stamp-line-limit 8 ;Do not change! See comment above.
66 "Number of lines at the beginning of a file that are searched.
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.")
70
71(defvar time-stamp-start "Time-stamp: \\\\?[\"<]+" ;Do not change!
72 "Regexp after which the time stamp is written by \\[time-stamp].
73See also the variables time-stamp-end and time-stamp-line-limit.
74
75Do not change time-stamp-line-limit, time-stamp-start, or
76time-stamp-end for yourself or you will be incompatible
77with other people's files! If you must change them for some application,
78do so in the local variables section of the time-stamped file itself.")
79
80
81(defvar time-stamp-end "\\\\?[\">]" ;Do not change! See comment above.
82 "Regexp marking the text after the time stamp.
83\\[time-stamp] deletes the text between the first match of time-stamp-start
84\(which see) and the following match of time-stamp-end on the same line,
85then writes the time stamp specified by time-stamp-format between them.")
86
59b644e8 87;;;###autoload
9565745a
RS
88(defun time-stamp ()
89 "Update the time stamp string in the buffer.
90Only does its thing if the variable time-stamp-active is non-nil.
91Typically used on write-file-hooks for automatic time-stamping.
92The format of the time stamp is determined by the variable
93time-stamp-format. The first time-stamp-line-limit lines of the
94buffer (normally 8) are searched for the time stamp template,
95and if it is found, a new time stamp is written into it."
96 (interactive)
97 (if time-stamp-active
98 (let ((case-fold-search nil))
99 (if (and (stringp time-stamp-start)
100 (stringp time-stamp-end))
101 (save-excursion
102 (goto-char (point-min))
103 (if (re-search-forward time-stamp-start
104 (save-excursion
105 (forward-line time-stamp-line-limit)
106 (point))
107 t)
108 (let ((start (point)))
109 (if (re-search-forward time-stamp-end
110 (save-excursion (end-of-line) (point))
111 t)
112 (let ((end (match-beginning 0)))
113 (delete-region start end)
114 (goto-char start)
115 (insert (time-stamp-string))
116 (setq end (point))
117 ;; remove any tabs used to format the time stamp
118 (goto-char start)
119 (if (search-forward "\t" end t)
120 (untabify start end)))))))
121 ;; don't signal an error in a write-file-hook
122 (message "time-stamp-start or time-stamp-end is not a string"))))
123 ;; be sure to return nil so can be used on write-file-hooks
124 nil)
125
126(defun time-stamp-string ()
127 "Generate the new string to be inserted by \\[time-stamp]."
128 (time-stamp-fconcat time-stamp-format " "))
129
130(defun time-stamp-fconcat (list sep)
131 "Similar to (mapconcat 'funcall LIST SEP) but LIST can have literals.
132If an element of LIST is a symbol, it is funcalled to get the string to use;
133the separator SEP is used between two strings obtained by funcalling a
134symbol. Otherwise the element itself is inserted; no separator is used
135around literals."
136 (let ((return-string "")
137 (insert-sep-p nil))
138 (while list
139 (cond ((symbolp (car list))
140 (if insert-sep-p
141 (setq return-string (concat return-string sep)))
142 (setq return-string (concat return-string (funcall (car list))))
143 (setq insert-sep-p t))
144 (t
145 (setq return-string (concat return-string (car list)))
146 (setq insert-sep-p nil)))
147 (setq list (cdr list)))
148 return-string))
149
150
151(defconst time-stamp-month-numbers
152 '(("Jan" . 1) ("Feb" . 2) ("Mar" . 3) ("Apr" . 4) ("May" . 5) ("Jun" . 6)
153 ("Jul" . 7) ("Aug" . 8) ("Sep" . 9) ("Oct" . 10) ("Nov" . 11) ("Dec" . 12))
154 "Assoc list of months and their number.")
155
156(defconst time-stamp-month-full-names
157 ["(zero)" "January" "February" "March" "April" "May" "June"
158 "July" "August" "September" "October" "November" "December"])
159
160(defvar time-stamp-mail-host nil
161 "Name of the host where the user receives mail.
162See the function time-stamp-mail-host-name.")
163
164;;; Some useful functions to use in time-stamp-format
165
166;;; Could generate most of a message-id with
75ee4bfe 167;;; '(time-stamp-yymmdd "" time-stamp-hhmm "@" mail-host-name)
9565745a
RS
168
169(defun time-stamp-mail-host-name ()
170 "Return the name of the host where the user receives mail.
171This is the value of time-stamp-mail-host if bound and a string,
172otherwise the value of the function system-name."
173 (or (and (boundp 'time-stamp-mail-host)
174 (stringp time-stamp-mail-host)
175 time-stamp-mail-host)
176 (system-name)))
177
178(defun time-stamp-current-year ()
179 "Return the current year as a four-character string."
180 (substring (current-time-string) -4))
181
182;;; pretty form, suitable for a title page
183
184(defun time-stamp-month-dd-yyyy ()
185 "Return the current date as a string in \"Month dd, yyyy\" form."
186 (let ((date (current-time-string)))
579cc01c 187 (format "%s %d, %s"
9565745a
RS
188 (aref time-stamp-month-full-names
189 (cdr (assoc (substring date 4 7) time-stamp-month-numbers)))
190 (string-to-int (substring date 8 10))
191 (substring date -4))))
192
193;;; same as __DATE__ in ANSI C
194
195(defun time-stamp-mon-dd-yyyy ()
196 "Return the current date as a string in \"Mon dd yyyy\" form.
197The first character of dd is Space if the value is less than 10."
198 (let ((date (current-time-string)))
199 (format "%s %2d %s"
200 (substring date 4 7)
201 (string-to-int (substring date 8 10))
202 (substring date -4))))
203
204;;; RFC 822 date
205
206(defun time-stamp-dd-mon-yy ()
207 "Return the current date as a string in \"dd Mon yy\" form."
208 (let ((date (current-time-string)))
209 (format "%02d %s %s"
210 (string-to-int (substring date 8 10))
211 (substring date 4 7)
212 (substring date -2))))
213
214;;; RCS 3 date
215
216(defun time-stamp-yy/mm/dd ()
217 "Return the current date as a string in \"yy/mm/dd\" form."
218 (let ((date (current-time-string)))
219 (format "%s/%02d/%02d"
220 (substring date -2)
221 (cdr (assoc (substring date 4 7) time-stamp-month-numbers))
222 (string-to-int (substring date 8 10)))))
223
224;;; RCS 5 date
225
226(defun time-stamp-yyyy/mm/dd ()
227 "Return the current date as a string in \"yyyy/mm/dd\" form."
228 (let ((date (current-time-string)))
229 (format "%s/%02d/%02d"
230 (substring date -4)
231 (cdr (assoc (substring date 4 7) time-stamp-month-numbers))
232 (string-to-int (substring date 8 10)))))
233
234(defun time-stamp-yymmdd ()
235 "Return the current date as a string in \"yymmdd\" form."
236 (let ((date (current-time-string)))
237 (format "%s%02d%02d"
238 (substring date -2)
239 (cdr (assoc (substring date 4 7) time-stamp-month-numbers))
240 (string-to-int (substring date 8 10)))))
241
242(defun time-stamp-dd/mm/yy ()
243 "Return the current date as a string in \"dd/mm/yy\" form."
244 (let ((date (current-time-string)))
245 (format "%02d/%02d/%s"
246 (string-to-int (substring date 8 10))
247 (cdr (assoc (substring date 4 7) time-stamp-month-numbers))
248 (substring date -2))))
249
250(defun time-stamp-mm/dd/yy ()
251 "Return the current date as a string in \"mm/dd/yy\" form."
252 (let ((date (current-time-string)))
253 (format "%02d/%02d/%s"
254 (cdr (assoc (substring date 4 7) time-stamp-month-numbers))
255 (string-to-int (substring date 8 10))
256 (substring date -2))))
257
258(defun time-stamp-hh:mm:ss ()
259 "Return the current time as a string in \"hh:mm:ss\" form."
260 (substring (current-time-string) 11 19))
261
262(defun time-stamp-hh:mm ()
263 "Return the current time as a string in \"hh:mm\" form."
264 (substring (current-time-string) 11 16))
265
266(defun time-stamp-hhmm ()
267 "Return the current time as a string in \"hhmm\" form."
268 (let ((date (current-time-string)))
269 (concat (substring date 11 13)
270 (substring date 14 16))))
271
272(provide 'time-stamp)
273
274;;; time-stamp.el ends here
75ee4bfe 275