noweb 的用法

释名

noweb 就是 Norman Ramsey 的 WEB。

此 WEB 非彼 Web,它是文学编程工具。

Donald Knuth 说:『选择 WEB 作为名字,部分因为它是英语中很少的几个没有用于计算机的三字词语之一。但随着时间流逝,我越来越喜爱这个名字,因为我认为最好把一个复杂的软件确确实实地看成由简单材料以精巧的方式拼出来的一张网。我们通过理解复杂系统的各个简单部分和这些部分与其直接邻居的简单关系来理解复杂系统本身。如果我们用网的概念来表达程序,我们就能用一种自然且圆满地方式强调其结构上的属性。』

语法

文学编程就是将人类的语言与机器的语言交织到一起。

@ 符号是某文本行的第一个字符,那么 @ 之后的文本都是人类的语言(事实上是 TeX 语言)。

< 符号是某文本行的第一个字符,并且这个字符后面跟随 <...>>= 这样的字符,那么这些字符之后的文本都是机器的语言(程序代码)。... 是程序代码的名字。

也可以这么来理解,将 <<...>>= 视为机器语言的开始,将 @ 符号视为机器语言的终止,这两种符号之间的区域,是代码块,... 是代码块的名字。

代码块可以同名,noweb 会把同名的代码块按照它们出现的顺序连到一起。

在一个代码块中,可以使用 <<...>> 来引入其他代码块。

noweb 语法的具体示例,可参考『论文式编程』与『M4 说要有 lambda,就有了 lambda』中的示例。

程序代码的抽取

noweb 程序的源文件以 .nw 为后缀。

使用

$ notangle -Rfoo.c foo.nw > foo.c

可以从 foo.nw 文件中抽取出程序代码(这里是 C 语言),将其输出到 foo.c 文件之中。-Rfoo.c 表示从 foo.nw 中的 foo.c 处抽取代码,这需要 foo.nw 中必须存在下面这样的代码块:

<<foo.c>>=
... ... ...
... ... ...
@

程序文档的生成

$ noweave -x foo.nw > foo.tex
$ xelatex foo
$ xelatex foo

之所以要执行两次 xelatex 命令,是因为 foo.tex 中存在着许多交叉引用。

noweave 支持管道,因此你可以根据自己的需要去修改 noweave 生成的文档内容。例如,我写了一个叫做 zhtex 的脚本,其内容如下:

#!/bin/bash

sed -e 's/\\documentclass{article}/\
\\documentclass[adobefonts]{ctexart}\
\\usepackage{amsmath}\
\\usepackage{graphicx, float}\
\\usepackage{cprotect}\
\\usepackage{booktabs}\
\\newtheorem{theorem}{定理}\
\\usepackage[top=2cm,bottom=2cm,left=2cm,right=2cm]{geometry}\n/g ; 
s/\\nwbegindocs{0}//g ; 
s/\\maketitle/\\maketitle\n\\nwbegindocs{0}/g'

我可以将 zhtex 挂到 noweave 命令中:

$ noweave -x foo.nw | zhtex > foo.tex

也可以生成 HTML 文档(不支持数学公式与图表,不过可以在 noweave 管道中做一些 hack 来支持它们):

$ noweave -filter l2h -index -html foo.nw > foo.html

hack

要对 noweb 的管线进行 hack,可参考:https://www.cs.tufts.edu/~nr/noweb/extensibility.html

虽然 noweb 源文件主要是 TeX 格式文本,但是可以写转换器,将 TeX 文本转换成其他的标记语言。

更详细的指南

比本文更详细但是内容更少(只有一页)的 noweb 指南,见:https://www.cs.tufts.edu/~nr/noweb/onepage.ps

阅读 2.3k

推荐阅读
while(1) { }
用户专栏

NULL

240 人关注
125 篇文章
专栏主页