summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Goaziou <mail@nicolasgoaziou.fr>2017-06-05 17:05:58 +0200
committerNicolas Goaziou <mail@nicolasgoaziou.fr>2017-06-05 18:08:42 +0200
commit82db669de6a4b7cd1f39bbf692a42c32a96ebb31 (patch)
tree40429591d2165409e155bc838eb74e0995d05dc5
parent88de98a778846f91679a57abcf4a6758bc49c9e1 (diff)
downloadorg-mode-82db669de6a4b7cd1f39bbf692a42c32a96ebb31.tar.gz
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.
-rw-r--r--lisp/org-macro.el102
-rw-r--r--testing/lisp/test-org-macro.el6
2 files changed, 51 insertions, 57 deletions
diff --git a/lisp/org-macro.el b/lisp/org-macro.el
index 71e917b..8927b3a 100644
--- a/lisp/org-macro.el
+++ b/lisp/org-macro.el
@@ -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.
diff --git a/testing/lisp/test-org-macro.el b/testing/lisp/test-org-macro.el
index 26c5674..bc493b3 100644
--- a/testing/lisp/test-org-macro.el
+++ b/testing/lisp/test-org-macro.el
@@ -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))