summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Goaziou <n.goaziou@gmail.com>2012-09-28 14:50:21 +0200
committerNicolas Goaziou <n.goaziou@gmail.com>2012-10-28 16:29:55 +0100
commitc1e3aaece33f8d603ece5709d5191fe780dd26cc (patch)
treeae872799a5df72d2b767596e4989cca3e30d3c1d
parent2f2a80fe062df5eaacbd5bc3a34a52f6684dcee9 (diff)
downloadorg-mode-c1e3aaece33f8d603ece5709d5191fe780dd26cc.tar.gz
org-element: Improve timestamps parsing
* lisp/org-element.el (org-element-timestamp-parser): Modify timestamp objects properties. (org-element-headline-parser, org-element-inlinetask-parser): Remove `:timestamp' and `:clock' property. Add `:clockedp' property. Also, set `:closed', `:deadline' and `:scheduled' values to timestamp objects, not strings. Small refactoring. (org-element-clock-parser): Rename `:time' property into `:duration'. Also, set `:value' value as a timestamp object, not a string. (org-element-planning-parser): Set `:closed', `:deadline' and `:scheduled' values to timestamp objects, not strings. (org-element-clock-interpreter, org-element-planning-interpreter) (org-element-timestamp-interpreter): Update interpreters. (org-element--current-element): Tiny refactoring. * testing/lisp/test-org-element.el: Add tests.
-rw-r--r--lisp/org-element.el355
-rw-r--r--testing/lisp/test-org-element.el171
2 files changed, 374 insertions, 152 deletions
diff --git a/lisp/org-element.el b/lisp/org-element.el
index c60d979..44449d5 100644
--- a/lisp/org-element.el
+++ b/lisp/org-element.el
@@ -116,6 +116,8 @@
(eval-when-compile (require 'cl))
(require 'org)
+(declare-function org-clocking-buffer "org-clock" ())
+
;;; Definitions And Rules
@@ -711,9 +713,8 @@ Return a list whose CAR is `headline' and CDR is a plist
containing `:raw-value', `:title', `:begin', `:end',
`:pre-blank', `:hiddenp', `:contents-begin' and `:contents-end',
`:level', `:priority', `:tags', `:todo-keyword',`:todo-type',
-`:scheduled', `:deadline', `:timestamp', `:clock', `:category',
-`:quotedp', `:archivedp', `:commentedp' and `:footnote-section-p'
-keywords.
+`:scheduled', `:deadline', `:closed', `:clockedp', `:quotedp',
+`:archivedp', `:commentedp' and `:footnote-section-p' keywords.
The plist also contains any property set in the property drawer,
with its name in lowercase, the underscores replaced with hyphens
@@ -745,23 +746,36 @@ Assume point is at beginning of the headline."
(string= org-footnote-section raw-value)))
;; Normalize property names: ":SOME_PROP:" becomes
;; ":some-prop".
- (standard-props (let (plist)
- (mapc
- (lambda (p)
- (let ((p-name (downcase (car p))))
- (while (string-match "_" p-name)
- (setq p-name
- (replace-match "-" nil nil p-name)))
- (setq p-name (intern (concat ":" p-name)))
- (setq plist
- (plist-put plist p-name (cdr p)))))
- (org-entry-properties nil 'standard))
- plist))
- (time-props (org-entry-properties nil 'special "CLOCK"))
- (scheduled (cdr (assoc "SCHEDULED" time-props)))
- (deadline (cdr (assoc "DEADLINE" time-props)))
- (clock (cdr (assoc "CLOCK" time-props)))
- (timestamp (cdr (assoc "TIMESTAMP" time-props)))
+ (standard-props
+ (let (plist)
+ (mapc
+ (lambda (p)
+ (setq plist
+ (plist-put plist
+ (intern (concat ":"
+ (replace-regexp-in-string
+ "_" "-" (downcase (car p)))))
+ (cdr p))))
+ (org-entry-properties nil 'standard))
+ plist))
+ (time-props
+ ;; Read time properties on the line below the headline.
+ (save-excursion
+ (when (progn (forward-line)
+ (looking-at org-planning-or-clock-line-re))
+ (let ((end (line-end-position)) plist)
+ (while (re-search-forward
+ org-keyword-time-not-clock-regexp end t)
+ (goto-char (match-end 1))
+ (skip-chars-forward " \t")
+ (let ((keyword (match-string 1))
+ (time (org-element-timestamp-parser)))
+ (cond ((equal keyword org-scheduled-string)
+ (setq plist (plist-put plist :scheduled time)))
+ ((equal keyword org-deadline-string)
+ (setq plist (plist-put plist :deadline time)))
+ (t (setq plist (plist-put plist :closed time))))))
+ plist))))
(begin (point))
(end (save-excursion (goto-char (org-end-of-subtree t t))))
(pos-after-head (progn (forward-line) (point)))
@@ -773,7 +787,13 @@ Assume point is at beginning of the headline."
(progn (goto-char end)
(skip-chars-backward " \r\t\n")
(forward-line)
- (point)))))
+ (point))))
+ (clockedp (and (eq (org-clocking-buffer)
+ (or (buffer-base-buffer) (current-buffer)))
+ (save-excursion
+ (goto-char (marker-position org-clock-marker))
+ (org-back-to-heading t)
+ (= (point) begin)))))
;; Clean RAW-VALUE from any quote or comment string.
(when (or quotedp commentedp)
(let ((case-fold-search nil))
@@ -803,10 +823,6 @@ Assume point is at beginning of the headline."
:tags tags
:todo-keyword todo
:todo-type todo-type
- :scheduled scheduled
- :deadline deadline
- :timestamp timestamp
- :clock clock
:post-blank (count-lines
(if (not contents-end) pos-after-head
(goto-char contents-end)
@@ -815,8 +831,10 @@ Assume point is at beginning of the headline."
end)
:footnote-section-p footnote-section-p
:archivedp archivedp
+ :clockedp clockedp
:commentedp commentedp
:quotedp quotedp)
+ time-props
standard-props))))
(org-element-put-property
headline :title
@@ -880,7 +898,7 @@ Return a list whose CAR is `inlinetask' and CDR is a plist
containing `:title', `:begin', `:end', `:hiddenp',
`:contents-begin' and `:contents-end', `:level', `:priority',
`:raw-value', `:tags', `:todo-keyword', `:todo-type',
-`:scheduled', `:deadline', `:timestamp', `:clock' and
+`:scheduled', `:deadline', `:clockedp', `:closed' and
`:post-blank' keywords.
The plist also contains any property set in the property drawer,
@@ -904,27 +922,45 @@ Assume point is at beginning of the inline task."
(raw-value (or (nth 4 components) ""))
;; Normalize property names: ":SOME_PROP:" becomes
;; ":some-prop".
- (standard-props (let (plist)
- (mapc
- (lambda (p)
- (let ((p-name (downcase (car p))))
- (while (string-match "_" p-name)
- (setq p-name
- (replace-match "-" nil nil p-name)))
- (setq p-name (intern (concat ":" p-name)))
- (setq plist
- (plist-put plist p-name (cdr p)))))
- (org-entry-properties nil 'standard))
- plist))
- (time-props (org-entry-properties nil 'special "CLOCK"))
- (scheduled (cdr (assoc "SCHEDULED" time-props)))
- (deadline (cdr (assoc "DEADLINE" time-props)))
- (clock (cdr (assoc "CLOCK" time-props)))
- (timestamp (cdr (assoc "TIMESTAMP" time-props)))
+ (standard-props
+ (let (plist)
+ (mapc
+ (lambda (p)
+ (setq plist
+ (plist-put plist
+ (intern (concat ":"
+ (replace-regexp-in-string
+ "_" "-" (downcase (car p)))))
+ (cdr p))))
+ (org-entry-properties nil 'standard))
+ plist))
+ (time-props
+ ;; Read time properties on the line below the inlinetask
+ ;; opening string.
+ (save-excursion
+ (when (progn (forward-line)
+ (looking-at org-planning-or-clock-line-re))
+ (let ((end (line-end-position)) plist)
+ (while (re-search-forward
+ org-keyword-time-not-clock-regexp end t)
+ (goto-char (match-end 1))
+ (skip-chars-forward " \t")
+ (let ((keyword (match-string 1))
+ (time (org-element-timestamp-parser)))
+ (cond ((equal keyword org-scheduled-string)
+ (setq plist (plist-put plist :scheduled time)))
+ ((equal keyword org-deadline-string)
+ (setq plist (plist-put plist :deadline time)))
+ (t (setq plist (plist-put plist :closed time))))))
+ plist))))
(task-end (save-excursion
(end-of-line)
(and (re-search-forward "^\\*+ END" limit t)
(match-beginning 0))))
+ (clockedp (and (eq (org-clocking-buffer)
+ (or (buffer-base-buffer) (current-buffer)))
+ (let ((clock (marker-position org-clock-marker)))
+ (and (> clock begin) (< clock task-end)))))
(contents-begin (progn (forward-line)
(and task-end (< (point) task-end) (point))))
(hidden (and contents-begin (org-invisible-p2)))
@@ -950,11 +986,9 @@ Assume point is at beginning of the inline task."
:tags tags
:todo-keyword todo
:todo-type todo-type
- :scheduled scheduled
- :deadline deadline
- :timestamp timestamp
- :clock clock
+ :clockedp clockedp
:post-blank (count-lines before-blank end))
+ time-props
standard-props
(cadr keywords)))))
(org-element-put-property
@@ -1427,13 +1461,13 @@ as keywords."
(let* ((case-fold-search nil)
(begin (point))
(value (progn (search-forward org-clock-string (line-end-position) t)
- (org-skip-whitespace)
- (looking-at "\\[.*\\]")
- (org-match-string-no-properties 0)))
- (time (and (progn (goto-char (match-end 0))
- (looking-at " +=> +\\(\\S-+\\)[ \t]*$"))
- (org-match-string-no-properties 1)))
- (status (if time 'closed 'running))
+ (skip-chars-forward " \t")
+ (org-element-timestamp-parser)))
+ (duration (and (search-forward " => " (line-end-position) t)
+ (progn (skip-chars-forward " \t")
+ (looking-at "\\(\\S-+\\)[ \t]*$"))
+ (org-match-string-no-properties 1)))
+ (status (if duration 'closed 'running))
(post-blank (let ((before-blank (progn (forward-line) (point))))
(skip-chars-forward " \r\t\n" limit)
(skip-chars-backward " \t")
@@ -1443,7 +1477,7 @@ as keywords."
(list 'clock
(list :status status
:value value
- :time time
+ :duration duration
:begin begin
:end end
:post-blank post-blank)))))
@@ -1452,13 +1486,14 @@ as keywords."
"Interpret CLOCK element as Org syntax.
CONTENTS is nil."
(concat org-clock-string " "
- (org-element-property :value clock)
- (let ((time (org-element-property :time clock)))
- (and time
+ (org-element-timestamp-interpreter
+ (org-element-property :value clock) nil)
+ (let ((duration (org-element-property :duration clock)))
+ (and duration
(concat " => "
(apply 'format
"%2s:%02s"
- (org-split-string time ":")))))))
+ (org-split-string duration ":")))))))
;;;; Comment
@@ -2049,13 +2084,11 @@ and `:post-blank' keywords."
(end (point))
closed deadline scheduled)
(goto-char begin)
- (while (re-search-forward org-keyword-time-not-clock-regexp
- (line-end-position) t)
+ (while (re-search-forward org-keyword-time-not-clock-regexp end t)
(goto-char (match-end 1))
- (org-skip-whitespace)
- (let ((time (buffer-substring-no-properties
- (1+ (point)) (1- (match-end 0))))
- (keyword (match-string 1)))
+ (skip-chars-forward " \t" end)
+ (let ((keyword (match-string 1))
+ (time (org-element-timestamp-parser)))
(cond ((equal keyword org-closed-string) (setq closed time))
((equal keyword org-deadline-string) (setq deadline time))
(t (setq scheduled time)))))
@@ -2073,13 +2106,18 @@ CONTENTS is nil."
(mapconcat
'identity
(delq nil
- (list (let ((closed (org-element-property :closed planning)))
- (when closed (concat org-closed-string " [" closed "]")))
- (let ((deadline (org-element-property :deadline planning)))
- (when deadline (concat org-deadline-string " <" deadline ">")))
+ (list (let ((deadline (org-element-property :deadline planning)))
+ (when deadline
+ (concat org-deadline-string " "
+ (org-element-timestamp-interpreter deadline nil))))
(let ((scheduled (org-element-property :scheduled planning)))
(when scheduled
- (concat org-scheduled-string " <" scheduled ">")))))
+ (concat org-scheduled-string " "
+ (org-element-timestamp-interpreter scheduled nil))))
+ (let ((closed (org-element-property :closed planning)))
+ (when closed
+ (concat org-closed-string " "
+ (org-element-timestamp-interpreter closed nil))))))
" "))
@@ -3358,39 +3396,168 @@ Assume point is at the beginning of the timestamp."
(save-excursion
(let* ((begin (point))
(activep (eq (char-after) ?<))
- (main-value
+ (raw-value
(progn
- (looking-at "[<[]\\(\\(%%\\)?.*?\\)[]>]\\(?:--[<[]\\(.*?\\)[]>]\\)?")
- (match-string-no-properties 1)))
- (range-end (match-string-no-properties 3))
- (type (cond ((match-string 2) 'diary)
- ((and activep range-end) 'active-range)
+ (looking-at "\\([<[]\\(%%\\)?.*?\\)[]>]\\(?:--\\([<[].*?[]>]\\)\\)?")
+ (match-string-no-properties 0)))
+ (date-start (match-string-no-properties 1))
+ (date-end (match-string 3))
+ (diaryp (match-beginning 2))
+ (type (cond (diaryp 'diary)
+ ((and activep date-end) 'active-range)
(activep 'active)
- (range-end 'inactive-range)
+ (date-end 'inactive-range)
(t 'inactive)))
(post-blank (progn (goto-char (match-end 0))
(skip-chars-forward " \t")))
- (end (point)))
+ (end (point))
+ (with-time-p (string-match "[012]?[0-9]:[0-5][0-9]" date-start))
+ (repeater-props
+ (and (not diaryp)
+ (string-match "\\([.+]?\\+\\)\\([0-9]+\\)\\([hdwmy]\\)>"
+ raw-value)
+ (list
+ :repeater-type
+ (let ((type (match-string 1 raw-value)))
+ (cond ((equal "++" type) 'catch-up)
+ ((equal ".+" type) 'restart)
+ (t 'cumulate)))
+ :repeater-value (string-to-number (match-string 2 raw-value))
+ :repeater-unit
+ (case (string-to-char (match-string 3 raw-value))
+ (?h 'hour) (?d 'day) (?w 'week) (?m 'month) (t 'year)))))
+ time-range year-start month-start day-start hour-start minute-start
+ year-end month-end day-end hour-end minute-end)
+ ;; Extract time range, if any, and remove it from date start.
+ (setq time-range
+ (and (not diaryp)
+ (string-match
+ "[012]?[0-9]:[0-5][0-9]\\(-\\([012]?[0-9]\\):\\([0-5][0-9]\\)\\)"
+ date-start)
+ (cons (string-to-number (match-string 2 date-start))
+ (string-to-number (match-string 3 date-start)))))
+ (when time-range
+ (setq date-start (replace-match "" nil nil date-start 1)))
+ ;; Parse date-start.
+ (unless diaryp
+ (let ((date (org-parse-time-string date-start)))
+ (setq year-start (nth 5 date)
+ month-start (nth 4 date)
+ day-start (nth 3 date)
+ hour-start (and with-time-p (nth 2 date))
+ minute-start (and with-time-p (nth 1 date)))))
+ ;; Compute date-end. It can be provided directly in time-stamp,
+ ;; or extracted from time range. Otherwise, it defaults to the
+ ;; same values as date-start.
+ (unless diaryp
+ (let ((date (and date-end (org-parse-time-string date-end))))
+ (setq year-end (or (nth 5 date) year-start)
+ month-end (or (nth 4 date) month-start)
+ day-end (or (nth 3 date) day-start)
+ hour-end (or (nth 2 date) (car time-range) hour-start)
+ minute-end (or (nth 1 date) (cdr time-range) minute-start))))
(list 'timestamp
- (list :type type
- :value main-value
- :range-end range-end
- :begin begin
- :end end
- :post-blank post-blank)))))
+ (nconc (list :type type
+ :raw-value raw-value
+ :year-start year-start
+ :month-start month-start
+ :day-start day-start
+ :hour-start hour-start
+ :minute-start minute-start
+ :year-end year-end
+ :month-end month-end
+ :day-end day-end
+ :hour-end hour-end
+ :minute-end minute-end
+ :begin begin
+ :end end
+ :post-blank post-blank)
+ repeater-props)))))
(defun org-element-timestamp-interpreter (timestamp contents)
"Interpret TIMESTAMP object as Org syntax.
CONTENTS is nil."
- (let ((type (org-element-property :type timestamp) ))
- (concat
- (format (if (memq type '(inactive inactive-range)) "[%s]" "<%s>")
- (org-element-property :value timestamp))
- (let ((range-end (org-element-property :range-end timestamp)))
- (when range-end
- (concat "--"
- (format (if (eq type 'inactive-range) "[%s]" "<%s>")
- range-end)))))))
+ ;; Use `:raw-value' if specified.
+ (or (org-element-property :raw-value timestamp)
+ ;; Otherwise, build timestamp string.
+ (let ((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 repeat-string)
+ (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))))
+ (when (org-string-nw-p repeat-string)
+ (setq ts (concat (substring ts 0 -1)
+ " "
+ repeat-string
+ (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)
+ (concat (case (org-element-property :repeater-type timestamp)
+ (cumulate "+") (catch-up "++") (restart ".+"))
+ (org-element-property :repeater-value timestamp)
+ (org-element-property :repeater-unit timestamp)))))
+ ((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 (limit)
"Search for the next timestamp object.
@@ -3539,7 +3706,7 @@ element it has to parse."
;; a footnote definition: next item is always a paragraph.
((not (bolp)) (org-element-paragraph-parser limit (list (point))))
;; Planning and Clock.
- ((and (looking-at org-planning-or-clock-line-re))
+ ((looking-at org-planning-or-clock-line-re)
(if (equal (match-string 1) org-clock-string)
(org-element-clock-parser limit)
(org-element-planning-parser limit)))
diff --git a/testing/lisp/test-org-element.el b/testing/lisp/test-org-element.el
index 18f78b0..768f3d3 100644
--- a/testing/lisp/test-org-element.el
+++ b/testing/lisp/test-org-element.el
@@ -278,22 +278,24 @@ Some other text
;; Running clock.
(let* ((org-clock-string "CLOCK:")
(clock (org-test-with-temp-text "CLOCK: [2012-01-01 sun. 00:01]"
- (org-element-map
- (org-element-parse-buffer) 'clock 'identity nil t))))
+ (org-element-at-point))))
(should (eq (org-element-property :status clock) 'running))
- (should (equal (org-element-property :value clock)
- "[2012-01-01 sun. 00:01]"))
- (should-not (org-element-property :time clock)))
+ (should
+ (equal (org-element-property :raw-value
+ (org-element-property :value clock))
+ "[2012-01-01 sun. 00:01]"))
+ (should-not (org-element-property :duration clock)))
;; Closed clock.
(let* ((org-clock-string "CLOCK:")
- (clock (org-test-with-temp-text "
-CLOCK: [2012-01-01 sun. 00:01]--[2012-01-01 sun. 00:02] => 0:01"
- (org-element-map
- (org-element-parse-buffer) 'clock 'identity nil t))))
+ (clock
+ (org-test-with-temp-text
+ "CLOCK: [2012-01-01 sun. 00:01]--[2012-01-01 sun. 00:02] => 0:01"
+ (org-element-at-point))))
(should (eq (org-element-property :status clock) 'closed))
- (should (equal (org-element-property :value clock)
+ (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 :time clock) "0:01"))))
+ (should (equal (org-element-property :duration clock) "0:01"))))
;;;; Code
@@ -1382,26 +1384,29 @@ Outside list"
(ert-deftest test-org-element/planning-parser ()
"Test `planning' parser."
(should
- (equal
- (org-element-property
- :closed
- (org-test-with-temp-text "CLOSED: [2012-03-29 thu.]"
- (org-element-map (org-element-parse-buffer) 'planning 'identity nil t)))
- "2012-03-29 thu."))
+ (equal "[2012-03-29 thu.]"
+ (org-element-property
+ :raw-value
+ (org-element-property
+ :closed
+ (org-test-with-temp-text "CLOSED: [2012-03-29 thu.]"
+ (org-element-at-point))))))
(should
- (equal
- (org-element-property
- :deadline
- (org-test-with-temp-text "DEADLINE: <2012-03-29 thu.>"
- (org-element-map (org-element-parse-buffer) 'planning 'identity nil t)))
- "2012-03-29 thu."))
+ (equal "<2012-03-29 thu.>"
+ (org-element-property
+ :raw-value
+ (org-element-property
+ :deadline
+ (org-test-with-temp-text "DEADLINE: <2012-03-29 thu.>"
+ (org-element-at-point))))))
(should
- (equal
- (org-element-property
- :scheduled
- (org-test-with-temp-text "SCHEDULED: <2012-03-29 thu.>"
- (org-element-map (org-element-parse-buffer) 'planning 'identity nil t)))
- "2012-03-29 thu.")))
+ (equal "<2012-03-29 thu.>"
+ (org-element-property
+ :raw-value
+ (org-element-property
+ :scheduled
+ (org-test-with-temp-text "SCHEDULED: <2012-03-29 thu.>"
+ (org-element-at-point)))))))
;;;; Property Drawer
@@ -1707,27 +1712,41 @@ Outside list"
;; Active timestamp.
(should
(org-test-with-temp-text "<2012-03-29 16:40>"
- (eq (org-element-property :type
- (org-element-map
- (org-element-parse-buffer)
- 'timestamp 'identity nil t))
- 'active)))
+ (eq (org-element-property :type (org-element-context)) 'active)))
+ (should
+ (equal '(2012 3 29 16 40)
+ (org-test-with-temp-text "<2012-03-29 16:40>"
+ (let ((object (org-element-context)))
+ (list (org-element-property :year-start object)
+ (org-element-property :month-start object)
+ (org-element-property :day-start object)
+ (org-element-property :hour-start object)
+ (org-element-property :minute-start object))))))
;; Inactive timestamp.
(should
(org-test-with-temp-text "[2012-03-29 16:40]"
- (eq (org-element-property :type
- (org-element-map
- (org-element-parse-buffer)
- 'timestamp 'identity nil t))
- 'inactive)))
+ (eq (org-element-property :type (org-element-context)) 'inactive)))
+ ;; Time range.
+ (should
+ (equal '(2012 3 29 16 40 7 30)
+ (org-test-with-temp-text "<2012-03-29 7:30-16:40>"
+ (let ((object (org-element-context)))
+ (list (org-element-property :year-end object)
+ (org-element-property :month-end object)
+ (org-element-property :day-end object)
+ (org-element-property :hour-end object)
+ (org-element-property :minute-end object)
+ (org-element-property :hour-start object)
+ (org-element-property :minute-start object))))))
;; Date range.
(should
(org-test-with-temp-text "[2012-03-29 16:40]--[2012-03-29 16:41]"
- (eq (org-element-property :type
- (org-element-map
- (org-element-parse-buffer)
- 'timestamp 'identity nil t))
- 'inactive-range)))
+ (eq (org-element-property :type (org-element-context)) 'inactive-range)))
+ ;; With repeater.
+ (should
+ (eq 'catch-up
+ (org-test-with-temp-text "<2012-03-29 ++1y>"
+ (org-element-property :repeater-type (org-element-context)))))
;; Timestamps are not planning elements.
(should-not
(org-test-with-temp-text "SCHEDULED: <2012-03-29 16:40>"
@@ -2102,9 +2121,9 @@ CLOCK: [2012-01-01 sun. 00:01]--[2012-01-01 sun. 00:02] => 0:01"))
(equal
(org-test-parse-and-interpret
"* Headline
-CLOSED: [2012-01-01] DEADLINE: <2012-01-01> SCHEDULED: <2012-01-01>")
+DEADLINE: <2012-01-01> SCHEDULED: <2012-01-01> CLOSED: [2012-01-01]")
"* Headline
-CLOSED: [2012-01-01] DEADLINE: <2012-01-01> SCHEDULED: <2012-01-01>\n"))))
+DEADLINE: <2012-01-01> SCHEDULED: <2012-01-01> CLOSED: [2012-01-01]\n"))))
(ert-deftest test-org-element/property-drawer-interpreter ()
"Test property drawer interpreter."
@@ -2159,25 +2178,61 @@ CLOSED: [2012-01-01] DEADLINE: <2012-01-01> SCHEDULED: <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 16:40>")
- "<2012-03-29 16:40>\n"))
+ (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-element-timestamp-interpreter
+ '(timestamp
+ (: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 16:40]")
- "[2012-03-29 16:40]\n"))
+ (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-element-timestamp-interpreter
+ '(timestamp
+ (: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 16:40>--<2012-03-29 16:41>")
- "<2012-03-29 16:40>--<2012-03-29 16:41>\n"))
+ "<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-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)))
;; Inactive range.
(should (equal (org-test-parse-and-interpret
- "[2012-03-29 16:40]--[2012-03-29 16:41]")
- "[2012-03-29 16:40]--[2012-03-29 16:41]\n"))
+ "[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-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 "<%%org-float t 4 2>")
- "<%%org-float t 4 2>\n"))
+ (should (equal (org-test-parse-and-interpret "<%%(org-float t 4 2)>")
+ "<%%(org-float t 4 2)>\n"))
;; Timestamp with repeater interval.
- (should (equal (org-test-parse-and-interpret "<2012-03-29 +1y>")
- "<2012-03-29 +1y>\n")))
+ (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-element-timestamp-interpreter
+ '(timestamp
+ (:type active :year-start 2012 :month-start 3 :day-start 29
+ :repeater-type cumulate :repeater-value "1y")) nil))))
(ert-deftest test-org-element/verse-block-interpreter ()
"Test verse block interpretation."