summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Goaziou <n.goaziou@gmail.com>2013-02-26 23:32:36 +0100
committerNicolas Goaziou <n.goaziou@gmail.com>2013-02-26 23:35:36 +0100
commit677433d9b4005da3d804bbc5a458d2174f1a460c (patch)
treefc32dee4385506a46b11f7dcace94a14089848f6
parent7604fe1e803a94553d90e36f6326bb9256ea446c (diff)
downloadorg-mode-677433d9b4005da3d804bbc5a458d2174f1a460c.tar.gz
ox: Fix bug where properties read from setupfile overwrite previous properties
* lisp/ox.el (org-export--get-inbuffer-options): Remove an optional argument. Rewrite function. Properties read from a setupfile do not overwrite anymore previously computed properties. (org-export-get-environment): Apply changes to previous function. * lisp/org.el (org-create-formula--latex-header): Apply arity change from `org-export--get-inbuffer-options'. * testing/lisp/test-ox.el: Add test. * testing/examples/setupfile.org: New file.
-rw-r--r--lisp/org.el6
-rw-r--r--lisp/ox.el176
-rw-r--r--testing/examples/setupfile.org4
-rw-r--r--testing/lisp/test-ox.el61
4 files changed, 140 insertions, 107 deletions
diff --git a/lisp/org.el b/lisp/org.el
index b53d821..9b95733 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -18101,7 +18101,7 @@ share a good deal of logic."
string tofile options buffer))
(declare-function org-export--get-global-options "org-export" (&optional backend))
-(declare-function org-export--get-inbuffer-options "org-export" (&optional backend files))
+(declare-function org-export--get-inbuffer-options "org-export" (&optional backend))
(defun org-create-formula--latex-header ()
"Return LaTeX header appropriate for previewing a LaTeX snippet."
(org-latex-guess-inputenc
@@ -18112,9 +18112,7 @@ share a good deal of logic."
(plist-get
(org-combine-plists
(org-export--get-global-options 'latex)
- (org-export--get-inbuffer-options
- 'latex
- (and buffer-file-name (org-remove-double-quotes buffer-file-name))))
+ (org-export--get-inbuffer-options 'latex))
:latex-header-extra))))
;; This function borrows from Ganesh Swami's latex2png.el
diff --git a/lisp/ox.el b/lisp/ox.el
index f5a2bc2..30299f2 100644
--- a/lisp/ox.el
+++ b/lisp/ox.el
@@ -1404,9 +1404,7 @@ inferior to file-local settings."
;; ... from an external property list...
ext-plist
;; ... from in-buffer settings...
- (org-export--get-inbuffer-options
- backend
- (and buffer-file-name (org-remove-double-quotes buffer-file-name)))
+ (org-export--get-inbuffer-options backend)
;; ... and from subtree, when appropriate.
(and subtreep (org-export--get-subtree-options backend))
;; Eventually add misc. properties.
@@ -1531,106 +1529,112 @@ for export. Return options as a plist."
;; Return value.
plist)))
-(defun org-export--get-inbuffer-options (&optional backend files)
+(defun org-export--get-inbuffer-options (&optional backend)
"Return current buffer export options, as a plist.
Optional argument BACKEND, when non-nil, is a symbol specifying
which back-end specific options should also be read in the
process.
-Optional argument FILES is a list of setup files names read so
-far, used to avoid circular dependencies.
-
Assume buffer is in Org mode. Narrowing, if any, is ignored."
- (org-with-wide-buffer
- (goto-char (point-min))
- (let ((case-fold-search t) plist)
- ;; 1. Special keywords, as in `org-export-special-keywords'.
- (let ((special-re
- (format "^[ \t]*#\\+%s:" (regexp-opt org-export-special-keywords))))
- (while (re-search-forward special-re nil t)
- (let ((element (org-element-at-point)))
- (when (eq (org-element-type element) 'keyword)
- (let* ((key (org-element-property :key element))
- (val (org-element-property :value element))
- (prop
+ (let* (plist
+ get-options ; For byte-compiler.
+ (case-fold-search t)
+ (options (append
+ ;; Priority is given to back-end specific options.
+ (and backend (org-export-backend-options backend))
+ org-export-options-alist))
+ (regexp (format "^[ \t]*#\\+%s:"
+ (regexp-opt (nconc (delq nil (mapcar 'cadr options))
+ org-export-special-keywords))))
+ (find-opt
+ (lambda (keyword)
+ ;; Return property name associated to KEYWORD.
+ (catch 'exit
+ (mapc (lambda (option)
+ (when (equal (nth 1 option) keyword)
+ (throw 'exit (car option))))
+ options))))
+ (get-options
+ (lambda (&optional files plist)
+ ;; Recursively read keywords in buffer. FILES is a list
+ ;; of files read so far. PLIST is the current property
+ ;; list obtained.
+ (org-with-wide-buffer
+ (goto-char (point-min))
+ (while (re-search-forward regexp nil t)
+ (let ((element (org-element-at-point)))
+ (when (eq (org-element-type element) 'keyword)
+ (let ((key (org-element-property :key element))
+ (val (org-element-property :value element)))
(cond
+ ;; Options in `org-export-special-keywords'.
((equal key "SETUPFILE")
- (let ((file
- (expand-file-name
- (org-remove-double-quotes (org-trim val)))))
+ (let ((file (expand-file-name
+ (org-remove-double-quotes (org-trim val)))))
;; Avoid circular dependencies.
(unless (member file files)
(with-temp-buffer
(insert (org-file-contents file 'noerror))
(org-mode)
- (org-export--get-inbuffer-options
- backend (cons file files))))))
+ (setq plist (funcall get-options
+ (cons file files) plist))))))
((equal key "OPTIONS")
- (org-export--parse-option-keyword val backend))
+ (setq plist
+ (org-combine-plists
+ plist
+ (org-export--parse-option-keyword val backend))))
((equal key "FILETAGS")
- (list :filetags
- (org-uniquify
- (append (org-split-string val ":")
- (plist-get plist :filetags))))))))
- (setq plist (org-combine-plists plist prop)))))))
- ;; 2. Standard options, as in `org-export-options-alist'.
- (let* ((all (append
- ;; Priority is given to back-end specific options.
- (and backend (org-export-backend-options backend))
- org-export-options-alist)))
- (dolist (option all)
- (let ((prop (car option)))
- (when (and (nth 1 option) (not (plist-member plist prop)))
- (goto-char (point-min))
- (let ((opt-re (format "^[ \t]*#\\+%s:" (nth 1 option)))
- (behaviour (nth 4 option)))
- (while (re-search-forward opt-re nil t)
- (let ((element (org-element-at-point)))
- (when (eq (org-element-type element) 'keyword)
- (let((key (org-element-property :key element))
- (val (org-element-property :value element)))
(setq plist
- (plist-put
- plist (car option)
- ;; Handle value depending on specified
- ;; BEHAVIOUR.
- (case behaviour
- (space
- (if (not (plist-get plist prop)) (org-trim val)
- (concat (plist-get plist prop)
- " "
- (org-trim val))))
- (newline
- (org-trim (concat (plist-get plist prop)
- "\n"
- (org-trim val))))
- (split `(,@(plist-get plist prop)
- ,@(org-split-string val)))
- ('t val)
- (otherwise
- (if (not (plist-member plist prop)) val
- (plist-get plist prop))))))))))))))
- ;; Parse keywords specified in
- ;; `org-element-document-properties'.
- (mapc
- (lambda (key)
- ;; Find the property associated to the keyword.
- (let* ((prop (catch 'found
- (mapc (lambda (option)
- (when (equal (nth 1 option) key)
- (throw 'found (car option))))
- all)))
- (value (and prop (plist-get plist prop))))
- (when (stringp value)
- (setq plist
- (plist-put
- plist prop
- (org-element-parse-secondary-string
- value (org-element-restriction 'keyword)))))))
- org-element-document-properties))
- ;; 3. Return final value.
- plist)))
+ (org-combine-plists
+ plist
+ (list :filetags
+ (org-uniquify
+ (append (org-split-string val ":")
+ (plist-get plist :filetags)))))))
+ (t
+ ;; Options in `org-export-options-alist'.
+ (let* ((prop (funcall find-opt key))
+ (behaviour (nth 4 (assq prop options))))
+ (setq plist
+ (plist-put
+ plist prop
+ ;; Handle value depending on specified
+ ;; BEHAVIOUR.
+ (case behaviour
+ (space
+ (if (not (plist-get plist prop))
+ (org-trim val)
+ (concat (plist-get plist prop)
+ " "
+ (org-trim val))))
+ (newline
+ (org-trim (concat (plist-get plist prop)
+ "\n"
+ (org-trim val))))
+ (split `(,@(plist-get plist prop)
+ ,@(org-split-string val)))
+ ('t val)
+ (otherwise
+ (if (not (plist-member plist prop)) val
+ (plist-get plist prop)))))))))))))
+ ;; Return final value.
+ plist))))
+ ;; Read options in the current buffer.
+ (setq plist (funcall get-options buffer-file-name nil))
+ ;; Parse keywords specified in `org-element-document-properties'.
+ (mapc (lambda (keyword)
+ ;; Find the property associated to the keyword.
+ (let* ((prop (funcall find-opt keyword))
+ (value (and prop (plist-get plist prop))))
+ (when (stringp value)
+ (setq plist
+ (plist-put plist prop
+ (org-element-parse-secondary-string
+ value (org-element-restriction 'keyword)))))))
+ org-element-document-properties)
+ ;; Return value.
+ plist))
(defun org-export--get-buffer-attributes ()
"Return properties related to buffer attributes, as a plist."
diff --git a/testing/examples/setupfile.org b/testing/examples/setupfile.org
new file mode 100644
index 0000000..5b24315
--- /dev/null
+++ b/testing/examples/setupfile.org
@@ -0,0 +1,4 @@
+#+DESCRIPTION: l2
+#+LANGUAGE: en
+#+SELECT_TAGS: b
+#+TITLE: b
diff --git a/testing/lisp/test-ox.el b/testing/lisp/test-ox.el
index ffd6161..c2ba86c 100644
--- a/testing/lisp/test-ox.el
+++ b/testing/lisp/test-ox.el
@@ -122,26 +122,53 @@ already filled in `info'."
(ert-deftest test-org-export/get-inbuffer-options ()
"Test reading all standard export keywords."
+ ;; Properties should follow buffer order.
(should
(equal
- (org-test-with-temp-text "#+AUTHOR: Me, Myself and I
-#+CREATOR: Idem
-#+DATE: Today
-#+DESCRIPTION: Testing
-#+DESCRIPTION: with two lines
-#+EMAIL: some@email.org
-#+EXCLUDE_TAGS: noexport invisible
-#+KEYWORDS: test
-#+LANGUAGE: en
-#+SELECT_TAGS: export
-#+TITLE: Some title
-#+TITLE: with spaces"
+ (org-test-with-temp-text "#+LANGUAGE: fr\n#+CREATOR: Me\n#+EMAIL: email"
(org-export--get-inbuffer-options))
- '(:author
- ("Me, Myself and I") :creator "Idem" :date ("Today")
- :description "Testing\nwith two lines" :email "some@email.org"
- :exclude-tags ("noexport" "invisible") :keywords "test" :language "en"
- :select-tags ("export") :title ("Some title with spaces")))))
+ '(:language "fr" :creator "Me" :email "email")))
+ ;; Parse document keywords.
+ (should
+ (equal
+ (org-test-with-temp-text "#+AUTHOR: Me"
+ (org-export--get-inbuffer-options))
+ '(:author ("Me"))))
+ ;; Test `space' behaviour.
+ (should
+ (equal
+ (org-test-with-temp-text "#+TITLE: Some title\n#+TITLE: with spaces"
+ (org-export--get-inbuffer-options))
+ '(:title ("Some title with spaces"))))
+ ;; Test `newline' behaviour.
+ (should
+ (equal
+ (org-test-with-temp-text "#+DESCRIPTION: With\n#+DESCRIPTION: two lines"
+ (org-export--get-inbuffer-options))
+ '(:description "With\ntwo lines")))
+ ;; Test `split' behaviour.
+ (should
+ (equal
+ (org-test-with-temp-text "#+SELECT_TAGS: a\n#+SELECT_TAGS: b"
+ (org-export--get-inbuffer-options))
+ '(:select-tags ("a" "b"))))
+ ;; Options set through SETUPFILE.
+ (should
+ (equal
+ (org-test-with-temp-text
+ (format "#+DESCRIPTION: l1
+#+LANGUAGE: es
+#+SELECT_TAGS: a
+#+TITLE: a
+#+SETUPFILE: \"%s/examples/setupfile.org\"
+#+DESCRIPTION: l3
+#+LANGUAGE: fr
+#+SELECT_TAGS: c
+#+TITLE: c"
+ org-test-dir)
+ (org-export--get-inbuffer-options))
+ '(:description "l1\nl2\nl3":language "fr" :select-tags ("a" "b" "c")
+ :title ("a b c")))))
(ert-deftest test-org-export/get-subtree-options ()
"Test setting options from headline's properties."