Browse Source

Merge branch 'master' of orgmode.org:org-mode

Bastien Guerry 11 years ago
parent
commit
255f060ad0
5 changed files with 184 additions and 174 deletions
  1. 12 13
      contrib/lisp/org-license.el
  2. 116 113
      lisp/org-element.el
  3. 9 8
      lisp/org.el
  4. 43 36
      testing/lisp/test-org-element.el
  5. 4 4
      testing/lisp/test-ox.el

+ 12 - 13
contrib/lisp/org-license.el

@@ -97,9 +97,9 @@ Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons Naamsverme
 	  (insert (concat "* Licença
 Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição 3.0 Portugal]]\n")))
 	 (t
-	  (setq org-license-cc-url "http://creativecommons.org/licenses/by/3.0/en/deed.en") 
+	  (setq org-license-cc-url "http://creativecommons.org/licenses/by/4.0/deed") 
 	  (concat (insert "* License
-This document is under a [[" org-license-cc-url "][Creative Commons Attribution 3.0]]\n"))))
+This document is under a [[" org-license-cc-url "][Creative Commons Attribution 4.0 International]]\n"))))
   (if (string= "" org-license-images-directory)
       (insert (concat "\n[[" org-license-cc-url "][file:http://i.creativecommons.org/l/by/3.0/80x15.png]]\n"))
     (insert (concat "\n[[" org-license-cc-url "][file:" org-license-images-directory "/by/3.0/80x15.png]]\n"))))
@@ -155,9 +155,9 @@ Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons Naamsverme
 	 (insert (concat "* Licença
 Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição-CompartilhaIgual 3.0 Portugal]]\n")))
 	(t
-	 (setq org-license-cc-url "http://creativecommons.org/licenses/by-sa/3.0/deed")
+	 (setq org-license-cc-url "http://creativecommons.org/licenses/by-sa/4.0/deed")
 	 (insert (concat "* License
-This document is under a [[" org-license-cc-url "][Creative Commons Attribution-ShareAlike Unported 3.0]]\n"))))
+This document is under a [[" org-license-cc-url "][Creative Commons Attribution-ShareAlike 4.0 International]]\n"))))
   (if (string= "" org-license-images-directory)
       (insert (concat "\n[[" org-license-cc-url "][file:http://i.creativecommons.org/l/by-sa/3.0/80x15.png]]\n"))
     (insert (concat "\n[[" org-license-cc-url "][file:" org-license-images-directory "/by-sa/3.0/80x15.png]]\n"))))
@@ -213,9 +213,9 @@ Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons Naamsverme
 	 (insert (concat "* Licença
 Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição Sem Derivados 3.0 Portugal]]\n")))
 	(t
-	 (setq org-license-cc-url "http://creativecommons.org/licenses/by-nd/3.0/deed")
+	 (setq org-license-cc-url "http://creativecommons.org/licenses/by-nd/4.0/deed")
 	 (insert (concat "* License
-This document is under a [[" org-license-cc-url "][Creative Commons No Derivatives Unported 3.0]]\n"))))
+This document is under a [[" org-license-cc-url "][Creative Commons No Derivatives 4.0 International]]\n"))))
   (if (string= "" org-license-images-directory)
       (insert (concat "\n[[" org-license-cc-url "][file:http://i.creativecommons.org/l/by-nd/3.0/80x15.png]]\n"))
     (insert (concat "\n[[" org-license-cc-url "][file:" org-license-images-directory "/by-nd/3.0/80x15.png]]\n"))))
@@ -272,9 +272,9 @@ Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons Naamsverme
 	 (insert (concat "* Licença
 Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição Não Comercial 3.0 Portugal]]\n")))
 	(t 
-	 (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/3.0/deed")
+	 (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/4.0/deed")
 	 (insert (concat "* License 
-This document is under a [[" org-license-cc-url "][Creative Commons Attribution-NonCommercial 3.0 Unported]]\n"))))
+This document is under a [[" org-license-cc-url "][Creative Commons Attribution-NonCommercial 4.0 International]]\n"))))
   (if (string= "" org-license-images-directory)
       (insert (concat "\n[[" org-license-cc-url "][file:http://i.creativecommons.org/l/by-nc/3.0/80x15.png]]\n"))
     (insert (concat "\n[[" org-license-cc-url "][file:" org-license-images-directory "/by-nc/3.0/80x15.png]]\n"))))
@@ -330,9 +330,9 @@ Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons Naamsverme
 	 (insert (concat "* Licença
 Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição NãoComercial Compartil ha Igual 3.0 Portugal]]\n")))
 	(t 
-	 (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-sa/3.0/deed")
+	 (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-sa/4.0/deed")
 	 (insert (concat "* License
-This document is under a [[" org-license-cc-url "][License Creative Commons Attribution Non Commercial Share Alike 3.0 Unported]]\n"))))
+This document is under a [[" org-license-cc-url "][License Creative Commons Attribution Non Commercial Share Alike 4.0 International]]\n"))))
   (if (string= "" org-license-images-directory)
       (insert (concat "\n[[" org-license-cc-url  "][file:http://i.creativecommons.org/l/by-nc-sa/3.0/80x15.png]]\n"))
     (insert (concat "\n[[" org-license-cc-url "][file:" org-license-images-directory "/by-nc-sa/3.0/80x15.png]]\n"))))
@@ -388,10 +388,9 @@ Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons Naamsverme
 	 (insert (concat "* Licença
 Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição Não Comercial Sem Derivados 3.0 Portugal]]\n")))
 	(t 
-	 (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/3.0/deed")
+	 (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/4.0/deed")
 	 (insert (concat "* License
-This document is under a [[" org-license-cc-url "][License Creative Commons
-Reconocimiento-NoComercial-SinObraDerivada 3.0 Unported]]\n"))))
+This document is under a [[" org-license-cc-url "][License Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International]]\n"))))
   (if (string= "" org-license-images-directory)
       (insert (concat "\n[[" org-license-cc-url "][file:http://i.creativecommons.org/l/by-nc-nd/3.0/80x15.png]]\n"))
     (insert (concat "\n[[" org-license-cc-url "][file:" org-license-images-directory "/by-nc-nd/3.0/80x15.png]]\n"))))

+ 116 - 113
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)
@@ -1396,34 +1391,34 @@ containing `:begin', `:end', `:contents-begin', `:contents-end',
 `:post-blank' and `:post-affiliated' keywords.
 
 Assume point is at the beginning of the property drawer."
-  (save-excursion
-    (let ((case-fold-search t))
-      (if (not (save-excursion
-		 (re-search-forward "^[ \t]*:END:[ \t]*$" limit t)))
-	  ;; Incomplete drawer: parse it as a paragraph.
-	  (org-element-paragraph-parser limit affiliated)
-	(save-excursion
-	  (let* ((drawer-end-line (match-beginning 0))
-		 (begin (car affiliated))
-		 (post-affiliated (point))
-		 (contents-begin (progn (forward-line)
-					(and (< (point) drawer-end-line)
-					     (point))))
-		 (contents-end (and contents-begin drawer-end-line))
-		 (pos-before-blank (progn (goto-char drawer-end-line)
-					  (forward-line)
-					  (point)))
-		 (end (progn (skip-chars-forward " \r\t\n" limit)
-			     (if (eobp) (point) (line-beginning-position)))))
-	    (list 'property-drawer
-		  (nconc
-		   (list :begin begin
-			 :end end
-			 :contents-begin contents-begin
-			 :contents-end contents-end
-			 :post-blank (count-lines pos-before-blank end)
-			 :post-affiliated post-affiliated)
-		   (cdr affiliated)))))))))
+  (let ((case-fold-search t))
+    (if (not (save-excursion (re-search-forward "^[ \t]*:END:[ \t]*$" limit t)))
+	;; Incomplete drawer: parse it as a paragraph.
+	(org-element-paragraph-parser limit affiliated)
+      (save-excursion
+	(let* ((drawer-end-line (match-beginning 0))
+	       (begin (car affiliated))
+	       (post-affiliated (point))
+	       (contents-begin
+		(progn
+		  (forward-line)
+		  (and (re-search-forward org-property-re drawer-end-line t)
+		       (line-beginning-position))))
+	       (contents-end (and contents-begin drawer-end-line))
+	       (pos-before-blank (progn (goto-char drawer-end-line)
+					(forward-line)
+					(point)))
+	       (end (progn (skip-chars-forward " \r\t\n" limit)
+			   (if (eobp) (point) (line-beginning-position)))))
+	  (list 'property-drawer
+		(nconc
+		 (list :begin begin
+		       :end end
+		       :contents-begin contents-begin
+		       :contents-end contents-end
+		       :post-blank (count-lines pos-before-blank end)
+		       :post-affiliated post-affiliated)
+		 (cdr affiliated))))))))
 
 (defun org-element-property-drawer-interpreter (property-drawer contents)
   "Interpret PROPERTY-DRAWER element as Org syntax.
@@ -2105,29 +2100,30 @@ LIMIT bounds the search.
 Return a list whose CAR is `node-property' and CDR is a plist
 containing `:key', `:value', `:begin', `:end', `:post-blank' and
 `:post-affiliated' keywords."
-  (save-excursion
-    (looking-at org-property-re)
-    (let ((case-fold-search t)
-	  (begin (point))
-	  (key   (org-match-string-no-properties 2))
-	  (value (org-match-string-no-properties 3))
-	  (pos-before-blank (progn (forward-line) (point)))
-	  (end (progn (skip-chars-forward " \r\t\n" limit)
-		      (if (eobp) (point) (point-at-bol)))))
-      (list 'node-property
-	    (list :key key
-		  :value value
-		  :begin begin
-		  :end end
-		  :post-blank (count-lines pos-before-blank end)
-		  :post-affiliated begin)))))
+  (looking-at org-property-re)
+  (let ((case-fold-search t)
+	(begin (point))
+	(key   (org-match-string-no-properties 2))
+	(value (org-match-string-no-properties 3))
+	(end (save-excursion
+	       (end-of-line)
+	       (if (re-search-forward org-property-re limit t)
+		   (line-beginning-position)
+		 limit))))
+    (list 'node-property
+	  (list :key key
+		:value value
+		:begin begin
+		:end end
+		:post-blank 0
+		:post-affiliated begin))))
 
 (defun org-element-node-property-interpreter (node-property contents)
   "Interpret NODE-PROPERTY element as Org syntax.
 CONTENTS is nil."
   (format org-property-format
 	  (format ":%s:" (org-element-property :key node-property))
-	  (org-element-property :value node-property)))
+	  (or (org-element-property :value node-property) "")))
 
 
 ;;;; Paragraph
@@ -2238,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.
@@ -3612,8 +3610,7 @@ CONTENTS is nil."
 ;; `section').  Special modes are: `first-section', `item',
 ;; `node-property', `section' and `table-row'.
 
-(defun org-element--current-element
-  (limit &optional granularity special structure)
+(defun org-element--current-element (limit &optional granularity mode structure)
   "Parse the element starting at point.
 
 Return value is a list like (TYPE PROPS) where TYPE is the type
@@ -3630,12 +3627,12 @@ recursion.  Allowed values are `headline', `greater-element',
 nil), secondary values will not be parsed, since they only
 contain objects.
 
-Optional argument SPECIAL, when non-nil, can be either
-`first-section', `item', `node-property', `section', and
-`table-row'.
+Optional argument MODE, when non-nil, can be either
+`first-section', `section', `planning', `item', `node-property'
+and `table-row'.
 
-If STRUCTURE isn't provided but SPECIAL is set to `item', it will
-be computed.
+If STRUCTURE isn't provided but MODE is set to `item', it will be
+computed.
 
 This function assumes point is always at the beginning of the
 element it has to parse."
@@ -3647,29 +3644,29 @@ element it has to parse."
 	  (raw-secondary-p (and granularity (not (eq granularity 'object)))))
       (cond
        ;; Item.
-       ((eq special 'item)
+       ((eq mode 'item)
 	(org-element-item-parser limit structure raw-secondary-p))
        ;; Table Row.
-       ((eq special 'table-row) (org-element-table-row-parser limit))
+       ((eq mode 'table-row) (org-element-table-row-parser limit))
        ;; Node Property.
-       ((eq special 'node-property) (org-element-node-property-parser limit))
+       ((eq mode 'node-property) (org-element-node-property-parser limit))
        ;; Headline.
        ((org-with-limited-levels (org-at-heading-p))
         (org-element-headline-parser limit raw-secondary-p))
        ;; Sections (must be checked after headline).
-       ((eq special 'section) (org-element-section-parser limit))
-       ((eq special 'first-section)
+       ((eq mode 'section) (org-element-section-parser limit))
+       ((eq mode 'first-section)
 	(org-element-section-parser
 	 (or (save-excursion (org-with-limited-levels (outline-next-heading)))
 	     limit)))
+       ;; Planning.
+       ((and (eq mode 'planning) (looking-at org-planning-line-re))
+	(org-element-planning-parser limit))
        ;; When not at bol, point is at the beginning of an item or
        ;; 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)))
+       ;; Clock.
+       ((looking-at org-clock-line-re) (org-element-clock-parser limit))
        ;; Inlinetask.
        ((org-at-heading-p)
 	(org-element-inlinetask-parser limit raw-secondary-p))
@@ -4082,6 +4079,18 @@ looking into captions:
 ;; object is searched only once at top level (but sometimes more for
 ;; nested types).
 
+(defsubst org-element--next-mode (type)
+  "Return next special mode according to TYPE, or nil.
+TYPE is a symbol representing the type of an element or object.
+Modes can be either `first-section', `section', `planning',
+`item', `node-property' and `table-row'."
+  (case type
+    (headline 'section)
+    (section 'planning)
+    (plain-list 'item)
+    (property-drawer 'node-property)
+    (table 'table-row)))
+
 (defun org-element--parse-elements
   (beg end special structure granularity visible-only acc)
   "Parse elements between BEG and END positions.
@@ -4136,11 +4145,7 @@ Elements are accumulated into ACC."
 	  (org-element--parse-elements
 	   cbeg (org-element-property :contents-end element)
 	   ;; Possibly switch to a special mode.
-	   (case type
-	     (headline 'section)
-	     (plain-list 'item)
-	     (property-drawer 'node-property)
-	     (table 'table-row))
+	   (org-element--next-mode type)
 	   (and (memq type '(item plain-list))
 		(org-element-property :structure element))
 	   granularity visible-only element))
@@ -5224,7 +5229,7 @@ the process stopped before finding the expected result."
      (let* ((cached (and (org-element--cache-active-p)
 			 (org-element--cache-find pos nil)))
             (begin (org-element-property :begin cached))
-            element next)
+            element next mode)
        (cond
         ;; Nothing in cache before point: start parsing from first
         ;; element following headline above, or first element in
@@ -5233,7 +5238,8 @@ the process stopped before finding the expected result."
          (when (org-with-limited-levels (outline-previous-heading))
            (forward-line))
          (skip-chars-forward " \r\t\n")
-         (beginning-of-line))
+         (beginning-of-line)
+	 (setq mode 'planning))
         ;; Cache returned exact match: return it.
         ((= pos begin)
 	 (throw 'exit (if syncp (org-element-property :parent cached) cached)))
@@ -5244,7 +5250,8 @@ the process stopped before finding the expected result."
           (org-with-limited-levels org-outline-regexp-bol) begin t)
          (forward-line)
          (skip-chars-forward " \r\t\n")
-         (beginning-of-line))
+         (beginning-of-line)
+	 (setq mode 'planning))
         ;; Check if CACHED or any of its ancestors contain point.
         ;;
         ;; If there is such an element, we inspect it in order to know
@@ -5278,8 +5285,7 @@ the process stopped before finding the expected result."
 		      (save-excursion
 			(org-with-limited-levels (outline-next-heading))
 			(point))))
-	     (parent element)
-	     special-flag)
+	     (parent element))
 	 (while t
 	   (when syncp
 	     (cond ((= (point) pos) (throw 'exit parent))
@@ -5287,7 +5293,7 @@ the process stopped before finding the expected result."
 		    (throw 'interrupt nil))))
 	   (unless element
 	     (setq element (org-element--current-element
-			    end 'element special-flag
+			    end 'element mode
 			    (org-element-property :structure parent)))
 	     (org-element-put-property element :parent parent)
 	     (org-element--cache-put element))
@@ -5327,10 +5333,7 @@ the process stopped before finding the expected result."
 				    (and (= cend pos) (= (point-max) pos)))))
 		   (goto-char (or next cbeg))
 		   (setq next nil
-			 special-flag (case type
-					(plain-list 'item)
-					(property-drawer 'node-property)
-					(table 'table-row))
+			 mode (org-element--next-mode type)
 			 parent element
 			 end cend))))
 	      ;; Otherwise, return ELEMENT as it is the smallest

+ 9 - 8
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
@@ -6261,9 +6260,9 @@ Use `org-reduced-level' to remove the effect of `org-odd-levels'."
  Match group 3 will be set to the value if it exists."
   (concat "^\\(?4:[ \t]*\\)\\(?1::\\(?2:"
  	  (if literal property (regexp-quote property))
-	  "\\):\\)[ \t]+\\(?3:[^ \t\r\n]"
-	  (if allow-null "*")
-	  ".*?\\)\\(?5:[ \t]*\\)$"))
+	  "\\):\\)\\(?:[ \t]+\\(?3:[^ \t\r\n].*?\\)\\)"
+	  (and allow-null "?")
+	  "\\(?5:[ \t]*\\)$"))
 
 (defconst org-property-re
   (org-re-property ".*?" 'literal t)
@@ -22469,7 +22468,9 @@ Alignment is done according to `org-property-format', which see."
 	  (looking-at org-property-re))
     (replace-match
      (concat (match-string 4)
-	     (format org-property-format (match-string 1) (match-string 3)))
+	     (if (match-string 3)
+		 (format org-property-format (match-string 1) (match-string 3))
+	       (match-string 1)))
      t t)))
 
 (defun org-indent-line ()

+ 43 - 36
testing/lisp/test-org-element.el

@@ -1571,23 +1571,37 @@ e^{i\\pi}+1=0
   ;; Standard test.
   (should
    (equal '("abc" "value")
-	  (org-test-with-temp-text ":PROPERTIES:\n:abc: value\n:END:"
-	    (progn (forward-line)
-		   (let ((element (org-element-at-point)))
-		     (list (org-element-property :key element)
-			   (org-element-property :value element)))))))
+	  (org-test-with-temp-text ":PROPERTIES:\n<point>:abc: value\n:END:"
+	    (let ((element (org-element-at-point)))
+	      (list (org-element-property :key element)
+		    (org-element-property :value element))))))
   ;; Value should be trimmed.
   (should
    (equal "value"
-	  (org-test-with-temp-text ":PROPERTIES:\n:abc: value  \n:END:"
-	    (progn (forward-line)
-		   (let ((element (org-element-at-point)))
-		     (org-element-property :value element))))))
+	  (org-test-with-temp-text ":PROPERTIES:\n<point>:abc: value  \n:END:"
+	    (org-element-property :value (org-element-at-point)))))
   ;; A node property requires to be wrapped within a property drawer.
   (should-not
    (eq 'node-property
        (org-test-with-temp-text ":abc: value"
-	 (org-element-type (org-element-at-point))))))
+	 (org-element-type (org-element-at-point)))))
+  ;; Accept empty properties.
+  (should
+   (equal '(("foo" "value") ("bar" nil))
+	  (org-test-with-temp-text ":PROPERTIES:\n:foo: value\n:bar:\n:END:"
+	    (org-element-map (org-element-parse-buffer) 'node-property
+	      (lambda (p)
+		(list (org-element-property :key p)
+		      (org-element-property :value p)))))))
+  ;; Ignore all non-property lines in property drawers.
+  (should
+   (equal
+    '(("foo" "value"))
+    (org-test-with-temp-text ":PROPERTIES:\nWrong1\n:foo: value\nWrong2\n:END:"
+      (org-element-map (org-element-parse-buffer) 'node-property
+	(lambda (p)
+	  (list (org-element-property :key p)
+		(org-element-property :value p))))))))
 
 
 ;;;; Paragraph
@@ -1679,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
@@ -2075,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.