From 17072a46908b2bf75df85c19306417171b8eeae9 Mon Sep 17 00:00:00 2001 From: Ihor Radchenko Date: Sun, 14 Apr 2024 15:46:15 +0300 Subject: [PATCH] Allow clock elements without timestamp, like CLOCK: => 12:00 This syntax has been introduced in Org 4.78, but not supported later, when Org element parser have been created. Fix this omission to not remove an existing (and announced!) feature. This kind of clock is of limited use though - all the customizations relying upon knowing _when_ clocking time was recorded, like ranges in clock tables or limits on the displayed clocked-in time, will include such clocks unconditionally. So, not adding this to the manual, as it is not very clear how to use it in actual workflow. * lisp/org-element.el (org-element-clock-line-re): Update the regexp. (org-element-clock-parser): Do not assume that timestamp always follows CLOCK: line. * testing/lisp/test-org-element.el (test-org-element/clock-parser): (test-org-element/clock-interpreter): Add tests checking parser and interpreter output of clocks without timestamps. Link: https://orgmode.org/list/87frvpyzrf.fsf@localhost --- lisp/org-element.el | 31 +++++++++++++++++++------------ testing/lisp/test-org-element.el | 17 +++++++++++++++-- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/lisp/org-element.el b/lisp/org-element.el index e7561f16f..ed036a3ff 100644 --- a/lisp/org-element.el +++ b/lisp/org-element.el @@ -126,17 +126,24 @@ Key is located in match group 1.") Style, if any, is located in match group 1.") (defconst org-element-clock-line-re - (rx-to-string - `(seq - line-start (0+ (or ?\t ?\s)) - "CLOCK: " - (regexp ,org-ts-regexp-inactive) - (opt "--" - (regexp ,org-ts-regexp-inactive) - (1+ (or ?\t ?\s)) "=>" (1+ (or ?\t ?\s)) - (1+ digit) ":" digit digit) - (0+ (or ?\t ?\s)) - line-end)) + (let ((duration ; "=> 212:12" + '(seq + (1+ (or ?\t ?\s)) "=>" (1+ (or ?\t ?\s)) + (1+ digit) ":" digit digit))) + (rx-to-string + `(seq + line-start (0+ (or ?\t ?\s)) + "CLOCK:" + (or + (seq + (1+ (or ?\t ?\s)) + (regexp ,org-ts-regexp-inactive) + (opt "--" + (regexp ,org-ts-regexp-inactive) + ,duration)) + ,duration) + (0+ (or ?\t ?\s)) + line-end))) "Regexp matching a clock line.") (defconst org-element-comment-string "COMMENT" @@ -2295,7 +2302,7 @@ Return a new syntax node of `clock' type containing `:status', (value (progn (search-forward "CLOCK:" (line-end-position)) (skip-chars-forward " \t") (org-element-timestamp-parser))) - (duration (and (search-forward " => " (line-end-position) t) + (duration (and (search-forward "=> " (line-end-position) t) (progn (skip-chars-forward " \t") (looking-at "\\(\\S-+\\)[ \t]*$")) (match-string-no-properties 1))) diff --git a/testing/lisp/test-org-element.el b/testing/lisp/test-org-element.el index ddd601690..8b2cf1642 100644 --- a/testing/lisp/test-org-element.el +++ b/testing/lisp/test-org-element.el @@ -1175,7 +1175,15 @@ CLOCK: [2023-10-13 Fri 14:40]--[2023-10-13 Fri 14:51] => 0:11" (should (equal (org-element-property :raw-value (org-element-property :value clock)) "[2012-01-01 sun. 00:01]--[2012-01-01 sun. 00:02]")) - (should (equal (org-element-property :duration clock) "0:01")))) + (should (equal (org-element-property :duration clock) "0:01"))) + ;; Closed clock without timestamp. + (let ((clock + (org-test-with-temp-text + "CLOCK: => 0:11" + (org-element-at-point)))) + (should (eq (org-element-property :status clock) 'closed)) + (should-not (org-element-property :value clock)) + (should (equal (org-element-property :duration clock) "0:11")))) ;;;; Code @@ -3682,7 +3690,12 @@ Outside list" (string-match "CLOCK: \\[2012-01-01 .* 00:01\\]--\\[2012-01-01 .* 00:02\\] => 0:01" (org-test-parse-and-interpret " -CLOCK: [2012-01-01 sun. 00:01]--[2012-01-01 sun. 00:02] => 0:01")))) +CLOCK: [2012-01-01 sun. 00:01]--[2012-01-01 sun. 00:02] => 0:01"))) + ;; Closed clock without timestamp. + (should + (string-match + "CLOCK: => 0:01" + (org-test-parse-and-interpret "CLOCK: => 0:01")))) (ert-deftest test-org-element/comment-interpreter () "Test comment interpreter."