Browse Source

org-element: Recognize planning info only right after a headline

* 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.
Nicolas Goaziou 3 years ago
parent
commit
539eac9211
4 changed files with 61 additions and 74 deletions
  1. 35 40
      lisp/org-element.el
  2. 3 4
      lisp/org.el
  3. 19 26
      testing/lisp/test-org-element.el
  4. 4 4
      testing/lisp/test-ox.el

+ 35 - 40
lisp/org-element.el

@@ -153,12 +153,8 @@
           "-\\{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))

+ 3 - 4
lisp/org.el

@@ -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

+ 19 - 26
testing/lisp/test-org-element.el

@@ -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

+ 4 - 4
testing/lisp/test-ox.el

@@ -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.