2020-11-15 20:12:45 +01:00
|
|
|
;;; time-stamp.el --- Maintain last change time stamps in files edited by Emacs -*- lexical-binding: t -*-
|
1993-06-21 05:05:59 +00:00
|
|
|
|
2025-01-01 07:39:17 +00:00
|
|
|
;; Copyright (C) 1989, 1993-1995, 1997, 2000-2025 Free Software
|
2013-01-01 09:11:05 +00:00
|
|
|
;; Foundation, Inc.
|
1996-01-14 07:34:30 +00:00
|
|
|
|
2001-07-16 12:23:00 +00:00
|
|
|
;; This file is part of GNU Emacs.
|
|
|
|
|
2024-11-01 09:32:27 -07:00
|
|
|
;; Author: Stephen Gildea <stepheng+emacs@gildea.com>
|
|
|
|
;; Keywords: files, tools
|
1993-06-21 05:05:59 +00:00
|
|
|
|
2008-05-06 08:06:51 +00:00
|
|
|
;; GNU Emacs is free software: you can redistribute it and/or modify
|
1993-06-21 05:05:59 +00:00
|
|
|
;; it under the terms of the GNU General Public License as published by
|
2008-05-06 08:06:51 +00:00
|
|
|
;; the Free Software Foundation, either version 3 of the License, or
|
|
|
|
;; (at your option) any later version.
|
1993-06-21 05:05:59 +00:00
|
|
|
|
2002-05-18 11:26:16 +00:00
|
|
|
;; GNU Emacs is distributed in the hope that it will be useful,
|
1993-06-21 05:05:59 +00:00
|
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
;; GNU General Public License for more details.
|
|
|
|
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
2017-09-13 15:52:52 -07:00
|
|
|
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
1993-06-21 05:05:59 +00:00
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
|
1996-09-22 22:20:58 +00:00
|
|
|
;; A template in a file can be updated with a new time stamp when
|
|
|
|
;; you save the file. For example:
|
2025-03-29 16:48:58 -07:00
|
|
|
;; static char *ts = "sdmain.c Time-stamp: <2025-03-28 21:31:56 gildea>";
|
1996-09-22 22:20:58 +00:00
|
|
|
|
2012-09-17 13:41:04 +08:00
|
|
|
;; To use time-stamping, add this line to your init file:
|
2004-06-13 21:23:24 +00:00
|
|
|
;; (add-hook 'before-save-hook 'time-stamp)
|
1996-09-22 22:20:58 +00:00
|
|
|
;; Now any time-stamp templates in your files will be updated automatically.
|
|
|
|
|
2025-03-29 16:48:58 -07:00
|
|
|
;; For details, see the documentation for function `time-stamp'
|
|
|
|
;; and the Info node `Time Stamps'.
|
1996-01-14 07:34:30 +00:00
|
|
|
|
1993-06-21 05:05:59 +00:00
|
|
|
;;; Code:
|
|
|
|
|
1997-04-13 20:08:59 +00:00
|
|
|
(defgroup time-stamp nil
|
|
|
|
"Maintain last change time stamps in files edited by Emacs."
|
2024-11-01 09:32:27 -07:00
|
|
|
:group 'files
|
1997-04-13 20:08:59 +00:00
|
|
|
:group 'extensions)
|
|
|
|
|
2021-09-26 08:23:29 -07:00
|
|
|
|
2024-12-10 09:09:39 -08:00
|
|
|
(defcustom time-stamp-format "%Y-%m-%d %H:%M:%S %l"
|
2008-12-03 05:48:14 +00:00
|
|
|
"Format of the string inserted by \\[time-stamp].
|
2024-12-10 09:09:39 -08:00
|
|
|
The string is inserted verbatim except for character sequences beginning
|
|
|
|
with %, which are converted as follows:
|
|
|
|
|
|
|
|
%A weekday name: `Monday' %a abbreviated weekday name: `Mon'
|
|
|
|
%B month name: `January' %b abbreviated month name: `Jan'
|
|
|
|
%d day of month
|
|
|
|
%H 24-hour clock hour %I 12-hour clock hour
|
|
|
|
%m month number
|
|
|
|
%M minute
|
2025-01-06 11:00:07 -08:00
|
|
|
%p meridian indicator: `AM', `PM'
|
2024-12-10 09:09:39 -08:00
|
|
|
%S seconds
|
2024-11-01 09:32:27 -07:00
|
|
|
%w day number of week, Sunday is 0
|
2024-12-10 09:09:39 -08:00
|
|
|
%Y 4-digit year %y 2-digit year
|
|
|
|
%Z time zone name: `EST'
|
|
|
|
%-z zone offset with hour: `-08' %:::z adds colons as needed: `+05:30'
|
|
|
|
%5z zone offset with mins: `-0800' %:z adds colon: `-08:00'
|
1997-06-08 21:43:08 +00:00
|
|
|
|
|
|
|
Non-date items:
|
2024-12-10 09:09:39 -08:00
|
|
|
%% literal percent character: \"%\"
|
|
|
|
%f file name without directory %F absolute file name
|
|
|
|
%l login name %L full name of logged-in user
|
|
|
|
%q unqualified host name %Q fully-qualified host name
|
2024-11-01 09:32:27 -07:00
|
|
|
%h mail host name
|
1997-06-08 21:43:08 +00:00
|
|
|
|
2025-01-06 11:00:07 -08:00
|
|
|
The % may be followed by a modifier affecting the letter case.
|
|
|
|
The modifier \"#\" changes the case of letters, usually to uppercase,
|
|
|
|
or if the word is already uppercase, to lowercase.
|
|
|
|
The modifier \"^\" converts letters to uppercase;
|
|
|
|
\"^\" may be followed by \"#\" to convert to lowercase.
|
|
|
|
The modifier \"*\" converts words to title case (capitalized).
|
|
|
|
|
|
|
|
Here are some example conversions on Mondays, in two locales:
|
|
|
|
|
|
|
|
English French
|
|
|
|
%A Monday lundi
|
|
|
|
%^A MONDAY LUNDI
|
|
|
|
%^#A monday lundi
|
|
|
|
%*A Monday Lundi
|
1997-04-30 01:12:24 +00:00
|
|
|
|
2024-12-10 09:09:39 -08:00
|
|
|
Decimal digits before the type character specify the minimum field
|
|
|
|
width. A \"0\" before the field width adds insignificant zeroes
|
|
|
|
as appropriate, otherwise the padding is done with spaces.
|
|
|
|
|
2025-01-06 11:00:07 -08:00
|
|
|
If no padding is specified, a field that can be one or two digits is
|
|
|
|
padded with \"0\" to two digits if necessary. Follow the % with \"_\"
|
|
|
|
to pad with a space instead, or follow it with \"-\" to suppress this
|
|
|
|
padding entirely.
|
2024-12-10 09:09:39 -08:00
|
|
|
Thus, on the 5th of the month, the day is converted as follows:
|
|
|
|
|
|
|
|
\"%d\" -> \"05\"
|
|
|
|
\"%_d\" -> \" 5\"
|
|
|
|
\"%-d\" -> \"5\"
|
|
|
|
|
|
|
|
For example, to get a common format used by the \"date\" command,
|
|
|
|
use \"%a %b %_d %H:%M:%S %Z %Y\".
|
1997-06-08 21:43:08 +00:00
|
|
|
|
2021-08-23 20:04:02 -07:00
|
|
|
The values of non-numeric formatted items depend on the locale
|
|
|
|
setting recorded in `system-time-locale' and `locale-coding-system'.
|
2024-12-10 09:09:39 -08:00
|
|
|
The examples here are for the default (\"C\") locale.
|
2021-08-23 20:04:02 -07:00
|
|
|
`time-stamp-time-zone' controls the time zone used.
|
|
|
|
|
2024-12-10 09:09:39 -08:00
|
|
|
Some of the conversions recommended here work only in Emacs 27 or later.
|
2025-01-06 11:00:07 -08:00
|
|
|
The title-case and lowercase modifiers work only in Emacs 31 or later.
|
2024-12-10 09:09:39 -08:00
|
|
|
If your files might be edited by older versions of Emacs also, you should
|
|
|
|
limit yourself to the formats recommended by that older version."
|
1997-04-13 20:08:59 +00:00
|
|
|
:type 'string
|
2025-01-06 11:00:07 -08:00
|
|
|
:version "31.1")
|
2006-04-13 00:31:32 +00:00
|
|
|
;;;###autoload(put 'time-stamp-format 'safe-local-variable 'stringp)
|
1996-09-22 22:20:58 +00:00
|
|
|
|
2021-09-26 08:23:29 -07:00
|
|
|
|
1997-08-24 03:32:38 +00:00
|
|
|
(defcustom time-stamp-active t
|
2025-02-07 09:17:26 -08:00
|
|
|
"Non-nil enables time-stamping of buffers by \\[time-stamp].
|
1997-08-24 03:32:38 +00:00
|
|
|
Can be toggled by \\[time-stamp-toggle-active].
|
2020-01-24 09:15:44 -08:00
|
|
|
|
|
|
|
This option does not affect when `time-stamp' is run, only what it
|
|
|
|
does when it runs. To activate automatic time-stamping of buffers
|
|
|
|
when they are saved, either add this line to your init file:
|
|
|
|
(add-hook \\='before-save-hook \\='time-stamp)
|
|
|
|
or customize option `before-save-hook'.
|
|
|
|
|
2021-08-23 20:04:02 -07:00
|
|
|
To enable automatic time-stamping for only a specific file, add this
|
|
|
|
line to a local variables list near the end of the file:
|
|
|
|
eval: (add-hook \\='before-save-hook \\='time-stamp nil t)
|
|
|
|
|
1997-08-24 03:32:38 +00:00
|
|
|
See also the variable `time-stamp-warn-inactive'."
|
2020-11-15 20:12:45 +01:00
|
|
|
:type 'boolean)
|
1997-08-24 03:32:38 +00:00
|
|
|
|
2021-09-26 08:23:29 -07:00
|
|
|
|
1997-08-24 03:32:38 +00:00
|
|
|
(defcustom time-stamp-warn-inactive t
|
2000-10-13 11:30:53 +00:00
|
|
|
"Have \\[time-stamp] warn if a buffer did not get time-stamped.
|
Update example date in preamble commentary.
(time-stamp): Fix parsing of "%%a" in time-stamp-pattern (change
regexp subpattern 5)
(time-stamp-pattern): Initialize to nil to avoid regexp work in
default case.
(time-stamp-string): Call set-time-zone-rule instead of setenv
(time-stamp-hhmmss): Remove (not needed after all).
(time-stamp-month-dd-yyyy, time-stamp-dd/mm/yyyy,
time-stamp-mon-dd-yyyy, time-stamp-dd-mon-yy, time-stamp-yy/mm/dd,
time-stamp-yyyy/mm/dd, time-stamp-yyyy-mm-dd, time-stamp-yymmdd,
time-stamp-hh:mm:ss, time-stamp-hhmm): Make obsolete.
(time-stamp-format, time-stamp-pattern, time-stamp-warn-inactive,
time-stamp-inserts-lines, time-stamp-count, time-stamp-time-zone,
time-stamp, time-stamp-toggle-active, time-stamp-string-preprocess,
time-stamp-once, time-stamp-conv-warn): Tweak doc strings.
2003-02-01 14:29:31 +00:00
|
|
|
If non-nil, a warning is displayed if `time-stamp-active' has
|
|
|
|
deactivated time stamping and the buffer contains a template that
|
|
|
|
otherwise would have been updated."
|
1997-08-24 03:32:38 +00:00
|
|
|
:type 'boolean
|
Update example date in preamble commentary.
(time-stamp): Fix parsing of "%%a" in time-stamp-pattern (change
regexp subpattern 5)
(time-stamp-pattern): Initialize to nil to avoid regexp work in
default case.
(time-stamp-string): Call set-time-zone-rule instead of setenv
(time-stamp-hhmmss): Remove (not needed after all).
(time-stamp-month-dd-yyyy, time-stamp-dd/mm/yyyy,
time-stamp-mon-dd-yyyy, time-stamp-dd-mon-yy, time-stamp-yy/mm/dd,
time-stamp-yyyy/mm/dd, time-stamp-yyyy-mm-dd, time-stamp-yymmdd,
time-stamp-hh:mm:ss, time-stamp-hhmm): Make obsolete.
(time-stamp-format, time-stamp-pattern, time-stamp-warn-inactive,
time-stamp-inserts-lines, time-stamp-count, time-stamp-time-zone,
time-stamp, time-stamp-toggle-active, time-stamp-string-preprocess,
time-stamp-once, time-stamp-conv-warn): Tweak doc strings.
2003-02-01 14:29:31 +00:00
|
|
|
:version "19.29")
|
1997-08-24 03:32:38 +00:00
|
|
|
|
2021-09-26 08:23:29 -07:00
|
|
|
|
1997-08-24 03:32:38 +00:00
|
|
|
(defcustom time-stamp-time-zone nil
|
2016-01-12 09:09:27 -08:00
|
|
|
"The time zone to be used by \\[time-stamp].
|
2016-02-16 15:01:50 -08:00
|
|
|
Its format is that of the ZONE argument of the `format-time-string' function."
|
2016-01-12 09:09:27 -08:00
|
|
|
:type '(choice (const :tag "Emacs local time" nil)
|
|
|
|
(const :tag "Universal Time" t)
|
|
|
|
(const :tag "system wall clock time" wall)
|
2019-10-27 08:20:13 -07:00
|
|
|
(string :tag "TZ environment variable value")
|
|
|
|
(list :tag "Offset and name"
|
|
|
|
(integer :tag "Offset (seconds east of UTC)")
|
|
|
|
(string :tag "Time zone abbreviation"))
|
|
|
|
(integer :tag "Offset (seconds east of UTC)"))
|
Update example date in preamble commentary.
(time-stamp): Fix parsing of "%%a" in time-stamp-pattern (change
regexp subpattern 5)
(time-stamp-pattern): Initialize to nil to avoid regexp work in
default case.
(time-stamp-string): Call set-time-zone-rule instead of setenv
(time-stamp-hhmmss): Remove (not needed after all).
(time-stamp-month-dd-yyyy, time-stamp-dd/mm/yyyy,
time-stamp-mon-dd-yyyy, time-stamp-dd-mon-yy, time-stamp-yy/mm/dd,
time-stamp-yyyy/mm/dd, time-stamp-yyyy-mm-dd, time-stamp-yymmdd,
time-stamp-hh:mm:ss, time-stamp-hhmm): Make obsolete.
(time-stamp-format, time-stamp-pattern, time-stamp-warn-inactive,
time-stamp-inserts-lines, time-stamp-count, time-stamp-time-zone,
time-stamp, time-stamp-toggle-active, time-stamp-string-preprocess,
time-stamp-once, time-stamp-conv-warn): Tweak doc strings.
2003-02-01 14:29:31 +00:00
|
|
|
:version "20.1")
|
2019-10-27 08:20:13 -07:00
|
|
|
;;;###autoload(put 'time-stamp-time-zone 'safe-local-variable 'time-stamp-zone-type-p)
|
|
|
|
|
2021-09-26 08:23:29 -07:00
|
|
|
|
2019-10-27 08:20:13 -07:00
|
|
|
;;;###autoload
|
|
|
|
(defun time-stamp-zone-type-p (zone)
|
2021-10-01 08:54:10 -07:00
|
|
|
"Return non-nil if ZONE is of the correct type for a timezone rule.
|
2019-10-27 08:20:13 -07:00
|
|
|
Valid ZONE values are described in the documentation of `format-time-string'."
|
|
|
|
(or (memq zone '(nil t wall))
|
|
|
|
(stringp zone)
|
|
|
|
(and (consp zone)
|
|
|
|
(integerp (car zone))
|
|
|
|
(consp (cdr zone))
|
|
|
|
(stringp (cadr zone)))
|
|
|
|
(integerp zone)))
|
1997-04-30 01:12:24 +00:00
|
|
|
|
2021-09-26 08:23:29 -07:00
|
|
|
|
1998-03-06 03:48:15 +00:00
|
|
|
;;; Do not change time-stamp-line-limit, time-stamp-start,
|
1999-08-27 01:47:33 +00:00
|
|
|
;;; time-stamp-end, time-stamp-pattern, time-stamp-inserts-lines,
|
|
|
|
;;; or time-stamp-count in your .emacs or you will be incompatible
|
|
|
|
;;; with other people's files! If you must change them, do so only
|
|
|
|
;;; in the local variables section of the file itself.
|
1993-06-21 05:05:59 +00:00
|
|
|
|
1996-09-22 22:20:58 +00:00
|
|
|
|
1994-01-19 13:57:16 +00:00
|
|
|
(defvar time-stamp-line-limit 8 ;Do not change!
|
1996-01-06 01:03:24 +00:00
|
|
|
"Lines of a file searched; positive counts from start, negative from end.
|
1999-08-27 01:47:33 +00:00
|
|
|
The patterns `time-stamp-start' and `time-stamp-end' must be found in
|
|
|
|
the first (last) `time-stamp-line-limit' lines of the file for the
|
1999-02-06 05:00:54 +00:00
|
|
|
file to be time-stamped by \\[time-stamp]. A value of 0 searches the
|
|
|
|
entire buffer (use with care).
|
1994-01-19 13:57:16 +00:00
|
|
|
|
2021-08-23 20:04:02 -07:00
|
|
|
It may be more convenient to use `time-stamp-pattern' if you set more
|
|
|
|
than one of `time-stamp-line-limit', `time-stamp-start', `time-stamp-end',
|
|
|
|
or `time-stamp-format'.
|
2005-09-12 01:05:55 +00:00
|
|
|
|
2021-08-23 20:04:02 -07:00
|
|
|
These variables are best changed with file-local variables.
|
2021-08-25 18:14:36 -07:00
|
|
|
If you were to change `time-stamp-line-limit', `time-stamp-start',
|
2021-08-23 20:04:02 -07:00
|
|
|
`time-stamp-end', or `time-stamp-pattern' in your init file, you
|
2021-08-25 18:14:36 -07:00
|
|
|
would be incompatible with other people's files.")
|
2006-04-13 00:31:32 +00:00
|
|
|
;;;###autoload(put 'time-stamp-line-limit 'safe-local-variable 'integerp)
|
1993-06-21 05:05:59 +00:00
|
|
|
|
2021-09-26 08:23:29 -07:00
|
|
|
|
1994-02-17 03:44:17 +00:00
|
|
|
(defvar time-stamp-start "Time-stamp:[ \t]+\\\\?[\"<]+" ;Do not change!
|
1993-06-21 05:05:59 +00:00
|
|
|
"Regexp after which the time stamp is written by \\[time-stamp].
|
|
|
|
|
2021-08-23 20:04:02 -07:00
|
|
|
It may be more convenient to use `time-stamp-pattern' if you set more
|
|
|
|
than one of `time-stamp-line-limit', `time-stamp-start', `time-stamp-end',
|
|
|
|
or `time-stamp-format'.
|
2005-09-12 01:05:55 +00:00
|
|
|
|
2021-08-23 20:04:02 -07:00
|
|
|
These variables are best changed with file-local variables.
|
2021-08-25 18:14:36 -07:00
|
|
|
If you were to change `time-stamp-line-limit', `time-stamp-start',
|
2021-08-23 20:04:02 -07:00
|
|
|
`time-stamp-end', or `time-stamp-pattern' in your init file, you
|
2021-08-25 18:14:36 -07:00
|
|
|
would be incompatible with other people's files.")
|
2006-04-26 05:25:32 +00:00
|
|
|
;;;###autoload(put 'time-stamp-start 'safe-local-variable 'stringp)
|
1993-06-21 05:05:59 +00:00
|
|
|
|
2021-09-26 08:23:29 -07:00
|
|
|
|
1994-01-19 13:57:16 +00:00
|
|
|
(defvar time-stamp-end "\\\\?[\">]" ;Do not change!
|
1993-06-21 05:05:59 +00:00
|
|
|
"Regexp marking the text after the time stamp.
|
1994-01-19 13:57:16 +00:00
|
|
|
\\[time-stamp] deletes the text between the first match of `time-stamp-start'
|
1999-08-27 01:47:33 +00:00
|
|
|
and the following match of `time-stamp-end', then writes the
|
|
|
|
time stamp specified by `time-stamp-format' between them.
|
1994-01-19 13:57:16 +00:00
|
|
|
|
2021-08-23 20:04:02 -07:00
|
|
|
It may be more convenient to use `time-stamp-pattern' if you set more
|
|
|
|
than one of `time-stamp-line-limit', `time-stamp-start', `time-stamp-end',
|
|
|
|
or `time-stamp-format'.
|
2005-09-12 01:05:55 +00:00
|
|
|
|
1999-08-27 01:47:33 +00:00
|
|
|
The end text normally starts on the same line as the start text ends,
|
|
|
|
but if there are any newlines in `time-stamp-format', the same number
|
2021-09-26 08:23:29 -07:00
|
|
|
of newlines must separate the start and end. Thus \\[time-stamp] tries
|
|
|
|
to not change the number of lines in the buffer; `time-stamp-inserts-lines'
|
1999-08-27 01:47:33 +00:00
|
|
|
controls this behavior.
|
|
|
|
|
2021-08-23 20:04:02 -07:00
|
|
|
These variables are best changed with file-local variables.
|
2021-08-25 18:14:36 -07:00
|
|
|
If you were to change `time-stamp-line-limit', `time-stamp-start',
|
2021-08-23 20:04:02 -07:00
|
|
|
`time-stamp-end', `time-stamp-pattern', or `time-stamp-inserts-lines' in
|
2021-08-25 18:14:36 -07:00
|
|
|
your init file, you would be incompatible with other people's files.")
|
2006-04-26 05:25:32 +00:00
|
|
|
;;;###autoload(put 'time-stamp-end 'safe-local-variable 'stringp)
|
1994-01-19 13:57:16 +00:00
|
|
|
|
1993-06-21 05:05:59 +00:00
|
|
|
|
1999-08-27 01:47:33 +00:00
|
|
|
(defvar time-stamp-inserts-lines nil ;Do not change!
|
Update example date in preamble commentary.
(time-stamp): Fix parsing of "%%a" in time-stamp-pattern (change
regexp subpattern 5)
(time-stamp-pattern): Initialize to nil to avoid regexp work in
default case.
(time-stamp-string): Call set-time-zone-rule instead of setenv
(time-stamp-hhmmss): Remove (not needed after all).
(time-stamp-month-dd-yyyy, time-stamp-dd/mm/yyyy,
time-stamp-mon-dd-yyyy, time-stamp-dd-mon-yy, time-stamp-yy/mm/dd,
time-stamp-yyyy/mm/dd, time-stamp-yyyy-mm-dd, time-stamp-yymmdd,
time-stamp-hh:mm:ss, time-stamp-hhmm): Make obsolete.
(time-stamp-format, time-stamp-pattern, time-stamp-warn-inactive,
time-stamp-inserts-lines, time-stamp-count, time-stamp-time-zone,
time-stamp, time-stamp-toggle-active, time-stamp-string-preprocess,
time-stamp-once, time-stamp-conv-warn): Tweak doc strings.
2003-02-01 14:29:31 +00:00
|
|
|
"Whether \\[time-stamp] can change the number of lines in a file.
|
1999-08-27 01:47:33 +00:00
|
|
|
If nil, \\[time-stamp] skips as many lines as there are newlines in
|
|
|
|
`time-stamp-format' before looking for the `time-stamp-end' pattern,
|
|
|
|
thus it tries not to change the number of lines in the buffer.
|
|
|
|
If non-nil, \\[time-stamp] starts looking for the end pattern
|
|
|
|
immediately after the start pattern. This behavior can cause
|
|
|
|
unexpected changes in the buffer if used carelessly, but it is useful
|
|
|
|
for generating repeated time stamps.
|
|
|
|
|
2021-08-23 20:04:02 -07:00
|
|
|
These variables are best changed with file-local variables.
|
2021-08-25 18:14:36 -07:00
|
|
|
If you were to change `time-stamp-end' or `time-stamp-inserts-lines' in
|
|
|
|
your init file, you would be incompatible with other people's files.")
|
2024-11-08 10:42:30 -08:00
|
|
|
;;;###autoload(put 'time-stamp-inserts-lines 'safe-local-variable 'booleanp)
|
1999-08-27 01:47:33 +00:00
|
|
|
|
|
|
|
|
|
|
|
(defvar time-stamp-count 1 ;Do not change!
|
2000-10-13 11:30:53 +00:00
|
|
|
"How many templates \\[time-stamp] will look for in a buffer.
|
2025-02-02 20:14:40 -08:00
|
|
|
|
|
|
|
If the value is greater than 1, the same time stamp will be written in
|
|
|
|
each case. If you want to insert different text on different lines,
|
|
|
|
then instead of changing this variable, include a newline (written as
|
|
|
|
\"\\n\") in `time-stamp-format' or the format part of `time-stamp-pattern'.
|
1999-08-27 01:47:33 +00:00
|
|
|
|
2021-08-23 20:04:02 -07:00
|
|
|
`time-stamp-count' is best changed with a file-local variable.
|
2021-08-25 18:14:36 -07:00
|
|
|
If you were to change it in your init file, you would be incompatible
|
|
|
|
with other people's files.")
|
2025-02-07 09:17:26 -08:00
|
|
|
;;;###autoload(put 'time-stamp-count 'safe-local-variable (lambda (c) (and (integerp c) (< c 100))))
|
1999-08-27 01:47:33 +00:00
|
|
|
|
|
|
|
|
Update example date in preamble commentary.
(time-stamp): Fix parsing of "%%a" in time-stamp-pattern (change
regexp subpattern 5)
(time-stamp-pattern): Initialize to nil to avoid regexp work in
default case.
(time-stamp-string): Call set-time-zone-rule instead of setenv
(time-stamp-hhmmss): Remove (not needed after all).
(time-stamp-month-dd-yyyy, time-stamp-dd/mm/yyyy,
time-stamp-mon-dd-yyyy, time-stamp-dd-mon-yy, time-stamp-yy/mm/dd,
time-stamp-yyyy/mm/dd, time-stamp-yyyy-mm-dd, time-stamp-yymmdd,
time-stamp-hh:mm:ss, time-stamp-hhmm): Make obsolete.
(time-stamp-format, time-stamp-pattern, time-stamp-warn-inactive,
time-stamp-inserts-lines, time-stamp-count, time-stamp-time-zone,
time-stamp, time-stamp-toggle-active, time-stamp-string-preprocess,
time-stamp-once, time-stamp-conv-warn): Tweak doc strings.
2003-02-01 14:29:31 +00:00
|
|
|
(defvar time-stamp-pattern nil ;Do not change!
|
1999-08-27 01:47:33 +00:00
|
|
|
"Convenience variable setting all `time-stamp' location and format values.
|
1998-03-06 03:48:15 +00:00
|
|
|
This string has four parts, each of which is optional.
|
2025-02-02 20:14:40 -08:00
|
|
|
These four parts override `time-stamp-line-limit', `time-stamp-start',
|
|
|
|
`time-stamp-format' and `time-stamp-end', respectively. See the
|
|
|
|
documentation for each of these variables for details.
|
1998-03-06 03:48:15 +00:00
|
|
|
|
|
|
|
The first part is a number followed by a slash; the number sets the number
|
|
|
|
of lines at the beginning (negative counts from end) of the file searched
|
Update example date in preamble commentary.
(time-stamp): Fix parsing of "%%a" in time-stamp-pattern (change
regexp subpattern 5)
(time-stamp-pattern): Initialize to nil to avoid regexp work in
default case.
(time-stamp-string): Call set-time-zone-rule instead of setenv
(time-stamp-hhmmss): Remove (not needed after all).
(time-stamp-month-dd-yyyy, time-stamp-dd/mm/yyyy,
time-stamp-mon-dd-yyyy, time-stamp-dd-mon-yy, time-stamp-yy/mm/dd,
time-stamp-yyyy/mm/dd, time-stamp-yyyy-mm-dd, time-stamp-yymmdd,
time-stamp-hh:mm:ss, time-stamp-hhmm): Make obsolete.
(time-stamp-format, time-stamp-pattern, time-stamp-warn-inactive,
time-stamp-inserts-lines, time-stamp-count, time-stamp-time-zone,
time-stamp, time-stamp-toggle-active, time-stamp-string-preprocess,
time-stamp-once, time-stamp-conv-warn): Tweak doc strings.
2003-02-01 14:29:31 +00:00
|
|
|
for the time stamp. The number and the slash may be omitted to use the
|
2025-02-02 20:14:40 -08:00
|
|
|
value of `time-stamp-line-limit' as the number.
|
1998-03-06 03:48:15 +00:00
|
|
|
|
|
|
|
The second part is a regexp identifying the pattern preceding the time stamp.
|
2025-02-02 20:14:40 -08:00
|
|
|
This part may be omitted to use the value of `time-stamp-start'.
|
1998-03-06 03:48:15 +00:00
|
|
|
|
2025-02-02 20:14:40 -08:00
|
|
|
The third part specifies the format of the time stamp inserted. Specify
|
|
|
|
this part as \"%%\" to use the value of `time-stamp-format'.
|
1998-03-06 03:48:15 +00:00
|
|
|
|
|
|
|
The fourth part is a regexp identifying the pattern following the time stamp.
|
2025-02-02 20:14:40 -08:00
|
|
|
This part may be omitted to use the value of `time-stamp-end'.
|
1998-03-06 03:48:15 +00:00
|
|
|
|
2021-08-23 20:04:02 -07:00
|
|
|
The pattern does not need to match the entire line of the time stamp.
|
2025-02-02 20:14:40 -08:00
|
|
|
The pattern will update time stamp information on multiple lines if the
|
2025-03-28 07:04:03 -07:00
|
|
|
pattern includes newlines, which can be written as \"\\n\".
|
2021-08-23 20:04:02 -07:00
|
|
|
|
|
|
|
These variables are best changed with file-local variables.
|
2021-08-25 18:14:36 -07:00
|
|
|
If you were to change `time-stamp-pattern', `time-stamp-line-limit',
|
2021-08-23 20:04:02 -07:00
|
|
|
`time-stamp-start', or `time-stamp-end' in your init file, you
|
2021-08-25 18:14:36 -07:00
|
|
|
would be incompatible with other people's files.
|
2021-08-23 20:04:02 -07:00
|
|
|
|
Update example date in preamble commentary.
(time-stamp): Fix parsing of "%%a" in time-stamp-pattern (change
regexp subpattern 5)
(time-stamp-pattern): Initialize to nil to avoid regexp work in
default case.
(time-stamp-string): Call set-time-zone-rule instead of setenv
(time-stamp-hhmmss): Remove (not needed after all).
(time-stamp-month-dd-yyyy, time-stamp-dd/mm/yyyy,
time-stamp-mon-dd-yyyy, time-stamp-dd-mon-yy, time-stamp-yy/mm/dd,
time-stamp-yyyy/mm/dd, time-stamp-yyyy-mm-dd, time-stamp-yymmdd,
time-stamp-hh:mm:ss, time-stamp-hhmm): Make obsolete.
(time-stamp-format, time-stamp-pattern, time-stamp-warn-inactive,
time-stamp-inserts-lines, time-stamp-count, time-stamp-time-zone,
time-stamp, time-stamp-toggle-active, time-stamp-string-preprocess,
time-stamp-once, time-stamp-conv-warn): Tweak doc strings.
2003-02-01 14:29:31 +00:00
|
|
|
Examples:
|
2019-07-26 12:38:28 +02:00
|
|
|
|
2024-11-01 09:32:27 -07:00
|
|
|
;; time-stamp-pattern: \"-10/\"
|
|
|
|
(sets only `time-stamp-line-limit')
|
|
|
|
|
|
|
|
// time-stamp-pattern: \"-9/^Last modified: %%$\"
|
|
|
|
(sets `time-stamp-line-limit', `time-stamp-start' and `time-stamp-end')
|
|
|
|
|
2024-12-10 09:09:39 -08:00
|
|
|
@c time-stamp-pattern: \"@set Time-stamp: %B %-d, %Y$\"
|
2024-11-01 09:32:27 -07:00
|
|
|
(sets `time-stamp-start', `time-stamp-format' and `time-stamp-end')
|
2019-07-26 12:38:28 +02:00
|
|
|
|
2024-11-01 09:32:27 -07:00
|
|
|
%% time-stamp-pattern: \"newcommand{\\\\\\\\timestamp}{%%}\"
|
2024-12-10 09:09:39 -08:00
|
|
|
(sets `time-stamp-start' and `time-stamp-end')
|
2019-07-26 12:38:28 +02:00
|
|
|
|
2025-02-02 20:14:40 -08:00
|
|
|
// time-stamp-pattern: \"10/Author %L\\nRevised %-d %b %Y$\"
|
|
|
|
(sets all four variables and updates text on two lines)
|
|
|
|
|
2025-03-28 07:04:03 -07:00
|
|
|
See Info node `Time Stamp Customization' for more discussion and more
|
|
|
|
in-depth examples.
|
2025-02-02 20:14:40 -08:00
|
|
|
|
2019-07-26 12:38:28 +02:00
|
|
|
|
2024-11-01 09:32:27 -07:00
|
|
|
See also `time-stamp-count' and `time-stamp-inserts-lines'.")
|
2006-04-13 00:31:32 +00:00
|
|
|
;;;###autoload(put 'time-stamp-pattern 'safe-local-variable 'stringp)
|
1998-03-06 03:48:15 +00:00
|
|
|
|
|
|
|
|
1996-09-22 22:20:58 +00:00
|
|
|
|
1993-07-28 23:51:08 +00:00
|
|
|
;;;###autoload
|
1993-06-21 05:05:59 +00:00
|
|
|
(defun time-stamp ()
|
2025-01-08 10:24:55 -08:00
|
|
|
"Update any time stamp strings (timestamps) in the buffer.
|
2025-03-28 07:04:03 -07:00
|
|
|
Look for a time stamp template and update it with the current
|
|
|
|
date, time, author, and/or other info.
|
2021-08-23 20:04:02 -07:00
|
|
|
|
|
|
|
The template, which you manually create on one of the first 8 lines
|
|
|
|
of the file before running this function, by default can look like
|
|
|
|
one of the following (your choice):
|
1996-09-22 22:20:58 +00:00
|
|
|
Time-stamp: <>
|
|
|
|
Time-stamp: \" \"
|
2021-08-23 20:04:02 -07:00
|
|
|
This function writes the current time between the brackets or quotes,
|
|
|
|
by default formatted like this:
|
2024-11-01 09:32:27 -07:00
|
|
|
Time-stamp: <2024-08-07 17:10:21 gildea>
|
2019-10-13 07:58:55 -07:00
|
|
|
|
2021-08-23 20:04:02 -07:00
|
|
|
Although you can run this function manually to update a time stamp
|
|
|
|
once, usually you want automatic time stamp updating.
|
|
|
|
|
|
|
|
A time stamp can be automatically updated with current information
|
|
|
|
every time you save a file. To enable time-stamping for all files,
|
|
|
|
customize option `before-save-hook' or add this line to your init file:
|
|
|
|
(add-hook \\='before-save-hook \\='time-stamp)
|
|
|
|
|
|
|
|
To enable automatic time-stamping for only a specific file, add
|
|
|
|
this line to a local variables list near the end of the file:
|
|
|
|
eval: (add-hook \\='before-save-hook \\='time-stamp nil t)
|
|
|
|
|
2025-02-07 09:17:26 -08:00
|
|
|
If the file has no time stamp template or if `time-stamp-active' is nil,
|
|
|
|
this function does nothing.
|
2021-08-23 20:04:02 -07:00
|
|
|
|
2021-10-01 08:54:10 -07:00
|
|
|
You can set `time-stamp-pattern' in a file's local variables list
|
2025-02-07 09:17:26 -08:00
|
|
|
to customize the information in the time stamp and where it is written."
|
1993-06-21 05:05:59 +00:00
|
|
|
(interactive)
|
1999-08-27 01:47:33 +00:00
|
|
|
(let ((line-limit time-stamp-line-limit)
|
1998-03-06 03:48:15 +00:00
|
|
|
(ts-start time-stamp-start)
|
|
|
|
(ts-format time-stamp-format)
|
1999-08-27 01:47:33 +00:00
|
|
|
(ts-end time-stamp-end)
|
|
|
|
(ts-count time-stamp-count)
|
|
|
|
(format-lines 0)
|
|
|
|
(end-lines 1)
|
|
|
|
(start nil)
|
|
|
|
search-limit)
|
1998-03-06 03:48:15 +00:00
|
|
|
(if (stringp time-stamp-pattern)
|
|
|
|
(progn
|
Update example date in preamble commentary.
(time-stamp): Fix parsing of "%%a" in time-stamp-pattern (change
regexp subpattern 5)
(time-stamp-pattern): Initialize to nil to avoid regexp work in
default case.
(time-stamp-string): Call set-time-zone-rule instead of setenv
(time-stamp-hhmmss): Remove (not needed after all).
(time-stamp-month-dd-yyyy, time-stamp-dd/mm/yyyy,
time-stamp-mon-dd-yyyy, time-stamp-dd-mon-yy, time-stamp-yy/mm/dd,
time-stamp-yyyy/mm/dd, time-stamp-yyyy-mm-dd, time-stamp-yymmdd,
time-stamp-hh:mm:ss, time-stamp-hhmm): Make obsolete.
(time-stamp-format, time-stamp-pattern, time-stamp-warn-inactive,
time-stamp-inserts-lines, time-stamp-count, time-stamp-time-zone,
time-stamp, time-stamp-toggle-active, time-stamp-string-preprocess,
time-stamp-once, time-stamp-conv-warn): Tweak doc strings.
2003-02-01 14:29:31 +00:00
|
|
|
(string-match "\\`\\(\\(-?[0-9]+\\)/\\)?\\([^%]+\\)?\\(\\(%[-.,:@+_ #^()0-9]*[A-Za-z%][^%]*\\)*%[-.,:@+_ #^()0-9]*[A-Za-z%]\\)?\\([^%]+\\)?\\'" time-stamp-pattern)
|
1998-03-06 03:48:15 +00:00
|
|
|
(and (match-beginning 2)
|
|
|
|
(setq line-limit
|
2005-05-16 11:34:49 +00:00
|
|
|
(string-to-number (match-string 2 time-stamp-pattern))))
|
1998-03-06 03:48:15 +00:00
|
|
|
(and (match-beginning 3)
|
|
|
|
(setq ts-start (match-string 3 time-stamp-pattern)))
|
|
|
|
(and (match-beginning 4)
|
|
|
|
(not (string-equal (match-string 4 time-stamp-pattern) "%%"))
|
|
|
|
(setq ts-format (match-string 4 time-stamp-pattern)))
|
1998-06-19 16:50:37 +00:00
|
|
|
(and (match-beginning 6)
|
|
|
|
(setq ts-end (match-string 6 time-stamp-pattern)))))
|
1997-04-30 01:12:24 +00:00
|
|
|
(cond ((not (integerp line-limit))
|
|
|
|
(setq line-limit 8)
|
1998-03-06 03:48:15 +00:00
|
|
|
(message "time-stamp-line-limit is not an integer")
|
1997-04-30 01:12:24 +00:00
|
|
|
(sit-for 1)))
|
1999-08-27 01:47:33 +00:00
|
|
|
(cond ((not (integerp ts-count))
|
|
|
|
(setq ts-count 1)
|
|
|
|
(message "time-stamp-count is not an integer")
|
|
|
|
(sit-for 1))
|
|
|
|
((< ts-count 1)
|
|
|
|
;; We need to call time-stamp-once at least once
|
|
|
|
;; to output any warnings about time-stamp not being active.
|
|
|
|
(setq ts-count 1)))
|
|
|
|
;; Figure out what lines the end should be on.
|
2000-10-13 11:30:53 +00:00
|
|
|
(if (stringp ts-format)
|
|
|
|
(let ((nl-start 0))
|
|
|
|
(while (string-match "\n" ts-format nl-start)
|
|
|
|
(setq format-lines (1+ format-lines) nl-start (match-end 0)))))
|
1999-08-27 01:47:33 +00:00
|
|
|
(let ((nl-start 0))
|
|
|
|
(while (string-match "\n" ts-end nl-start)
|
|
|
|
(setq end-lines (1+ end-lines) nl-start (match-end 0))))
|
|
|
|
;; Find overall what lines to look at
|
1997-04-30 01:12:24 +00:00
|
|
|
(save-excursion
|
|
|
|
(save-restriction
|
|
|
|
(widen)
|
|
|
|
(cond ((> line-limit 0)
|
|
|
|
(goto-char (setq start (point-min)))
|
|
|
|
(forward-line line-limit)
|
2024-12-14 10:23:04 -08:00
|
|
|
(setq search-limit (point-marker)))
|
1999-02-06 05:00:54 +00:00
|
|
|
((< line-limit 0)
|
2024-12-14 10:23:04 -08:00
|
|
|
(goto-char (setq search-limit (point-max-marker)))
|
1997-04-30 01:12:24 +00:00
|
|
|
(forward-line line-limit)
|
1999-02-06 05:00:54 +00:00
|
|
|
(setq start (point)))
|
|
|
|
(t ;0 => no limit (use with care!)
|
|
|
|
(setq start (point-min))
|
2024-12-14 10:23:04 -08:00
|
|
|
(setq search-limit (point-max-marker))))))
|
1999-08-27 01:47:33 +00:00
|
|
|
(while (and start
|
|
|
|
(< start search-limit)
|
|
|
|
(> ts-count 0))
|
|
|
|
(setq start (time-stamp-once start search-limit ts-start ts-end
|
|
|
|
ts-format format-lines end-lines))
|
2024-12-14 10:23:04 -08:00
|
|
|
(setq ts-count (1- ts-count)))
|
|
|
|
(set-marker search-limit nil))
|
1999-08-27 01:47:33 +00:00
|
|
|
nil)
|
|
|
|
|
|
|
|
(defun time-stamp-once (start search-limit ts-start ts-end
|
|
|
|
ts-format format-lines end-lines)
|
Update example date in preamble commentary.
(time-stamp): Fix parsing of "%%a" in time-stamp-pattern (change
regexp subpattern 5)
(time-stamp-pattern): Initialize to nil to avoid regexp work in
default case.
(time-stamp-string): Call set-time-zone-rule instead of setenv
(time-stamp-hhmmss): Remove (not needed after all).
(time-stamp-month-dd-yyyy, time-stamp-dd/mm/yyyy,
time-stamp-mon-dd-yyyy, time-stamp-dd-mon-yy, time-stamp-yy/mm/dd,
time-stamp-yyyy/mm/dd, time-stamp-yyyy-mm-dd, time-stamp-yymmdd,
time-stamp-hh:mm:ss, time-stamp-hhmm): Make obsolete.
(time-stamp-format, time-stamp-pattern, time-stamp-warn-inactive,
time-stamp-inserts-lines, time-stamp-count, time-stamp-time-zone,
time-stamp, time-stamp-toggle-active, time-stamp-string-preprocess,
time-stamp-once, time-stamp-conv-warn): Tweak doc strings.
2003-02-01 14:29:31 +00:00
|
|
|
"Update one time stamp. Internal routine called by \\[time-stamp].
|
1999-08-27 01:47:33 +00:00
|
|
|
Returns the end point, which is where `time-stamp' begins the next search."
|
|
|
|
(let ((case-fold-search nil)
|
|
|
|
(end nil)
|
2025-02-07 09:17:26 -08:00
|
|
|
(advance-nudge 0)
|
1999-08-27 01:47:33 +00:00
|
|
|
end-search-start
|
|
|
|
(end-length nil))
|
|
|
|
(save-excursion
|
|
|
|
(save-restriction
|
|
|
|
(widen)
|
|
|
|
;; Find the location of the time stamp.
|
|
|
|
(while (and (< (goto-char start) search-limit)
|
1997-04-30 01:12:24 +00:00
|
|
|
(not end)
|
1998-03-06 03:48:15 +00:00
|
|
|
(re-search-forward ts-start search-limit 'move))
|
2025-02-07 09:17:26 -08:00
|
|
|
;; Whether or not we find a template, we must
|
|
|
|
;; advance through the buffer.
|
|
|
|
(setq advance-nudge (if (> (point) start) 0 1))
|
1997-04-30 01:12:24 +00:00
|
|
|
(setq start (point))
|
1999-08-27 01:47:33 +00:00
|
|
|
(if (not time-stamp-inserts-lines)
|
|
|
|
(forward-line format-lines))
|
|
|
|
(setq end-search-start (max start (point)))
|
|
|
|
(if (= (forward-line end-lines) 0)
|
|
|
|
(progn
|
|
|
|
(and (bolp) (backward-char))
|
|
|
|
(let ((line-end (min (point) search-limit)))
|
|
|
|
(if (>= line-end end-search-start)
|
|
|
|
(progn
|
|
|
|
(goto-char end-search-start)
|
|
|
|
(if (re-search-forward ts-end line-end t)
|
|
|
|
(progn
|
|
|
|
(setq end (match-beginning 0))
|
2025-02-07 09:17:26 -08:00
|
|
|
(setq end-length (- (match-end 0) end)))
|
|
|
|
(setq start (+ start advance-nudge)))))))))))
|
1998-03-06 03:48:15 +00:00
|
|
|
(if end
|
|
|
|
(progn
|
|
|
|
;; do all warnings outside save-excursion
|
|
|
|
(cond
|
|
|
|
((not time-stamp-active)
|
|
|
|
(if time-stamp-warn-inactive
|
2024-11-01 09:32:27 -07:00
|
|
|
;; don't signal an error in a hook
|
1998-03-06 03:48:15 +00:00
|
|
|
(progn
|
|
|
|
(message "Warning: time-stamp-active is off; did not time-stamp buffer.")
|
|
|
|
(sit-for 1))))
|
|
|
|
((not (and (stringp ts-start)
|
|
|
|
(stringp ts-end)))
|
|
|
|
(message "time-stamp-start or time-stamp-end is not a string")
|
|
|
|
(sit-for 1))
|
|
|
|
(t
|
|
|
|
(let ((new-time-stamp (time-stamp-string ts-format)))
|
1999-02-06 05:00:54 +00:00
|
|
|
(if (and (stringp new-time-stamp)
|
|
|
|
(not (string-equal (buffer-substring start end)
|
|
|
|
new-time-stamp)))
|
1998-03-06 03:48:15 +00:00
|
|
|
(save-excursion
|
|
|
|
(save-restriction
|
|
|
|
(widen)
|
|
|
|
(delete-region start end)
|
|
|
|
(goto-char start)
|
|
|
|
(insert-and-inherit new-time-stamp)
|
|
|
|
(setq end (point))
|
|
|
|
;; remove any tabs used to format time stamp
|
1999-08-27 01:47:33 +00:00
|
|
|
(if (search-backward "\t" start t)
|
|
|
|
(progn
|
|
|
|
(untabify start end)
|
|
|
|
(setq end (point))))))))))))
|
|
|
|
;; return the location after this time stamp, if there was one
|
|
|
|
(and end end-length
|
2025-02-07 09:17:26 -08:00
|
|
|
(+ end (max advance-nudge end-length)))))
|
1999-08-27 01:47:33 +00:00
|
|
|
|
1993-06-21 05:05:59 +00:00
|
|
|
|
1995-04-13 01:33:08 +00:00
|
|
|
;;;###autoload
|
|
|
|
(defun time-stamp-toggle-active (&optional arg)
|
1996-09-22 22:20:58 +00:00
|
|
|
"Toggle `time-stamp-active', setting whether \\[time-stamp] updates a buffer.
|
2021-06-21 21:28:20 -07:00
|
|
|
With ARG, turn time stamping on if and only if ARG is positive."
|
1995-04-13 01:33:08 +00:00
|
|
|
(interactive "P")
|
|
|
|
(setq time-stamp-active
|
|
|
|
(if (null arg)
|
|
|
|
(not time-stamp-active)
|
|
|
|
(> (prefix-numeric-value arg) 0)))
|
1999-08-27 01:47:33 +00:00
|
|
|
(message "time-stamp is now %s." (if time-stamp-active "active" "off")))
|
|
|
|
|
2016-01-12 09:09:27 -08:00
|
|
|
(defun time-stamp--format (format time)
|
2021-08-23 20:04:02 -07:00
|
|
|
"FORMAT a TIME in zone `time-stamp-time-zone'.
|
|
|
|
Internal helper used by `time-stamp-string-preprocess'."
|
2016-01-12 09:09:27 -08:00
|
|
|
(format-time-string format time time-stamp-time-zone))
|
1999-08-27 01:47:33 +00:00
|
|
|
|
2019-09-22 20:27:53 -07:00
|
|
|
(defun time-stamp-string (&optional ts-format time)
|
2025-01-24 09:44:03 -08:00
|
|
|
"Return the current time and other info formatted for \\[time-stamp].
|
|
|
|
Optional first argument TS-FORMAT gives the format to use; it defaults
|
|
|
|
to the value of `time-stamp-format'. Thus, with no arguments,
|
|
|
|
this function returns the string `time-stamp' would use to update
|
|
|
|
its template in the buffer. The format accepted is similar to the
|
|
|
|
format used by `format-time-string' with some extensions; see the
|
|
|
|
documentation of `time-stamp-format' for details.
|
|
|
|
Optional second argument TIME is only for testing; normally the current
|
|
|
|
time is used. The time zone is determined by `time-stamp-time-zone'."
|
2016-01-20 20:11:16 -05:00
|
|
|
(if (stringp (or ts-format (setq ts-format time-stamp-format)))
|
2019-09-22 20:27:53 -07:00
|
|
|
(time-stamp-string-preprocess ts-format time)))
|
2016-01-20 20:11:16 -05:00
|
|
|
|
1996-09-22 22:20:58 +00:00
|
|
|
|
1996-12-17 00:14:41 +00:00
|
|
|
(defconst time-stamp-no-file "(no file)"
|
|
|
|
"String to use when the buffer is not associated with a file.")
|
|
|
|
|
2021-09-26 08:23:29 -07:00
|
|
|
;;; time-stamp is transitioning to be more compatible with format-time-string.
|
|
|
|
;;; This function implements the differences.
|
1997-06-08 21:43:08 +00:00
|
|
|
;;; At all times, all the formats recommended in the doc string
|
|
|
|
;;; of time-stamp-format will work not only in the current version of
|
|
|
|
;;; Emacs, but in all versions that have been released within the past
|
2024-12-10 09:09:39 -08:00
|
|
|
;;; five years.
|
1997-06-08 21:43:08 +00:00
|
|
|
;;; The : modifier is a temporary conversion feature used to resolve
|
|
|
|
;;; ambiguous formats--formats that are changing (over time) incompatibly.
|
2025-03-28 07:04:03 -07:00
|
|
|
|
1997-06-08 21:43:08 +00:00
|
|
|
(defun time-stamp-string-preprocess (format &optional time)
|
2001-01-26 23:04:44 +00:00
|
|
|
"Use a FORMAT to format date, time, file, and user information.
|
|
|
|
Optional second argument TIME is only for testing.
|
2021-08-23 20:04:02 -07:00
|
|
|
This is an internal routine implementing extensions to `format-time-string'
|
Update example date in preamble commentary.
(time-stamp): Fix parsing of "%%a" in time-stamp-pattern (change
regexp subpattern 5)
(time-stamp-pattern): Initialize to nil to avoid regexp work in
default case.
(time-stamp-string): Call set-time-zone-rule instead of setenv
(time-stamp-hhmmss): Remove (not needed after all).
(time-stamp-month-dd-yyyy, time-stamp-dd/mm/yyyy,
time-stamp-mon-dd-yyyy, time-stamp-dd-mon-yy, time-stamp-yy/mm/dd,
time-stamp-yyyy/mm/dd, time-stamp-yyyy-mm-dd, time-stamp-yymmdd,
time-stamp-hh:mm:ss, time-stamp-hhmm): Make obsolete.
(time-stamp-format, time-stamp-pattern, time-stamp-warn-inactive,
time-stamp-inserts-lines, time-stamp-count, time-stamp-time-zone,
time-stamp, time-stamp-toggle-active, time-stamp-string-preprocess,
time-stamp-once, time-stamp-conv-warn): Tweak doc strings.
2003-02-01 14:29:31 +00:00
|
|
|
and all `time-stamp-format' compatibility."
|
2025-03-12 06:48:55 -07:00
|
|
|
(let*
|
|
|
|
((fmt-len (length format))
|
|
|
|
(ind 0)
|
|
|
|
cur-char
|
2025-03-12 07:02:44 -07:00
|
|
|
(result nil)
|
2025-03-12 06:48:55 -07:00
|
|
|
(handle-one-conversion
|
|
|
|
(lambda ()
|
2021-05-30 09:08:08 -07:00
|
|
|
(let ((prev-char nil)
|
|
|
|
(field-width "")
|
|
|
|
field-result
|
2025-01-24 10:12:58 -08:00
|
|
|
(colon-cnt 0)
|
2021-05-30 09:08:08 -07:00
|
|
|
(change-case nil)
|
2025-01-06 11:00:07 -08:00
|
|
|
(title-case nil)
|
2021-05-30 09:08:08 -07:00
|
|
|
(upcase nil)
|
2021-06-21 21:28:20 -07:00
|
|
|
(flag-pad-with-spaces nil)
|
|
|
|
(flag-pad-with-zeros nil)
|
|
|
|
(flag-minimize nil)
|
2021-05-30 09:08:08 -07:00
|
|
|
(paren-level 0))
|
|
|
|
;; eat any additional args to allow for future expansion
|
|
|
|
(while (progn
|
|
|
|
(setq ind (1+ ind))
|
|
|
|
(setq cur-char (if (< ind fmt-len)
|
|
|
|
(aref format ind)
|
|
|
|
?\0))
|
2025-01-06 11:00:07 -08:00
|
|
|
(or (eq ?. cur-char) (eq ?~ cur-char) (eq ?* cur-char)
|
2024-11-08 10:42:30 -08:00
|
|
|
(eq ?E cur-char) (eq ?O cur-char)
|
2021-05-30 09:08:08 -07:00
|
|
|
(eq ?, cur-char) (eq ?: cur-char) (eq ?@ cur-char)
|
|
|
|
(eq ?- cur-char) (eq ?+ cur-char) (eq ?_ cur-char)
|
|
|
|
(eq ?\s cur-char) (eq ?# cur-char) (eq ?^ cur-char)
|
|
|
|
(and (eq ?\( cur-char)
|
1997-06-08 21:43:08 +00:00
|
|
|
(not (eq prev-char ?\\))
|
2021-05-30 09:08:08 -07:00
|
|
|
(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)))
|
|
|
|
(if (and (<= ?0 cur-char) (>= ?9 cur-char))
|
|
|
|
;; get format width
|
2021-05-30 11:05:42 -07:00
|
|
|
(let ((field-index ind)
|
|
|
|
(first-digit cur-char))
|
2021-05-30 09:08:08 -07:00
|
|
|
(while (progn
|
|
|
|
(setq ind (1+ 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))
|
|
|
|
(setq ind (1- ind))
|
2021-05-30 11:05:42 -07:00
|
|
|
(setq cur-char first-digit)
|
2021-05-30 09:08:08 -07:00
|
|
|
t))))
|
|
|
|
(setq prev-char cur-char)
|
|
|
|
;; some characters we actually use
|
|
|
|
(cond ((eq cur-char ?:)
|
2025-01-24 10:12:58 -08:00
|
|
|
(setq colon-cnt (1+ colon-cnt)))
|
2021-05-30 09:08:08 -07:00
|
|
|
((eq cur-char ?#)
|
|
|
|
(setq change-case t))
|
|
|
|
((eq cur-char ?^)
|
2025-01-06 11:00:07 -08:00
|
|
|
(setq upcase t title-case nil change-case nil))
|
|
|
|
((eq cur-char ?*)
|
|
|
|
(setq title-case t upcase nil change-case nil))
|
2021-06-21 21:28:20 -07:00
|
|
|
((eq cur-char ?0)
|
|
|
|
(setq flag-pad-with-zeros t))
|
2021-05-30 09:08:08 -07:00
|
|
|
((eq cur-char ?-)
|
2021-06-21 21:28:20 -07:00
|
|
|
(setq field-width "1" flag-minimize t))
|
2021-05-30 09:08:08 -07:00
|
|
|
((eq cur-char ?_)
|
2021-06-21 21:28:20 -07:00
|
|
|
(setq field-width "2" flag-pad-with-spaces t))))
|
2024-12-13 08:53:54 -08:00
|
|
|
(if (> (string-to-number field-width) 99)
|
|
|
|
(setq field-width (if flag-pad-with-zeros "099" "99")))
|
2025-01-06 11:00:07 -08:00
|
|
|
(setq field-result
|
|
|
|
(cond
|
2021-05-30 09:08:08 -07:00
|
|
|
((eq cur-char ?%)
|
|
|
|
"%")
|
|
|
|
((eq cur-char ?a) ;day of week
|
2025-01-06 11:00:07 -08:00
|
|
|
(time-stamp-do-letter-case
|
|
|
|
nil upcase title-case change-case
|
2025-01-24 10:12:58 -08:00
|
|
|
(if (> colon-cnt 0)
|
2025-01-06 11:00:07 -08:00
|
|
|
(if (string-equal field-width "")
|
|
|
|
(time-stamp--format "%A" time)
|
|
|
|
"") ;discourage "%:3a"
|
|
|
|
(time-stamp--format "%a" time))))
|
2021-05-30 09:08:08 -07:00
|
|
|
((eq cur-char ?A)
|
2025-01-24 10:12:58 -08:00
|
|
|
(cond
|
|
|
|
((and (>= (string-to-number field-width) 1)
|
|
|
|
(<= (string-to-number field-width) 3)
|
|
|
|
(not flag-minimize)
|
|
|
|
(not flag-pad-with-spaces))
|
|
|
|
(time-stamp-conv-warn "%3A" "%#a")
|
|
|
|
(time-stamp--format "%#a" time))
|
|
|
|
((or (> colon-cnt 0)
|
|
|
|
change-case upcase title-case
|
|
|
|
flag-minimize flag-pad-with-spaces
|
|
|
|
(string-equal field-width ""))
|
|
|
|
(time-stamp-do-letter-case
|
|
|
|
nil upcase title-case change-case
|
|
|
|
(time-stamp--format "%A" time)))
|
|
|
|
(t (time-stamp-conv-warn (format "%%%sA" field-width)
|
2025-01-06 11:00:07 -08:00
|
|
|
(format "%%#%sA" field-width)
|
|
|
|
(format "%%:%sA" field-width))
|
|
|
|
(time-stamp--format "%#A" time))))
|
2021-05-30 09:08:08 -07:00
|
|
|
((eq cur-char ?b) ;month name
|
2025-01-06 11:00:07 -08:00
|
|
|
(time-stamp-do-letter-case
|
|
|
|
nil upcase title-case change-case
|
2025-01-24 10:12:58 -08:00
|
|
|
(if (> colon-cnt 0)
|
2025-01-06 11:00:07 -08:00
|
|
|
(if (string-equal field-width "")
|
|
|
|
(time-stamp--format "%B" time)
|
|
|
|
"") ;discourage "%:3b"
|
|
|
|
(time-stamp--format "%b" time))))
|
2021-05-30 09:08:08 -07:00
|
|
|
((eq cur-char ?B)
|
2025-01-24 10:12:58 -08:00
|
|
|
(cond
|
|
|
|
((and (>= (string-to-number field-width) 1)
|
|
|
|
(<= (string-to-number field-width) 3)
|
|
|
|
(not flag-minimize)
|
|
|
|
(not flag-pad-with-spaces))
|
|
|
|
(time-stamp-conv-warn "%3B" "%#b")
|
|
|
|
(time-stamp--format "%#b" time))
|
|
|
|
((or (> colon-cnt 0)
|
|
|
|
change-case upcase title-case
|
|
|
|
flag-minimize flag-pad-with-spaces
|
|
|
|
(string-equal field-width ""))
|
|
|
|
(time-stamp-do-letter-case
|
|
|
|
nil upcase title-case change-case
|
|
|
|
(time-stamp--format "%B" time)))
|
|
|
|
(t (time-stamp-conv-warn (format "%%%sB" field-width)
|
2025-01-06 11:00:07 -08:00
|
|
|
(format "%%#%sB" field-width)
|
|
|
|
(format "%%:%sB" field-width))
|
|
|
|
(time-stamp--format "%#B" time))))
|
2021-05-30 09:08:08 -07:00
|
|
|
((eq cur-char ?d) ;day of month, 1-31
|
2025-01-24 10:12:58 -08:00
|
|
|
(time-stamp-do-number cur-char colon-cnt field-width time))
|
2021-05-30 09:08:08 -07:00
|
|
|
((eq cur-char ?H) ;hour, 0-23
|
2025-01-24 10:12:58 -08:00
|
|
|
(time-stamp-do-number cur-char colon-cnt field-width time))
|
2021-05-30 09:08:08 -07:00
|
|
|
((eq cur-char ?I) ;hour, 1-12
|
2025-01-24 10:12:58 -08:00
|
|
|
(time-stamp-do-number cur-char colon-cnt field-width time))
|
2021-05-30 09:08:08 -07:00
|
|
|
((eq cur-char ?m) ;month number, 1-12
|
2025-01-24 10:12:58 -08:00
|
|
|
(time-stamp-do-number cur-char colon-cnt field-width time))
|
2021-05-30 09:08:08 -07:00
|
|
|
((eq cur-char ?M) ;minute, 0-59
|
2025-01-24 10:12:58 -08:00
|
|
|
(time-stamp-do-number cur-char colon-cnt field-width time))
|
2024-11-08 10:42:30 -08:00
|
|
|
((eq cur-char ?p) ;AM or PM
|
2025-01-06 11:00:07 -08:00
|
|
|
(time-stamp-do-letter-case
|
|
|
|
t upcase title-case change-case
|
|
|
|
(time-stamp--format "%p" time)))
|
2021-05-30 09:08:08 -07:00
|
|
|
((eq cur-char ?P) ;AM or PM
|
2025-01-06 11:00:07 -08:00
|
|
|
(if (and upcase (not change-case))
|
|
|
|
"" ;discourage inconsistent "%^P"
|
|
|
|
(time-stamp-do-letter-case
|
|
|
|
t upcase title-case change-case
|
|
|
|
(time-stamp--format "%p" time))))
|
2021-05-30 09:08:08 -07:00
|
|
|
((eq cur-char ?S) ;seconds, 00-60
|
2025-01-24 10:12:58 -08:00
|
|
|
(time-stamp-do-number cur-char colon-cnt field-width time))
|
2021-05-30 09:08:08 -07:00
|
|
|
((eq cur-char ?w) ;weekday number, Sunday is 0
|
|
|
|
(time-stamp--format "%w" time))
|
|
|
|
((eq cur-char ?y) ;year
|
2025-01-24 10:12:58 -08:00
|
|
|
(if (= colon-cnt 0)
|
2024-12-10 09:09:39 -08:00
|
|
|
(if (or (string-equal field-width "")
|
|
|
|
(<= (string-to-number field-width) 2))
|
|
|
|
(string-to-number (time-stamp--format "%y" time))
|
|
|
|
(time-stamp-conv-warn
|
|
|
|
(format "%%%sy" field-width) "%Y")
|
|
|
|
(string-to-number (time-stamp--format "%Y" time)))
|
|
|
|
(time-stamp-conv-warn "%:y" "%Y")
|
|
|
|
(string-to-number (time-stamp--format "%Y" time))))
|
2021-05-30 09:08:08 -07:00
|
|
|
((eq cur-char ?Y) ;4-digit year
|
|
|
|
(string-to-number (time-stamp--format "%Y" time)))
|
|
|
|
((eq cur-char ?z) ;time zone offset
|
2021-06-21 21:28:20 -07:00
|
|
|
(let ((field-width-num (string-to-number field-width))
|
|
|
|
;; Handle numeric time zone ourselves, because
|
|
|
|
;; current-time-zone cannot handle offsets
|
|
|
|
;; greater than 24 hours.
|
|
|
|
(offset-secs
|
|
|
|
(cond ((numberp time-stamp-time-zone)
|
|
|
|
time-stamp-time-zone)
|
|
|
|
((and (consp time-stamp-time-zone)
|
|
|
|
(numberp (car time-stamp-time-zone)))
|
|
|
|
(car time-stamp-time-zone))
|
|
|
|
;; interpret text time zone
|
|
|
|
(t (car (current-time-zone
|
|
|
|
time time-stamp-time-zone))))))
|
|
|
|
;; we do our own padding; do not let it be updated further
|
|
|
|
(setq field-width "")
|
|
|
|
(cond (change-case
|
|
|
|
"") ;discourage %z variations
|
2025-01-24 10:12:58 -08:00
|
|
|
((and (= colon-cnt 0)
|
2021-06-21 21:28:20 -07:00
|
|
|
(not flag-minimize)
|
|
|
|
(not flag-pad-with-spaces)
|
|
|
|
(not flag-pad-with-zeros)
|
|
|
|
(= field-width-num 0))
|
2024-12-14 10:23:04 -08:00
|
|
|
(time-stamp-conv-warn "%z" "%#Z" "%5z")
|
2021-06-21 21:28:20 -07:00
|
|
|
(time-stamp--format "%#Z" time))
|
|
|
|
(t (time-stamp-formatz-from-parsed-options
|
|
|
|
flag-minimize
|
|
|
|
flag-pad-with-spaces
|
|
|
|
flag-pad-with-zeros
|
2025-01-24 10:12:58 -08:00
|
|
|
colon-cnt
|
2021-06-21 21:28:20 -07:00
|
|
|
field-width-num
|
|
|
|
offset-secs)))))
|
2021-05-30 09:08:08 -07:00
|
|
|
((eq cur-char ?Z) ;time zone name
|
2025-01-06 11:00:07 -08:00
|
|
|
(time-stamp-do-letter-case
|
|
|
|
t upcase title-case change-case
|
|
|
|
(time-stamp--format "%Z" time)))
|
2021-05-30 09:08:08 -07:00
|
|
|
((eq cur-char ?f) ;buffer-file-name, base name only
|
|
|
|
(if buffer-file-name
|
2025-01-27 10:44:37 -08:00
|
|
|
(time-stamp-filtered-buffer-file-name :nondirectory)
|
2021-05-30 09:08:08 -07:00
|
|
|
time-stamp-no-file))
|
2021-11-09 20:09:22 -08:00
|
|
|
((eq cur-char ?F) ;buffer-file-name, absolute name
|
2025-01-27 10:44:37 -08:00
|
|
|
(if buffer-file-name
|
|
|
|
(time-stamp-filtered-buffer-file-name :absolute)
|
|
|
|
time-stamp-no-file))
|
2021-05-30 09:08:08 -07:00
|
|
|
((eq cur-char ?s) ;system name, legacy
|
2024-12-10 09:09:39 -08:00
|
|
|
(time-stamp-conv-warn "%s" "%Q")
|
2021-05-30 09:08:08 -07:00
|
|
|
(system-name))
|
|
|
|
((eq cur-char ?u) ;user name, legacy
|
2024-12-10 09:09:39 -08:00
|
|
|
(time-stamp-conv-warn "%u" "%l")
|
2021-05-30 09:08:08 -07:00
|
|
|
(user-login-name))
|
|
|
|
((eq cur-char ?U) ;user full name, legacy
|
2024-12-10 09:09:39 -08:00
|
|
|
(time-stamp-conv-warn "%U" "%L")
|
2021-05-30 09:08:08 -07:00
|
|
|
(user-full-name))
|
|
|
|
((eq cur-char ?l) ;login name
|
|
|
|
(user-login-name))
|
|
|
|
((eq cur-char ?L) ;full name of logged-in user
|
|
|
|
(user-full-name))
|
|
|
|
((eq cur-char ?h) ;mail host name
|
|
|
|
(or mail-host-address (system-name)))
|
2025-01-06 11:00:07 -08:00
|
|
|
((or (eq cur-char ?q) ;unqualified host name
|
|
|
|
(eq cur-char ?x)) ;short system name, experimental
|
|
|
|
(let ((shortname (system-name)))
|
|
|
|
(if (string-match "\\." shortname)
|
|
|
|
(substring shortname 0 (match-beginning 0))
|
|
|
|
shortname)))
|
|
|
|
((or (eq cur-char ?Q) ;fully-qualified host name
|
|
|
|
(eq cur-char ?X)) ;full system name, experimental
|
2021-05-30 09:08:08 -07:00
|
|
|
(system-name))
|
|
|
|
))
|
|
|
|
(and (numberp field-result)
|
2025-01-24 10:12:58 -08:00
|
|
|
(= colon-cnt 0)
|
2024-12-10 09:09:39 -08:00
|
|
|
(or (string-equal field-width "")
|
|
|
|
(string-equal field-width "0"))
|
2021-05-30 09:08:08 -07:00
|
|
|
;; no width provided; set width for default
|
|
|
|
(setq field-width "02"))
|
2024-12-10 09:09:39 -08:00
|
|
|
(format (format "%%%s%c"
|
|
|
|
field-width
|
|
|
|
(if (numberp field-result) ?d ?s))
|
2025-03-12 06:48:55 -07:00
|
|
|
(or field-result "")))))) ;end of handle-one-conversion
|
|
|
|
;; iterate over the format string
|
|
|
|
(while (< ind fmt-len)
|
|
|
|
(setq cur-char (aref format ind))
|
2025-03-12 07:02:44 -07:00
|
|
|
(push (cond ((eq cur-char ?%)
|
|
|
|
(funcall handle-one-conversion))
|
|
|
|
(t
|
|
|
|
(char-to-string cur-char)))
|
|
|
|
result)
|
1997-06-08 21:43:08 +00:00
|
|
|
(setq ind (1+ ind)))
|
2025-03-12 07:02:44 -07:00
|
|
|
(apply #'concat (nreverse result))))
|
1997-06-08 21:43:08 +00:00
|
|
|
|
2025-01-06 11:00:07 -08:00
|
|
|
(defun time-stamp-do-letter-case (change-is-downcase
|
|
|
|
upcase title-case change-case text)
|
|
|
|
"Apply upper- and lower-case conversions to TEXT according to the flags.
|
|
|
|
CHANGE-IS-DOWNCASE non-nil indicates that modifier CHANGE-CASE requests
|
|
|
|
lowercase, otherwise the modifier requests uppercase.
|
|
|
|
UPCASE is non-nil if the \"^\" modifier is active.
|
|
|
|
TITLE-CASE is non-nil if the \"*\" modifier is active.
|
|
|
|
CHANGE-CASE is non-nil if the \"#\" modifier is active.
|
|
|
|
This is an internal helper for `time-stamp-string-preprocess'."
|
|
|
|
(cond ((and upcase change-case)
|
|
|
|
(downcase text))
|
|
|
|
((and title-case change-case)
|
|
|
|
(upcase text))
|
|
|
|
((and change-is-downcase change-case)
|
|
|
|
(downcase text))
|
|
|
|
((or change-case upcase)
|
|
|
|
(upcase text))
|
|
|
|
(title-case
|
|
|
|
(capitalize text))
|
|
|
|
(t
|
|
|
|
text)))
|
|
|
|
|
2025-01-24 10:12:58 -08:00
|
|
|
(defun time-stamp-do-number (format-char colon-count field-width time)
|
2001-01-26 23:04:44 +00:00
|
|
|
"Handle compatible FORMAT-CHAR where only default width/padding will change.
|
2025-01-24 10:12:58 -08:00
|
|
|
COLON-COUNT is non-0 if \":\" was specified. FIELD-WIDTH is the string
|
2021-08-23 20:04:02 -07:00
|
|
|
width specification or \"\". TIME is the time to convert.
|
|
|
|
This is an internal helper for `time-stamp-string-preprocess'."
|
1997-06-08 21:43:08 +00:00
|
|
|
(let ((format-string (concat "%" (char-to-string format-char))))
|
2025-01-24 10:12:58 -08:00
|
|
|
(if (and (> colon-count 0) (not (string-equal field-width "")))
|
1997-06-08 21:43:08 +00:00
|
|
|
"" ;discourage "%:2d" and the like
|
2016-01-12 09:09:27 -08:00
|
|
|
(string-to-number (time-stamp--format format-string time)))))
|
1997-06-08 21:43:08 +00:00
|
|
|
|
2025-01-27 10:44:37 -08:00
|
|
|
(defun time-stamp-filtered-buffer-file-name (type)
|
|
|
|
"Return the buffer file name, but with non-graphic characters replaced by ?.
|
|
|
|
TYPE is :absolute for the full name or :nondirectory for base name only."
|
|
|
|
(declare (ftype (function ((member :absolute :nondirectory)) string)))
|
|
|
|
(let ((file-name buffer-file-name)
|
|
|
|
(safe-character-filter
|
|
|
|
(lambda (chr)
|
|
|
|
(let ((category (get-char-code-property chr 'general-category)))
|
|
|
|
(if (or
|
|
|
|
;; Letter, Mark, Number, Punctuation, or Symbol
|
|
|
|
(member (aref (symbol-name category) 0) '(?L ?M ?N ?P ?S))
|
|
|
|
;; spaces of various widths, but not ctrl chars like CR or LF
|
|
|
|
(eq category 'Zs))
|
|
|
|
chr
|
|
|
|
;; substitute "?" for format or control character
|
|
|
|
??)))))
|
|
|
|
(when (eq type :nondirectory)
|
|
|
|
(setq file-name (file-name-nondirectory file-name)))
|
|
|
|
(apply #'string (mapcar safe-character-filter file-name))))
|
|
|
|
|
2021-09-26 08:23:29 -07:00
|
|
|
|
1997-06-08 21:43:08 +00:00
|
|
|
(defvar time-stamp-conversion-warn t
|
2021-08-23 20:04:02 -07:00
|
|
|
"Enable warnings about soon-to-be-unsupported forms in `time-stamp-format'.
|
2000-10-13 11:30:53 +00:00
|
|
|
If nil, these warnings are disabled, which would be a bad idea!
|
1997-06-08 21:43:08 +00:00
|
|
|
You really need to update your files instead.
|
|
|
|
|
|
|
|
The new formats will work with old versions of Emacs.
|
1999-08-27 01:47:33 +00:00
|
|
|
New formats are being recommended now to allow `time-stamp-format'
|
|
|
|
to change in the future to be compatible with `format-time-string'.
|
1997-06-08 21:43:08 +00:00
|
|
|
The new forms being recommended now will continue to work then.")
|
|
|
|
|
|
|
|
|
2024-12-14 10:23:04 -08:00
|
|
|
(defun time-stamp-conv-warn (old-form new-form &optional standard-form)
|
Update example date in preamble commentary.
(time-stamp): Fix parsing of "%%a" in time-stamp-pattern (change
regexp subpattern 5)
(time-stamp-pattern): Initialize to nil to avoid regexp work in
default case.
(time-stamp-string): Call set-time-zone-rule instead of setenv
(time-stamp-hhmmss): Remove (not needed after all).
(time-stamp-month-dd-yyyy, time-stamp-dd/mm/yyyy,
time-stamp-mon-dd-yyyy, time-stamp-dd-mon-yy, time-stamp-yy/mm/dd,
time-stamp-yyyy/mm/dd, time-stamp-yyyy-mm-dd, time-stamp-yymmdd,
time-stamp-hh:mm:ss, time-stamp-hhmm): Make obsolete.
(time-stamp-format, time-stamp-pattern, time-stamp-warn-inactive,
time-stamp-inserts-lines, time-stamp-count, time-stamp-time-zone,
time-stamp, time-stamp-toggle-active, time-stamp-string-preprocess,
time-stamp-once, time-stamp-conv-warn): Tweak doc strings.
2003-02-01 14:29:31 +00:00
|
|
|
"Display a warning about a soon-to-be-obsolete format.
|
2024-12-14 10:23:04 -08:00
|
|
|
Suggests replacing OLD-FORM with NEW-FORM (same effect, but stable)
|
|
|
|
or (if provided) STANDARD-FORM (the effect the user may have expected
|
|
|
|
if they didn't read the documentation)."
|
1997-06-08 21:43:08 +00:00
|
|
|
(cond
|
|
|
|
(time-stamp-conversion-warn
|
* x-dnd.el (x-dnd-maybe-call-test-function):
* window.el (split-window-vertically):
* whitespace.el (whitespace-help-on):
* vc-rcs.el (vc-rcs-consult-headers):
* userlock.el (ask-user-about-lock-help)
(ask-user-about-supersession-help):
* type-break.el (type-break-force-mode-line-update):
* time-stamp.el (time-stamp-conv-warn):
* terminal.el (te-set-output-log, te-more-break, te-filter)
(te-sentinel,terminal-emulator):
* term.el (make-term, term-exec, term-sentinel, term-read-input-ring)
(term-write-input-ring, term-check-source, term-start-output-log):
(term-display-buffer-line, term-dynamic-list-completions):
(term-ansi-make-term, serial-term):
* subr.el (selective-display):
* strokes.el (strokes-xpm-to-compressed-string, strokes-decode-buffer)
(strokes-encode-buffer, strokes-xpm-for-compressed-string):
* speedbar.el (speedbar-buffers-tail-notes, speedbar-buffers-item-info)
(speedbar-reconfigure-keymaps, speedbar-add-localized-speedbar-support)
(speedbar-remove-localized-speedbar-support)
(speedbar-set-mode-line-format, speedbar-create-tag-hierarchy)
(speedbar-update-special-contents, speedbar-buffer-buttons-engine)
(speedbar-buffers-line-directory):
* simple.el (shell-command-on-region, append-to-buffer)
(prepend-to-buffer):
* shadowfile.el (shadow-save-todo-file):
* scroll-bar.el (scroll-bar-set-window-start, scroll-bar-drag-1)
(scroll-bar-maybe-set-window-start):
* sb-image.el (speedbar-image-dump):
* saveplace.el (save-place-alist-to-file, save-places-to-alist)
(load-save-place-alist-from-file):
* ps-samp.el (ps-print-message-from-summary):
* ps-print.el (ps-flush-output, ps-insert-file, ps-get-boundingbox)
(ps-background-image, ps-begin-job, ps-do-despool):
* ps-bdf.el (bdf-find-file, bdf-read-font-info):
* printing.el (pr-interface, pr-ps-file-print, pr-find-buffer-visiting)
(pr-ps-message-from-summary, pr-lpr-message-from-summary):
(pr-call-process, pr-file-list, pr-interface-save):
* novice.el (disabled-command-function)
(enable-command, disable-command):
* mouse.el (mouse-buffer-menu-alist):
* mouse-copy.el (mouse-kill-preserving-secondary):
* macros.el (kbd-macro-query):
* ledit.el (ledit-go-to-lisp, ledit-go-to-liszt):
* informat.el (batch-info-validate):
* ido.el (ido-copy-current-word, ido-initiate-auto-merge):
* hippie-exp.el (try-expand-dabbrev-visible):
* help-mode.el (help-make-xrefs):
* help-fns.el (describe-variable):
* generic-x.el (bat-generic-mode-run-as-comint):
* finder.el (finder-mouse-select):
* find-dired.el (find-dired-sentinel):
* filesets.el (filesets-file-close):
* files.el (list-directory):
* faces.el (list-faces-display, describe-face):
* facemenu.el (list-colors-display):
* ezimage.el (ezimage-image-association-dump, ezimage-image-dump):
* epg.el (epg--process-filter, epg-cancel):
* epa.el (epa--marked-keys, epa--select-keys, epa-display-info)
(epa--read-signature-type):
* emerge.el (emerge-copy-as-kill-A, emerge-copy-as-kill-B)
(emerge-file-names):
* ehelp.el (electric-helpify):
* ediff.el (ediff-regions-wordwise, ediff-regions-linewise):
* ediff-vers.el (rcs-ediff-view-revision):
* ediff-util.el (ediff-setup):
* ediff-mult.el (ediff-append-custom-diff):
* ediff-diff.el (ediff-exec-process, ediff-process-sentinel)
(ediff-wordify):
* echistory.el (Electric-command-history-redo-expression):
* dos-w32.el (find-file-not-found-set-buffer-file-coding-system):
* disp-table.el (describe-display-table):
* dired.el (dired-find-buffer-nocreate):
* dired-aux.el (dired-rename-subdir, dired-dwim-target-directory):
* dabbrev.el (dabbrev--same-major-mode-p):
* chistory.el (list-command-history):
* apropos.el (apropos-documentation):
* allout.el (allout-obtain-passphrase):
(allout-copy-exposed-to-buffer):
(allout-verify-passphrase): Use with-current-buffer.
2009-11-13 22:19:45 +00:00
|
|
|
(with-current-buffer (get-buffer-create "*Time-stamp-compatibility*")
|
1997-06-08 21:43:08 +00:00
|
|
|
(goto-char (point-max))
|
2024-12-14 10:23:04 -08:00
|
|
|
(cond
|
|
|
|
((bobp)
|
|
|
|
(insert
|
|
|
|
(substitute-quotes
|
|
|
|
(concat
|
|
|
|
"The conversions recognized in `time-stamp-format' will change in a future\n"
|
|
|
|
"release to be more compatible with the function `format-time-string'.\n"
|
|
|
|
(cond
|
|
|
|
(standard-form
|
|
|
|
(concat
|
|
|
|
"Conversions that are changing are ambiguous and should be replaced by\n"
|
2025-01-08 10:24:55 -08:00
|
|
|
"stable conversions that make your intention clear.\n")))
|
2024-12-14 10:23:04 -08:00
|
|
|
"\n"
|
|
|
|
"The following obsolescent `time-stamp-format' conversion(s) were found:\n\n")))))
|
|
|
|
(insert old-form " -- use " new-form)
|
|
|
|
(if standard-form
|
|
|
|
(insert " or " standard-form))
|
|
|
|
(insert "\n")
|
|
|
|
(help-make-xrefs))
|
1997-06-08 21:43:08 +00:00
|
|
|
(display-buffer "*Time-stamp-compatibility*"))))
|
1997-08-24 03:32:38 +00:00
|
|
|
|
2021-09-26 08:23:29 -07:00
|
|
|
|
2021-06-21 21:28:20 -07:00
|
|
|
;;; A principled, expressive implementation of time zone offset
|
|
|
|
;;; formatting ("%z" and variants).
|
|
|
|
|
|
|
|
;;; * Overarching principle for %z
|
|
|
|
|
|
|
|
;; The output should be clear and complete.
|
|
|
|
;;
|
|
|
|
;; That is,
|
|
|
|
;; a) it should be unambiguous what offset is represented, and
|
|
|
|
;; b) it should be possible to exactly recreate the offset.
|
|
|
|
|
|
|
|
;;; * Principles for %z
|
|
|
|
|
|
|
|
;; - The numeric fields are HHMMSS.
|
|
|
|
;; - The fixed point is at the left. The first 2 digits are always
|
|
|
|
;; hours, the next 2 (if they exist) minutes, and next 2 (if they
|
|
|
|
;; exist) seconds. "+11" is 11 hours (not 11 minutes, not 11 seconds).
|
|
|
|
;; "+1015" is 10 hours 15 minutes (not 10 minutes 15 seconds).
|
|
|
|
;; - Each of the three numeric fields is two digits.
|
|
|
|
;; "+1" and "+100" are illegal. (Is that 1 hour? 10 hours? 100 hours?)
|
|
|
|
;; - The MMSS fields may be omitted only if both are 00. Thus, the width
|
|
|
|
;; of the field depends on the data. (This is similar to how
|
|
|
|
;; %B is always long enough to spell the entire month name.)
|
|
|
|
;; - The SS field may be omitted only if it is 00.
|
|
|
|
;; - Colons between the numeric fields are an option, unless the hours
|
|
|
|
;; field is greater than 99, when colons are needed to prevent ambiguity.
|
|
|
|
;; - If padding with zeros, we must pad on the right, because the
|
|
|
|
;; fixed point is at the left. (This is similar to how %N,
|
|
|
|
;; fractional seconds, must add its zeros on the right.)
|
|
|
|
;; - After zero-padding has filled out minutes and seconds with zeros,
|
|
|
|
;; further padding can be blanks only.
|
|
|
|
;; Any additional zeros would be confusing.
|
|
|
|
|
|
|
|
;;; * Padding for %z
|
|
|
|
|
|
|
|
;; Padding is under-specified, so we had to make choices.
|
|
|
|
;;
|
|
|
|
;; Principles guiding our choices:
|
|
|
|
;;
|
|
|
|
;; - The syntax should be easy to remember and the effect predictable.
|
2021-08-23 20:04:02 -07:00
|
|
|
;; - The syntax should enable as many useful effects as possible.
|
2021-06-21 21:28:20 -07:00
|
|
|
;;
|
|
|
|
;; Padding choices:
|
|
|
|
;;
|
|
|
|
;; - By default, pad with spaces, as other formats with non-digits do.
|
|
|
|
;; The "0" flag pads first with zeros, until seconds are filled out.
|
|
|
|
;; - If padding with spaces, pad on the right. This is consistent with
|
|
|
|
;; how zero-padding works. Padding on the right also keeps the fixed
|
|
|
|
;; point in the same place, as other formats do for any given width.
|
|
|
|
;; - The %_z format always outputs seconds, allowing all added padding
|
|
|
|
;; to be spaces. Without this rule, there would be no way to
|
|
|
|
;; request seconds that worked for both 2- and 3-digit hours.
|
2024-11-01 09:32:27 -07:00
|
|
|
;; (We consider 3-digit hours not because such offsets are in use but
|
|
|
|
;; instead to guide our design toward consistency and extensibility.)
|
2021-06-21 21:28:20 -07:00
|
|
|
;; - Conflicting options are rejected, lest users depend
|
|
|
|
;; on incidental behavior.
|
|
|
|
;;
|
|
|
|
;; Padding combos that make no sense and are thus disallowed:
|
|
|
|
;;
|
|
|
|
;; %-:z - minus minimizes to hours, : expands to minutes
|
|
|
|
;; %-::z - minus minimizes to hours, :: expands to seconds
|
|
|
|
;; %_:z - underscore requires seconds, : displays minutes
|
|
|
|
;; %_:::z - underscore requires seconds, ::: minimizes to hours
|
|
|
|
;;
|
|
|
|
;; Example padding effects (with offsets of 99 and 100 hours):
|
|
|
|
;;
|
|
|
|
;; %-7z "+99 " "+100:00"
|
|
|
|
;; %7z "+9900 " "+100:00"
|
|
|
|
;; %07z "+990000" "+100:00"
|
|
|
|
;; %_7z "+990000" "+100:00:00"
|
|
|
|
;;
|
|
|
|
;; %7:::z "+99 " "+100:00"
|
|
|
|
;; %7:z "+99:00 " "+100:00"
|
|
|
|
;; %07:z "+99:00:00" "+100:00"
|
|
|
|
;; %7::z "+99:00:00" "+100:00:00"
|
|
|
|
|
2021-08-23 20:04:02 -07:00
|
|
|
;;; * ABNF syntax of the offset string produced by %z
|
|
|
|
|
2021-09-26 08:23:29 -07:00
|
|
|
;; offset = sign ( hours [minutes [seconds]] /
|
|
|
|
;; hours [":" minutes [":" seconds]] /
|
|
|
|
;; bighours ":" minutes [":" seconds] ) padding
|
2021-08-23 20:04:02 -07:00
|
|
|
;; sign = "+" / "-"
|
|
|
|
;; hours = digitpair
|
|
|
|
;; minutes = digitpair
|
|
|
|
;; seconds = digitpair
|
|
|
|
;; digitpair = digit digit
|
|
|
|
;; digit = "0" / "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9"
|
|
|
|
;; bighours = 1*digit digitpair
|
|
|
|
;; padding = *" "
|
2021-06-21 21:28:20 -07:00
|
|
|
|
|
|
|
(defun time-stamp-formatz-from-parsed-options (flag-minimize
|
|
|
|
flag-pad-spaces-only
|
|
|
|
flag-pad-zeros-first
|
|
|
|
colon-count
|
|
|
|
field-width
|
|
|
|
offset-secs)
|
2024-11-01 09:32:27 -07:00
|
|
|
"Format a time offset according to a %z variation.
|
2021-06-21 21:28:20 -07:00
|
|
|
|
|
|
|
With no flags, the output includes hours and minutes: +-HHMM
|
|
|
|
unless there is a non-zero seconds part, in which case the seconds
|
|
|
|
are included: +-HHMMSS
|
|
|
|
|
|
|
|
FLAG-MINIMIZE is whether \"-\" was specified. If non-nil, the
|
|
|
|
output may be limited to hours if minutes and seconds are zero.
|
|
|
|
|
|
|
|
FLAG-PAD-SPACES-ONLY is whether \"_\" was specified. If non-nil,
|
|
|
|
seconds must be output, so that any padding can be spaces only.
|
|
|
|
|
|
|
|
FLAG-PAD-ZEROS-FIRST is whether \"0\" was specified. If non-nil,
|
|
|
|
padding to the requested FIELD-WIDTH (if any) is done by adding
|
|
|
|
00 seconds before padding with spaces.
|
|
|
|
|
|
|
|
COLON-COUNT is the number of colons preceding the \"z\" (0-3). One or
|
|
|
|
two colons put that many colons in the output (+-HH:MM or +-HH:MM:SS).
|
|
|
|
Three colons outputs only hours if minutes and seconds are zero and
|
|
|
|
includes colon separators if minutes and seconds are output.
|
|
|
|
|
|
|
|
FIELD-WIDTH is a whole number giving the minimum number of characters
|
|
|
|
in the output; 0 specifies no minimum. Additional characters will be
|
|
|
|
added on the right if necessary. The added characters will be spaces
|
|
|
|
unless FLAG-PAD-ZEROS-FIRST is non-nil.
|
|
|
|
|
|
|
|
OFFSET-SECS is the time zone offset (in seconds east of UTC) to be
|
2021-09-26 08:23:29 -07:00
|
|
|
formatted according to the preceding parameters.
|
|
|
|
|
|
|
|
This is an internal function used by `time-stamp'."
|
2024-12-10 09:09:39 -08:00
|
|
|
;; Callers of this function need to have already parsed the %z
|
2021-09-26 08:23:29 -07:00
|
|
|
;; format string; this function accepts just the parts of the format.
|
|
|
|
;; `time-stamp-string-preprocess' is the full-fledged parser normally
|
|
|
|
;; used. The unit test (in time-stamp-tests.el) defines the simpler
|
|
|
|
;; parser `format-time-offset'.
|
2021-06-21 21:28:20 -07:00
|
|
|
(let ((hrs (/ (abs offset-secs) 3600))
|
|
|
|
(mins (/ (% (abs offset-secs) 3600) 60))
|
|
|
|
(secs (% (abs offset-secs) 60))
|
|
|
|
(result ""))
|
|
|
|
;; valid option combo?
|
|
|
|
(cond
|
|
|
|
((not (or (and flag-minimize (> colon-count 0))
|
|
|
|
(and flag-pad-spaces-only (> colon-count 0))
|
|
|
|
(and flag-pad-spaces-only flag-minimize)
|
|
|
|
(and flag-pad-spaces-only flag-pad-zeros-first)
|
|
|
|
(and flag-pad-zeros-first flag-minimize)))
|
|
|
|
(setq result (concat result (if (>= offset-secs 0) "+" "-")))
|
|
|
|
(setq result (concat result (format "%02d" hrs)))
|
|
|
|
;; Need minutes?
|
|
|
|
(cond
|
|
|
|
((or (> hrs 99)
|
|
|
|
(> mins 0)
|
|
|
|
(> secs 0)
|
|
|
|
(not (or flag-minimize (= colon-count 3)))
|
|
|
|
(and (> field-width (length result))
|
|
|
|
flag-pad-zeros-first))
|
|
|
|
;; Need colon before minutes?
|
|
|
|
(if (or (> colon-count 0)
|
|
|
|
(> hrs 99))
|
|
|
|
(setq result (concat result ":")))
|
|
|
|
(setq result (concat result (format "%02d" mins)))
|
|
|
|
;; Need seconds, too?
|
|
|
|
(cond
|
|
|
|
((or (> secs 0)
|
|
|
|
(= colon-count 2)
|
|
|
|
flag-pad-spaces-only
|
|
|
|
(and (> field-width (length result))
|
|
|
|
flag-pad-zeros-first))
|
|
|
|
;; Need colon before seconds?
|
|
|
|
(if (or (> colon-count 0)
|
|
|
|
(> hrs 99))
|
|
|
|
(setq result (concat result ":")))
|
|
|
|
(setq result (concat result (format "%02d" secs)))))))
|
|
|
|
;; Need padding?
|
|
|
|
(let ((needed-padding (- field-width (length result))))
|
|
|
|
(if (> needed-padding 0)
|
|
|
|
(setq result (concat result (make-string needed-padding ?\s)))))))
|
|
|
|
result))
|
|
|
|
|
1993-06-21 05:05:59 +00:00
|
|
|
(provide 'time-stamp)
|
|
|
|
|
|
|
|
;;; time-stamp.el ends here
|