From fc95ee2768549dfd1f8fd3d6e3a77161cefc1f56 Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Sat, 16 Nov 2013 10:15:28 +0100 Subject: [PATCH] org-element: Change to timestamp interpreter * lisp/org-element.el (org-element-timestamp-interpreter): Ignore :raw-value and build timestamp from numeric properties instead. * testing/lisp/test-org-element.el: Update tests. * testing/lisp/test-ox.el: Update tests. This change allow to modify and update a timestamp easily without requiring to reset :raw-value first, which was not intuitive. --- lisp/org-element.el | 185 +++++++++++++++++++-------------------- testing/lisp/test-org-element.el | 57 ++++++------ testing/lisp/test-ox.el | 41 ++++----- 3 files changed, 144 insertions(+), 139 deletions(-) diff --git a/lisp/org-element.el b/lisp/org-element.el index fc59d4414..57e26ffb5 100644 --- a/lisp/org-element.el +++ b/lisp/org-element.el @@ -3550,100 +3550,97 @@ Assume point is at the beginning of the timestamp." (defun org-element-timestamp-interpreter (timestamp contents) "Interpret TIMESTAMP object as Org syntax. CONTENTS is nil." - ;; Use `:raw-value' if specified. - (or (org-element-property :raw-value timestamp) - ;; Otherwise, build timestamp string. - (let* ((repeat-string - (concat - (case (org-element-property :repeater-type timestamp) - (cumulate "+") (catch-up "++") (restart ".+")) - (let ((val (org-element-property :repeater-value timestamp))) - (and val (number-to-string val))) - (case (org-element-property :repeater-unit timestamp) - (hour "h") (day "d") (week "w") (month "m") (year "y")))) - (warning-string - (concat - (case (org-element-property :warning-type timestamp) - (first "--") - (all "-")) - (let ((val (org-element-property :warning-value timestamp))) - (and val (number-to-string val))) - (case (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 - (funcall (if with-time-p 'cdr 'car) - org-time-stamp-formats) - 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))) - (case type - ((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 - (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)))) - ((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 (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 - (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))))))))) + (let* ((repeat-string + (concat + (case (org-element-property :repeater-type timestamp) + (cumulate "+") (catch-up "++") (restart ".+")) + (let ((val (org-element-property :repeater-value timestamp))) + (and val (number-to-string val))) + (case (org-element-property :repeater-unit timestamp) + (hour "h") (day "d") (week "w") (month "m") (year "y")))) + (warning-string + (concat + (case (org-element-property :warning-type timestamp) + (first "--") + (all "-")) + (let ((val (org-element-property :warning-value timestamp))) + (and val (number-to-string val))) + (case (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 + (funcall (if with-time-p 'cdr 'car) + org-time-stamp-formats) + 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))) + (case type + ((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 + (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)))) + ((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 (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 + (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)))))))) (defun org-element-timestamp-successor () "Search for the next timestamp object. diff --git a/testing/lisp/test-org-element.el b/testing/lisp/test-org-element.el index ad98199b5..45a0bfa11 100644 --- a/testing/lisp/test-org-element.el +++ b/testing/lisp/test-org-element.el @@ -2211,16 +2211,17 @@ Outside list" "Test clock interpreter." ;; Running clock. (should - (equal (let ((org-clock-string "CLOCK:")) - (org-test-parse-and-interpret "CLOCK: [2012-01-01 sun. 00:01]")) - "CLOCK: [2012-01-01 sun. 00:01]\n")) + (string-match + "CLOCK: \\[2012-01-01 .* 00:01\\]" + (let ((org-clock-string "CLOCK:")) + (org-test-parse-and-interpret "CLOCK: [2012-01-01 sun. 00:01]")))) ;; Closed clock. (should - (equal + (string-match + "CLOCK: \\[2012-01-01 .* 00:01\\]--\\[2012-01-01 .* 00:02\\] => 0:01" (let ((org-clock-string "CLOCK:")) (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\n"))) +CLOCK: [2012-01-01 sun. 00:01]--[2012-01-01 sun. 00:02] => 0:01"))))) (ert-deftest test-org-element/comment-interpreter () "Test comment interpreter." @@ -2320,12 +2321,12 @@ CLOCK: [2012-01-01 sun. 00:01]--[2012-01-01 sun. 00:02] => 0:01")) (org-deadline-string "DEADLINE:") (org-scheduled-string "SCHEDULED:")) (should - (equal + (string-match + "\\* Headline +DEADLINE: <2012-03-29 .*?> SCHEDULED: <2012-03-29 .*?> CLOSED: \\[2012-03-29 .*?\\]" (org-test-parse-and-interpret "* Headline -DEADLINE: <2012-01-01> SCHEDULED: <2012-01-01> CLOSED: [2012-01-01]") - "* Headline -DEADLINE: <2012-01-01> SCHEDULED: <2012-01-01> CLOSED: [2012-01-01]\n")))) +DEADLINE: <2012-03-29 thu.> SCHEDULED: <2012-03-29 thu.> CLOSED: [2012-03-29 thu.]"))))) (ert-deftest test-org-element/property-drawer-interpreter () "Test property drawer interpreter." @@ -2395,8 +2396,9 @@ DEADLINE: <2012-01-01> SCHEDULED: <2012-01-01> CLOSED: [2012-01-01]\n")))) (ert-deftest test-org-element/timestamp-interpreter () "Test timestamp interpreter." ;; Active. - (should (equal (org-test-parse-and-interpret "<2012-03-29 thu. 16:40>") - "<2012-03-29 thu. 16:40>\n")) + (should + (string-match "<2012-03-29 .* 16:40>" + (org-test-parse-and-interpret "<2012-03-29 thu. 16:40>"))) (should (string-match "<2012-03-29 .* 16:40>" (org-element-timestamp-interpreter @@ -2404,8 +2406,9 @@ DEADLINE: <2012-01-01> SCHEDULED: <2012-01-01> CLOSED: [2012-01-01]\n")))) (:type active :year-start 2012 :month-start 3 :day-start 29 :hour-start 16 :minute-start 40)) nil))) ;; Inactive. - (should (equal (org-test-parse-and-interpret "[2012-03-29 thu. 16:40]") - "[2012-03-29 thu. 16:40]\n")) + (should + (string-match "\\[2012-03-29 .* 16:40\\]" + (org-test-parse-and-interpret "[2012-03-29 thu. 16:40]"))) (should (string-match "\\[2012-03-29 .* 16:40\\]" @@ -2414,9 +2417,10 @@ DEADLINE: <2012-01-01> SCHEDULED: <2012-01-01> CLOSED: [2012-01-01]\n")))) (:type inactive :year-start 2012 :month-start 3 :day-start 29 :hour-start 16 :minute-start 40)) nil))) ;; Active range. - (should (equal (org-test-parse-and-interpret - "<2012-03-29 thu. 16:40>--<2012-03-29 thu. 16:41>") - "<2012-03-29 thu. 16:40>--<2012-03-29 thu. 16:41>\n")) + (should + (string-match "<2012-03-29 .* 16:40>--<2012-03-29 .* 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>" @@ -2426,9 +2430,10 @@ DEADLINE: <2012-01-01> SCHEDULED: <2012-01-01> CLOSED: [2012-01-01]\n")))) :hour-start 16 :minute-start 40 :year-end 2012 :month-end 3 :day-end 29 :hour-end 16 :minute-end 41)) nil))) ;; Inactive range. - (should (equal (org-test-parse-and-interpret - "[2012-03-29 thu. 16:40]--[2012-03-29 thu. 16:41]") - "[2012-03-29 thu. 16:40]--[2012-03-29 thu. 16:41]\n")) + (should + (string-match "\\[2012-03-29 .* 16:40\\]--\\[2012-03-29 .* 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\\]" @@ -2441,8 +2446,9 @@ DEADLINE: <2012-01-01> SCHEDULED: <2012-01-01> CLOSED: [2012-01-01]\n")))) (should (equal (org-test-parse-and-interpret "<%%diary-float t 4 2>") "<%%diary-float t 4 2>\n")) ;; Timestamp with repeater interval, with delay, with both. - (should (equal (org-test-parse-and-interpret "<2012-03-29 thu. +1y>") - "<2012-03-29 thu. +1y>\n")) + (should + (string-match "<2012-03-29 .* \\+1y>" + (org-test-parse-and-interpret "<2012-03-29 thu. +1y>"))) (should (string-match "<2012-03-29 .* \\+1y>" @@ -2469,9 +2475,10 @@ DEADLINE: <2012-01-01> SCHEDULED: <2012-01-01> CLOSED: [2012-01-01]\n")))) :repeater-type cumulate :repeater-value 1 :repeater-unit year)) nil))) ;; Timestamp range with repeater interval - (should (equal (org-test-parse-and-interpret - "<2012-03-29 Thu +1y>--<2012-03-30 Thu +1y>") - "<2012-03-29 Thu +1y>--<2012-03-30 Thu +1y>\n")) + (should + (string-match "<2012-03-29 .* \\+1y>--<2012-03-30 .* \\+1y>" + (org-test-parse-and-interpret + "<2012-03-29 Thu +1y>--<2012-03-30 Thu +1y>"))) (should (string-match "<2012-03-29 .* \\+1y>--<2012-03-30 .* \\+1y>" diff --git a/testing/lisp/test-ox.el b/testing/lisp/test-ox.el index b375f9c35..c9b2eed89 100644 --- a/testing/lisp/test-ox.el +++ b/testing/lisp/test-ox.el @@ -400,11 +400,11 @@ Paragraph" nil nil nil '(:with-archived-trees t)))))) ;; Clocks. (should - (equal "CLOCK: [2012-04-29 sun. 10:45]\n" - (let ((org-clock-string "CLOCK:")) - (org-test-with-temp-text "CLOCK: [2012-04-29 sun. 10:45]" - (org-export-as (org-test-default-backend) - nil nil nil '(:with-clocks t)))))) + (string-match "CLOCK: \\[2012-04-29 .* 10:45\\]" + (let ((org-clock-string "CLOCK:")) + (org-test-with-temp-text "CLOCK: [2012-04-29 sun. 10:45]" + (org-export-as (org-test-default-backend) + nil nil nil '(:with-clocks t)))))) (should (equal "" (let ((org-clock-string "CLOCK:")) @@ -464,11 +464,12 @@ Paragraph" nil nil nil '(:with-inlinetasks nil))))))) ;; Plannings. (should - (equal "CLOSED: [2012-04-29 sun. 10:45]\n" - (let ((org-closed-string "CLOSED:")) - (org-test-with-temp-text "CLOSED: [2012-04-29 sun. 10:45]" - (org-export-as (org-test-default-backend) - nil nil nil '(:with-planning t)))))) + (string-match + "CLOSED: \\[2012-04-29 .* 10:45\\]" + (let ((org-closed-string "CLOSED:")) + (org-test-with-temp-text "CLOSED: [2012-04-29 sun. 10:45]" + (org-export-as (org-test-default-backend) + nil nil nil '(:with-planning t)))))) (should (equal "" (let ((org-closed-string "CLOSED:")) @@ -505,8 +506,8 @@ Paragraph" "Test `org-export-with-timestamps' specifications." ;; t value. (should - (equal - "[2012-04-29 sun. 10:45]<2012-04-29 sun. 10:45>\n" + (string-match + "\\[2012-04-29 .*? 10:45\\]<2012-04-29 .*? 10:45>" (org-test-with-temp-text "[2012-04-29 sun. 10:45]<2012-04-29 sun. 10:45>" (org-export-as (org-test-default-backend) nil nil nil '(:with-timestamps t))))) @@ -519,24 +520,24 @@ Paragraph" nil nil nil '(:with-timestamps nil))))) ;; `active' value. (should - (equal - "<2012-03-29 Thu>\n\nParagraph <2012-03-29 Thu>[2012-03-29 Thu]" + (string-match + "<2012-03-29 .*?>\n\nParagraph <2012-03-29 .*?>\\[2012-03-29 .*?\\]" (org-test-with-temp-text "<2012-03-29 Thu>[2012-03-29 Thu] Paragraph <2012-03-29 Thu>[2012-03-29 Thu]" - (org-trim (org-export-as (org-test-default-backend) - nil nil nil '(:with-timestamps active)))))) + (org-export-as (org-test-default-backend) + nil nil nil '(:with-timestamps active))))) ;; `inactive' value. (should - (equal - "[2012-03-29 Thu]\n\nParagraph <2012-03-29 Thu>[2012-03-29 Thu]" + (string-match + "\\[2012-03-29 .*?\\]\n\nParagraph <2012-03-29 .*?>\\[2012-03-29 .*?\\]" (org-test-with-temp-text "<2012-03-29 Thu>[2012-03-29 Thu] Paragraph <2012-03-29 Thu>[2012-03-29 Thu]" - (org-trim (org-export-as (org-test-default-backend) - nil nil nil '(:with-timestamps inactive))))))) + (org-export-as (org-test-default-backend) + nil nil nil '(:with-timestamps inactive)))))) (ert-deftest test-org-export/comment-tree () "Test if export process ignores commented trees." -- 2.11.4.GIT