diff --git a/doc/org.texi b/doc/org.texi index aacf95a7b..77da6d335 100644 --- a/doc/org.texi +++ b/doc/org.texi @@ -16580,8 +16580,8 @@ Do things when True @cindex @code{:noweb-ref}, src header argument When expanding Noweb style references, Org concatenates @samp{src} code -blocks by matching the reference name to either the code block name or the -@code{:noweb-ref} header argument. +blocks by matching the reference name to either the code block name or, if +none is found, to the @code{:noweb-ref} header argument. For simple concatenation, set this @code{:noweb-ref} header argument at the sub-tree or file level. In the example Org file shown next, the body of the @@ -17164,11 +17164,6 @@ Note that now the expansion contains the @emph{results} of the code block 100 @end example -For faster tangling of large Org mode files, set -@code{org-babel-use-quick-and-dirty-noweb-expansion} variable to @code{t}. -The speedup comes at the expense of not correctly resolving inherited values -of the @code{:noweb-ref} header argument. - @node Key bindings and useful functions @section Key bindings and useful functions diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS index 1076dd970..391ef94ac 100644 --- a/etc/ORG-NEWS +++ b/etc/ORG-NEWS @@ -12,6 +12,46 @@ Please send Org bug reports to mailto:emacs-orgmode@gnu.org. * Version 9.2 ** Incompatible changes +*** Change to Noweb expansion + +Expansion check =:noweb-ref= only if no matching named block is found +in the buffer. As a consequence, any =:noweb-ref= value matching the +name of a source block in the buffer is ignored. A simple fix is to +give every concerned source-block, including the named one, a new, +unique, Noweb reference. + +#+BEGIN_SRC org + ,#+NAME: foo + ,#+BEGIN_SRC emacs-lisp + 1 + ,#+END_SRC + + ,#+BEGIN_SRC emacs-lisp :noweb-ref foo + 2 + ,#+END_SRC + + ,#+BEGIN_SRC emacs-lisp :noweb yes + <> + ,#+END_SRC +#+END_SRC + +should become + +#+BEGIN_SRC org + ,#+NAME: foo + ,#+BEGIN_SRC emacs-lisp :noweb-ref bar + 1 + ,#+END_SRC + + ,#+BEGIN_SRC emacs-lisp :noweb-ref bar + 2 + ,#+END_SRC + + ,#+BEGIN_SRC emacs-lisp :noweb yes + <> + ,#+END_SRC +#+END_SRC + *** =align= STARTUP value no longer narrow table columns Columns narrowing (or shrinking) is now dynamic. See [[*Dynamically @@ -114,6 +154,10 @@ you should expect to see something like: See docstring for details. +** Removed variables + +*** org-babel-use-quick-and-dirty-noweb-expansion + ** Miscellaneous *** ~org-publish-resolve-external-link~ accepts a new optional argument. diff --git a/lisp/ob-core.el b/lisp/ob-core.el index c7c038454..71233c56a 100644 --- a/lisp/ob-core.el +++ b/lisp/ob-core.el @@ -2651,12 +2651,6 @@ parameters when merging lists." ;; Return merged params. params)) -(defvar org-babel-use-quick-and-dirty-noweb-expansion nil - "Set to true to use regular expressions to expand noweb references. -This results in much faster noweb reference expansion but does -not properly allow code blocks to inherit the \":noweb-ref\" -header argument from buffer or subtree wide properties.") - (defun org-babel-noweb-p (params context) "Check if PARAMS require expansion in CONTEXT. CONTEXT may be one of :tangle, :export or :eval." @@ -2703,16 +2697,8 @@ block but are passed literally to the \"example-block\"." (body (nth 1 info)) (ob-nww-start org-babel-noweb-wrap-start) (ob-nww-end org-babel-noweb-wrap-end) - (comment (string= "noweb" (cdr (assq :comments (nth 2 info))))) - (rx-prefix (concat "\\(" org-babel-src-name-regexp "\\|" - ":noweb-ref[ \t]+" "\\)")) (new-body "") (nb-add (lambda (text) (setq new-body (concat new-body text)))) - (c-wrap (lambda (text) - (with-temp-buffer - (funcall (intern (concat lang "-mode"))) - (comment-region (point) (progn (insert text) (point))) - (org-trim (buffer-string))))) index source-name evaluate prefix) (with-temp-buffer (setq-local org-babel-noweb-wrap-start ob-nww-start) @@ -2750,52 +2736,68 @@ block but are passed literally to the \"example-block\"." ;; Return the contents of headlines literally. (save-excursion (when (org-babel-ref-goto-headline-id source-name) - (org-babel-ref-headline-body))) + (org-babel-ref-headline-body))) ;; Find the expansion of reference in this buffer. - (let ((rx (concat rx-prefix source-name "[ \t\n]")) - expansion) - (save-excursion - (goto-char (point-min)) - (if org-babel-use-quick-and-dirty-noweb-expansion - (while (re-search-forward rx nil t) - (let* ((i (org-babel-get-src-block-info 'light)) - (body (org-babel-expand-noweb-references i)) - (sep (or (cdr (assq :noweb-sep (nth 2 i))) - "\n")) - (full (if comment - (let ((cs (org-babel-tangle-comment-links i))) - (concat (funcall c-wrap (car cs)) "\n" - body "\n" - (funcall c-wrap (cadr cs)))) - body))) - (setq expansion (cons sep (cons full expansion))))) - (org-babel-map-src-blocks nil - (let ((i (org-babel-get-src-block-info 'light))) - (when (equal (or (cdr (assq :noweb-ref (nth 2 i))) - (nth 4 i)) - source-name) - (let* ((body (org-babel-expand-noweb-references i)) - (sep (or (cdr (assq :noweb-sep (nth 2 i))) - "\n")) - (full (if comment - (let ((cs (org-babel-tangle-comment-links i))) - (concat (funcall c-wrap (car cs)) "\n" - body "\n" - (funcall c-wrap (cadr cs)))) - body))) - (setq expansion - (cons sep (cons full expansion))))))))) - (and expansion - (mapconcat #'identity (nreverse (cdr expansion)) ""))) + (save-excursion + (goto-char (point-min)) + (let* ((name-regexp + (org-babel-named-src-block-regexp-for-name + source-name)) + (comment + (string= "noweb" + (cdr (assq :comments (nth 2 info))))) + (c-wrap + (lambda (s) + ;; Comment, according to LANG mode, + ;; string S. Return new string. + (with-temp-buffer + (funcall (intern (concat lang "-mode"))) + (comment-region (point) + (progn (insert s) (point))) + (org-trim (buffer-string))))) + (expand-body + (lambda (i) + ;; Expand body of code blocked + ;; represented by block info I. + (let ((b (org-babel-expand-noweb-references i))) + (if (not comment) b + (let ((cs (org-babel-tangle-comment-links i))) + (concat (funcall c-wrap (car cs)) "\n" + b "\n" + (funcall c-wrap (cadr cs))))))))) + (if (re-search-forward name-regexp nil t) + ;; Found a source block named SOURCE-NAME. + ;; Assume it is unique; do not look after + ;; `:noweb-ref' header argument. + (funcall expand-body + (org-babel-get-src-block-info 'light)) + ;; Though luck. We go into the long process + ;; of checking each source block and expand + ;; those with a matching Noweb reference. + (let ((expansion nil)) + (org-babel-map-src-blocks nil + (let ((i (org-babel-get-src-block-info 'light))) + (when (equal source-name + (cdr (assq :noweb-ref (nth 2 i)))) + (let ((sep (or (cdr (assq :noweb-sep (nth 2 i))) + "\n"))) + (setq expansion + (cons sep + (cons (funcall expand-body i) + expansion))))))) + (and expansion + (mapconcat #'identity + (nreverse (cdr expansion)) + "")))))) ;; Possibly raise an error if named block doesn't exist. (if (or org-babel-noweb-error-all-langs (member lang org-babel-noweb-error-langs)) - (error "%s" (concat - (org-babel-noweb-wrap source-name) - "could not be resolved (see " - "`org-babel-noweb-error-langs')")) + (error "%s could not be resolved (see \ +`org-babel-noweb-error-langs')" + (org-babel-noweb-wrap source-name)) ""))) - "[\n\r]") (concat "\n" prefix)))))) + "[\n\r]") + (concat "\n" prefix)))))) (funcall nb-add (buffer-substring index (point-max)))) new-body)) diff --git a/testing/lisp/test-ob-exp.el b/testing/lisp/test-ob-exp.el index fc67c4f8e..a625c3554 100644 --- a/testing/lisp/test-ob-exp.el +++ b/testing/lisp/test-ob-exp.el @@ -90,10 +90,8 @@ Current buffer is a copy of the original buffer." (should (equal '("(message \"expanded1\")" "(message \"expanded2\")" ";; noweb-1-yes-start - (message \"expanded1\") (message \"expanded1\")" ";; noweb-no-start <>" ";; noweb-2-yes-start - (message \"expanded2\") (message \"expanded2\")" ";; noweb-tangle-start <> diff --git a/testing/lisp/test-ob.el b/testing/lisp/test-ob.el index cc73946ee..bc66a942c 100644 --- a/testing/lisp/test-ob.el +++ b/testing/lisp/test-ob.el @@ -684,8 +684,7 @@ x <> #+end_src -#+name: foo -#+begin_src sh :noweb-sep \"\" +#+begin_src sh :noweb-ref foo :noweb-sep \"\" bar #+end_src