mirror of
https://git.savannah.gnu.org/git/emacs/org-mode.git
synced 2024-12-23 10:34:17 +00:00
org-macro: Allow macros in parsed keywords and associated properties
* lisp/org-macro.el (org-macro-replace-all): Add optional argument. Now accept macros in parsed keywords and associated properties. * lisp/ox.el (org-export-as): Apply signature change. * testing/lisp/test-ox.el (test-org-export/expand-macro): Add test.
This commit is contained in:
parent
ae9db17482
commit
fa64b59b05
@ -159,7 +159,7 @@ default value. Return nil if no template was found."
|
||||
;; Return string.
|
||||
(format "%s" (or value ""))))))
|
||||
|
||||
(defun org-macro-replace-all (templates &optional finalize)
|
||||
(defun org-macro-replace-all (templates &optional finalize keywords)
|
||||
"Replace all macros in current buffer by their expansion.
|
||||
|
||||
TEMPLATES is an alist of templates used for expansion. See
|
||||
@ -169,35 +169,53 @@ If optional arg FINALIZE is non-nil, raise an error if a macro is
|
||||
found in the buffer with no definition in TEMPLATES."
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(let (record)
|
||||
(let ((properties-regexp
|
||||
(format "\\`EXPORT_%s\\+?\\'" (regexp-opt keywords)))
|
||||
record)
|
||||
(while (re-search-forward "{{{[-A-Za-z0-9_]" nil t)
|
||||
(let ((object (org-element-context)))
|
||||
(when (eq (org-element-type object) 'macro)
|
||||
(let* ((value (org-macro-expand object templates))
|
||||
(begin (org-element-property :begin object))
|
||||
(let* ((datum (save-match-data (org-element-context)))
|
||||
(type (org-element-type datum))
|
||||
(macro
|
||||
(cond
|
||||
((eq type 'macro) datum)
|
||||
;; In parsed keywords and associated node properties,
|
||||
;; force macro recognition.
|
||||
((or (and (eq type 'keyword)
|
||||
(member (org-element-property :key datum) keywords))
|
||||
(and (eq type 'node-property)
|
||||
(org-string-match-p
|
||||
properties-regexp
|
||||
(org-element-property :key datum))))
|
||||
(save-restriction
|
||||
(narrow-to-region (match-beginning 0) (line-end-position))
|
||||
(org-element-map (org-element-parse-buffer) 'macro
|
||||
#'identity nil t))))))
|
||||
(when macro
|
||||
(let* ((value (org-macro-expand macro templates))
|
||||
(begin (org-element-property :begin macro))
|
||||
(signature (list begin
|
||||
object
|
||||
(org-element-property :args object))))
|
||||
macro
|
||||
(org-element-property :args macro))))
|
||||
;; Avoid circular dependencies by checking if the same
|
||||
;; macro with the same arguments is expanded at the same
|
||||
;; position twice.
|
||||
(if (member signature record)
|
||||
(error "Circular macro expansion: %s"
|
||||
(org-element-property :key object))
|
||||
(cond (value
|
||||
(push signature record)
|
||||
(delete-region
|
||||
begin
|
||||
;; Preserve white spaces after the macro.
|
||||
(progn (goto-char (org-element-property :end object))
|
||||
(skip-chars-backward " \t")
|
||||
(point)))
|
||||
;; Leave point before replacement in case of recursive
|
||||
;; expansions.
|
||||
(save-excursion (insert value)))
|
||||
(finalize
|
||||
(error "Undefined Org macro: %s; aborting"
|
||||
(org-element-property :key object))))))))))))
|
||||
(cond ((member signature record)
|
||||
(error "Circular macro expansion: %s"
|
||||
(org-element-property :key macro)))
|
||||
(value
|
||||
(push signature record)
|
||||
(delete-region
|
||||
begin
|
||||
;; Preserve white spaces after the macro.
|
||||
(progn (goto-char (org-element-property :end macro))
|
||||
(skip-chars-backward " \t")
|
||||
(point)))
|
||||
;; Leave point before replacement in case of
|
||||
;; recursive expansions.
|
||||
(save-excursion (insert value)))
|
||||
(finalize
|
||||
(error "Undefined Org macro: %s; aborting"
|
||||
(org-element-property :key macro)))))))))))
|
||||
|
||||
(defun org-macro-escape-arguments (&rest args)
|
||||
"Build macro's arguments string from ARGS.
|
||||
|
10
lisp/ox.el
10
lisp/ox.el
@ -2850,6 +2850,11 @@ Return code as a string."
|
||||
(and visible-only 'visible-only)
|
||||
(and body-only 'body-only))))
|
||||
(org-export--get-buffer-attributes)))
|
||||
(parsed-keywords
|
||||
(delq nil
|
||||
(mapcar (lambda (o) (and (eq (nth 4 o) 'parse) (nth 1 o)))
|
||||
(append (org-export-get-all-options backend)
|
||||
org-export-options-alist))))
|
||||
tree)
|
||||
;; Update communication channel and get parse tree. Buffer
|
||||
;; isn't parsed directly. Instead, a temporary copy is
|
||||
@ -2864,7 +2869,7 @@ Return code as a string."
|
||||
;; Update macro templates since #+INCLUDE keywords might have
|
||||
;; added some new ones.
|
||||
(org-macro-initialize-templates)
|
||||
(org-macro-replace-all org-macro-templates)
|
||||
(org-macro-replace-all org-macro-templates nil parsed-keywords)
|
||||
(org-export-execute-babel-code)
|
||||
;; Update radio targets since keyword inclusion might have
|
||||
;; added some more.
|
||||
@ -2908,7 +2913,8 @@ Return code as a string."
|
||||
(cons "email" (org-element-interpret-data (plist-get info :email)))
|
||||
(cons "title" (org-element-interpret-data (plist-get info :title)))
|
||||
(cons "results" "$1"))
|
||||
'finalize)
|
||||
'finalize
|
||||
parsed-keywords)
|
||||
;; Parse buffer.
|
||||
(setq tree (org-element-parse-buffer nil visible-only))
|
||||
;; Prune tree from non-exported elements and transform
|
||||
|
@ -1091,6 +1091,25 @@ Footnotes[fn:2], foot[fn:test], digit only[3], and [fn:inline:anonymous footnote
|
||||
(equal "#+MACRO: macro1 value\nvalue\n"
|
||||
(org-test-with-temp-text "#+MACRO: macro1 value\n{{{macro1}}}"
|
||||
(org-export-as (org-test-default-backend)))))
|
||||
;; Allow macro in parsed keywords and associated properties.
|
||||
;; Standard macro expansion.
|
||||
(should
|
||||
(string-match
|
||||
"#\\+K: value"
|
||||
(let ((backend (org-export-create-backend
|
||||
:parent 'org
|
||||
:options '((:k "K" nil nil parse)))))
|
||||
(org-test-with-temp-text "#+MACRO: macro value\n#+K: {{{macro}}}"
|
||||
(org-export-as backend)))))
|
||||
(should
|
||||
(string-match
|
||||
":EXPORT_K: v"
|
||||
(let ((backend (org-export-create-backend
|
||||
:parent 'org
|
||||
:options '((:k "K" nil nil parse)))))
|
||||
(org-test-with-temp-text
|
||||
"#+MACRO: m v\n* H\n:PROPERTIES:\n:EXPORT_K: {{{m}}}\n:END:"
|
||||
(org-export-as backend nil nil nil '(:with-properties t))))))
|
||||
;; Expand specific macros.
|
||||
(should
|
||||
(equal "me 2012-03-29 me@here Title\n"
|
||||
|
Loading…
Reference in New Issue
Block a user