ConTeXt 文稿的物理结构
声明:可转载,可修改,也可以不注明作者和出处。
在阅读本文之前,建议读完前面我写过的一系列文章:
第一篇: 序幕有些长
第二篇: 这就是 ConTeXt Minimals
第三篇: 不仅仅是为了中文
第四篇: 那年挖的坑,今年开始填……
至少要阅读第一篇和第二篇。
现在,我们开始逐步探寻 ConTeXt 排版方面的知识。
本文讲述 ConTeXt 文稿的物理结构。所谓“ConTeXt 文稿”,如果读过上述的第一篇文章,你应该知道这只不过是我自己定义的一个概念,实际上它是指代那些包含了 ConTeXt 控制序列的 .tex 文档。
ConTeXt 文稿的物理结构
事实上,TeX 文稿本身并没有什么物理结构这样的概念。整篇文稿就是 TeX 控制序列的堆积,只需要在文档的末尾加个“\bye”告诉 TeX 引擎:“文稿到此结束”。这种方式,对于那些有着整齐有序的好习惯的 TeX 用户而言没什么不好,但是对于那些比较随意的 TeX 用户,则很容易写出控制序列漫天飞从而很难看懂的 TeX 文稿。
LaTeX 与 ConTeXt 定义了一些控制序列,对 TeX 文稿进行概念上的分割,从而形成了各自的物理结构。例如 LaTeX 文稿基本的物理结构:
% 设定文稿类型 \documentclass{article} % 导言区 ... ... % 正文区 \begin{document} ... 正文 ... \end{document}
ConTeXt 的等价结构如下:
% 导言区 ... ... % 文档内容 \starttext ... ... \stoptext
之所以说 LaTeX 与 ConTeXt 对 TeX 文稿进行了概念上的分割,是因为它们并没有对 TeX 文稿进行真正的区域划分。比如,LaTeX 与 ConTeXt 都建议用户尽量在导言区进行一些全局性的排版参数设定,但是用户也完全可以不遵守这个建议。
好了,我不再提 LaTeX,下面只关心 ConTeXt。
可以将 ConTeXt 文稿的物理结构简单理解为 ConTeXt 提供的文稿编写规范,沿用这种规范所写的 TeX 文稿,大家一看既知:这份 TeX 文稿是 ConTeXt 格式的,而且阅读起来感觉清爽(当然,大部分人所阅读的是 ConTeXt 所排版的文档)。要明确这样的概念:ConTeXt 文稿的物理结构只用于描述 ConTeXt 文稿自身的结构,而非它所排版的文档结构。
注意:这一“物理结构”的概念,我是从包太雷人的《LaTeX Notes》[1]中挖过来并适度拓展一下而形成的。
前面展示了一份非常基本的 ConTeXt 文稿物理结构,它看起来很简单,但是什么也不能做。如果只是打算写一篇只有一个标题的文档,那么下面这份文稿的结构也许可以满足需求。
\usemodule[zhfonts] \zhfonts[rm, 11pt] \starttext \title{庄子和惠子游于濠梁} 庄子与惠子游于濠梁之上。 庄子曰:“鯈鱼出游从容,是鱼之乐也。” 惠子曰:“子非鱼,安知鱼之乐?” 庄子曰:“子非我,安知我不知鱼之乐?” 惠子曰:“我非子,固不知子矣;子固非鱼也,子之不知鱼之乐全矣!” 庄子曰:“请循其本。子曰‘汝安知鱼乐’云者,既已知吾知之而问我。我知之濠上也。” \stoptext
这份文稿依然非常简单:
- 在导言区(\starttext 之前的区域)加载 zhfonts 模块,并使用 \zhfonts 控制序列将 11pt 的衬线字体定义为文档的主字体。
- 在正文区域(即 \starttext 与 \stoptext 所包含的区域,并非所排版文档的正文区域,而是 ConTeXt 文稿自身的正文区域,相对于文稿的导言区而言),使用 \title 控制序列设定文档标题,其后就是文档内容。
假设这份文稿的文件名为 test-01.tex,那么在启用 ConTeXt Minimals 工作环境的情况下,并且将终端的工作目录设为 test-01.tex 所在目录,便可使用命令:
$ context test-01
编译该文稿,产生 PDF 文档输出,其主要部分见下面的截图。
也许你会认为这样的排版结果很难看。
的确很难看!标题没有用醒目的粗体字,段落首行没有缩进,行距过紧。我们可以向导言区添加一些排版参数的设定语句来解决这些问题。于是,test-01.tex 文稿进化成了下面的 test-02.tex:
\usemodule[zhfonts] \zhfonts[rm, 11pt] \setuphead[title][style=\bfb, indentnext=yes] \setupindenting[always, first, 2em] \setupinterlinespace[line=1.6em] \starttext \title{庄子和惠子游于濠梁} 庄子与惠子游于濠梁之上。 庄子曰:“鯈鱼出游从容,是鱼之乐也。” 惠子曰:“子非鱼,安知鱼之乐?” 庄子曰:“子非我,安知我不知鱼之乐?” 惠子曰:“我非子,固不知子矣;子固非鱼也,子之不知鱼之乐全矣!” 庄子曰:“请循其本。子曰‘汝安知鱼乐’云者,既已知吾知之而问我。我知之濠上也。” \stoptext
排版结果截图如下:
暂 且不需要理会 test-02.tex 中新添加代码的效用,只需关注一下它们对文稿的负面影响,那就是它们将导言区变复杂甚至稍微有些混乱了。如果后续需要更多的排版设定,那么导言区也许会变 的很长,其内容通常也与文档正文内容毫无关系。为了避免这种现象,可以将导言区中的代码存放到环境 (Environment) 文件中。
环境文件
例如有这样一份 ConTeXt 文稿,其文件名为 plain-sty.tex,内容如下:
\startenvironment plain-sty \usemodule[zhfonts] \zhfonts[rm, 11pt] \setuphead[title][style=\bfb, indentnext=yes] \setupindenting[always, first, 2em] \setupinterlinespace[line=1.6em] \stopenvironment
这样的 ConTeXt 文稿即为环境文件。
上面的环境文件示例中的主要内容是 test-02.tex 文稿导言区中的语句,这些语句置于 \startenvironment ... \stopenvironment 区域。尾随 \startenvironment 控制序列之后的是环境的名字,它必须与环境文件名相同。ConTeXt 建议用户将文档所有的全局排版设定均置于环境文件中。
对于像 plain-sty.tex 这样一份定义好的环境文件,在 ConTeXt 文稿中的使用方式参考下面的示例 test-03.tex:
\environment plain-sty \starttext \title{庄子和惠子游于濠梁} 庄子与惠子游于濠梁之上。 庄子曰:“鯈鱼出游从容,是鱼之乐也。” 惠子曰:“子非鱼,安知鱼之乐?” 庄子曰:“子非我,安知我不知鱼之乐?” 惠子曰:“我非子,固不知子矣;子固非鱼也,子之不知鱼之乐全矣!” 庄子曰:“请循其本。子曰‘汝安知鱼乐’云者,既已知吾知之而问我。我知之濠上也。” \stoptext
只需使用 \environment 控制序列,并向其提供环境文件名,便可以将环境文件的内容载入包含正文区域的 ConTeXt 文稿中。
可将 ConTeXt 环境文件等同于衣服,而将包含正文区域的 ConTeXt 文稿视身体。我们可以为同样的身体提供各种各样的衣服。
ConTeXt 环境文件的存在,实现了 ConTeXt 文稿内容与外观在概念上的分离。
如果你了解一些 Plain TeX 或 LaTeX 的知识,可能会认为 \input 控制序列也可以起到 \environment 控制序列的作用。事实上,ConTeXt 的环境文件机制可以保证环境文件仅被加载一次。
环境文件仅被加载一次,这有什么优势?如果你知道不管是 Plain TeX、LaTeX 还是 ConTeXt,在处理交叉引用时,通常要对 TeX 文稿重复编译多次,就大致可以明白环境文件仅被加载一次可以提高一点点的 TeX 文稿编译效率。
作品(Product)与组件(Component)
采用 \starttext ... \stoptext 的 ConTeXt 文稿物理结构,尽管有环境文件的辅助,但是它不足以构建规模较大一些的文档,譬如一本页数较多书。于是,ConTeXt 提供了作品(Product)与组件(Component)的文稿物理结构。
下面示例建立了一份文件名为 prd.tex 的作品文稿,现在它还是一个空壳。
\startproduct prd % ... 暂且无内容 ... \stopproduct
注意:作品名要与其文件名相同,就像环境文件那样,这种名称冗余主要是为了仅文稿只被加载一次。
组件是对作品结构的进一步分割,也就是说一份作品由一些组件构成。下面的示例建立了一份文件名为 c-1.tex 的组件文稿,其定义方式类似作品文稿。
\startcomponent c-1 \product prd % 表示该组件隶属于作品 prd % 暂且无内容 \stopcomponent
现在假设我们建立了多个组件,例如 c-1.tex, c-2.tex 等,那么可以像下面的示例那样将组件插入作品文稿。
\startproduct prd \component c-1 \component c-2 ... ... \stopproduct
为了更方便控制作品的外观,我们可以向作品文稿中插入环境文件,例如:
\startproduct prd \environment plain-sty \component c-1 \component c-2 ... ... \stopproduc
作品、组件与环境文件的逻辑关系如下图所示:
项目(Project)
有时可能要围绕一个主题写很多本书,这些书虽然内容不同,但是排版风格是相同的,例如出版某种期刊。ConTeXt 为这类应用提供了相应的文稿物理结构,即项目(Project)。
项目是建立在作品之上的,即一个项目可以包含多份作品。
项目文稿的构建方式与作品文稿相似。例如,下面示例建立了名为 prj 的项目,其中包含了两份作品 prd-1 与 prd-2 :
\startproject prj \product prd-1 \product prd-2 \stopproject
若作品文稿被某个项目包含,那么需要在作品文稿中声明它所隶属的项目,例如:
\startproduct prd-1 \project prj \component cmp-1 \component cmp-2 ... ... \stopproduct
同时,隶属于该作品的组件中也要相应之指定所隶属的项目名称,例如:
\startcomponent cmp-1 \product prd-1 \project prj % 内容暂且为空 \stopcomponent
但是,要注意,如果采用项目文稿,那么环境文件应该插入到项目文稿中,例如:
\startproject prj \environment plain-sty \product prd-1 \product prd-2 ... ... \stopproject
此时,作品文稿便不再需要插入环境文件。因为同一项目中的作品与组件,均可共享项目文稿的环境文件。
项目、作品、组件与环境文件的逻辑关系如下图所示:
技巧
为 了让各种类型的文稿看起来一目了然,建议环境、项目、作品及组件对应的文件名分别采用 env-, prj-, prd-, c- 作为前缀。例如,env-plain.tex, prj-gtk.tex, prd-glib.tex, prd-gdk.tex, c-base-type.tex, c-main-event-loop.tex 等。
为了便于管理,各份作品的组件可存放在单独的子目录中。例如要进行一个 gtk+ 编程技术书籍项目,该项目可分为 glib、gobject、gdk、gtk 等作品,可以采用下图所示的文稿物理结构。
对于存放在子目录中的组件文稿,向作品文稿中插入它们时,需要指定它们的相对路径。例如对于上图种的 prd-glib.tex,可以这样撰写:
\startproduct prd-glib \project prj-gtk+-book \component glib/c-base-types \component glib/c-main-event-loop \component glib/c-threads ... ... \stopproduc
我们可以使用 \usepath 控制序列来指定相对目录,这样可以避免重复输入组件文稿所在目录名称。例如:
\startproduct prd-glib \project prj-gtk+-book \usepath[glib] \component c-base-types \component c-main-event-loop \component c-threads ... ... \stopproduc
预告
下一篇,应该是“ConTeXt 文稿的逻辑结构”。
参考文献
[1] LaTeX Notes,包太雷. 他那远在墙外的主页 http://www.dralpha.com/
转载时,希望不要链接文中图片,另外请保留本文原始出处:http://garfileo.is-programmer.com
2011年1月13日 11:41
博主又更新了,哈哈,赞!
2011年1月14日 23:06
学习,期待下篇。
2011年1月17日 13:14
这个物理结构得概念创建得还是不错得。
2011年6月14日 17:44
你好,我的contex配置总是会遇到各种问题,你可不可以把你系统上的的context下的third文件夹打个包传到那个地方供下载呢?谢谢
2011年6月15日 04:27
@lxping: 不需要什么配置,只需将 zhfonts 目录放到 texmf-local/tex/context/third 目录,然后 `luatools --generate`