代码块可使用 noweb158 风格语法引用其他代码块:
<<CODE-BLOCK-ID>>
其中 CODE-BLOCK-ID 可以是单个代码块的 ‘NAME’ ,或是一组共享相同 ‘noweb-ref’ 头参数的代码块集合(见 Using Header Arguments)。Org 可将此类引用替换为被引用块的代码;若为具名 ‘NAME’ 的单个代码块,也可替换为该块的执行结果。
‘noweb’ 头参数控制 noweb 语法引用的展开行为,展开发生在代码块执行、导出或导出时。
默认值。在执行、导出、导出时均不展开代码中的 noweb 引用。
在执行、导出、导出时均展开代码中的 noweb 引用。
仅在导出时展开 noweb 引用,执行和导出时不展开。
在执行和导出时展开 noweb 引用,导出时移除引用。
在执行和导出时展开 noweb 引用,导出时不展开。
在执行或导出前展开 noweb 引用,导出时移除引用。
仅在执行前展开代码中的 noweb 引用。
最简单的用法是将单个代码块内容插入其他块中。如下例所示:
#+NAME: initialization #+BEGIN_SRC emacs-lisp (setq sentence "Never a foot too far, even.") #+END_SRC #+BEGIN_SRC emacs-lisp :noweb yes <<initialization>> (reverse sentence) #+END_SRC
第二个代码块展开后为:
#+BEGIN_SRC emacs-lisp :noweb yes (setq sentence "Never a foot too far, even.") (reverse sentence) #+END_SRC
注意 noweb 展开不会自动继承 ‘:var’ 头参数159。
也可以引用共享同一 ‘noweb-ref’ 头参数的多个代码块,该参数可在文件、子树或代码块层级设置。下例 Org 文件中,所有代码块内容会在导出时拼接为纯代码文件。
#+BEGIN_SRC sh :tangle yes :noweb yes :shebang #!/bin/sh
<<fullest-disk>>
#+END_SRC
* the mount point of the fullest disk
:PROPERTIES:
:header-args: :noweb-ref fullest-disk
:END:
** query all mounted disks
#+BEGIN_SRC sh
df \
#+END_SRC
** strip the header row
#+BEGIN_SRC sh
|sed '1d' \
#+END_SRC
** output mount point of fullest disk
#+BEGIN_SRC sh
|awk '{if (u < +$5) {u = +$5; m = $6}} END {print m}'
#+END_SRC
默认情况下,换行符会分隔每个 noweb 引用的拼接内容。如需使用其他分隔符,可修改 ‘noweb-sep’ 头部参数。
此外,Org 可以插入单个代码块的执行结果,而非其代码体本身[160。当在代码块名称后附加括号(可包含参数)时,便会触发执行,如下所示。
<<NAME(optional arguments)>>
注意这种用法必须使用 ‘NAME’ 关键字指定的名称,使用 ‘noweb-ref’ 设置的引用无法触发执行。
下例展示带括号与不带括号的 noweb 引用在导出内容上的区别。给定:
#+NAME: some-code #+BEGIN_SRC python :var num=0 :results output :exports none print(num*10) #+END_SRC
该代码块:
#+BEGIN_SRC text :noweb yes <<some-code>> #+END_SRC
展开为:
print(num*10)
下面使用带括号的 noweb 引用,并将变量 ‘num’ 设为 10:
#+BEGIN_SRC text :noweb yes <<some-code(num=10)>> #+END_SRC
展开结果为代码块 ‘some-code’ 的执行结果,而非代码本身:
100
noweb 插入会保留引用前的前缀字符。下例演示该行为:由于 ‘<<example>>’ 引用位于 SQL 注释符后,展开后的每一行都会被注释。给定:
#+NAME: example #+BEGIN_SRC text this is the multi-line body of example #+END_SRC
该代码块:
#+BEGIN_SRC sql :noweb yes ---<<example>> #+END_SRC
展开为:
#+BEGIN_SRC sql :noweb yes ---this is the ---multi-line body of example #+END_SRC
该行为不会影响不含换行的内联 noweb 引用,因此内联引用可以正常使用。
该特性也可用于管理导出代码片段的缩进。给定:
#+NAME: if-true
#+BEGIN_SRC python :exports none
print('do things when true')
#+end_src
#+name: if-false
#+begin_src python :exports none
print('do things when false')
#+end_src
该代码块:
#+begin_src python :noweb yes :results output
if true:
<<if-true>>
else:
<<if-false>>
#+end_src
展开为:
if true:
print('do things when true')
else:
print('do things when false')
在代码块中设置 ‘noweb-prefix’ 为 ‘no’ 可关闭此前缀行为,例如:
#+BEGIN_SRC elisp :noweb-prefix no (setq example-data "<<example>>") #+END_SRC
展开为:
(setq example-data "this is the multi-line body of example")
如不确定代码块展开后的结果,可使用以下命令预览
org-babel-expand-src-block) ¶根据头参数展开当前代码块,并在预览缓冲区中显示结果。
有关 noweb 文学编程详情,参见 https://www.cs.tufts.edu/~nr/noweb/.
下例中尝试执行第二个代码块会报错,因为第一个代码块中定义的变量在第二个块中无效。
#+NAME: get-prompt #+BEGIN_SRC emacs-lisp :var prompt="root> " :var command="ls" (concat prompt command) #+END_SRC #+RESULTS: get-prompt : root> ls #+BEGIN_SRC emacs-lisp :noweb yes <<get-prompt>> #+END_SRC
上一代码块展开时未设置 prompt 与 command 的值。
#+BEGIN_SRC emacs-lisp (concat prompt command) #+END_SRC
引用执行时,光标会定位在被引用代码块处,并使用其头部参数(含继承而来的参数)