Forráskód Böngészése

ox: Handle subtree properties referring to multiple options

* lisp/ox.el (org-export--get-subtree-options): When multiple options
  refer to the same keyword, and, as a consequence, to the same export
  property, make sure all of them get updated.
* testing/lisp/test-ox.el (test-org-export/get-subtree-options): Add
  test.

Reported-by: Myles English <mylesenglish@gmail.com>
<http://permalink.gmane.org/gmane.emacs.orgmode/98583>
Nicolas Goaziou 9 éve
szülő
commit
b07bd32081
2 módosított fájl, 70 hozzáadás és 73 törlés
  1. 35 42
      lisp/ox.el
  2. 35 31
      testing/lisp/test-ox.el

+ 35 - 42
lisp/ox.el

@@ -1364,52 +1364,45 @@ for export.  Return options as a plist."
   ;; same property in communication channel.  The name for the
   ;; property is the keyword with "EXPORT_" appended to it.
   (org-with-wide-buffer
-   (let (plist
+   ;; Make sure point is at a heading.
+   (if (org-at-heading-p) (org-up-heading-safe) (org-back-to-heading t))
+   (let ((plist
+	  ;; EXPORT_OPTIONS are parsed in a non-standard way.  Take
+	  ;; care of them right from the start.
+	  (let ((o (org-entry-get (point) "EXPORT_OPTIONS")))
+	    (and o (org-export--parse-option-keyword o backend))))
+	 ;; Take care of EXPORT_TITLE.  If it isn't defined, use
+	 ;; headline's title (with no todo keyword, priority cookie or
+	 ;; tag) as its fallback value.
+	 (cache (list
+		 (cons "TITLE"
+		       (or (org-entry-get (point) "EXPORT_TITLE")
+			   (progn (looking-at org-complex-heading-regexp)
+				  (org-match-string-no-properties 4))))))
 	 ;; Look for both general keywords and back-end specific
 	 ;; options, with priority given to the latter.
 	 (options (append (and backend (org-export-get-all-options backend))
 			  org-export-options-alist)))
-     ;; Make sure point is at a heading.
-     (if (org-at-heading-p) (org-up-heading-safe) (org-back-to-heading t))
-     ;; Take care of EXPORT_TITLE.  If it isn't defined, use
-     ;; headline's title (with no todo keyword, priority cookie or
-     ;; tag) as its fallback value.
-     (let ((title (or (org-entry-get (point) "EXPORT_TITLE")
-		      (progn (looking-at org-complex-heading-regexp)
-			     (org-match-string-no-properties 4)))))
-       (setq plist
-	     (plist-put
-	      plist :title
-	      (if (eq (nth 4 (assq :title options)) 'parse)
-		  (org-element-parse-secondary-string
-		   title (org-element-restriction 'keyword))
-		title))))
-     ;; EXPORT_OPTIONS are parsed in a non-standard way.
-     (let ((o (org-entry-get (point) "EXPORT_OPTIONS")))
-       (when o
-	 (setq plist
-	       (nconc plist (org-export--parse-option-keyword o backend)))))
-     ;; Handle other keywords.  TITLE keyword is excluded as it has
-     ;; been handled already.  Then return PLIST.
-     (let ((seen '("TITLE")))
-       (dolist (option options plist)
-	 (let ((property (car option))
-	       (keyword (nth 1 option)))
-	   (when (and keyword (not (member keyword seen)))
-	     (let* ((subtree-prop (concat "EXPORT_" keyword))
-		    (value (org-entry-get (point) subtree-prop)))
-	       (push keyword seen)
-	       (when (and value (not (plist-member plist property)))
-		 (setq plist
-		       (plist-put
-			plist
-			property
-			(case (nth 4 option)
-			  (parse
-			   (org-element-parse-secondary-string
-			    value (org-element-restriction 'keyword)))
-			  (split (org-split-string value))
-			  (t value)))))))))))))
+     ;; Handle other keywords.  Then return PLIST.
+     (dolist (option options plist)
+       (let ((property (car option))
+	     (keyword (nth 1 option)))
+	 (when keyword
+	   (let ((value
+		  (or (cdr (assoc keyword cache))
+		      (let ((v (org-entry-get (point)
+					      (concat "EXPORT_" keyword))))
+			(push (cons keyword v) cache) v))))
+	     (when value
+	       (setq plist
+		     (plist-put plist
+				property
+				(case (nth 4 option)
+				  (parse
+				   (org-element-parse-secondary-string
+				    value (org-element-restriction 'keyword)))
+				  (split (org-split-string value))
+				  (t value))))))))))))
 
 (defun org-export--get-inbuffer-options (&optional backend)
   "Return current buffer export options, as a plist.

+ 35 - 31
testing/lisp/test-ox.el

@@ -225,77 +225,81 @@ variable, and communication channel under `info'."
 (ert-deftest test-org-export/get-subtree-options ()
   "Test setting options from headline's properties."
   ;; EXPORT_TITLE.
-  (org-test-with-temp-text "#+TITLE: Title
-* Headline
+  (should
+   (equal '("Subtree Title")
+	  (org-test-with-temp-text "#+TITLE: Title
+* Headline<point>
   :PROPERTIES:
   :EXPORT_TITLE: Subtree Title
   :END:
 Paragraph"
-    (forward-line)
-    (should (equal (plist-get (org-export-get-environment nil t) :title)
-		   '("Subtree Title"))))
-  :title
-  '("subtree-title")
+	    (plist-get (org-export-get-environment nil t) :title))))
   ;; EXPORT_OPTIONS.
-  (org-test-with-temp-text "#+OPTIONS: H:1
-* Headline
+  (should
+   (= 2
+      (org-test-with-temp-text "#+OPTIONS: H:1
+* Headline<point>
   :PROPERTIES:
   :EXPORT_OPTIONS: H:2
   :END:
 Paragraph"
-    (forward-line)
-    (should
-     (= 2 (plist-get (org-export-get-environment nil t) :headline-levels))))
+	(plist-get (org-export-get-environment nil t) :headline-levels))))
   ;; EXPORT_DATE.
-  (org-test-with-temp-text "#+DATE: today
-* Headline
+  (should
+   (equal '("29-03-2012")
+	  (org-test-with-temp-text "#+DATE: today
+* Headline<point>
   :PROPERTIES:
   :EXPORT_DATE: 29-03-2012
   :END:
 Paragraph"
-    (forward-line)
-    (should (equal (plist-get (org-export-get-environment nil t) :date)
-		   '("29-03-2012"))))
+	    (plist-get (org-export-get-environment nil t) :date))))
   ;; Properties with `split' behaviour are stored as a list of
   ;; strings.
   (should
    (equal '("a" "b")
 	  (org-test-with-temp-text "#+EXCLUDE_TAGS: noexport
-* Headline
+* Headline<point>
   :PROPERTIES:
   :EXPORT_EXCLUDE_TAGS: a b
   :END:
 Paragraph"
-	    (progn
-	      (forward-line)
-	      (plist-get (org-export-get-environment nil t) :exclude-tags)))))
+	    (plist-get (org-export-get-environment nil t) :exclude-tags))))
   ;; Handle :PROPERTY+: syntax.
   (should
    (equal '("a" "b")
 	  (org-test-with-temp-text "#+EXCLUDE_TAGS: noexport
-* Headline
+* Headline<point>
   :PROPERTIES:
   :EXPORT_EXCLUDE_TAGS: a
   :EXPORT_EXCLUDE_TAGS+: b
   :END:
 Paragraph"
-	    (progn
-	      (forward-line)
-	      (plist-get (org-export-get-environment nil t) :exclude-tags)))))
+	    (plist-get (org-export-get-environment nil t) :exclude-tags))))
   ;; Export properties are case-insensitive.
-  (org-test-with-temp-text "* Headline
+  (should
+   (equal '("29-03-2012")
+	  (org-test-with-temp-text "* Headline
   :PROPERTIES:
   :EXPORT_Date: 29-03-2012
   :END:
 Paragraph"
-    (should (equal (plist-get (org-export-get-environment nil t) :date)
-		   '("29-03-2012"))))
+	    (plist-get (org-export-get-environment nil t) :date))))
   ;; Still grab correct options when section above is empty.
   (should
    (equal '("H1")
-	  (org-test-with-temp-text "* H1\n** H11\n** H12"
-	    (progn (forward-line 2)
-		   (plist-get (org-export-get-environment nil t) :title))))))
+	  (org-test-with-temp-text "* H1\n** H11\n** H12<point>"
+	    (plist-get (org-export-get-environment nil t) :title))))
+  ;; More than one property can refer to the same node property.
+  (should
+   (equal '("1" "1")
+	  (org-test-with-temp-text
+	      "* H\n:PROPERTIES:\n:EXPORT_A: 1\n:END:\n<point>"
+	    (let* ((backend (org-export-create-backend
+			     :options '((:k1 "A")
+					(:k2 "A"))))
+		   (options (org-export-get-environment backend t)))
+	      (list (plist-get options :k1) (plist-get options :k2)))))))
 
 (ert-deftest test-org-export/set-title ()
   "Test title setting."