emacs-orgmode
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v4] org-encode-time compatibility and convenience helper


From: Max Nikulin
Subject: Re: [PATCH v4] org-encode-time compatibility and convenience helper
Date: Tue, 10 May 2022 21:31:25 +0700
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.8.1

On 05/05/2022 22:22, Max Nikulin wrote:
On 04/05/2022 16:56, Ihor Radchenko wrote:
Max Nikulin writes:

Resetting timezone to UTC should be fixed in timestamps generated by a testing helper function. I was disappointed that `mapcar' can not be used with multiple lists, but I have found an old function created namely for zeroing nils in timestamps.

Most of the changes are rather trivial. Some code I do not like though or unsure that I chose a proper approach.

+      (defmacro org-encode-time (&rest time)
+        (pcase (length time) ; Emacs-29 since d75e2c12eb
+          (1 `(encode-time ,@time))
+          ((or 6 9) `(encode-time (list ,@time)))
+          (_ (error "`org-encode-time' may be called with 1, 6, or 9 arguments but 
%d given"
+                    (length time)))))

Should it be something like the following?

(signal 'wrong-type-argument (list '(1 6 9) (length time)))

or even

(signal 'wrong-type-argument
         (list '(lambda (n-args) (memq n-args) '(1 6 9)) (length time)))

Usually "wrong type argument" errors give no clue even related to called function til enabling enter debugger on error and realizing how to reproduce the problem.

diff --git a/lisp/org-clock.el b/lisp/org-clock.el
index 9f80dea04..da5c310b7 100644
--- a/lisp/org-clock.el
+++ b/lisp/org-clock.el
@@ -2866,20 +2866,21 @@ a number of clock tables."
       ;; Compute NEXT, which is the end of the current clock table,
       ;; according to step.
       (let* ((next
-              (apply #'encode-time
-                     (pcase-let
-                         ((`(,_ ,_ ,_ ,d ,m ,y ,dow . ,_) (decode-time start)))
-                       (pcase step
-                         (`day (list 0 0 org-extend-today-until (1+ d) m y))
-                         (`week
-                          (let ((offset (if (= dow week-start) 7
-                                          (mod (- week-start dow) 7))))
-                            (list 0 0 org-extend-today-until (+ d offset) m 
y)))
-                         (`semimonth (list 0 0 0
-                                           (if (< d 16) 16 1)
-                                           (if (< d 16) m (1+ m)) y))
-                         (`month (list 0 0 0 month-start (1+ m) y))
-                         (`year (list 0 0 org-extend-today-until 1 1 (1+ 
y)))))))
+              ;; In Emacs-27 and Emacs-28 `encode-time' does not support 6 
elements
+              ;; list argument so `org-encode-time' can not be outside of 
`pcase'.
+              (pcase-let
+                  ((`(,_ ,_ ,_ ,d ,m ,y ,dow . ,_) (decode-time start)))
+                (pcase step
+                  (`day (org-encode-time 0 0 org-extend-today-until (1+ d) m 
y))
+                  (`week
+                   (let ((offset (if (= dow week-start) 7
+                                   (mod (- week-start dow) 7))))
+                     (org-encode-time 0 0 org-extend-today-until (+ d offset) 
m y)))
+                  (`semimonth (org-encode-time 0 0 0
+                                               (if (< d 16) 16 1)
+                                               (if (< d 16) m (1+ m)) y))
+                  (`month (org-encode-time 0 0 0 month-start (1+ m) y))
+                  (`year (org-encode-time 0 0 org-extend-today-until 1 1 (1+ 
y))))))
              (table-begin (line-beginning-position 0))
             (step-time
               ;; Write clock table between START and NEXT.

I do not like repeating of `org-encode-time' but do not see another way till Emacs-29 will become the lowest supported version.

diff --git a/lisp/org.el b/lisp/org.el
index 165c83609..3288bb7b8 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -14472,14 +14474,15 @@ When SUPPRESS-TMP-DELAY is non-nil, suppress delays 
like
          (setcar (cdr time0) (+ (nth 1 time0)
                                 (if (> n 0) (- rem) (- dm rem))))))
       (setq time
-           (apply #'encode-time
-                  (or (car time0) 0)
-                  (+ (if (eq timestamp? 'minute) n 0) (nth 1 time0))
-                  (+ (if (eq timestamp? 'hour) n 0)   (nth 2 time0))
-                  (+ (if (eq timestamp? 'day) n 0)    (nth 3 time0))
-                  (+ (if (eq timestamp? 'month) n 0)  (nth 4 time0))
-                  (+ (if (eq timestamp? 'year) n 0)   (nth 5 time0))
-                  (nthcdr 6 time0)))
+           (org-encode-time
+             (apply #'list
+                    (or (car time0) 0)
+                    (+ (if (eq timestamp? 'minute) n 0) (nth 1 time0))
+                    (+ (if (eq timestamp? 'hour) n 0)   (nth 2 time0))
+                    (+ (if (eq timestamp? 'day) n 0)    (nth 3 time0))
+                    (+ (if (eq timestamp? 'month) n 0)  (nth 4 time0))
+                    (+ (if (eq timestamp? 'year) n 0)   (nth 5 time0))
+                    (nthcdr 6 time0))))
       (when (and (memq timestamp? '(hour minute))
                 extra
                 (string-match "-\\([012][0-9]\\):\\([0-5][0-9]\\)" extra))

I am tempting to write something like

  (let* ((ts (copy-sequence time0))
         (ord (memq timestamp? '(year month day hour minute)))
         (field (and ord (nthcdr (length ord) ts))))
    (when field
      (setcar field (+ (car field) n)))
    (org-encode-time ts))

but I am afraid it will make the code rather obscure.

@@ -19276,12 +19279,14 @@ return an active timestamp."
   "Convert TIMESTAMP object into an Emacs internal time value.
 Use end of date range or time range when END is non-nil.
 Otherwise, use its start."
-  (apply #'encode-time 0
-        (mapcar
-         (lambda (prop) (or (org-element-property prop timestamp) 0))
-         (if end '(:minute-end :hour-end :day-end :month-end :year-end)
-           '(:minute-start :hour-start :day-start :month-start
-                           :year-start)))))
+  (org-encode-time
+   (append '(0)
+           (mapcar
+            (lambda (prop) (or (org-element-property prop timestamp) 0))
+            (if end '(:minute-end :hour-end :day-end :month-end :year-end)
+              '(:minute-start :hour-start :day-start :month-start
+                              :year-start)))
+           '(nil -1 nil))))
(defun org-timestamp-has-time-p (timestamp)
   "Non-nil when TIMESTAMP has a time specified."

Hardly may be considered as an example of elegant code.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]