Backport expansion of Time Stamp documentation

* doc/emacs/files.texi (Time Stamps): Add examples of enabling
time stamping with add-hook, setting time-stamp-pattern as a
file-local variable, and showing a time stamp at the end of a
file.  Divide into three sections.
* doc/emacs/emacs.texi: Add new nodes to menu.
* lisp/info.el (Info-file-list-for-emacs): Remove entry that
points Info at time-stamp discussion in the Autotype document.
* lisp/time-stamp.el (time-stamp-format, time-stamp-active,
time-stamp-count, time-stamp-pattern, time-stamp, time-stamp-string):
Expand doc strings.  Include Info cross-references.

Cherry picked from commits on the main branch.
Do not merge to master.
This commit is contained in:
Stephen Gildea 2025-03-30 11:39:53 -07:00
parent 38fec86281
commit 43c9eb3df6
4 changed files with 186 additions and 51 deletions

View file

@ -486,6 +486,11 @@ Backup Files
* Backup Deletion:: Emacs deletes excess numbered backups. * Backup Deletion:: Emacs deletes excess numbered backups.
* Backup Copying:: Backups can be made by copying or renaming. * Backup Copying:: Backups can be made by copying or renaming.
Updating Time Stamps Automatically
* Time Stamp Customization:: How to customize with time-stamp-pattern.
* Time Stamps for One File:: Ensure automatic time-stamp of a specific file.
@ifnottex @ifnottex
Auto Reverting Non-File Buffers Auto Reverting Non-File Buffers

View file

@ -411,7 +411,7 @@ that was visited in the buffer.
* Interlocking:: How Emacs protects against simultaneous editing * Interlocking:: How Emacs protects against simultaneous editing
of one file by two users. of one file by two users.
* Shadowing: File Shadowing. Copying files to ``shadows'' automatically. * Shadowing: File Shadowing. Copying files to ``shadows'' automatically.
* Time Stamps:: Emacs can update time stamps on saved files. * Time Stamps:: Emacs can update time stamps when a file is saved.
@end menu @end menu
@node Save Commands @node Save Commands
@ -992,35 +992,152 @@ File Shadowing is not available on MS Windows.
@node Time Stamps @node Time Stamps
@subsection Updating Time Stamps Automatically @subsection Updating Time Stamps Automatically
@cindex time stamps @cindex time stamps, automatic file timestamps
@cindex modification dates @cindex modification dates
@cindex locale, date format @cindex last modified time
You can arrange to put a time stamp in a file, so that it is updated You can arrange to have a time stamp in a file be updated
automatically each time you edit and save the file. The time stamp automatically each time you save the file.
must be in the first eight lines of the file, and you should insert it (A time stamp may also be called a date stamp or a last modified time.)
like this: Having a time stamp in the text of a file ensures that the time the file
was written will be preserved even if the file is copied or transformed
in a way that loses the file system's modification time.
There are two steps to setting up automatic time stamping.
First, the file needs a time stamp template
somewhere in the first eight lines.
The template looks like this:
@example @example
Time-stamp: <> Time-stamp: <>
@end example @end example
@noindent @noindent
or like this: or (your choice) like this:
@example @example
Time-stamp: " " Time-stamp: " "
@end example @end example
@findex time-stamp @findex time-stamp
Then add the function @code{time-stamp} to the hook With that template in place, you can update the current buffer's time
@code{before-save-hook} (@pxref{Hooks}). When you save the file, this stamp once immediately with the command @kbd{M-x time-stamp}.
function then automatically updates the time stamp with the current Emacs will check for a template; if a template is found,
date and time. You can also use the command @kbd{M-x time-stamp} to Emacs will write the current date, time, author, and/or
update the time stamp manually. By default the time stamp is other info between the brackets or quotes.
(If the buffer has no template, @code{time-stamp} does nothing.)
After the first time stamp, the line might look like this:
@example
Time-stamp: <1993-07-06 11:05:14 terryg>
@end example
Second, configure Emacs to run @code{time-stamp} any time it saves a
file, by adding @code{time-stamp}
to @code{before-save-hook} (@pxref{Hooks}).
You can either customize the option @code{before-save-hook}
(with @kbd{M-x customize-option}, @pxref{Specific Customization}),
or you can edit your init file adding this line:
@example
(add-hook 'before-save-hook 'time-stamp)
@end example
@menu
* Time Stamp Customization:: How to customize with time-stamp-pattern.
* Time Stamps for One File:: Ensure automatic time-stamp of a specific file.
@end menu
@node Time Stamp Customization
@subsubsection Customizing the Time Stamp
@vindex time-stamp-pattern
To customize the time stamp in a particular file, set the
variable @code{time-stamp-pattern} in that file's local variables
list (@pxref{Specifying File Variables}).
You can change what pattern @code{time-stamp} will match against to
identify a template and where in the file to look for the pattern using
@code{time-stamp-pattern}; for details, see the variable's built-in
documentation (with @kbd{C-h v}, @pxref{Name Help}).
As a simple example, if this line occurs near the top of a file:
@example
publishing_year_and_city = "Published nnnn in Boston, Mass.";
@end example
@noindent
then the following comment at the end of the same file tells
@code{time-stamp} how to identify and update that custom template:
@example
@group
// Local variables:
// time-stamp-pattern: "Published %Y in Boston"
// End:
@end group
@end example
This pattern says that the text before the start of the time stamp is
``Published '', and the text after the end is `` in Boston''.
If @code{time-stamp} finds both in one of the first eight lines,
what is between will be replaced by the current year, as requested by
the @code{%Y} format.
After any change to file-local variables,
type @kbd{M-x normal-mode} to re-read them.
Here is another example, with the time stamp inserted into
the last paragraph of an HTML document.
Since this template is at the end of the document, not in the first
eight lines, @code{time-stamp-format} starts with @code{-10/} to tell
@code{time-stamp} to look at the last 10 lines.
The @code{%%} asks for the default format
(specified by @code{time-stamp-format}).
@example
@r{@dots{}}
<p>Last modified: </p>
</body>
</html>
<!--
Local variables:
time-stamp-pattern: "-10/Last modified: %%</p>$"
End:
-->
@end example
@vindex time-stamp-format
By default the time stamp is
formatted according to your locale setting (@pxref{Environment}) and formatted according to your locale setting (@pxref{Environment}) and
time zone (@pxref{Time of Day,,, elisp, The Emacs Lisp Reference time zone (@pxref{Time of Day,,, elisp, The Emacs Lisp Reference
Manual}). For customizations, see the Custom group @code{time-stamp}. Manual}).
See the built-in documentation for the variable @code{time-stamp-format}
for specifics and other variables that affect the formatting.
@node Time Stamps for One File
@subsubsection Forcing Time Stamps for One File
If you are working on a file with multiple authors, and you cannot
be sure the other authors have enabled time-stamping globally in
their Emacs init files, you can force it to be enabled for a
particular file by adding @code{time-stamp} to that buffer's
@code{before-save-hook} in that file's local variables list.
To extend one of the previous examples:
@example
@group
// Local variables:
// eval: (add-hook 'before-save-hook 'time-stamp nil t)
// time-stamp-pattern: "Published %Y in Boston"
// End:
@end group
@end example
@noindent
Although this example shows them both set together,
you can use @code{eval} without also setting @code{time-stamp-pattern}
if you like the default pattern.
@node Reverting @node Reverting
@section Reverting a Buffer @section Reverting a Buffer

View file

@ -4666,7 +4666,6 @@ Advanced commands:
("java" . "ccmode") ("idl" . "ccmode") ("pike" . "ccmode") ("java" . "ccmode") ("idl" . "ccmode") ("pike" . "ccmode")
("skeleton" . "autotype") ("auto-insert" . "autotype") ("skeleton" . "autotype") ("auto-insert" . "autotype")
("copyright" . "autotype") ("executable" . "autotype") ("copyright" . "autotype") ("executable" . "autotype")
("time-stamp" . "autotype")
("tempo" . "autotype") ("hippie-expand" . "autotype") ("tempo" . "autotype") ("hippie-expand" . "autotype")
("cvs" . "pcl-cvs") ("ada" . "ada-mode") "calc" ("cvs" . "pcl-cvs") ("ada" . "ada-mode") "calc"
("calcAlg" . "calc") ("calcDigit" . "calc") ("calcVar" . "calc") ("calcAlg" . "calc") ("calcDigit" . "calc") ("calcVar" . "calc")

View file

@ -31,8 +31,8 @@
;; (add-hook 'before-save-hook 'time-stamp) ;; (add-hook 'before-save-hook 'time-stamp)
;; Now any time-stamp templates in your files will be updated automatically. ;; Now any time-stamp templates in your files will be updated automatically.
;; See the documentation for the functions `time-stamp' ;; For details, see the documentation for function `time-stamp'
;; and `time-stamp-toggle-active' for details. ;; and the Info node `Time Stamps'.
;;; Code: ;;; Code:
@ -64,7 +64,7 @@ with %, as follows.
%5z time zone offset: `-0500' (since Emacs 27; see note below) %5z time zone offset: `-0500' (since Emacs 27; see note below)
Non-date items: Non-date items:
%% a literal percent character: `%' %% literal percent character: \"%\"
%f file name without directory %F absolute file name %f file name without directory %F absolute file name
%l login name %L full name of logged-in user %l login name %L full name of logged-in user
%q unqualified host name %Q fully-qualified host name %q unqualified host name %Q fully-qualified host name
@ -74,12 +74,12 @@ Decimal digits between the % and the type character specify the
field width. Strings are truncated on the right. field width. Strings are truncated on the right.
A leading zero in the field width zero-fills a number. A leading zero in the field width zero-fills a number.
For example, to get the format used by the `date' command, For example, to get a common format used by the \"date\" command,
use \"%3a %3b %2d %02H:%02M:%02S %Z %Y\". use \"%3a %3b %2d %02H:%02M:%02S %Z %Y\".
The values of non-numeric formatted items depend on the locale The values of non-numeric formatted items depend on the locale
setting recorded in `system-time-locale' and `locale-coding-system'. setting recorded in `system-time-locale' and `locale-coding-system'.
The examples here are for the default (`C') locale. The examples here are for the default (\"C\") locale.
`time-stamp-time-zone' controls the time zone used. `time-stamp-time-zone' controls the time zone used.
The default padding of some formats has changed to be more compatible The default padding of some formats has changed to be more compatible
@ -95,7 +95,7 @@ edited by older versions of Emacs also, do not use this format yet."
(defcustom time-stamp-active t (defcustom time-stamp-active t
"Non-nil to enable time-stamping of buffers by \\[time-stamp]. "Non-nil enables time-stamping of buffers by \\[time-stamp].
Can be toggled by \\[time-stamp-toggle-active]. Can be toggled by \\[time-stamp-toggle-active].
This option does not affect when `time-stamp' is run, only what it This option does not affect when `time-stamp' is run, only what it
@ -229,7 +229,11 @@ your init file, you would be incompatible with other people's files.")
(defvar time-stamp-count 1 ;Do not change! (defvar time-stamp-count 1 ;Do not change!
"How many templates \\[time-stamp] will look for in a buffer. "How many templates \\[time-stamp] will look for in a buffer.
The same time stamp will be written in each case.
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'.
`time-stamp-count' is best changed with a file-local variable. `time-stamp-count' is best changed with a file-local variable.
If you were to change it in your init file, you would be incompatible If you were to change it in your init file, you would be incompatible
@ -240,55 +244,61 @@ with other people's files.")
(defvar time-stamp-pattern nil ;Do not change! (defvar time-stamp-pattern nil ;Do not change!
"Convenience variable setting all `time-stamp' location and format values. "Convenience variable setting all `time-stamp' location and format values.
This string has four parts, each of which is optional. This string has four parts, each of which is optional.
These four parts set `time-stamp-line-limit', `time-stamp-start', These four parts override `time-stamp-line-limit', `time-stamp-start',
`time-stamp-format', and `time-stamp-end'. See the documentation `time-stamp-format' and `time-stamp-end', respectively. See the
for each of these variables for details. documentation for each of these variables for details.
The first part is a number followed by a slash; the number sets the number 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 of lines at the beginning (negative counts from end) of the file searched
for the time stamp. The number and the slash may be omitted to use the for the time stamp. The number and the slash may be omitted to use the
normal value. value of `time-stamp-line-limit' as the number.
The second part is a regexp identifying the pattern preceding the time stamp. The second part is a regexp identifying the pattern preceding the time stamp.
This part may be omitted to use the normal pattern. This part may be omitted to use the value of `time-stamp-start'.
The third part specifies the format of the time stamp inserted. See The third part specifies the format of the time stamp inserted. Specify
the documentation for `time-stamp-format' for details. Specify this this part as \"%%\" to use the value of `time-stamp-format'.
part as \"%%\" to use the normal format.
The fourth part is a regexp identifying the pattern following the time stamp. The fourth part is a regexp identifying the pattern following the time stamp.
This part may be omitted to use the normal pattern. This part may be omitted to use the value of `time-stamp-end'.
The pattern does not need to match the entire line of the time stamp. The pattern does not need to match the entire line of the time stamp.
The pattern will update time stamp information on multiple lines if the
pattern includes newlines, which can be written as \"\\n\".
These variables are best changed with file-local variables. These variables are best changed with file-local variables.
If you were to change `time-stamp-pattern', `time-stamp-line-limit', If you were to change `time-stamp-pattern', `time-stamp-line-limit',
`time-stamp-start', or `time-stamp-end' in your init file, you `time-stamp-start', or `time-stamp-end' in your init file, you
would be incompatible with other people's files. would be incompatible with other people's files.
See also `time-stamp-count' and `time-stamp-inserts-lines'.
Examples: Examples:
\"-10/\" (sets only `time-stamp-line-limit') ;; time-stamp-pattern: \"-10/\"
(sets only `time-stamp-line-limit')
\"-9/^Last modified: %%$\" (sets `time-stamp-line-limit', // time-stamp-pattern: \"-9/^Last modified: %%$\"
`time-stamp-start' and `time-stamp-end') (sets `time-stamp-line-limit', `time-stamp-start' and `time-stamp-end')
\"@set Time-stamp: %:B %1d, %Y$\" (sets `time-stamp-start', @c time-stamp-pattern: \"@set Time-stamp: %:B %1d, %Y$\"
`time-stamp-format' and `time-stamp-end') (sets `time-stamp-start', `time-stamp-format' and `time-stamp-end')
\"newcommand{\\\\\\\\timestamp}{%%}\" (sets `time-stamp-start' %% time-stamp-pattern: \"newcommand{\\\\\\\\timestamp}{%%}\"
and `time-stamp-end')") (sets `time-stamp-start' and `time-stamp-end')
See Info node `Time Stamp Customization' for more discussion and more
in-depth examples.
See also `time-stamp-count' and `time-stamp-inserts-lines'.")
;;;###autoload(put 'time-stamp-pattern 'safe-local-variable 'stringp) ;;;###autoload(put 'time-stamp-pattern 'safe-local-variable 'stringp)
;;;###autoload ;;;###autoload
(defun time-stamp () (defun time-stamp ()
"Update any time stamp string(s) in the buffer. "Update any time stamp strings (timestamps) in the buffer.
This function looks for a time stamp template and updates it with Look for a time stamp template and update it with the current
the current date, time, and/or other info. date, time, author, and/or other info.
The template, which you manually create on one of the first 8 lines 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 of the file before running this function, by default can look like
@ -311,12 +321,11 @@ To enable automatic time-stamping for only a specific file, add
this line to a local variables list near the end of the file: this line to a local variables list near the end of the file:
eval: (add-hook \\='before-save-hook \\='time-stamp nil t) eval: (add-hook \\='before-save-hook \\='time-stamp nil t)
If the file has no time-stamp template, this function does nothing. If the file has no time stamp template or if `time-stamp-active' is nil,
this function does nothing.
You can set `time-stamp-pattern' in a file's local variables list You can set `time-stamp-pattern' in a file's local variables list
to customize the information in the time stamp and where it is written. to customize the information in the time stamp and where it is written."
The time stamp is updated only if `time-stamp-active' is non-nil."
(interactive) (interactive)
(let ((line-limit time-stamp-line-limit) (let ((line-limit time-stamp-line-limit)
(ts-start time-stamp-start) (ts-start time-stamp-start)
@ -466,10 +475,15 @@ Internal helper used by `time-stamp-string-preprocess'."
(format-time-string format time time-stamp-time-zone)) (format-time-string format time time-stamp-time-zone))
(defun time-stamp-string (&optional ts-format time) (defun time-stamp-string (&optional ts-format time)
"Generate the new string to be inserted by \\[time-stamp]. "Return the current time and other info formatted for \\[time-stamp].
Optionally use format TS-FORMAT instead of `time-stamp-format' to Optional first argument TS-FORMAT gives the format to use; it defaults
format the string. Optional second argument TIME is only for testing; to the value of `time-stamp-format'. Thus, with no arguments,
normally the current time is used." 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'."
(if (stringp (or ts-format (setq ts-format time-stamp-format))) (if (stringp (or ts-format (setq ts-format time-stamp-format)))
(time-stamp-string-preprocess ts-format time))) (time-stamp-string-preprocess ts-format time)))