Function: org-babel-expand-noweb-references
org-babel-expand-noweb-references is a byte-compiled function defined
in ob-core.el.gz.
Signature
(org-babel-expand-noweb-references &optional INFO PARENT-BUFFER)
Documentation
Expand Noweb references in the body of the current source code block.
For example the following reference would be replaced with the
body of the source-code block named example-block.
<<example-block>>
Note that any text preceding the <<foo>> construct on a line will be interposed between the lines of the replacement text. So for example if <<foo>> is placed behind a comment, then the entire replacement text will also be commented.
This function must be called from inside of the buffer containing the source-code block which holds BODY.
In addition the following syntax can be used to insert the
results of evaluating the source-code block named example-block.
<<example-block()>>
Any optional arguments can be passed to example-block by placing
the arguments inside the parenthesis following the convention
defined by org-babel-lob. For example
<<example-block(a=9)>>
would set the value of argument "a" equal to "9". Note that these arguments are not evaluated in the current source-code block but are passed literally to the "example-block".
Source Code
;; Defined in /usr/src/emacs/lisp/org/ob-core.el.gz
(defun org-babel-expand-noweb-references (&optional info parent-buffer)
"Expand Noweb references in the body of the current source code block.
For example the following reference would be replaced with the
body of the source-code block named `example-block'.
<<example-block>>
Note that any text preceding the <<foo>> construct on a line will
be interposed between the lines of the replacement text. So for
example if <<foo>> is placed behind a comment, then the entire
replacement text will also be commented.
This function must be called from inside of the buffer containing
the source-code block which holds BODY.
In addition the following syntax can be used to insert the
results of evaluating the source-code block named `example-block'.
<<example-block()>>
Any optional arguments can be passed to example-block by placing
the arguments inside the parenthesis following the convention
defined by `org-babel-lob'. For example
<<example-block(a=9)>>
would set the value of argument \"a\" equal to \"9\". Note that
these arguments are not evaluated in the current source-code
block but are passed literally to the \"example-block\"."
(let* ((parent-buffer (or parent-buffer (current-buffer)))
(info (or info (org-babel-get-src-block-info 'no-eval)))
(lang (nth 0 info))
(body (nth 1 info))
(comment (string= "noweb" (cdr (assq :comments (nth 2 info)))))
(noweb-prefix (let ((v (assq :noweb-prefix (nth 2 info))))
(or (not v)
(and (org-not-nil (cdr v))
(not (equal (cdr v) "no"))))))
(noweb-re (format "\\(.*?\\)\\(%s\\)"
(with-current-buffer parent-buffer
(org-babel-noweb-wrap)))))
(unless (equal (cons parent-buffer
(with-current-buffer parent-buffer
(buffer-chars-modified-tick)))
org-babel-expand-noweb-references--cache-buffer)
(setq org-babel-expand-noweb-references--cache nil
org-babel-expand-noweb-references--cache-buffer
(cons parent-buffer
(with-current-buffer parent-buffer
(buffer-chars-modified-tick)))))
(cl-macrolet ((c-wrap
(s)
;; Comment string S, according to LANG mode. Return new
;; string.
`(unless org-babel-tangle-uncomment-comments
(with-temp-buffer
(funcall (org-src-get-lang-mode lang))
(comment-region (point)
(progn (insert ,s) (point)))
(org-trim (buffer-string)))))
(expand-body
(i)
;; Expand body of code represented by block info I.
`(let ((b (if (org-babel-noweb-p (nth 2 ,i) :eval)
(org-babel-expand-noweb-references ,i)
(nth 1 ,i))))
(if (not comment) b
(let ((cs (org-babel-tangle-comment-links ,i)))
(concat (c-wrap (car cs)) "\n"
b "\n"
(c-wrap (cadr cs)))))))
(expand-references
(ref)
`(pcase (gethash ,ref org-babel-expand-noweb-references--cache)
(`(,last . ,previous)
;; Ignore separator for last block.
(let ((strings (list (expand-body last))))
(dolist (i previous)
(let ((parameters (nth 2 i)))
;; Since we're operating in reverse order, first
;; push separator, then body.
(push (or (cdr (assq :noweb-sep parameters)) "\n")
strings)
(push (expand-body i) strings)))
(mapconcat #'identity strings "")))
;; Raise an error about missing reference, or return the
;; empty string.
((guard (or org-babel-noweb-error-all-langs
(member lang org-babel-noweb-error-langs)))
(error "Cannot resolve %s (see `org-babel-noweb-error-langs')"
(org-babel-noweb-wrap ,ref)))
(_ ""))))
(replace-regexp-in-string
noweb-re
(lambda (m)
(with-current-buffer parent-buffer
(save-match-data
(let* ((prefix (match-string 1 m))
(id (match-string 3 m))
(evaluate (string-match-p "(.*)" id))
(expansion
(cond
(evaluate
(prog1
(let ((raw (org-babel-ref-resolve id)))
(if (stringp raw) raw (format "%S" raw)))
;; Evaluation can potentially modify the buffer
;; and invalidate the cache: reset it.
(unless (equal org-babel-expand-noweb-references--cache-buffer
(cons parent-buffer
(buffer-chars-modified-tick)))
(setq org-babel-expand-noweb-references--cache nil
org-babel-expand-noweb-references--cache-buffer
(cons parent-buffer
(with-current-buffer parent-buffer
(buffer-chars-modified-tick)))))))
;; Already cached.
((and (hash-table-p org-babel-expand-noweb-references--cache)
(gethash id org-babel-expand-noweb-references--cache))
(expand-references id))
;; Return the contents of headlines literally.
((org-babel-ref-goto-headline-id id)
(org-babel-ref-headline-body))
;; Look for a source block named SOURCE-NAME. If
;; found, assume it is unique; do not look after
;; `:noweb-ref' header argument.
((org-with-point-at 1
(let ((r (org-babel-named-src-block-regexp-for-name id)))
(and (re-search-forward r nil t)
(not (org-in-commented-heading-p))
(let ((info (org-babel-get-src-block-info t)))
(unless (hash-table-p org-babel-expand-noweb-references--cache)
(setq org-babel-expand-noweb-references--cache (make-hash-table :test #'equal)))
(push info (gethash id org-babel-expand-noweb-references--cache))
(expand-body info))))))
;; Retrieve from the Library of Babel.
((nth 2 (assoc-string id org-babel-library-of-babel)))
;; All Noweb references were cached in a previous
;; run. Yet, ID is not in cache (see the above
;; condition). Process missing reference in
;; `expand-references'.
((and (hash-table-p org-babel-expand-noweb-references--cache)
(gethash 'buffer-processed org-babel-expand-noweb-references--cache))
(expand-references id))
;; Though luck. We go into the long process of
;; checking each source block and expand those
;; with a matching Noweb reference. Since we're
;; going to visit all source blocks in the
;; document, cache information about them as well.
(t
(setq org-babel-expand-noweb-references--cache (make-hash-table :test #'equal))
(org-with-wide-buffer
(org-babel-map-src-blocks nil
(if (org-in-commented-heading-p)
(org-forward-heading-same-level nil t)
(let* ((info (org-babel-get-src-block-info t))
(ref (cdr (assq :noweb-ref (nth 2 info)))))
(push info (gethash ref org-babel-expand-noweb-references--cache))))))
(puthash 'buffer-processed t org-babel-expand-noweb-references--cache)
(expand-references id)))))
;; Interpose PREFIX between every line.
(if noweb-prefix
(mapconcat #'identity
(split-string expansion "[\n\r]")
(concat "\n" prefix))
expansion)))))
body t t 2))))