org-element: Preserve order of multiple affiliated keywords

* lisp/org-element.el: Do not reverse affiliated keyword order.
(org-element-map): Remove special arrangement to restore keyword
ordering.
(org-element--interpret-affiliated-keywords): Obey the new keyword order.
* lisp/ox.el (org-export-get-caption):
* testing/lisp/test-org-element.el (test-org-element/affiliated-keywords-parser):
* testing/lisp/test-org-element.el (test-org-element/interpret-data):
Do not assume reverse order.

This is one of the undocumented conventions that is inconsistent with
other aspects of the parser.
This commit is contained in:
Ihor Radchenko 2023-04-24 15:38:14 +02:00
parent 924a64da39
commit f4aa3747e1
No known key found for this signature in database
GPG Key ID: 6470762A7DA11D8B
3 changed files with 25 additions and 21 deletions

View File

@ -4283,7 +4283,7 @@ When PARSE is non-nil, values from keywords belonging to
(when (or (member kwd org-element-multiple-keywords)
;; Attributes can always appear on multiple lines.
(string-match "^ATTR_" kwd))
(setq value (cons value (plist-get output kwd-sym))))
(setq value (nconc (plist-get output kwd-sym) (list value))))
;; Eventually store the new value in OUTPUT.
(setq output (plist-put output kwd-sym value))
;; Move to next keyword.
@ -4538,13 +4538,13 @@ looking into captions:
((not value))
((member kwd org-element-dual-keywords)
(if (member kwd org-element-multiple-keywords)
(dolist (line (reverse value))
(dolist (line value)
(funcall --walk-tree (cdr line))
(funcall --walk-tree (car line)))
(funcall --walk-tree (cdr value))
(funcall --walk-tree (car value))))
((member kwd org-element-multiple-keywords)
(mapc --walk-tree (reverse value)))
(mapc --walk-tree value))
(t (funcall --walk-tree value))))))
;; Determine if a recursion into --DATA is possible.
(cond
@ -4950,20 +4950,23 @@ If there is no affiliated keyword, return the empty string."
;; All attribute keywords can have multiple lines.
(string-match "^ATTR_" keyword))
(mapconcat (lambda (line) (funcall keyword-to-org keyword line))
(reverse value)
"")
value "")
(funcall keyword-to-org keyword value)))))
;; List all ELEMENT's properties matching an attribute line or an
;; affiliated keyword, but ignore translated keywords since they
;; cannot belong to the property list.
(cl-loop for prop in (nth 1 element) by 'cddr
when (let ((keyword (upcase (substring (symbol-name prop) 1))))
(or (string-match "^ATTR_" keyword)
(and
(member keyword org-element-affiliated-keywords)
(not (assoc keyword
org-element-keyword-translation-alist)))))
collect prop)
(let (acc)
(org-element-properties-mapc
(lambda (prop _ _)
(let ((keyword (upcase (substring (symbol-name prop) 1))))
(when (or (string-match "^ATTR_" keyword)
(and
(member keyword org-element-affiliated-keywords)
(not (assoc keyword
org-element-keyword-translation-alist))))
(push prop acc))))
element t)
(nreverse acc))
"")))
;; Because interpretation of the parse tree must return the same

View File

@ -3910,9 +3910,10 @@ Caption lines are separated by a white space."
(`nil nil)
(c
(setq caption
(nconc (list " ")
(copy-sequence c) caption)))))
(cdr caption)))
(if caption
(nconc caption (list " ") (copy-sequence c))
(copy-sequence c))))))
caption))
;;;; For Derived Backends

View File

@ -374,7 +374,7 @@ Some other text
;; Parse multiple keywords.
(should
(equal
'("line2" "line1")
'("line1" "line2")
(org-element-property
:attr_ascii
(org-test-with-temp-text
@ -409,12 +409,12 @@ Some other text
;; Allow multiple caption keywords.
(should
(equal
'((("l2") "s2") (("l1") "s1"))
'((("l1") "s1") (("l2") "s2"))
(org-test-with-temp-text "#+CAPTION[s1]: l1\n#+CAPTION[s2]: l2\nParagraph"
(org-element-property :caption (org-element-at-point)))))
(should
(equal
'((("l1")) (nil "s1"))
'((nil "s1") (("l1")))
(org-test-with-temp-text "#+CAPTION[s1]:\n#+CAPTION: l1\nParagraph"
(org-element-property :caption (org-element-at-point)))))
;; Corner case: orphaned keyword at the end of an element.
@ -2772,7 +2772,7 @@ Outside list"
(should
(equal
(org-element-interpret-data
'(org-data nil (paragraph (:attr_ascii ("line2" "line1")) "Paragraph")))
'(org-data nil (paragraph (:attr_ascii ("line1" "line2")) "Paragraph")))
"#+attr_ascii: line1\n#+attr_ascii: line2\nParagraph\n"))
;; Interpret parsed affiliated keywords.
(should
@ -2791,7 +2791,7 @@ Outside list"
(equal
(org-element-interpret-data
'(org-data nil (paragraph
(:caption ((("l2") "s2") (("l1") "s1"))) "Paragraph")))
(:caption ((("l1") "s1") (("l2") "s2"))) "Paragraph")))
"#+caption[s1]: l1\n#+caption[s2]: l2\nParagraph\n"))
;; Pseudo objects and elements are transparent.
(should