diff options
| author | Richard M. Stallman | 1997-06-08 21:43:08 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1997-06-08 21:43:08 +0000 |
| commit | fd72ddf609b417abf526ccc8865631f813e066e1 (patch) | |
| tree | f02433fdddc5cedf57b86ef8c7aaa927c3d0af0a | |
| parent | e9f527a0ce960ebd79eb30fc56b349464a156572 (diff) | |
| download | emacs-fd72ddf609b417abf526ccc8865631f813e066e1.tar.gz emacs-fd72ddf609b417abf526ccc8865631f813e066e1.zip | |
(time-stamp-format): Doc fix. Use %;y.
(time-stamp-string-preprocess): Don't just call format-time-string;
handle compatibility for some old constructs. Handle padding
the historical way, while giving a warning if people actually depend on it.
(time-stamp-conv-warn, time-stamp-conversion-warn)
(time-stamp-do-number): New functions.
| -rw-r--r-- | lisp/time-stamp.el | 289 |
1 files changed, 249 insertions, 40 deletions
diff --git a/lisp/time-stamp.el b/lisp/time-stamp.el index 0944a73d611..f357ddc7068 100644 --- a/lisp/time-stamp.el +++ b/lisp/time-stamp.el | |||
| @@ -1,8 +1,8 @@ | |||
| 1 | ;;; time-stamp.el --- Maintain last change time stamps in files edited by Emacs | 1 | ;;; time-stamp.el --- Maintain last change time stamps in files edited by Emacs |
| 2 | 2 | ||
| 3 | ;; Copyright 1989, 1993, 1994, 1995 Free Software Foundation, Inc. | 3 | ;; Copyright 1989, 1993, 1994, 1995, 1997 Free Software Foundation, Inc. |
| 4 | 4 | ||
| 5 | ;; Maintainer's Time-stamp: <1997-04-28 11:51:22 gildea> | 5 | ;; Maintainer's Time-stamp: <1997-06-01 17:02:45 gildea> |
| 6 | ;; Maintainer: Stephen Gildea <gildea@alum.mit.edu> | 6 | ;; Maintainer: Stephen Gildea <gildea@alum.mit.edu> |
| 7 | ;; Keywords: tools | 7 | ;; Keywords: tools |
| 8 | 8 | ||
| @@ -66,23 +66,47 @@ If nil, no notification is given." | |||
| 66 | (const ask) (const warn)) | 66 | (const ask) (const warn)) |
| 67 | :group 'time-stamp) | 67 | :group 'time-stamp) |
| 68 | 68 | ||
| 69 | (defcustom time-stamp-format "%Y-%02m-%02d %02H:%02M:%02S %u" | 69 | (defcustom time-stamp-format "%:y-%02m-%02d %02H:%02M:%02S %u" |
| 70 | "*Format of the string inserted by \\[time-stamp]. | 70 | "*Format of the string inserted by \\[time-stamp]. |
| 71 | The value may be a string or a list. Lists are supported only for | 71 | The value may be a string or a list. Lists are supported only for |
| 72 | backward compatibility; see variable `time-stamp-old-format-warn'. | 72 | backward compatibility; see variable `time-stamp-old-format-warn'. |
| 73 | 73 | ||
| 74 | A string is used with `format-time-string'. | 74 | A string is used verbatim except for character sequences beginning with %: |
| 75 | In addition to the features of `format-time-string', | 75 | |
| 76 | you can use the following %-constructs: | 76 | %:a weekday name: `Monday'. %#A gives uppercase: `MONDAY' |
| 77 | 77 | %3a abbreviated weekday: `Mon'. %3A gives uppercase: `MON' | |
| 78 | %f file name without directory | 78 | %:b month name: `January'. %#B gives uppercase: `JANUARY' |
| 79 | %F full file name | 79 | %3b abbreviated month: `Jan'. %3B gives uppercase: `JAN' |
| 80 | %h mail host name | 80 | %02d day of month |
| 81 | %s system name | 81 | %02H 24-hour clock hour |
| 82 | %u user's login name | 82 | %02I 12-hour clock hour |
| 83 | %02m month number | ||
| 84 | %02M minute | ||
| 85 | %#p `am' or `pm'. %P gives uppercase: `AM' or `PM' | ||
| 86 | %02S seconds | ||
| 87 | %w day number of week, Sunday is 0 | ||
| 88 | %02y 2-digit year: `97' %:y 4-digit year: `1997' | ||
| 89 | %z time zone name: `est'. %Z gives uppercase: `EST' | ||
| 90 | |||
| 91 | Non-date items: | ||
| 92 | %% a literal percent character: `%' | ||
| 93 | %f file name without directory %F gives absolute pathname | ||
| 94 | %s system name | ||
| 95 | %u user's login name | ||
| 96 | %h mail host name | ||
| 97 | |||
| 98 | Decimal digits between the % and the type character specify the | ||
| 99 | field width. Strings are truncated on the right; years on the left. | ||
| 100 | A leading zero causes numbers to be zero-filled. | ||
| 83 | 101 | ||
| 84 | For example, to get the format used by the `date' command, | 102 | For example, to get the format used by the `date' command, |
| 85 | use \"%3a %3b %2d %02H:%02M:%02S %Z %Y\"." | 103 | use \"%3a %3b %2d %02H:%02M:%02S %Z %:y\". |
| 104 | |||
| 105 | In the future these formats will be aligned more with format-time-string. | ||
| 106 | Because of this transition, the default padding for numeric formats will | ||
| 107 | change in a future version. Therefore either a padding width should be | ||
| 108 | specified, or the : modifier should be used to explicitly request the | ||
| 109 | historical default." | ||
| 86 | :type 'string | 110 | :type 'string |
| 87 | :group 'time-stamp) | 111 | :group 'time-stamp) |
| 88 | 112 | ||
| @@ -221,33 +245,218 @@ With arg, turn time stamping on if and only if arg is positive." | |||
| 221 | (defconst time-stamp-no-file "(no file)" | 245 | (defconst time-stamp-no-file "(no file)" |
| 222 | "String to use when the buffer is not associated with a file.") | 246 | "String to use when the buffer is not associated with a file.") |
| 223 | 247 | ||
| 224 | (defun time-stamp-string-preprocess (format) | 248 | ;;; time-stamp is transitioning to using the new, expanded capabilities |
| 225 | "Process occurrences in FORMAT of %f, %F, %h, %s and %u. | 249 | ;;; of format-time-string. During the process, this function implements |
| 226 | These are replaced with the file name (nondirectory part), | 250 | ;;; intermediate, compatible formats and complains about old, soon to |
| 227 | full file name, host name for mail, system name, and user name. | 251 | ;;; be unsupported, formats. This function will get a lot (a LOT) shorter |
| 228 | Do not alter other %-combinations, and do detect %%." | 252 | ;;; when the transition is complete and we can just pass most things |
| 229 | (let ((result "") (pos 0) (case-fold-search nil)) | 253 | ;;; straight through to format-time-string. |
| 230 | (while (string-match "%[%uhfFs]" format pos) | 254 | ;;; At all times, all the formats recommended in the doc string |
| 231 | (setq result (concat result (substring format pos (match-beginning 0)))) | 255 | ;;; of time-stamp-format will work not only in the current version of |
| 232 | (let ((char (aref format (1+ (match-beginning 0))))) | 256 | ;;; Emacs, but in all versions that have been released within the past |
| 233 | (cond ((= char ?%) | 257 | ;;; two years. |
| 234 | (setq result (concat result "%%"))) | 258 | ;;; The : modifier is a temporary conversion feature used to resolve |
| 235 | ((= char ?u) | 259 | ;;; ambiguous formats--formats that are changing (over time) incompatibly. |
| 236 | (setq result (concat result (user-login-name)))) | 260 | (defun time-stamp-string-preprocess (format &optional time) |
| 237 | ((= char ?f) | 261 | ;; Uses a FORMAT to format date, time, file, and user information. |
| 238 | (setq result (concat result | 262 | ;; Optional second argument TIME is only for testing. |
| 239 | (if buffer-file-name | 263 | ;; Implements non-time extensions to format-time-string |
| 240 | (file-name-nondirectory buffer-file-name) | 264 | ;; and all time-stamp-format compatibility. |
| 241 | time-stamp-no-file)))) | 265 | (let ((fmt-len (length format)) |
| 242 | ((= char ?F) | 266 | (ind 0) |
| 243 | (setq result (concat result | 267 | cur-char |
| 244 | (or buffer-file-name time-stamp-no-file)))) | 268 | (prev-char nil) |
| 245 | ((= char ?s) | 269 | (result "") |
| 246 | (setq result (concat result (system-name)))) | 270 | field-index |
| 247 | ((= char ?h) | 271 | field-width |
| 248 | (setq result (concat result (time-stamp-mail-host-name)))))) | 272 | field-result |
| 249 | (setq pos (match-end 0))) | 273 | alt-form change-case require-padding |
| 250 | (concat result (substring format pos)))) | 274 | (paren-level 0)) |
| 275 | (while (< ind fmt-len) | ||
| 276 | (setq cur-char (aref format ind)) | ||
| 277 | (setq | ||
| 278 | result | ||
| 279 | (concat result | ||
| 280 | (cond | ||
| 281 | ((eq cur-char ?%) | ||
| 282 | ;; eat any additional args to allow for future expansion | ||
| 283 | (setq alt-form nil change-case nil require-padding nil) | ||
| 284 | (while (progn | ||
| 285 | (setq ind (1+ ind)) | ||
| 286 | (setq cur-char (if (< ind fmt-len) | ||
| 287 | (aref format ind) | ||
| 288 | ?\0)) | ||
| 289 | (or (eq ?. cur-char) | ||
| 290 | (eq ?, cur-char) (eq ?: cur-char) (eq ?@ cur-char) | ||
| 291 | (eq ?- cur-char) (eq ?+ cur-char) (eq ?_ cur-char) | ||
| 292 | (eq ?\ cur-char) (eq ?# cur-char) (eq ?^ cur-char) | ||
| 293 | (and (eq ?\( cur-char) | ||
| 294 | (not (eq prev-char ?\\)) | ||
| 295 | (setq paren-level (1+ paren-level))) | ||
| 296 | (if (and (eq ?\) cur-char) | ||
| 297 | (not (eq prev-char ?\\)) | ||
| 298 | (> paren-level 0)) | ||
| 299 | (setq paren-level (1- paren-level)) | ||
| 300 | (and (> paren-level 0) | ||
| 301 | (< ind fmt-len))))) | ||
| 302 | (setq prev-char cur-char) | ||
| 303 | ;; some characters we actually use | ||
| 304 | (cond ((eq cur-char ?:) | ||
| 305 | (setq alt-form t)) | ||
| 306 | ((eq cur-char ?#) | ||
| 307 | (setq change-case t)))) | ||
| 308 | ;; get format width | ||
| 309 | (setq field-index ind) | ||
| 310 | (setq ind (1- ind)) | ||
| 311 | (while (progn | ||
| 312 | (setq ind (1+ ind)) | ||
| 313 | (setq cur-char (if (< ind fmt-len) | ||
| 314 | (aref format ind) | ||
| 315 | ?\0)) | ||
| 316 | (and (<= ?0 cur-char) (>= ?9 cur-char)))) | ||
| 317 | (setq field-width (substring format field-index ind)) | ||
| 318 | (setq field-result | ||
| 319 | (cond | ||
| 320 | ((eq cur-char ?%) | ||
| 321 | "%") | ||
| 322 | ((eq cur-char ?a) ;day of week | ||
| 323 | (if change-case | ||
| 324 | (format-time-string "%#A" time) | ||
| 325 | (or alt-form (not (string-equal field-width "")) | ||
| 326 | (time-stamp-conv-warn "%a" "%:a")) | ||
| 327 | (if (and alt-form (not (string-equal field-width ""))) | ||
| 328 | "" ;discourage "%:3a" | ||
| 329 | (format-time-string "%A" time)))) | ||
| 330 | ((eq cur-char ?A) | ||
| 331 | (if alt-form | ||
| 332 | (format-time-string "%A" time) | ||
| 333 | (or change-case (not (string-equal field-width "")) | ||
| 334 | (time-stamp-conv-warn "%A" "%#A")) | ||
| 335 | (format-time-string "%#A" time))) | ||
| 336 | ((eq cur-char ?b) ;month name | ||
| 337 | (if change-case | ||
| 338 | (format-time-string "%#B" time) | ||
| 339 | (or alt-form (not (string-equal field-width "")) | ||
| 340 | (time-stamp-conv-warn "%b" "%:b")) | ||
| 341 | (if (and alt-form (not (string-equal field-width ""))) | ||
| 342 | "" ;discourage "%:3b" | ||
| 343 | (format-time-string "%B" time)))) | ||
| 344 | ((eq cur-char ?B) | ||
| 345 | (if alt-form | ||
| 346 | (format-time-string "%B" time) | ||
| 347 | (or change-case (not (string-equal field-width "")) | ||
| 348 | (time-stamp-conv-warn "%B" "%#B")) | ||
| 349 | (format-time-string "%#B" time))) | ||
| 350 | ((eq cur-char ?d) ;day of month, 1-31 | ||
| 351 | (time-stamp-do-number cur-char)) | ||
| 352 | ((eq cur-char ?H) ;hour, 0-23 | ||
| 353 | (time-stamp-do-number cur-char)) | ||
| 354 | ((eq cur-char ?I) ;hour, 1-12 | ||
| 355 | (time-stamp-do-number cur-char)) | ||
| 356 | ((eq cur-char ?m) ;month number, 1-12 | ||
| 357 | (time-stamp-do-number cur-char)) | ||
| 358 | ((eq cur-char ?M) ;minute, 0-59 | ||
| 359 | (time-stamp-do-number cur-char)) | ||
| 360 | ((eq cur-char ?p) ;am or pm | ||
| 361 | (or change-case | ||
| 362 | (time-stamp-conv-warn "%p" "%#p")) | ||
| 363 | (format-time-string "%#p" time)) | ||
| 364 | ((eq cur-char ?P) ;AM or PM | ||
| 365 | (format-time-string "%p" time)) | ||
| 366 | ((eq cur-char ?S) ;seconds, 00-60 | ||
| 367 | (time-stamp-do-number cur-char)) | ||
| 368 | ((eq cur-char ?w) ;weekday number, Sunday is 0 | ||
| 369 | (format-time-string "%w" time)) | ||
| 370 | ((eq cur-char ?y) ;year | ||
| 371 | (or alt-form (not (string-equal field-width "")) | ||
| 372 | (time-stamp-conv-warn "%y" "%:y")) | ||
| 373 | (string-to-int (format-time-string "%Y" time))) | ||
| 374 | ((eq cur-char ?Y) ;4-digit year, new style | ||
| 375 | (string-to-int (format-time-string "%Y" time))) | ||
| 376 | ((eq cur-char ?z) ;time zone lower case | ||
| 377 | (if change-case | ||
| 378 | "" ;discourage %z variations | ||
| 379 | (format-time-string "%#Z" time))) | ||
| 380 | ((eq cur-char ?Z) | ||
| 381 | (if change-case | ||
| 382 | (format-time-string "%#Z" time) | ||
| 383 | (format-time-string "%Z" time))) | ||
| 384 | ((eq cur-char ?f) ;buffer-file-name, base name only | ||
| 385 | (if buffer-file-name | ||
| 386 | (file-name-nondirectory buffer-file-name) | ||
| 387 | time-stamp-no-file)) | ||
| 388 | ((eq cur-char ?F) ;buffer-file-name, full path | ||
| 389 | (or buffer-file-name | ||
| 390 | time-stamp-no-file)) | ||
| 391 | ((eq cur-char ?s) ;system name | ||
| 392 | (system-name)) | ||
| 393 | ((eq cur-char ?u) ;user name | ||
| 394 | (user-login-name)) | ||
| 395 | ((eq cur-char ?h) ;mail host name | ||
| 396 | (time-stamp-mail-host-name)) | ||
| 397 | )) | ||
| 398 | (if (string-equal field-width "") | ||
| 399 | field-result | ||
| 400 | (let ((padded-result | ||
| 401 | (format (format "%%%s%c" | ||
| 402 | field-width | ||
| 403 | (if (numberp field-result) ?d ?s)) | ||
| 404 | (or field-result "")))) | ||
| 405 | (let ((initial-length (length padded-result)) | ||
| 406 | (desired-length (string-to-int field-width))) | ||
| 407 | (if (> initial-length desired-length) | ||
| 408 | ;; truncate strings on right, years on left | ||
| 409 | (if (stringp field-result) | ||
| 410 | (substring padded-result 0 desired-length) | ||
| 411 | (if (eq cur-char ?y) | ||
| 412 | (substring padded-result (- desired-length)) | ||
| 413 | padded-result)) ;non-year numbers don't truncate | ||
| 414 | padded-result))))) | ||
| 415 | (t | ||
| 416 | (char-to-string cur-char))))) | ||
| 417 | (setq ind (1+ ind))) | ||
| 418 | result)) | ||
| 419 | |||
| 420 | (defun time-stamp-do-number (format-char) | ||
| 421 | ;; Handle compatible cases where only | ||
| 422 | ;; the default width/padding will change. | ||
| 423 | ;; Uses dynamic vars field-width, time. | ||
| 424 | (let ((format-string (concat "%" (char-to-string format-char)))) | ||
| 425 | (and (not alt-form) (string-equal field-width "") | ||
| 426 | (time-stamp-conv-warn format-string | ||
| 427 | (format "%%:%c" format-char))) | ||
| 428 | (if (and alt-form (not (string-equal field-width ""))) | ||
| 429 | "" ;discourage "%:2d" and the like | ||
| 430 | (string-to-int (format-time-string format-string time))))) | ||
| 431 | |||
| 432 | (defvar time-stamp-conversion-warn t | ||
| 433 | "Non-nil to warn about soon-to-be-unsupported forms in time-stamp-format. | ||
| 434 | In would be a bad idea to disable these warnings! | ||
| 435 | You really need to update your files instead. | ||
| 436 | |||
| 437 | The new formats will work with old versions of Emacs. | ||
| 438 | New formats are being recommended now to allow time-stamp-format | ||
| 439 | to change in the future to be compatible with format-time-string. | ||
| 440 | The new forms being recommended now will continue to work then.") | ||
| 441 | |||
| 442 | |||
| 443 | (defun time-stamp-conv-warn (old-form new-form) | ||
| 444 | ;; Display a warning about a soon-to-be-obsolete format. | ||
| 445 | (cond | ||
| 446 | (time-stamp-conversion-warn | ||
| 447 | (save-excursion | ||
| 448 | (set-buffer (get-buffer-create "*Time-stamp-compatibility*")) | ||
| 449 | (goto-char (point-max)) | ||
| 450 | (if (bobp) | ||
| 451 | (progn | ||
| 452 | (insert | ||
| 453 | "The formats recognized in time-stamp-format will change in a future release\n" | ||
| 454 | "to be compatible with the new, expanded format-time-string function.\n\n" | ||
| 455 | "The following obsolescent time-stamp-format construct(s) were found:\n\n"))) | ||
| 456 | (insert "\"" old-form "\" -- use " new-form "\n")) | ||
| 457 | (display-buffer "*Time-stamp-compatibility*")))) | ||
| 458 | |||
| 459 | |||
| 251 | 460 | ||
| 252 | (defun time-stamp-string () | 461 | (defun time-stamp-string () |
| 253 | "Generate the new string to be inserted by \\[time-stamp]." | 462 | "Generate the new string to be inserted by \\[time-stamp]." |