From: Ilya Chernyshov <ichernyshovvv@gmail.com>
To: emacs-orgmode <emacs-orgmode@gnu.org>
Subject: Re: [PATCH] org-element-timestamp-interpreter: Return daterange anyway, if DATERANGE is non-nil
Date: Sun, 19 Feb 2023 21:11:38 +0700 [thread overview]
Message-ID: <87ttzh68w1.fsf@gmail.com> (raw)
In-Reply-To: <87y1ot6dqz.fsf@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 34 bytes --]
I forgot to attach the patch :)
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-org-element-timestamp-interpreter-Return-daterange-a.patch --]
[-- Type: text/x-patch, Size: 13338 bytes --]
From b47324bc804e64e6cef482ba4897a457252e803a Mon Sep 17 00:00:00 2001
From: Ilya Chernyshov <ichernyshovvv@gmail.com>
Date: Sat, 18 Feb 2023 14:55:39 +0700
Subject: [PATCH] org-element-timestamp-interpreter: Return daterange anyway,
if DATERANGE is non-nil
* lisp/org-element (org-element-timestamp-interpreter): Replace
silenced argument with optional argument DATERANGE which controls
whether to return daterange (even if dates in the range are equal) or
timerange (if it's possible). Refactor the code.
* lisp/org-element (org-element-planning-interpreter): Call
`org-element-timestamp-interpreter' without second argument.
* lisp/org-element (org-element-clock-interpreter): Call
`org-element-timestamp-interpreter' with DATERANGE set to t, because
clock entries only support daterange format.
* lisp/org-element (org-element-interpret-data): Call
`org-element-timestamp-interpreter' on timestamp object with DATERANGE
set to t, if it's inactive-range.
* testing/lisp/test-org-element
(test-org-element/timestamp-interpreter): Expect timerange returned
for timestamp of type active-range from
`org-element-timestamp-interpreter' and `org-test-parse-and-interpret'
calls. Add tests for `org-element-timestamp-interpreter' with
DATERANGE argument.
---
lisp/org-element.el | 180 ++++++++++++++-----------------
testing/lisp/test-org-element.el | 28 ++++-
2 files changed, 106 insertions(+), 102 deletions(-)
diff --git a/lisp/org-element.el b/lisp/org-element.el
index d7847a678..9649c6951 100644
--- a/lisp/org-element.el
+++ b/lisp/org-element.el
@@ -2042,7 +2042,7 @@ (defun org-element-clock-interpreter (clock _)
"Interpret CLOCK element as Org syntax."
(concat "CLOCK: "
(org-element-timestamp-interpreter
- (org-element-property :value clock) nil)
+ (org-element-property :value clock) t)
(let ((duration (org-element-property :duration clock)))
(and duration
(concat " => "
@@ -2673,15 +2673,15 @@ (defun org-element-planning-interpreter (planning _)
(list (let ((deadline (org-element-property :deadline planning)))
(when deadline
(concat org-element-deadline-keyword " "
- (org-element-timestamp-interpreter deadline nil))))
+ (org-element-timestamp-interpreter deadline))))
(let ((scheduled (org-element-property :scheduled planning)))
(when scheduled
(concat org-element-scheduled-keyword " "
- (org-element-timestamp-interpreter scheduled nil))))
+ (org-element-timestamp-interpreter scheduled))))
(let ((closed (org-element-property :closed planning)))
(when closed
(concat org-element-closed-keyword " "
- (org-element-timestamp-interpreter closed nil))))))
+ (org-element-timestamp-interpreter closed))))))
" "))
@@ -4020,100 +4020,79 @@ (defun org-element-timestamp-parser ()
repeater-props
warning-props))))))
-(defun org-element-timestamp-interpreter (timestamp _)
- "Interpret TIMESTAMP object as Org syntax."
- (let* ((repeat-string
- (concat
- (pcase (org-element-property :repeater-type timestamp)
- (`cumulate "+") (`catch-up "++") (`restart ".+"))
- (let ((val (org-element-property :repeater-value timestamp)))
- (and val (number-to-string val)))
- (pcase (org-element-property :repeater-unit timestamp)
- (`hour "h") (`day "d") (`week "w") (`month "m") (`year "y"))))
- (warning-string
- (concat
- (pcase (org-element-property :warning-type timestamp)
- (`first "--") (`all "-"))
- (let ((val (org-element-property :warning-value timestamp)))
- (and val (number-to-string val)))
- (pcase (org-element-property :warning-unit timestamp)
- (`hour "h") (`day "d") (`week "w") (`month "m") (`year "y"))))
- (build-ts-string
- ;; Build an Org timestamp string from TIME. ACTIVEP is
- ;; non-nil when time stamp is active. If WITH-TIME-P is
- ;; non-nil, add a time part. HOUR-END and MINUTE-END
- ;; specify a time range in the timestamp. REPEAT-STRING is
- ;; the repeater string, if any.
- (lambda (time activep &optional with-time-p hour-end minute-end)
- (let ((ts (format-time-string
- (org-time-stamp-format with-time-p)
- time)))
- (when (and hour-end minute-end)
- (string-match "[012]?[0-9]:[0-5][0-9]" ts)
- (setq ts
- (replace-match
- (format "\\&-%02d:%02d" hour-end minute-end)
- nil nil ts)))
- (unless activep (setq ts (format "[%s]" (substring ts 1 -1))))
- (dolist (s (list repeat-string warning-string))
- (when (org-string-nw-p s)
- (setq ts (concat (substring ts 0 -1)
- " "
- s
- (substring ts -1)))))
- ;; Return value.
- ts)))
- (type (org-element-property :type timestamp)))
- (pcase type
- ((or `active `inactive)
- (let* ((minute-start (org-element-property :minute-start timestamp))
- (minute-end (org-element-property :minute-end timestamp))
- (hour-start (org-element-property :hour-start timestamp))
- (hour-end (org-element-property :hour-end timestamp))
- (time-range-p (and hour-start hour-end minute-start minute-end
- (or (/= hour-start hour-end)
- (/= minute-start minute-end)))))
- (funcall
- build-ts-string
- (org-encode-time 0
- (or minute-start 0)
- (or hour-start 0)
- (org-element-property :day-start timestamp)
- (org-element-property :month-start timestamp)
- (org-element-property :year-start timestamp))
- (eq type 'active)
- (and hour-start minute-start)
- (and time-range-p hour-end)
- (and time-range-p minute-end))))
- ((or `active-range `inactive-range)
- (let ((minute-start (org-element-property :minute-start timestamp))
- (minute-end (org-element-property :minute-end timestamp))
- (hour-start (org-element-property :hour-start timestamp))
- (hour-end (org-element-property :hour-end timestamp)))
- (concat
- (funcall
- build-ts-string (org-encode-time
- 0
- (or minute-start 0)
- (or hour-start 0)
- (org-element-property :day-start timestamp)
- (org-element-property :month-start timestamp)
- (org-element-property :year-start timestamp))
- (eq type 'active-range)
- (and hour-start minute-start))
- "--"
- (funcall build-ts-string
- (org-encode-time
- 0
- (or minute-end 0)
- (or hour-end 0)
- (org-element-property :day-end timestamp)
- (org-element-property :month-end timestamp)
- (org-element-property :year-end timestamp))
- (eq type 'active-range)
- (and hour-end minute-end)))))
- (_ (org-element-property :raw-value timestamp)))))
-
+(defun org-element-timestamp-interpreter (timestamp &optional daterange)
+ "Interpret TIMESTAMP object as Org syntax.
+
+If DATERANGE is non-nil, create daterange even if dates in the
+range are equal."
+ (if (member
+ (org-element-property :type timestamp)
+ '(active inactive inactive-range active-range))
+ (let((start-date
+ (format-time-string
+ (org-time-stamp-format nil 'no-brackets)
+ (org-encode-time
+ 0 0 0
+ (org-element-property :day-start timestamp)
+ (org-element-property :month-start timestamp)
+ (org-element-property :year-start timestamp)))))
+ (when start-date
+ (let*((repeat-string
+ (concat
+ (pcase (org-element-property :repeater-type timestamp)
+ (`cumulate "+") (`catch-up "++") (`restart ".+"))
+ (let ((val (org-element-property :repeater-value timestamp)))
+ (and val (number-to-string val)))
+ (pcase (org-element-property :repeater-unit timestamp)
+ (`hour "h") (`day "d") (`week "w") (`month "m") (`year "y"))))
+ (warning-string
+ (concat
+ (pcase (org-element-property :warning-type timestamp)
+ (`first "--") (`all "-"))
+ (let ((val (org-element-property :warning-value timestamp)))
+ (and val (number-to-string val)))
+ (pcase (org-element-property :warning-unit timestamp)
+ (`hour "h") (`day "d") (`week "w") (`month "m") (`year "y"))))
+ (hour-start (org-element-property :hour-start timestamp))
+ (minute-start (org-element-property :minute-start timestamp))
+ (start-time
+ (and hour-start minute-start
+ (format "%02d:%02d" hour-start minute-start)))
+ (hour-end (org-element-property :hour-end timestamp))
+ (minute-end (org-element-property :minute-end timestamp))
+ (end-time (and hour-end minute-end
+ (format "%02d:%02d" hour-end minute-end)))
+ (day-end (org-element-property :day-end timestamp))
+ (month-end (org-element-property :month-end timestamp))
+ (year-end (org-element-property :year-end timestamp))
+ (time-range-p (and start-time end-time
+ (not (string= start-time end-time))))
+ (end-date
+ (and year-end month-end day-end
+ (format-time-string
+ (org-time-stamp-format nil 'no-brackets)
+ (org-encode-time
+ 0 0 0 day-end month-end year-end))))
+ (date-range-p (or (and daterange time-range-p)
+ (and end-date (not (string= end-date start-date)))))
+ (ts
+ (concat
+ "<" start-date (and start-time (concat " " start-time))
+ (if date-range-p
+ (concat ">--<" end-date (and end-time (concat " " end-time)))
+ (if time-range-p (concat "-" end-time)))
+ ">")))
+ (dolist (s (list repeat-string warning-string))
+ (when (org-string-nw-p s)
+ (setq ts (string-replace ">" (concat " " s ">") ts))))
+ (pcase (org-element-property :type timestamp)
+ ((or `active `active-range)
+ ts)
+ ((or `inactive `inactive-range)
+ (string-replace
+ "<" "["
+ (string-replace ">" "]" ts)))))))
+ (org-element-property :raw-value timestamp)))
;;;; Underline
@@ -5050,7 +5029,10 @@ (defun org-element-interpret-data (data)
((stringp data) data)
;; Element or object without contents.
((not (org-element-contents data))
- (funcall interpret data nil))
+ (cond ((eq type 'timestamp)
+ (funcall interpret data
+ (eq (org-element-property :type data) 'inactive-range)))
+ (t (funcall interpret data nil))))
;; Element or object with contents.
(t
(funcall
diff --git a/testing/lisp/test-org-element.el b/testing/lisp/test-org-element.el
index 43f1d860f..fd865f38b 100644
--- a/testing/lisp/test-org-element.el
+++ b/testing/lisp/test-org-element.el
@@ -3235,17 +3235,28 @@ (ert-deftest test-org-element/timestamp-interpreter ()
:hour-start 16 :minute-start 40)) nil)))
;; Active range.
(should
- (string-match "<2012-03-29 .* 16:40>--<2012-03-29 .* 16:41>"
+ (string-match "<2012-03-29 .* 16:40-16:41>"
(org-test-parse-and-interpret
"<2012-03-29 thu. 16:40>--<2012-03-29 thu. 16:41>")))
(should
(string-match
- "<2012-03-29 .* 16:40>--<2012-03-29 .* 16:41>"
+ "<2012-03-29 .* 16:40-16:41>"
(org-element-timestamp-interpreter
'(timestamp
(:type active-range :year-start 2012 :month-start 3 :day-start 29
:hour-start 16 :minute-start 40 :year-end 2012 :month-end 3
:day-end 29 :hour-end 16 :minute-end 41)) nil)))
+
+ (should
+ (string-match
+ "<2012-03-29 .* 16:40>--<2012-03-29 .* 16:41>"
+ (org-element-timestamp-interpreter
+ '(timestamp
+ (:type active-range :year-start 2012 :month-start 3 :day-start 29
+ :hour-start 16 :minute-start 40 :year-end 2012 :month-end 3
+ :day-end 29 :hour-end 16 :minute-end 41))
+ t)))
+
;; Inactive range.
(should
(string-match "\\[2012-03-29 .* 16:40\\]--\\[2012-03-29 .* 16:41\\]"
@@ -3258,7 +3269,18 @@ (ert-deftest test-org-element/timestamp-interpreter ()
'(timestamp
(:type inactive-range :year-start 2012 :month-start 3 :day-start 29
:hour-start 16 :minute-start 40 :year-end 2012 :month-end 3
- :day-end 29 :hour-end 16 :minute-end 41)) nil)))
+ :day-end 29 :hour-end 16 :minute-end 41)) t)))
+
+ (should
+ (string-match
+ "\\[2012-03-29 .* 16:40-16:41\\]"
+ (org-element-timestamp-interpreter
+ '(timestamp
+ (:type inactive-range :year-start 2012 :month-start 3 :day-start 29
+ :hour-start 16 :minute-start 40 :year-end 2012 :month-end 3
+ :day-end 29 :hour-end 16 :minute-end 41))
+ nil)))
+
;; Diary.
(should (equal (org-test-parse-and-interpret "<%%diary-float t 4 2>")
"<%%diary-float t 4 2>\n"))
--
2.39.0
[-- Attachment #3: Type: text/plain, Size: 16 bytes --]
--
Best,
Ilya
next prev parent reply other threads:[~2023-02-19 14:14 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-02-19 12:25 [PATCH] org-element-timestamp-interpreter: Return daterange anyway, if DATERANGE is non-nil Ilya Chernyshov
2023-02-19 14:11 ` Ilya Chernyshov [this message]
2023-02-20 11:07 ` Ihor Radchenko
2023-02-20 16:36 ` Ilya Chernyshov
2023-02-22 11:21 ` Ihor Radchenko
2023-07-01 19:47 ` Ilya Chernyshov
2023-07-02 8:46 ` Ihor Radchenko
2023-07-07 7:24 ` Ilya Chernyshov
2023-07-08 8:35 ` Ihor Radchenko
2023-07-10 18:19 ` Ilya Chernyshov
2023-07-11 9:02 ` Ihor Radchenko
2023-07-11 13:16 ` Ilya Chernyshov
2023-07-12 8:16 ` Ihor Radchenko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.orgmode.org/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87ttzh68w1.fsf@gmail.com \
--to=ichernyshovvv@gmail.com \
--cc=emacs-orgmode@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).