;;; time-stamp.el --- Maintain last change time stamps in files edited by Emacs
-;;; Copyright 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
-;;; Maintainer's Time-stamp: <95/05/31 10:47:14 gildea>
+;; Copyright 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+;; Maintainer's Time-stamp: <95/12/28 19:48:49 gildea>
;; Maintainer: Stephen Gildea <gildea@lcs.mit.edu>
;; Keywords: tools
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;; along with GNU Emacs; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
;;; Commentary:
-;;; If you put a time stamp template anywhere in the first 8 lines of a file,
-;;; it can be updated every time you save the file. See the top of
-;;; time-stamp.el for a sample. The template looks like one of the following:
-;;; Time-stamp: <>
-;;; Time-stamp: " "
-;;; The time stamp is written between the brackets or quotes, resulting in
-;;; Time-stamp: <95/01/18 10:20:51 gildea>
-;;; Here is an example which puts the file name and time stamp in the binary:
-;;; static char *time_stamp = "sdmain.c Time-stamp: <>";
-
-;;; To activate automatic time stamping in GNU Emacs 19, add this code
-;;; to your .emacs file:
-;;; (add-hook 'write-file-hooks 'time-stamp)
-;;;
-;;; In Emacs 18 you will need to do this instead:
-;;; (if (not (memq 'time-stamp write-file-hooks))
-;;; (setq write-file-hooks
-;;; (cons 'time-stamp write-file-hooks)))
-;;; (autoload 'time-stamp "time-stamp" "Update the time stamp in a buffer." t)
-
-;;; See the documentation for the function `time-stamp' for more details.
+;; If you put a time stamp template anywhere in the first 8 lines of a file,
+;; it can be updated every time you save the file. See the top of
+;; time-stamp.el for a sample. The template looks like one of the following:
+;; Time-stamp: <>
+;; Time-stamp: " "
+;; The time stamp is written between the brackets or quotes, resulting in
+;; Time-stamp: <95/01/18 10:20:51 gildea>
+;; Here is an example that puts the file name and time stamp in the binary:
+;; static char *time_stamp = "sdmain.c Time-stamp: <>";
+
+;; To activate automatic time stamping in GNU Emacs 19, add this code
+;; to your .emacs file:
+;; (add-hook 'write-file-hooks 'time-stamp)
+;;
+;; In Emacs 18 you will need to do this instead:
+;; (if (not (memq 'time-stamp write-file-hooks))
+;; (setq write-file-hooks
+;; (cons 'time-stamp write-file-hooks)))
+;; (autoload 'time-stamp "time-stamp" "Update the time stamp in a buffer." t)
+
+;; See the documentation for the function `time-stamp' for more details.
;;; Change Log:
-;;; Originally based on the 19 Dec 88 version of
-;;; date.el by John Sturdy <mcvax!harlqn.co.uk!jcgs@uunet.uu.net>
-;;; version 2, January 1995: replaced functions with %-escapes
-;;; $Id: time-stamp.el,v 1.13 1995/05/30 21:20:09 kwzh Exp kwzh $
+;; Originally based on the 19 Dec 88 version of
+;; date.el by John Sturdy <mcvax!harlqn.co.uk!jcgs@uunet.uu.net>
+;; version 2, January 1995: replaced functions with %-escapes
+;; $Id: time-stamp.el,v 1.16 1996/01/06 01:03:24 kwzh Exp erik $
;;; Code:
(defvar time-stamp-active t
- "*Non-nil to enable time-stamping of files.
+ "*Non-nil to enable time-stamping of buffers by \\[time-stamp].
Can be toggled by \\[time-stamp-toggle-active].
See also the variable time-stamp-warn-inactive.")
(defvar time-stamp-warn-inactive t
- "*Non-nil to have time-stamp warn if time-stamp-active is nil.")
+ "*Non-nil to have \\[time-stamp] warn if a buffer did not get time-stamped.
+A warning is printed if time-stamp-active is nil and the buffer contains
+a time stamp template that would otherwise have been updated.")
(defvar time-stamp-format "%02y/%02m/%02d %02H:%02M:%02S %u"
- "*Template for the string inserted by the time-stamp function.
+ "*Template for the string inserted by \\[time-stamp].
Value may be a string or a list. (Lists are supported only for
-backward compatibility.) A string is used verbatim except for character
-sequences beginning with %. See the documentation for the function
-time-stamp-strftime for a list of %-escapes.
- Each element of a list is called as a function and the results are
-concatenated together separated by spaces. List elements may also be
-strings, which are included verbatim. Spaces are not inserted around
-literal strings.")
+backward compatibility.) A string is used verbatim except
+for character sequences beginning with %:
+
+%a weekday name: `Monday'. %A gives uppercase: `MONDAY'
+%b month name: `January'. %B gives uppercase: `JANUARY'
+%d day of month
+%H 24-hour clock hour
+%I 12-hour clock hour
+%m month number
+%M minute
+%p `am' or `pm'. %P gives uppercase: `AM' or `PM'
+%S seconds
+%w day number of week, Sunday is 0
+%y year: `1995'
+%z time zone name: `est'. %Z gives uppercase: `EST'
+
+Non-date items:
+%% a literal percent character: `%'
+%f file name without directory %F gives absolute pathname
+%s system name
+%u user's login name
+%h mail host name
+
+Decimal digits between the % and the type character specify the
+field width. Strings are truncated on the right; numbers on the left.
+A leading zero causes numbers to be zero-filled.
+
+For example, to get the format used by the `date' command,
+use \"%3a %3b %2d %02H:%02M:%02S %Z %y\"")
;;; Do not change time-stamp-line-limit, time-stamp-start, or
;;; do so only in the local variables section of the file itself.
(defvar time-stamp-line-limit 8 ;Do not change!
- "Number of lines at the beginning of a file that are searched.
+ "Lines of a file searched; positive counts from start, negative from end.
The patterns `time-stamp-start' and `time-stamp-end' must be found on one
-of the first `time-stamp-line-limit' lines of the file for the file to
-be time-stamped by \\[time-stamp].
+of the first (last) `time-stamp-line-limit' lines of the file for the
+file to be time-stamped by \\[time-stamp].
Do not change `time-stamp-line-limit', `time-stamp-start', or
`time-stamp-end' for yourself or you will be incompatible
control finding the template."
(interactive)
(let ((case-fold-search nil)
- (need-to-warn nil))
+ (need-to-warn nil)
+ start search-end)
(if (and (stringp time-stamp-start)
(stringp time-stamp-end))
(save-excursion
(save-restriction
(widen)
- (goto-char (point-min))
- (if (re-search-forward time-stamp-start
- (save-excursion
- (forward-line time-stamp-line-limit)
- (point))
- t)
- (let ((start (point)))
- (if (re-search-forward time-stamp-end
- (save-excursion
- (end-of-line)
- (point))
- t)
+ (if (> time-stamp-line-limit 0)
+ (progn
+ (goto-char (setq start (point-min)))
+ (forward-line time-stamp-line-limit)
+ (setq search-end (point)))
+ (goto-char (setq search-end (point-max)))
+ (forward-line time-stamp-line-limit)
+ (setq start (point)))
+ (goto-char start)
+ (while
+ (and (< (point) search-end)
+ (re-search-forward time-stamp-start search-end 'move))
+ (setq start (point))
+ (end-of-line)
+ (let ((line-end (point)))
+ (goto-char start)
+ (if (re-search-forward time-stamp-end line-end 'move)
+ (progn
(if time-stamp-active
(let ((end (match-beginning 0)))
(delete-region start end)
(goto-char start)
(insert (time-stamp-string))
(setq end (point))
- ;; remove any tabs used to format the time stamp
+ ;; remove any tabs used to format time stamp
(goto-char start)
(if (search-forward "\t" end t)
(untabify start end)))
(if time-stamp-warn-inactive
- ;; do the actual warning outside save-excursion
- (setq need-to-warn t))))))))
+ ;; do warning outside save-excursion
+ (setq need-to-warn t)))
+ (setq search-end (point))))))))
;; don't signal an error in a write-file-hook
(message "time-stamp-start or time-stamp-end is not a string")
(sit-for 1))
(if need-to-warn
(progn
- (message "Warning: did not time-stamp buffer.")
+ (message "Warning: time-stamp-active is off; did not time-stamp buffer.")
(sit-for 1))))
;; be sure to return nil so can be used on write-file-hooks
nil)
;;;###autoload
(defun time-stamp-toggle-active (&optional arg)
- "Toggle time-stamp-active, which enables time stamping of files.
+ "Toggle time-stamp-active, setting whether \\[time-stamp] updates a buffer.
With arg, turn time stamping on if and only if arg is positive."
(interactive "P")
(setq time-stamp-active
(defconst time-stamp-weekday-full-names
["Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday"])
+(defconst time-stamp-am-pm '("am" "pm")
+ "List of strings used to denote morning and afternoon.")
+
+(defconst time-stamp-no-file "(no file)"
+ "String to use when the buffer is not associated with a file.")
+
(defun time-stamp-strftime (format &optional time)
"Uses a FORMAT to format date, time, file, and user information.
Optional second argument TIME will be used instead of the current time.
-Characters in the format are copied literally except for %-directives:
-
-%a weekday name: `Monday'. %A gives uppercase: `MONDAY'
-%b month name: `January'. %B gives uppercase: `JANUARY'
-%d day of month
-%H 24-hour clock hour
-%I 12-hour clock hour
-%m month number
-%M minute
-%p `am' or `pm'. %P gives uppercase: `AM' or `PM'
-%S seconds
-%w day number of week, Sunday is 0
-%y year: `1995'
-%z time zone name: `est'. %Z gives uppercase: `EST'
-
-Non-date items:
-%% a literal percent character: `%'
-%f file name without directory %F gives absolute pathname
-%s system name
-%u user's login name
-%h mail host name
-
-Decimal digits between the % and the type character specify the
-field width. Strings are truncated on the right; numbers on the left.
-A leading zero causes numbers to be zero-filled.
-
-For example, to get the format used by the `date' command,
-use \"%3a %3b %2d %02H:%02M:%02S %Z %y\""
+See the description of the variable `time-stamp-format' for a description
+of the format string."
(let ((time-string (cond ((stringp time)
time)
(time
(fmt-len (length format))
(ind 0)
cur-char
+ (prev-char nil)
(result "")
field-index
field-width
- field-result)
+ field-result
+ (paren-level 0))
(while (< ind fmt-len)
(setq cur-char (aref format ind))
(setq
result
(concat result
(cond
- ((and (eq cur-char ?%)
- (< (1+ ind) fmt-len))
+ ((eq cur-char ?%)
(setq field-index (1+ ind))
(while (progn
(setq ind (1+ ind))
- (setq cur-char (aref format ind))
+ (setq cur-char (if (< ind fmt-len)
+ (aref format ind)
+ ?\0))
(and (<= ?0 cur-char) (>= ?9 cur-char))))
(setq field-width (substring format field-index ind))
+ ;; eat any additional args to allow for future expansion
+ (while (or (and (<= ?0 cur-char) (>= ?9 cur-char)) (eq ?. cur-char)
+ (eq ?, cur-char) (eq ?: cur-char) (eq ?@ cur-char)
+ (eq ?- cur-char) (eq ?+ cur-char)
+ (eq ?\ cur-char) (eq ?# cur-char)
+ (and (eq ?\( cur-char)
+ (not (eq prev-char ?\\))
+ (setq paren-level (1+ paren-level)))
+ (if (and (eq ?\) cur-char)
+ (not (eq prev-char ?\\))
+ (> paren-level 0))
+ (setq paren-level (1- paren-level))
+ (and (> paren-level 0)
+ (< ind fmt-len))))
+ (setq ind (1+ ind))
+ (setq prev-char cur-char)
+ (setq cur-char (if (< ind fmt-len)
+ (aref format ind)
+ ?\0)))
(setq field-result
(cond
((eq cur-char ?%)
(eq cur-char ?P))
(let ((name
(if (> 12 (string-to-int (substring time-string 11 13)))
- "am"
- "pm")))
+ (car time-stamp-am-pm)
+ (car (cdr time-stamp-am-pm)))))
(if (eq cur-char ?p)
name
(upcase name))))
((eq cur-char ?f) ;buffer-file-name, base name only
(if buffer-file-name
(file-name-nondirectory buffer-file-name)
- "(no file)"))
+ time-stamp-no-file))
((eq cur-char ?F) ;buffer-file-name, full path
(or buffer-file-name
- "(no file)"))
+ time-stamp-no-file))
((eq cur-char ?s) ;system name
(system-name))
((eq cur-char ?u) ;user name
"Return the name of the host where the user receives mail.
This is the value of `mail-host-address' if bound and a string,
otherwise the value of `time-stamp-mail-host' (for versions of Emacs
-before 19.29) otherwise the value of the function system-name.
-This function may be usefully referenced by `time-stamp-format'."
+before 19.29) otherwise the value of the function system-name."
(or (and (boundp 'mail-host-address)
(stringp mail-host-address)
mail-host-address)