org-element: Fix object parsing in captions

* lisp/org-element.el (org-element-parse-secondary-string): Clone all
  local variables from current buffer before parsing a secondary
  string.  Small refactoring.
(org-element-object-variables): Remove variable.

* testing/lisp/test-org-element.el (test-org-element/secondary-string-parsing):
  Add test.

Thanks to Thomas S. Dye for reporting it.
http://permalink.gmane.org/gmane.emacs.orgmode/88850
This commit is contained in:
Nicolas Goaziou 2014-07-25 14:47:38 +02:00
parent 43a8b979f8
commit 0e01e3eb13
2 changed files with 57 additions and 55 deletions

View File

@ -360,11 +360,6 @@ still has an entry since one of its properties (`:title') does.")
(footnote-reference . :inline-definition)) (footnote-reference . :inline-definition))
"Alist between element types and location of secondary value.") "Alist between element types and location of secondary value.")
(defconst org-element-object-variables '(org-link-abbrev-alist-local)
"List of buffer-local variables used when parsing objects.
These variables are copied to the temporary buffer created by
`org-export-secondary-string'.")
;;; Accessors and Setters ;;; Accessors and Setters
@ -4089,21 +4084,18 @@ looked after.
Optional argument PARENT, when non-nil, is the element or object Optional argument PARENT, when non-nil, is the element or object
containing the secondary string. It is used to set correctly containing the secondary string. It is used to set correctly
`:parent' property within the string." `:parent' property within the string."
;; Copy buffer-local variables listed in (let ((local-variables (buffer-local-variables)))
;; `org-element-object-variables' into temporary buffer. This is
;; required since object parsing is dependent on these variables.
(let ((pairs (delq nil (mapcar (lambda (var)
(when (boundp var)
(cons var (symbol-value var))))
org-element-object-variables))))
(with-temp-buffer (with-temp-buffer
(mapc (lambda (pair) (org-set-local (car pair) (cdr pair))) pairs) (dolist (v local-variables)
(ignore-errors
(if (symbolp v) (makunbound v)
(org-set-local (car v) (cdr v)))))
(insert string) (insert string)
(restore-buffer-modified-p nil)
(let ((secondary (org-element--parse-objects (let ((secondary (org-element--parse-objects
(point-min) (point-max) nil restriction))) (point-min) (point-max) nil restriction)))
(when parent (when parent
(mapc (lambda (obj) (org-element-put-property obj :parent parent)) (dolist (o secondary) (org-element-put-property o :parent parent)))
secondary))
secondary)))) secondary))))
(defun org-element-map (defun org-element-map

View File

@ -2789,47 +2789,57 @@ Paragraph \\alpha."
(ert-deftest test-org-element/secondary-string-parsing () (ert-deftest test-org-element/secondary-string-parsing ()
"Test if granularity correctly toggles secondary strings parsing." "Test if granularity correctly toggles secondary strings parsing."
;; 1. With a granularity bigger than `object', no secondary string ;; With a granularity bigger than `object', no secondary string
;; should be parsed. ;; should be parsed.
;; (should
;; 1.1. Test with `headline' type. (stringp
(org-test-with-temp-text "* Headline" (org-test-with-temp-text "* Headline"
(let ((headline (let ((headline
(org-element-map (org-element-parse-buffer 'headline) 'headline (org-element-map (org-element-parse-buffer 'headline) 'headline
'identity #'identity nil 'first-match)))
nil (org-element-property :title headline)))))
'first-match))) (should
(should (stringp (org-element-property :title headline))))) (stringp
;; 1.2. Test with `item' type. (org-test-with-temp-text "* Headline\n- tag :: item"
(org-test-with-temp-text "* Headline\n- tag :: item" (let ((item (org-element-map (org-element-parse-buffer 'element) 'item
(let ((item (org-element-map (org-element-parse-buffer 'element) #'identity nil 'first-match)))
'item (org-element-property :tag item)))))
'identity
nil
'first-match)))
(should (stringp (org-element-property :tag item)))))
;; 1.3. Test with `inlinetask' type, if avalaible.
(when (featurep 'org-inlinetask) (when (featurep 'org-inlinetask)
(let ((org-inlinetask-min-level 15)) (should
(org-test-with-temp-text "*************** Inlinetask" (stringp
(let ((inlinetask (org-element-map (org-element-parse-buffer 'element) (let ((org-inlinetask-min-level 15))
'inlinetask (org-test-with-temp-text "*************** Inlinetask"
'identity (let ((inlinetask (org-element-map (org-element-parse-buffer 'element)
nil 'inlinetask
'first-match))) #'identity nil 'first-match)))
(should (stringp (org-element-property :title inlinetask))))))) (org-element-property :title inlinetask)))))))
;; 2. With a default granularity, secondary strings should be ;; With a default granularity, secondary strings should be parsed.
;; parsed. (should
(org-test-with-temp-text "* Headline" (listp
(let ((headline (org-test-with-temp-text "* Headline"
(org-element-map (org-element-parse-buffer) 'headline (let ((headline
'identity (org-element-map (org-element-parse-buffer) 'headline
nil #'identity nil 'first-match)))
'first-match))) (org-element-property :title headline)))))
(should (listp (org-element-property :title headline))))) ;; `org-element-at-point' should never parse a secondary string.
;; 3. `org-element-at-point' should never parse a secondary string. (should-not
(org-test-with-temp-text "* Headline" (listp
(should (stringp (org-element-property :title (org-element-at-point)))))) (org-test-with-temp-text "* Headline"
(org-element-property :title (org-element-at-point)))))
;; Preserve current local variables when parsing a secondary string.
(should
(let ((org-entities nil)
(org-entities-user nil))
(org-test-with-temp-text "
#+CAPTION: \\foo
Text
# Local Variables:
# org-entities-user: ((\"foo\"))
# End:"
(let ((safe-local-variable-values '((org-entities-user . (("foo"))))))
(hack-local-variables))
(org-element-map (org-element-parse-buffer) 'entity
#'identity nil nil nil t)))))