]> git.eshelyaron.com Git - emacs.git/commitdiff
Make list-times not include zero elements
authorLars Ingebrigtsen <larsi@gnus.org>
Wed, 13 Apr 2022 13:31:02 +0000 (15:31 +0200)
committerLars Ingebrigtsen <larsi@gnus.org>
Wed, 13 Apr 2022 13:31:34 +0000 (15:31 +0200)
* 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.

doc/lispref/os.texi
etc/NEWS
lisp/calendar/time-date.el
lisp/emacs-lisp/timer-list.el
test/lisp/calendar/time-date-tests.el

index 9cb9bc75d045759e709fa4edacb986ea0c872a6d..4ee893f860f6e322105e6e70919b87a5d3e295f8 100644 (file)
@@ -1961,6 +1961,10 @@ encountered.  For example, the default format used by
 @w{@code{"%Y, %D, %H, %M, %z%S"}} means that the number of seconds
 will always be produced, but years, days, hours, and minutes will only
 be shown if they are non-zero.
+@item %x
+Non-printing control flag that works along the same lines as
+@samp{%z}, but instead suppresses printing of trailing zero-value time
+elements.
 @item %%
 Produces a literal @samp{%}.
 @end table
index 8665a825ce75b7681c8686714e6b47ed4018d9ee..c24f3f6ed5a1b43dc2361edcf9477f734c8b3321 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1856,6 +1856,11 @@ temporary transition aid for Emacs 27, has served its purpose.
 month, day, or time.  For example, (date-to-time "2021-12-04") now
 assumes a time of 00:00 instead of signaling an error.
 
++++
+** 'format-seconds' now allows suppressing zero-value trailing elements.
+The new "%x" non-printing control character will suppress zero-value
+elements that appear after "%x".
+
 +++
 ** New events for taking advantage of touchscreen devices.
 The events 'touchscreen-begin, 'touchscreen-update', and
index 51cf7eb213f5bfaaff71c0cc89a1b9f91146be37..0db973ea161a36c5e41d50b848458ec317e8a3a8 100644 (file)
@@ -287,17 +287,23 @@ use.  \"%,1s\" means \"use one decimal\".
 
 The \"%z\" specifier does not print anything.  When it is used, specifiers
 must be given in order of decreasing size.  To the left of \"%z\", nothing
-is output until the first non-zero unit is encountered."
+is output until the first non-zero unit is encountered.
+
+The \"%x\" specifier does not print anything.  When it is used,
+specifiers must be given in order of decreasing size.  To the
+right of \"%x\", trailing zero units are not output."
   (let ((start 0)
         (units '(("y" "year"   31536000)
                  ("d" "day"       86400)
                  ("h" "hour"       3600)
                  ("m" "minute"       60)
                  ("s" "second"        1)
-                 ("z")))
+                 ("z")
+                 ("x")))
         (case-fold-search t)
-        spec match usedunits zeroflag larger prev name unit num zeropos
-        fraction)
+        spec match usedunits zeroflag larger prev name unit num
+        leading-zeropos trailing-zeropos fraction
+        chop-leading chop-trailing)
     (while (string-match "%\\.?[0-9]*\\(,[0-9]\\)?\\(.\\)" string start)
       (setq start (match-end 0)
             spec (match-string 2 string))
@@ -306,15 +312,16 @@ is output until the first non-zero unit is encountered."
             (error "Bad format specifier: `%s'" spec))
         (if (assoc (downcase spec) usedunits)
             (error "Multiple instances of specifier: `%s'" spec))
-        (if (string-equal (car match) "z")
+        (if (or (string-equal (car match) "z")
+                (string-equal (car match) "x"))
             (setq zeroflag t)
           (unless larger
             (setq unit (nth 2 match)
                   larger (and prev (> unit prev))
                   prev unit)))
         (push match usedunits)))
-    (and zeroflag larger
-         (error "Units are not in decreasing order of size"))
+    (when (and zeroflag larger)
+      (error "Units are not in decreasing order of size"))
     (unless (numberp seconds)
       (setq seconds (float-time seconds)))
     (setq fraction (mod seconds 1)
@@ -326,18 +333,25 @@ is output until the first non-zero unit is encountered."
       (when (string-match
              (format "%%\\(\\.?[0-9]+\\)?\\(,[0-9]+\\)?\\(%s\\)" spec)
              string)
-        (if (string-equal spec "z")     ; must be last in units
-            (setq string
-                  (replace-regexp-in-string
-                   "%z" ""
-                   (substring string (min (or zeropos (match-end 0))
-                                          (match-beginning 0)))))
+        (cond
+         ((string-equal spec "z")
+          (setq chop-leading (and leading-zeropos
+                                  (min leading-zeropos (match-beginning 0)))))
+         ((string-equal spec "x")
+          (setq chop-trailing t))
+         (t
           ;; Cf article-make-date-line in gnus-art.
           (setq num (floor seconds unit)
                 seconds (- seconds (* num unit)))
           ;; Start position of the first non-zero unit.
-          (or zeropos
-              (setq zeropos (unless (zerop num) (match-beginning 0))))
+          (when (and (not leading-zeropos)
+                     (not (zerop num)))
+            (setq leading-zeropos (match-beginning 0)))
+          (unless (zerop num)
+            (setq trailing-zeropos nil))
+          (when (and (not trailing-zeropos)
+                     (zerop num))
+            (setq trailing-zeropos (match-beginning 0)))
           (setq string
                 (replace-match
                  (format (if (match-string 2 string)
@@ -360,7 +374,17 @@ is output until the first non-zero unit is encountered."
                            (format " %s%s" name
                                    (if (= num 1) "" "s"))))
                  t t string))))))
-  (string-replace "%%" "%" string))
+    (let ((pre string))
+      (when (and chop-trailing trailing-zeropos)
+        (setq string (substring string 0 trailing-zeropos)))
+      (when chop-leading
+        (setq string (substring string chop-leading)))
+      ;; If we ended up removing everything, return the formatted
+      ;; string in full.
+      (when (equal string "")
+        (setq string pre)))
+    (setq string (replace-regexp-in-string "%[zx]" "" string)))
+  (string-trim (string-replace "%%" "%" string)))
 
 (defvar seconds-to-string
   (list (list 1 "ms" 0.001)
index c93a50cabfe014cb0ad4e2203e4e52f535abbf44..aef18d0ba275730f2f458cc202d4a5d612537698 100644 (file)
@@ -62,7 +62,7 @@
                   ((numberp repeat)
                    (propertize
                     (format "%12s" (format-seconds
-                                    "%dd %hh %mm %z%,1ss" repeat))
+                                    "%x%dd %hh %mm %z%,1ss" repeat))
                     'help-echo "Repeat interval"))
                   ((null repeat)
                    (propertize "           -" 'help-echo "Runs once"))
index 5a37c9149313521a43d39d68d5a61d8a156e5dc7..fd4d5ac8a1bb2bd81e7dbfab6dbdf815c314d982 100644 (file)
 (ert-deftest test-format-seconds ()
   (should (equal (format-seconds "%y %d %h %m %s %%" 0) "0 0 0 0 0 %"))
   (should (equal (format-seconds "%y %d %h %m %s %%" 9999999) "0 115 17 46 39 %"))
-  (should (equal (format-seconds "%y %d %h %m %z %s %%" 1) " 1 %"))
+  (should (equal (format-seconds "%y %d %h %m %z %s %%" 1) "1 %"))
   (should (equal (format-seconds "%mm %ss" 66) "1m 6s"))
   (should (equal (format-seconds "%mm %5ss" 66) "1m     6s"))
   (should (equal (format-seconds "%mm %.5ss" 66.4) "1m 00006s"))
 
   (should (equal (format-seconds "%mm %,1ss" 66.4) "1m 6.4s"))
   (should (equal (format-seconds "%mm %5,1ss" 66.4) "1m   6.4s"))
-  (should (equal (format-seconds "%mm %.5,1ss" 66.4) "1m 006.4s")))
+  (should (equal (format-seconds "%mm %.5,1ss" 66.4) "1m 006.4s"))
+
+  (should (equal (format-seconds "%hh %z%x%mm %ss" (* 60 2)) "2m"))
+  (should (equal (format-seconds "%hh %z%mm %ss" (* 60 2)) "2m 0s"))
+  (should (equal (format-seconds "%hh %x%mm %ss" (* 60 2)) "0h 2m"))
+  (should (equal (format-seconds "%hh %x%mm %ss" 0) "0h 0m 0s")))
 
 (ert-deftest test-ordinal ()
   (should (equal (date-ordinal-to-time 2008 271)