Browse Source

ox: Allow multi-line objects in `parse' options

* lisp/ox.el (org-export--get-inbuffer-options): Allow multi-line objects.
* testing/lisp/test-ox.el (test-org-export/get-inbuffer-options): Add
  tests.  Update some others.

It is possible to write, e.g.,

  #+TITLE: *bold
  #+TITLE: sentence*
Nicolas Goaziou 10 years ago
parent
commit
105ec604c2
2 changed files with 41 additions and 17 deletions
  1. 27 14
      lisp/ox.el
  2. 14 3
      testing/lisp/test-ox.el

+ 27 - 14
lisp/ox.el

@@ -1474,6 +1474,7 @@ Assume buffer is in Org mode.  Narrowing, if any, is ignored."
 	      (dolist (option options properties)
 		(when (equal (nth 1 option) keyword)
 		  (pushnew (car option) properties))))))
+	 to-parse
 	 (get-options
 	  (lambda (&optional files plist)
 	    ;; Recursively read keywords in buffer.  FILES is a list
@@ -1522,19 +1523,18 @@ Assume buffer is in Org mode.  Narrowing, if any, is ignored."
 			   ;; BEHAVIOR.
 			   (case (nth 4 (assq property options))
 			     (parse
+			      (unless (memq property to-parse)
+				(push property to-parse))
+			      ;; Even if `parse' implies `space'
+			      ;; behavior, we separate line with "\n"
+			      ;; so as to preserve line-breaks.
+			      ;; However, empty lines are forbidden
+			      ;; since `parse' doesn't allow more than
+			      ;; one paragraph.
 			      (let ((old (plist-get plist property)))
-				(apply
-				 #'org-element-adopt-elements
-				 old
-				 (org-element-parse-secondary-string
-				  (concat
-				   (and
-				    old
-				    (not (eq (org-element-type (org-last old))
-					     'line-break))
-				    " ")
-				   val)
-				  (org-element-restriction 'keyword)))))
+				(cond ((not (org-string-nw-p val)) old)
+				      (old (concat old "\n" val))
+				      (t val))))
 			     (space
 			      (if (not (plist-get plist property))
 				  (org-trim val)
@@ -1552,10 +1552,23 @@ Assume buffer is in Org mode.  Narrowing, if any, is ignored."
 			     (otherwise
 			      (if (not (plist-member plist property)) val
 				(plist-get plist property)))))))))))))
-	     ;; Return final value.
 	     plist))))
     ;; Read options in the current buffer and return value.
-    (funcall get-options (and buffer-file-name (list buffer-file-name)) nil)))
+    (let ((options (funcall get-options
+			    (and buffer-file-name (list buffer-file-name))
+			    nil)))
+      ;; Parse properties in TO-PARSE.  Remove newline characters not
+      ;; involved in line breaks to simulate `space' behaviour.
+      ;; Finally return options.
+      (dolist (p to-parse options)
+	(let ((value (org-element-parse-secondary-string
+		      (plist-get options p)
+		      (org-element-restriction 'keyword))))
+	  (org-element-map value 'plain-text
+	    (lambda (s)
+	      (org-element-set-element
+	       s (replace-regexp-in-string "\n" " " s))))
+	  (setq options (plist-put options p value)))))))
 
 (defun org-export--get-buffer-attributes ()
   "Return properties related to buffer attributes, as a plist."

+ 14 - 3
testing/lisp/test-ox.el

@@ -162,7 +162,8 @@ variable, and communication channel under `info'."
     (org-test-with-temp-text "#+SELECT_TAGS: a\n#+SELECT_TAGS: b"
       (org-export--get-inbuffer-options))
     '(:select-tags ("a" "b"))))
-  ;; Test `parse' behaviour.
+  ;; Test `parse' behaviour.  `parse' implies `space' but preserve
+  ;; line breaks.  Multi-line objects are allowed.
   (should
    (org-element-map
        (org-test-with-temp-text "#+TITLE: *bold*"
@@ -172,7 +173,17 @@ variable, and communication channel under `info'."
    (equal
     (org-test-with-temp-text "#+TITLE: Some title\n#+TITLE: with spaces"
       (plist-get (org-export--get-inbuffer-options) :title))
-    '("Some title" " with spaces")))
+    '("Some title with spaces")))
+  (should
+   (org-element-map
+       (org-test-with-temp-text "#+TITLE: Some title\\\\\n#+TITLE: with spaces"
+	 (plist-get (org-export--get-inbuffer-options) :title))
+       'line-break #'identity nil t))
+  (should
+   (org-element-map
+       (org-test-with-temp-text "#+TITLE: *bold\n#+TITLE: sentence*"
+	 (plist-get (org-export--get-inbuffer-options) :title))
+       'bold #'identity nil t))
   ;; Options set through SETUPFILE.
   (should
    (equal
@@ -187,7 +198,7 @@ variable, and communication channel under `info'."
 #+TITLE: c"
 		org-test-dir)
       (org-export--get-inbuffer-options))
-    '(:language "fr" :select-tags ("a" "b" "c") :title ("a" " b" " c"))))
+    '(:language "fr" :select-tags ("a" "b" "c") :title ("a b c"))))
   ;; More than one property can refer to the same buffer keyword.
   (should
    (equal '(:k2 "value" :k1 "value")