Hi Nicolas, I think this patch is a welcome simplification. Would it be possible to merge the code that is used for reading babel header args (things like “:results output :file foo.txt”) with the code from the exporter? Unless they are parsed by the same code, the two syntaxes will differ in subtle and headache-inducing ways (for users and developers).
Both methods as it stands have their pros and cons. org-export-read-attribute seems* to give the wrong result for the case of #+ATTR_FOO: :key "one :two three" -> (:key "\"one" :two "three\"") Whereas org-babel-parse-header-arguments (returning an alist, not a plist) gives correctly ((:key . "one :two three")) OTOH ":key (one :two)" makes o-b-parse-header-arguments give an error because it tries to read (one :two) as elisp, and “one” isn’t an elisp function. For o-x-read-attribute we correctly(?) get (:key "(one :two)"). o-b-parse-header-arguments can cope with ":key '(one :two three)" (note the single quote to not barf on the lisp-like syntax) giving ((:key one :two three)) – which is a notational variant of ((:key . (one :two three))) – whereas o-x-read-attribute gives (:key "'(one" :two "three)") In this last case I think that either value is arguably correct – but it should be consistently one and not the other. * For testing, I extracted the following function from org-export-read-attribute. #+begin_src emacs-lisp (defun o-test (value) (let ((s value) result) (while (string-match "\\(?:^\\|[ \t]+\\)\\(:[-a-zA-Z0-9_]+\\)\\([ \t]+\\|$\\)" s) (let ((value (substring s 0 (match-beginning 0)))) (push (and (not (member value '("nil" ""))) value) result)) (push (intern (match-string 1 s)) result) (setq s (substring s (match-end 0)))) ;; Ignore any string before the first property with `cdr'. (cdr (nreverse (cons (and (org-string-nw-p s) (not (equal s "nil")) s) result)))) ) #+end_src -- Aaron Ecay