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.
This commit is contained in:
Nicolas Goaziou 2013-02-26 23:32:36 +01:00
parent 7604fe1e80
commit 677433d9b4
4 changed files with 141 additions and 108 deletions

View File

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

View File

@ -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))
((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
(org-export--parse-option-keyword val backend))))
((equal key "FILETAGS")
(setq 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."

View File

@ -0,0 +1,4 @@
#+DESCRIPTION: l2
#+LANGUAGE: en
#+SELECT_TAGS: b
#+TITLE: b

View File

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