aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Gildea2025-02-07 09:17:26 -0800
committerStephen Gildea2025-02-07 09:18:04 -0800
commit280b25e0096bb97fb473a8da9b4635fb2d6e5385 (patch)
tree5788c654020f7e667cc0ce2c189dbc55246926fe
parenta62b58648ac54feb8fb81aefdb0461cb11bf6a81 (diff)
downloademacs-280b25e0096bb97fb473a8da9b4635fb2d6e5385.tar.gz
emacs-280b25e0096bb97fb473a8da9b4635fb2d6e5385.zip
time-stamp: Better handling of some edge cases
* lisp/time-stamp.el (time-stamp-count): Require confirmation if large. (time-stamp-once): Correctly handle a start regexp matching 0 chars. * test/lisp/time-stamp-tests.el (time-stamp-custom-start): New test.
-rw-r--r--lisp/time-stamp.el20
-rw-r--r--test/lisp/time-stamp-tests.el36
2 files changed, 43 insertions, 13 deletions
diff --git a/lisp/time-stamp.el b/lisp/time-stamp.el
index ad356eb2bd6..4117db71058 100644
--- a/lisp/time-stamp.el
+++ b/lisp/time-stamp.el
@@ -114,7 +114,7 @@ limit yourself to the formats recommended by that older version."
114 114
115 115
116(defcustom time-stamp-active t 116(defcustom time-stamp-active t
117 "Non-nil to enable time-stamping of buffers by \\[time-stamp]. 117 "Non-nil enables time-stamping of buffers by \\[time-stamp].
118Can be toggled by \\[time-stamp-toggle-active]. 118Can be toggled by \\[time-stamp-toggle-active].
119 119
120This option does not affect when `time-stamp' is run, only what it 120This option does not affect when `time-stamp' is run, only what it
@@ -257,7 +257,7 @@ then instead of changing this variable, include a newline (written as
257`time-stamp-count' is best changed with a file-local variable. 257`time-stamp-count' is best changed with a file-local variable.
258If you were to change it in your init file, you would be incompatible 258If you were to change it in your init file, you would be incompatible
259with other people's files.") 259with other people's files.")
260;;;###autoload(put 'time-stamp-count 'safe-local-variable 'integerp) 260;;;###autoload(put 'time-stamp-count 'safe-local-variable (lambda (c) (and (integerp c) (< c 100))))
261 261
262 262
263(defvar time-stamp-pattern nil ;Do not change! 263(defvar time-stamp-pattern nil ;Do not change!
@@ -342,12 +342,11 @@ To enable automatic time-stamping for only a specific file, add
342this line to a local variables list near the end of the file: 342this line to a local variables list near the end of the file:
343 eval: (add-hook \\='before-save-hook \\='time-stamp nil t) 343 eval: (add-hook \\='before-save-hook \\='time-stamp nil t)
344 344
345If the file has no time stamp template, this function does nothing. 345If the file has no time stamp template or if `time-stamp-active' is nil,
346this function does nothing.
346 347
347You can set `time-stamp-pattern' in a file's local variables list 348You can set `time-stamp-pattern' in a file's local variables list
348to customize the information in the time stamp and where it is written. 349to customize the information in the time stamp and where it is written."
349
350The time stamp is updated only if `time-stamp-active' is non-nil."
351 (interactive) 350 (interactive)
352 (let ((line-limit time-stamp-line-limit) 351 (let ((line-limit time-stamp-line-limit)
353 (ts-start time-stamp-start) 352 (ts-start time-stamp-start)
@@ -421,6 +420,7 @@ The time stamp is updated only if `time-stamp-active' is non-nil."
421Returns the end point, which is where `time-stamp' begins the next search." 420Returns the end point, which is where `time-stamp' begins the next search."
422 (let ((case-fold-search nil) 421 (let ((case-fold-search nil)
423 (end nil) 422 (end nil)
423 (advance-nudge 0)
424 end-search-start 424 end-search-start
425 (end-length nil)) 425 (end-length nil))
426 (save-excursion 426 (save-excursion
@@ -430,6 +430,9 @@ Returns the end point, which is where `time-stamp' begins the next search."
430 (while (and (< (goto-char start) search-limit) 430 (while (and (< (goto-char start) search-limit)
431 (not end) 431 (not end)
432 (re-search-forward ts-start search-limit 'move)) 432 (re-search-forward ts-start search-limit 'move))
433 ;; Whether or not we find a template, we must
434 ;; advance through the buffer.
435 (setq advance-nudge (if (> (point) start) 0 1))
433 (setq start (point)) 436 (setq start (point))
434 (if (not time-stamp-inserts-lines) 437 (if (not time-stamp-inserts-lines)
435 (forward-line format-lines)) 438 (forward-line format-lines))
@@ -444,7 +447,8 @@ Returns the end point, which is where `time-stamp' begins the next search."
444 (if (re-search-forward ts-end line-end t) 447 (if (re-search-forward ts-end line-end t)
445 (progn 448 (progn
446 (setq end (match-beginning 0)) 449 (setq end (match-beginning 0))
447 (setq end-length (- (match-end 0) end)))))))))))) 450 (setq end-length (- (match-end 0) end)))
451 (setq start (+ start advance-nudge)))))))))))
448 (if end 452 (if end
449 (progn 453 (progn
450 ;; do all warnings outside save-excursion 454 ;; do all warnings outside save-excursion
@@ -478,7 +482,7 @@ Returns the end point, which is where `time-stamp' begins the next search."
478 (setq end (point)))))))))))) 482 (setq end (point))))))))))))
479 ;; return the location after this time stamp, if there was one 483 ;; return the location after this time stamp, if there was one
480 (and end end-length 484 (and end end-length
481 (+ end end-length)))) 485 (+ end (max advance-nudge end-length)))))
482 486
483 487
484;;;###autoload 488;;;###autoload
diff --git a/test/lisp/time-stamp-tests.el b/test/lisp/time-stamp-tests.el
index a7aa00dc267..f4fcce3e957 100644
--- a/test/lisp/time-stamp-tests.el
+++ b/test/lisp/time-stamp-tests.el
@@ -138,6 +138,31 @@
138 (iter-yield-from (time-stamp-test-pattern-sequential)) 138 (iter-yield-from (time-stamp-test-pattern-sequential))
139 (iter-yield-from (time-stamp-test-pattern-multiply))) 139 (iter-yield-from (time-stamp-test-pattern-multiply)))
140 140
141(ert-deftest time-stamp-custom-start ()
142 "Test that `time-stamp' isn't stuck by a start matching 0 characters."
143 (with-time-stamp-test-env
144 (with-time-stamp-test-time ref-time1
145 (let ((time-stamp-pattern "^%Y-%m-%d<-TS")) ;start matches 0 chars
146 (with-temp-buffer
147 (insert "\n<-TS\n")
148 ;; we should advance to line 2 and find the template
149 (time-stamp)
150 (should (equal (buffer-string) "\n2006-01-02<-TS\n"))))
151 (let ((time-stamp-pattern "\\b%Y-%m-%d\\b") ;start and end match 0 chars
152 (time-stamp-count 2))
153 (with-temp-buffer
154 (insert "..")
155 ;; the two time stamps should be in different places
156 (time-stamp)
157 (should (equal (buffer-string) "2006-01-02..2006-01-02"))))
158 (let ((time-stamp-pattern "::%S\\_>") ;end matches 0 chars
159 (time-stamp-count 2))
160 (with-temp-buffer
161 (insert "::0::0")
162 ;; the second template should be found immediately after the first
163 (time-stamp)
164 (should (equal (buffer-string) "::05::05")))))))
165
141(ert-deftest time-stamp-custom-pattern () 166(ert-deftest time-stamp-custom-pattern ()
142 "Test that `time-stamp-pattern' is parsed correctly." 167 "Test that `time-stamp-pattern' is parsed correctly."
143 (iter-do (pattern-parts (time-stamp-test-pattern-all)) 168 (iter-do (pattern-parts (time-stamp-test-pattern-all))
@@ -246,17 +271,17 @@
246 (let ((time-stamp-start "TS: <") 271 (let ((time-stamp-start "TS: <")
247 (time-stamp-format "%Y-%m-%d") 272 (time-stamp-format "%Y-%m-%d")
248 (time-stamp-count 0) ;changed later in the test 273 (time-stamp-count 0) ;changed later in the test
249 (buffer-expected-once "TS: <2006-01-02>\nTS: <>") 274 (buffer-expected-once "TS: <2006-01-02>TS: <>")
250 (buffer-expected-twice "TS: <2006-01-02>\nTS: <2006-01-02>")) 275 (buffer-expected-twice "TS: <2006-01-02>TS: <2006-01-02>"))
251 (with-time-stamp-test-time ref-time1 276 (with-time-stamp-test-time ref-time1
252 (with-temp-buffer 277 (with-temp-buffer
253 (insert "TS: <>\nTS: <>") 278 (insert "TS: <>TS: <>")
254 (time-stamp) 279 (time-stamp)
255 ;; even with count = 0, expect one time stamp 280 ;; even with count = 0, expect one time stamp
256 (should (equal (buffer-string) buffer-expected-once))) 281 (should (equal (buffer-string) buffer-expected-once)))
257 (with-temp-buffer 282 (with-temp-buffer
258 (setq time-stamp-count 1) 283 (setq time-stamp-count 1)
259 (insert "TS: <>\nTS: <>") 284 (insert "TS: <>TS: <>")
260 (time-stamp) 285 (time-stamp)
261 (should (equal (buffer-string) buffer-expected-once)) 286 (should (equal (buffer-string) buffer-expected-once))
262 287
@@ -698,7 +723,7 @@
698 (should (equal (time-stamp-string "%5z" ref-time1) "+0000")) 723 (should (equal (time-stamp-string "%5z" ref-time1) "+0000"))
699 (let ((time-stamp-time-zone "PST8")) 724 (let ((time-stamp-time-zone "PST8"))
700 (should (equal (time-stamp-string "%5z" ref-time1) "-0800"))) 725 (should (equal (time-stamp-string "%5z" ref-time1) "-0800")))
701 (let ((time-stamp-time-zone "HST10")) 726 (let ((time-stamp-time-zone '(-36000 "HST")))
702 (should (equal (time-stamp-string "%5z" ref-time1) "-1000"))) 727 (should (equal (time-stamp-string "%5z" ref-time1) "-1000")))
703 (let ((time-stamp-time-zone "CET-1")) 728 (let ((time-stamp-time-zone "CET-1"))
704 (should (equal (time-stamp-string "%5z" ref-time1) "+0100"))) 729 (should (equal (time-stamp-string "%5z" ref-time1) "+0100")))
@@ -887,6 +912,7 @@
887 (should (safe-local-variable-p 'time-stamp-inserts-lines t)) 912 (should (safe-local-variable-p 'time-stamp-inserts-lines t))
888 (should-not (safe-local-variable-p 'time-stamp-inserts-lines 17)) 913 (should-not (safe-local-variable-p 'time-stamp-inserts-lines 17))
889 (should (safe-local-variable-p 'time-stamp-count 2)) 914 (should (safe-local-variable-p 'time-stamp-count 2))
915 (should-not (safe-local-variable-p 'time-stamp-count 100))
890 (should-not (safe-local-variable-p 'time-stamp-count t)) 916 (should-not (safe-local-variable-p 'time-stamp-count t))
891 (should (safe-local-variable-p 'time-stamp-pattern "a string")) 917 (should (safe-local-variable-p 'time-stamp-pattern "a string"))
892 (should-not (safe-local-variable-p 'time-stamp-pattern 17))) 918 (should-not (safe-local-variable-p 'time-stamp-pattern 17)))