org-element: Recognize planning info only right after a headline
authorNicolas Goaziou <mail@nicolasgoaziou.fr>
Sun, 31 Aug 2014 13:39:35 +0000 (15:39 +0200)
committerNicolas Goaziou <mail@nicolasgoaziou.fr>
Sun, 31 Aug 2014 13:39:35 +0000 (15:39 +0200)
* lisp/org.el (org-planning-line-re): New variable.  Renamed from
  `org-planning-or-clock-line-re'.

* lisp/org-element.el (org-element-paragraph-separate,
  org-element-headline-parser, org-element-inlinetask-parser, ,
  org-element--current-element): Use new variable.
(org-element-planning-parser): Check previous line before parsing
planning info.  When right after a headline, fallback to paragraph
parsing.

* testing/lisp/test-org-element.el (test-org-element/planning-parser):
  Add a test.  Update others.
(test-org-element/timestamp): Remove a test.
* testing/lisp/test-ox.el (test-org-export/handle-options): Update
  test.

lisp/org-element.el
lisp/org.el
testing/lisp/test-org-element.el
testing/lisp/test-ox.el

index c1051f6..a02b453 100644 (file)
           "-\\{5,\\}[ \t]*$" "\\|"
           ;; LaTeX environments.
           "\\\\begin{\\([A-Za-z0-9]+\\*?\\)}" "\\|"
-          ;; Planning and Clock lines.
-          (regexp-opt (list org-scheduled-string
-                            org-deadline-string
-                            org-closed-string
-                            org-clock-string))
-          "\\|"
+          ;; Clock lines.
+          (regexp-quote org-clock-string) "\\|"
           ;; Lists.
           (let ((term (case org-plain-list-ordered-item-terminator
                         (?\) ")") (?. "\\.") (otherwise "[.)]")))
@@ -847,7 +843,7 @@ Assume point is at beginning of the headline."
            ;; Read time properties on the line below the headline.
            (save-excursion
              (forward-line)
-             (when (looking-at org-planning-or-clock-line-re)
+             (when (looking-at org-planning-line-re)
                (let ((end (line-end-position)) plist)
                  (while (re-search-forward
                          org-keyword-time-not-clock-regexp end t)
@@ -1006,8 +1002,7 @@ Assume point is at beginning of the inline task."
            ;; opening string.
            (when task-end
              (save-excursion
-               (when (progn (forward-line)
-                            (looking-at org-planning-or-clock-line-re))
+               (when (progn (forward-line) (looking-at org-planning-line-re))
                  (let ((end (line-end-position)) plist)
                    (while (re-search-forward
                            org-keyword-time-not-clock-regexp end t)
@@ -2239,33 +2234,35 @@ LIMIT bounds the search.
 Return a list whose CAR is `planning' and CDR is a plist
 containing `:closed', `:deadline', `:scheduled', `:begin',
 `:end', `:post-blank' and `:post-affiliated' keywords."
-  (save-excursion
-    (let* ((case-fold-search nil)
-          (begin (point))
-          (post-blank (let ((before-blank (progn (forward-line) (point))))
-                        (skip-chars-forward " \r\t\n" limit)
-                        (skip-chars-backward " \t")
-                        (unless (bolp) (end-of-line))
-                        (count-lines before-blank (point))))
-          (end (point))
-          closed deadline scheduled)
-      (goto-char begin)
-      (while (re-search-forward org-keyword-time-not-clock-regexp end t)
-       (goto-char (match-end 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)))))
-      (list 'planning
-           (list :closed closed
-                 :deadline deadline
-                 :scheduled scheduled
-                 :begin begin
-                 :end end
-                 :post-blank post-blank
-                 :post-affiliated begin)))))
+  (if (not (save-excursion (forward-line -1) (org-at-heading-p)))
+      (org-element-paragraph-parser limit (list (point)))
+    (save-excursion
+      (let* ((case-fold-search nil)
+            (begin (point))
+            (post-blank (let ((before-blank (progn (forward-line) (point))))
+                          (skip-chars-forward " \r\t\n" limit)
+                          (skip-chars-backward " \t")
+                          (unless (bolp) (end-of-line))
+                          (count-lines before-blank (point))))
+            (end (point))
+            closed deadline scheduled)
+       (goto-char begin)
+       (while (re-search-forward org-keyword-time-not-clock-regexp end t)
+         (goto-char (match-end 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)))))
+       (list 'planning
+             (list :closed closed
+                   :deadline deadline
+                   :scheduled scheduled
+                   :begin begin
+                   :end end
+                   :post-blank post-blank
+                   :post-affiliated begin))))))
 
 (defun org-element-planning-interpreter (planning contents)
   "Interpret PLANNING element as Org syntax.
@@ -3667,10 +3664,8 @@ 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.
-       ((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)))
+       ((looking-at org-planning-line-re) (org-element-planning-parser limit))
+       ((looking-at org-clock-line-re) (org-element-clock-parser limit))
        ;; Inlinetask.
        ((org-at-heading-p)
        (org-element-inlinetask-parser limit raw-secondary-p))
index bc89968..2b3d00a 100755 (executable)
@@ -387,13 +387,12 @@ A schedule is this string, followed by a time stamp.  Should be a word,
 terminated by a colon.  You can insert a schedule keyword and
 a timestamp with \\[org-schedule].")
 
-(defconst org-planning-or-clock-line-re
+(defconst org-planning-line-re
   (concat "^[ \t]*"
          (regexp-opt
-          (list org-clock-string org-closed-string org-deadline-string
-                org-scheduled-string)
+          (list org-closed-string org-deadline-string org-scheduled-string)
           t))
-  "Matches a line with planning or clock info.
+  "Matches a line with planning info.
 Matched keyword is in group 1.")
 
 (defconst org-clock-line-re
index ceff329..6fb8db8 100644 (file)
@@ -1693,30 +1693,27 @@ Outside list"
 
 (ert-deftest test-org-element/planning-parser ()
   "Test `planning' parser."
+  ;; Test various keywords.
   (should
-   (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))))))
+   (org-element-property
+    :closed
+    (org-test-with-temp-text "* H\n<point>CLOSED: [2012-03-29 thu.]"
+      (org-element-at-point))))
   (should
-   (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))))))
+   (org-element-property
+    :deadline
+    (org-test-with-temp-text "* H\n<point>DEADLINE: <2012-03-29 thu.>"
+      (org-element-at-point))))
   (should
-   (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)))))))
+   (org-element-property
+    :scheduled
+    (org-test-with-temp-text "* H\n<point>SCHEDULED: <2012-03-29 thu.>"
+      (org-element-at-point))))
+  ;; Planning line only exists right after a headline.
+  (should-not
+   (eq 'planning
+       (org-test-with-temp-text "DEADLINE: <2012-03-29 thu.>"
+        (org-element-type (org-element-at-point))))))
 
 
 ;;;; Property Drawer
@@ -2089,11 +2086,7 @@ Outside list"
          (org-test-with-temp-text "<2012-03-29 Thu +1y -1y>"
            (let ((ts (org-element-context)))
              (list (org-element-property :repeater-type ts)
-                   (org-element-property :warning-type ts))))))
-  ;; Timestamps are not planning elements.
-  (should-not
-   (org-test-with-temp-text "SCHEDULED: <2012-03-29 Thu 16:40>"
-     (org-element-map (org-element-parse-buffer) 'timestamp 'identity))))
+                   (org-element-property :warning-type ts)))))))
 
 
 ;;;; Underline
index e67ee95..1e92afe 100644 (file)
@@ -482,15 +482,15 @@ Paragraph"
   ;; Plannings.
   (should
    (string-match
-    "CLOSED: \\[2012-04-29 .* 10:45\\]"
+    "* H\nCLOSED: \\[2012-04-29 .* 10:45\\]"
     (let ((org-closed-string "CLOSED:"))
-      (org-test-with-temp-text "CLOSED: [2012-04-29 sun. 10:45]"
+      (org-test-with-temp-text "* H\nCLOSED: [2012-04-29 sun. 10:45]"
        (org-export-as (org-test-default-backend)
                       nil nil nil '(:with-planning t))))))
   (should
-   (equal ""
+   (equal "* H\n"
          (let ((org-closed-string "CLOSED:"))
-           (org-test-with-temp-text "CLOSED: [2012-04-29 sun. 10:45]"
+           (org-test-with-temp-text "* H\nCLOSED: [2012-04-29 sun. 10:45]"
              (org-export-as (org-test-default-backend)
                             nil nil nil '(:with-planning nil))))))
   ;; Property Drawers.