mirror of
https://git.savannah.gnu.org/git/emacs/org-mode.git
synced 2024-11-21 06:55:35 +00:00
org-macro: Expand macros only within narrowed part of buffer
* lisp/org-macro.el (org-macro-replace-all): Expand macros only within narrowed part of buffer. * testing/lisp/test-org-macro.el (test-org/macro-replace-all): Update test. Expanding macros outside in the whole buffer could make sense, e.g., if a macro expands to some Babel code, which, in turn, is evaluated prior to export. However, by principle of least surprise, it is better to limit expansion to current accessible part of the buffer.
This commit is contained in:
parent
88de98a778
commit
82db669de6
@ -49,11 +49,7 @@
|
||||
|
||||
(declare-function org-element-at-point "org-element" ())
|
||||
(declare-function org-element-context "org-element" (&optional element))
|
||||
(declare-function org-element-map "org-element"
|
||||
(data types fun &optional info first-match no-recursion
|
||||
with-affiliated))
|
||||
(declare-function org-element-parse-buffer "org-element"
|
||||
(&optional granularity visible-only))
|
||||
(declare-function org-element-macro-parser "org-element" ())
|
||||
(declare-function org-element-property "org-element" (property element))
|
||||
(declare-function org-element-type "org-element" (element))
|
||||
(declare-function org-file-contents "org" (file &optional noerror))
|
||||
@ -189,55 +185,53 @@ found in the buffer with no definition in TEMPLATES.
|
||||
|
||||
Optional argument KEYWORDS, when non-nil is a list of keywords,
|
||||
as strings, where macro expansion is allowed."
|
||||
(org-with-wide-buffer
|
||||
(goto-char (point-min))
|
||||
(let ((properties-regexp
|
||||
(format "\\`EXPORT_%s\\+?\\'" (regexp-opt keywords)))
|
||||
record)
|
||||
(while (re-search-forward "{{{[-A-Za-z0-9_]" nil t)
|
||||
(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)
|
||||
(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
|
||||
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.
|
||||
(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)))))))))))
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(let ((properties-regexp
|
||||
(format "\\`EXPORT_%s\\+?\\'" (regexp-opt keywords)))
|
||||
record)
|
||||
(while (re-search-forward "{{{[-A-Za-z0-9_]" nil t)
|
||||
(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)
|
||||
(string-match-p properties-regexp
|
||||
(org-element-property :key datum))))
|
||||
(save-excursion
|
||||
(goto-char (match-beginning 0))
|
||||
(org-element-macro-parser))))))
|
||||
(when macro
|
||||
(let* ((value (org-macro-expand macro templates))
|
||||
(begin (org-element-property :begin macro))
|
||||
(signature (list begin
|
||||
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.
|
||||
(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.
|
||||
|
@ -108,10 +108,10 @@
|
||||
"* H1\n:PROPERTIES:\n:A: 1\n:END:\n* H2\n{{{property(A,*???)}}}<point>"
|
||||
(org-macro-initialize-templates)
|
||||
(org-macro-replace-all org-macro-templates)))
|
||||
;; Macro expansion ignores narrowing.
|
||||
;; Macro expansion preserves narrowing.
|
||||
(should
|
||||
(string-match
|
||||
"expansion"
|
||||
(string-match-p
|
||||
"{{{macro}}}"
|
||||
(org-test-with-temp-text
|
||||
"#+MACRO: macro expansion\n{{{macro}}}\n<point>Contents"
|
||||
(narrow-to-region (point) (point-max))
|
||||
|
Loading…
Reference in New Issue
Block a user