diff options
| author | Lars Ingebrigtsen | 2022-04-13 15:31:02 +0200 |
|---|---|---|
| committer | Lars Ingebrigtsen | 2022-04-13 15:31:34 +0200 |
| commit | 918669cb3db21eebc9fb409098a4395f131379ee (patch) | |
| tree | 0b0dbff24165be2804c9911ba05cfca22b862ced | |
| parent | e587fc05a70c08a50258b152bb5403afd013007d (diff) | |
| download | emacs-918669cb3db21eebc9fb409098a4395f131379ee.tar.gz emacs-918669cb3db21eebc9fb409098a4395f131379ee.zip | |
Make list-times not include zero elements
* doc/lispref/os.texi (Time Parsing): Mention %x.
* lisp/calendar/time-date.el (format-seconds): Accept a new %x
spec that removes trailing zeros (bug#54904).
* lisp/emacs-lisp/timer-list.el (list-timers): Don't display
trailing zero bits.
| -rw-r--r-- | doc/lispref/os.texi | 4 | ||||
| -rw-r--r-- | etc/NEWS | 5 | ||||
| -rw-r--r-- | lisp/calendar/time-date.el | 56 | ||||
| -rw-r--r-- | lisp/emacs-lisp/timer-list.el | 2 | ||||
| -rw-r--r-- | test/lisp/calendar/time-date-tests.el | 9 |
5 files changed, 57 insertions, 19 deletions
diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi index 9cb9bc75d04..4ee893f860f 100644 --- a/doc/lispref/os.texi +++ b/doc/lispref/os.texi | |||
| @@ -1961,6 +1961,10 @@ encountered. For example, the default format used by | |||
| 1961 | @w{@code{"%Y, %D, %H, %M, %z%S"}} means that the number of seconds | 1961 | @w{@code{"%Y, %D, %H, %M, %z%S"}} means that the number of seconds |
| 1962 | will always be produced, but years, days, hours, and minutes will only | 1962 | will always be produced, but years, days, hours, and minutes will only |
| 1963 | be shown if they are non-zero. | 1963 | be shown if they are non-zero. |
| 1964 | @item %x | ||
| 1965 | Non-printing control flag that works along the same lines as | ||
| 1966 | @samp{%z}, but instead suppresses printing of trailing zero-value time | ||
| 1967 | elements. | ||
| 1964 | @item %% | 1968 | @item %% |
| 1965 | Produces a literal @samp{%}. | 1969 | Produces a literal @samp{%}. |
| 1966 | @end table | 1970 | @end table |
| @@ -1857,6 +1857,11 @@ month, day, or time. For example, (date-to-time "2021-12-04") now | |||
| 1857 | assumes a time of 00:00 instead of signaling an error. | 1857 | assumes a time of 00:00 instead of signaling an error. |
| 1858 | 1858 | ||
| 1859 | +++ | 1859 | +++ |
| 1860 | ** 'format-seconds' now allows suppressing zero-value trailing elements. | ||
| 1861 | The new "%x" non-printing control character will suppress zero-value | ||
| 1862 | elements that appear after "%x". | ||
| 1863 | |||
| 1864 | +++ | ||
| 1860 | ** New events for taking advantage of touchscreen devices. | 1865 | ** New events for taking advantage of touchscreen devices. |
| 1861 | The events 'touchscreen-begin, 'touchscreen-update', and | 1866 | The events 'touchscreen-begin, 'touchscreen-update', and |
| 1862 | 'touchscreen-end' have been added to take better advantage of | 1867 | 'touchscreen-end' have been added to take better advantage of |
diff --git a/lisp/calendar/time-date.el b/lisp/calendar/time-date.el index 51cf7eb213f..0db973ea161 100644 --- a/lisp/calendar/time-date.el +++ b/lisp/calendar/time-date.el | |||
| @@ -287,17 +287,23 @@ use. \"%,1s\" means \"use one decimal\". | |||
| 287 | 287 | ||
| 288 | The \"%z\" specifier does not print anything. When it is used, specifiers | 288 | The \"%z\" specifier does not print anything. When it is used, specifiers |
| 289 | must be given in order of decreasing size. To the left of \"%z\", nothing | 289 | must be given in order of decreasing size. To the left of \"%z\", nothing |
| 290 | is output until the first non-zero unit is encountered." | 290 | is output until the first non-zero unit is encountered. |
| 291 | |||
| 292 | The \"%x\" specifier does not print anything. When it is used, | ||
| 293 | specifiers must be given in order of decreasing size. To the | ||
| 294 | right of \"%x\", trailing zero units are not output." | ||
| 291 | (let ((start 0) | 295 | (let ((start 0) |
| 292 | (units '(("y" "year" 31536000) | 296 | (units '(("y" "year" 31536000) |
| 293 | ("d" "day" 86400) | 297 | ("d" "day" 86400) |
| 294 | ("h" "hour" 3600) | 298 | ("h" "hour" 3600) |
| 295 | ("m" "minute" 60) | 299 | ("m" "minute" 60) |
| 296 | ("s" "second" 1) | 300 | ("s" "second" 1) |
| 297 | ("z"))) | 301 | ("z") |
| 302 | ("x"))) | ||
| 298 | (case-fold-search t) | 303 | (case-fold-search t) |
| 299 | spec match usedunits zeroflag larger prev name unit num zeropos | 304 | spec match usedunits zeroflag larger prev name unit num |
| 300 | fraction) | 305 | leading-zeropos trailing-zeropos fraction |
| 306 | chop-leading chop-trailing) | ||
| 301 | (while (string-match "%\\.?[0-9]*\\(,[0-9]\\)?\\(.\\)" string start) | 307 | (while (string-match "%\\.?[0-9]*\\(,[0-9]\\)?\\(.\\)" string start) |
| 302 | (setq start (match-end 0) | 308 | (setq start (match-end 0) |
| 303 | spec (match-string 2 string)) | 309 | spec (match-string 2 string)) |
| @@ -306,15 +312,16 @@ is output until the first non-zero unit is encountered." | |||
| 306 | (error "Bad format specifier: `%s'" spec)) | 312 | (error "Bad format specifier: `%s'" spec)) |
| 307 | (if (assoc (downcase spec) usedunits) | 313 | (if (assoc (downcase spec) usedunits) |
| 308 | (error "Multiple instances of specifier: `%s'" spec)) | 314 | (error "Multiple instances of specifier: `%s'" spec)) |
| 309 | (if (string-equal (car match) "z") | 315 | (if (or (string-equal (car match) "z") |
| 316 | (string-equal (car match) "x")) | ||
| 310 | (setq zeroflag t) | 317 | (setq zeroflag t) |
| 311 | (unless larger | 318 | (unless larger |
| 312 | (setq unit (nth 2 match) | 319 | (setq unit (nth 2 match) |
| 313 | larger (and prev (> unit prev)) | 320 | larger (and prev (> unit prev)) |
| 314 | prev unit))) | 321 | prev unit))) |
| 315 | (push match usedunits))) | 322 | (push match usedunits))) |
| 316 | (and zeroflag larger | 323 | (when (and zeroflag larger) |
| 317 | (error "Units are not in decreasing order of size")) | 324 | (error "Units are not in decreasing order of size")) |
| 318 | (unless (numberp seconds) | 325 | (unless (numberp seconds) |
| 319 | (setq seconds (float-time seconds))) | 326 | (setq seconds (float-time seconds))) |
| 320 | (setq fraction (mod seconds 1) | 327 | (setq fraction (mod seconds 1) |
| @@ -326,18 +333,25 @@ is output until the first non-zero unit is encountered." | |||
| 326 | (when (string-match | 333 | (when (string-match |
| 327 | (format "%%\\(\\.?[0-9]+\\)?\\(,[0-9]+\\)?\\(%s\\)" spec) | 334 | (format "%%\\(\\.?[0-9]+\\)?\\(,[0-9]+\\)?\\(%s\\)" spec) |
| 328 | string) | 335 | string) |
| 329 | (if (string-equal spec "z") ; must be last in units | 336 | (cond |
| 330 | (setq string | 337 | ((string-equal spec "z") |
| 331 | (replace-regexp-in-string | 338 | (setq chop-leading (and leading-zeropos |
| 332 | "%z" "" | 339 | (min leading-zeropos (match-beginning 0))))) |
| 333 | (substring string (min (or zeropos (match-end 0)) | 340 | ((string-equal spec "x") |
| 334 | (match-beginning 0))))) | 341 | (setq chop-trailing t)) |
| 342 | (t | ||
| 335 | ;; Cf article-make-date-line in gnus-art. | 343 | ;; Cf article-make-date-line in gnus-art. |
| 336 | (setq num (floor seconds unit) | 344 | (setq num (floor seconds unit) |
| 337 | seconds (- seconds (* num unit))) | 345 | seconds (- seconds (* num unit))) |
| 338 | ;; Start position of the first non-zero unit. | 346 | ;; Start position of the first non-zero unit. |
| 339 | (or zeropos | 347 | (when (and (not leading-zeropos) |
| 340 | (setq zeropos (unless (zerop num) (match-beginning 0)))) | 348 | (not (zerop num))) |
| 349 | (setq leading-zeropos (match-beginning 0))) | ||
| 350 | (unless (zerop num) | ||
| 351 | (setq trailing-zeropos nil)) | ||
| 352 | (when (and (not trailing-zeropos) | ||
| 353 | (zerop num)) | ||
| 354 | (setq trailing-zeropos (match-beginning 0))) | ||
| 341 | (setq string | 355 | (setq string |
| 342 | (replace-match | 356 | (replace-match |
| 343 | (format (if (match-string 2 string) | 357 | (format (if (match-string 2 string) |
| @@ -360,7 +374,17 @@ is output until the first non-zero unit is encountered." | |||
| 360 | (format " %s%s" name | 374 | (format " %s%s" name |
| 361 | (if (= num 1) "" "s")))) | 375 | (if (= num 1) "" "s")))) |
| 362 | t t string)))))) | 376 | t t string)))))) |
| 363 | (string-replace "%%" "%" string)) | 377 | (let ((pre string)) |
| 378 | (when (and chop-trailing trailing-zeropos) | ||
| 379 | (setq string (substring string 0 trailing-zeropos))) | ||
| 380 | (when chop-leading | ||
| 381 | (setq string (substring string chop-leading))) | ||
| 382 | ;; If we ended up removing everything, return the formatted | ||
| 383 | ;; string in full. | ||
| 384 | (when (equal string "") | ||
| 385 | (setq string pre))) | ||
| 386 | (setq string (replace-regexp-in-string "%[zx]" "" string))) | ||
| 387 | (string-trim (string-replace "%%" "%" string))) | ||
| 364 | 388 | ||
| 365 | (defvar seconds-to-string | 389 | (defvar seconds-to-string |
| 366 | (list (list 1 "ms" 0.001) | 390 | (list (list 1 "ms" 0.001) |
diff --git a/lisp/emacs-lisp/timer-list.el b/lisp/emacs-lisp/timer-list.el index c93a50cabfe..aef18d0ba27 100644 --- a/lisp/emacs-lisp/timer-list.el +++ b/lisp/emacs-lisp/timer-list.el | |||
| @@ -62,7 +62,7 @@ | |||
| 62 | ((numberp repeat) | 62 | ((numberp repeat) |
| 63 | (propertize | 63 | (propertize |
| 64 | (format "%12s" (format-seconds | 64 | (format "%12s" (format-seconds |
| 65 | "%dd %hh %mm %z%,1ss" repeat)) | 65 | "%x%dd %hh %mm %z%,1ss" repeat)) |
| 66 | 'help-echo "Repeat interval")) | 66 | 'help-echo "Repeat interval")) |
| 67 | ((null repeat) | 67 | ((null repeat) |
| 68 | (propertize " -" 'help-echo "Runs once")) | 68 | (propertize " -" 'help-echo "Runs once")) |
diff --git a/test/lisp/calendar/time-date-tests.el b/test/lisp/calendar/time-date-tests.el index 5a37c914931..fd4d5ac8a1b 100644 --- a/test/lisp/calendar/time-date-tests.el +++ b/test/lisp/calendar/time-date-tests.el | |||
| @@ -88,14 +88,19 @@ | |||
| 88 | (ert-deftest test-format-seconds () | 88 | (ert-deftest test-format-seconds () |
| 89 | (should (equal (format-seconds "%y %d %h %m %s %%" 0) "0 0 0 0 0 %")) | 89 | (should (equal (format-seconds "%y %d %h %m %s %%" 0) "0 0 0 0 0 %")) |
| 90 | (should (equal (format-seconds "%y %d %h %m %s %%" 9999999) "0 115 17 46 39 %")) | 90 | (should (equal (format-seconds "%y %d %h %m %s %%" 9999999) "0 115 17 46 39 %")) |
| 91 | (should (equal (format-seconds "%y %d %h %m %z %s %%" 1) " 1 %")) | 91 | (should (equal (format-seconds "%y %d %h %m %z %s %%" 1) "1 %")) |
| 92 | (should (equal (format-seconds "%mm %ss" 66) "1m 6s")) | 92 | (should (equal (format-seconds "%mm %ss" 66) "1m 6s")) |
| 93 | (should (equal (format-seconds "%mm %5ss" 66) "1m 6s")) | 93 | (should (equal (format-seconds "%mm %5ss" 66) "1m 6s")) |
| 94 | (should (equal (format-seconds "%mm %.5ss" 66.4) "1m 00006s")) | 94 | (should (equal (format-seconds "%mm %.5ss" 66.4) "1m 00006s")) |
| 95 | 95 | ||
| 96 | (should (equal (format-seconds "%mm %,1ss" 66.4) "1m 6.4s")) | 96 | (should (equal (format-seconds "%mm %,1ss" 66.4) "1m 6.4s")) |
| 97 | (should (equal (format-seconds "%mm %5,1ss" 66.4) "1m 6.4s")) | 97 | (should (equal (format-seconds "%mm %5,1ss" 66.4) "1m 6.4s")) |
| 98 | (should (equal (format-seconds "%mm %.5,1ss" 66.4) "1m 006.4s"))) | 98 | (should (equal (format-seconds "%mm %.5,1ss" 66.4) "1m 006.4s")) |
| 99 | |||
| 100 | (should (equal (format-seconds "%hh %z%x%mm %ss" (* 60 2)) "2m")) | ||
| 101 | (should (equal (format-seconds "%hh %z%mm %ss" (* 60 2)) "2m 0s")) | ||
| 102 | (should (equal (format-seconds "%hh %x%mm %ss" (* 60 2)) "0h 2m")) | ||
| 103 | (should (equal (format-seconds "%hh %x%mm %ss" 0) "0h 0m 0s"))) | ||
| 99 | 104 | ||
| 100 | (ert-deftest test-ordinal () | 105 | (ert-deftest test-ordinal () |
| 101 | (should (equal (date-ordinal-to-time 2008 271) | 106 | (should (equal (date-ordinal-to-time 2008 271) |