Function: org-macro-replace-all

org-macro-replace-all is a byte-compiled function defined in org-macro.el.gz.

Signature

(org-macro-replace-all TEMPLATES &optional KEYWORDS)

Documentation

Replace all macros in current buffer by their expansion.

TEMPLATES is an alist of templates used for expansion. See org-macro-templates for a buffer-local default value.

Optional argument KEYWORDS, when non-nil is a list of keywords, as strings, where macro expansion is allowed.

Return an error if a macro in the buffer cannot be associated to a definition in TEMPLATES.

Source Code

;; Defined in /usr/src/emacs/lisp/org/org-macro.el.gz
(defun org-macro-replace-all (templates &optional keywords)
  "Replace all macros in current buffer by their expansion.

TEMPLATES is an alist of templates used for expansion.  See
`org-macro-templates' for a buffer-local default value.

Optional argument KEYWORDS, when non-nil is a list of keywords,
as strings, where macro expansion is allowed.

Return an error if a macro in the buffer cannot be associated to
a definition in TEMPLATES."
  (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)
       (unless (save-match-data (org-in-commented-heading-p))
	 (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
             ;; `:parent' property might change as we modify buffer.
             ;; We do not care about it when checking for circular
             ;; dependencies.  So, setting `:parent' to nil making sure
             ;; that actual macro element (if org-element-cache is
             ;; active) is unchanged.
             (setq macro (cl-copy-list macro))
             (org-element-put-property macro :parent nil)
	     (let* ((key (org-element-property :key macro))
		    (value (org-macro-expand macro templates))
		    (begin (org-element-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" key))
		     (value
		      (push signature record)
		      (delete-region
		       begin
		       ;; Preserve white spaces after the macro.
		       (progn (goto-char (org-element-end macro))
			      (skip-chars-backward " \t")
			      (point)))
		      ;; Leave point before replacement in case of
		      ;; recursive expansions.
		      (save-excursion (insert value)))
		     ;; Special "results" macro: if it is not defined,
		     ;; simply leave it as-is.  It will be expanded in
		     ;; a second phase.
		     ((equal key "results"))
		     (t
		      (error "Undefined Org macro: %s; aborting"
			     (org-element-property :key macro))))))))))))