by LiYanrui
Knuth 的 TeX
![]() |
Donald E. Knuth |
20 世纪 60 年代,著名计算机科学家和数学家,斯坦福大学 Donald Knuth 教授在忙于撰写那部叫做《计算机程 序设计艺术》 的书。这部书计划一共写七卷,Knuth 在写第四卷时,出版社拿来了第二卷的第二版书样给他过目,结果令他大失所望,因为当时出版社的印刷技术没有使他的书稿更好看,反而变糟了,尤其是在数学公 式和字体上面的缺陷更令他无法接受。于是他就开发了一个既能供科学家编排手稿,又符合出版社印刷要求的高质量的计算机排版系统。
这个排版系统的名字叫做 TeX。这个名称是由三个大写的希腊字母 ΤЄΧ 组成,在希腊语中是“科学”和“艺术”的意思。为了方便书写,一般在纯文本文档中将其写为“TeX”, 念做“泰赫”(我个人习惯将其读作“泰克”)。
Knuth 于 1977 年开始构造 TeX 系统,并为该系统设计了一个字体生成软件——METAFONT。1982 年 TeX 系统发布,之后又有几次版本升级。Knuth 用圆周率 π 的近似值作为 TeX 系统的版本号,并采用自然底数 e 的近似值作为 METAFONT 版本号。系统每升级一次,其版号就增加一位数字,从而不断地趋近于 π 和 e,这种别出心裁的版本号表示方式一方面可以展示 TeX 与科技文献排版的密切关系,同时也表达了 Knuth 对 TeX 系统与 METAFONT 系统不断追求完美的愿望 。
1990年 TeX 第3.1版发布时,Knuth 发出宣言:
- 不再对 TeX 进行任何功能上的扩张。
- 如果出现明显问题,修正的版本依次为3.14版,3.141版,3.1415版.....在自己离开这个世界的时候,将最后的 TeX 版本序号改为 π。 此后,即使再发现错误,也都将成为 TeX 的特征而保留。如果有人非要修改的话,就不要再叫 TeX 了,请另外起名。
- 关于 TeX 的一切,已经全部做了书面说明,可以自由利用来设计其他的软件。
TeX 系统的内核相当稳定,几乎没有 bug,1995 年以后版本号一直停止在3.14159,直到 2002 年 12 月才又进行了一次升级。到目前为止,TeX 系统的版本序号是3.141592,而 METAFONT 版本序号则为 2.71828。
TeX 的许多化身
Knuth 之所以很自信的宣布不再对 TeX 进行任何功能上的扩张,并非自视甚高,而是有一定客观原因的。其中最主要的原因就是 TeX 提供了宏扩展机制,开发者或者用户均可以对 TeX 提供的 300 多条基本的控制序列(Control Sequence)进行组合,定义更为高级的控制序列,从而增强 TeX 的排版能力。
尽管很多 TeX 没有原生提供的功能可以通过宏扩展来实现,但是终究是有一些比较重要的问题是宏扩展难以解决的,比如对多国语言文字的支持、对 TrueType、OpenType 字体的支持、图形支持等问题。所以在 Knuth 的 TeX 之后,许多人努力地对 TeX 进行改进,或者干脆开发一个全新的“TeX”。开发者们为了尊重 Knuth 宣言的第二条,这些改进版的 TeX 或者重新开发的 TeX 均不再叫 TeX,它们都有新的名字,诸如 e-TeX、Omega、pdfTeX、XeTeX、LuaTeX 等等。
自 1990 年以来,TeX 的改进项目层出不穷,但是大浪淘沙,许多项目都没有成功,有的已经死去,有的在苟延残喘。目前广为使用 TeX 改进版本主要有 pdfTeX、XeTeX 和 LuaTeX。应当注意的是 pdfTeX 项目开发者 于 2008 年 6 月宣布自 pdfTeX 1.50.0 版本之后只进行 bug 修正,不再提供新功能扩张。LuaTeX 项目则被看作是 pdfTeX 项目的延伸,并且添加了其它许多重要的新功能,并继续开发下去。
虽然 Knuth 的 TeX 系统出现了许多的改进版本和分化版本,但大都是良性的,并且变动的只是 TeX 引擎,它们大都兼容 Knuth 定义的 TeX 格式。这就好比只改进汽车 的发动机性能,并不改变或者只是略微改变汽车驾驶操作方式,这使得用户可以像往常一样去驾驶一辆性能更好的汽车。所以 TeX 用户们通常无需要担心 TeX 引擎太多,导致自己的 TeX 文稿在其他人的计算机上无法编译。
几个 TeX 术语
前一节出现了几个经常让 TeX 新用户难以理解的术语——控制序列 (Control Sequence)、TeX 引擎 (Engine) 以及 TeX 格式 (Format)。为了帮助那些没有太深的计算机使用背景的 TeX 新用户来理解这些概念,我要适当的找点东西来比喻一下。
首先,来看 TeX 引擎是什么。引擎,俗称发动机,是用来驱动某个系统运转的。比方说汽车引擎,就是给汽车提供动力的装置,让汽车的机械部件运作起来,从而可以日行千里,夜 行八百。TeX 引擎是一个计算机程序,它的作用就是驱动计算机为用户输出排版结果。
然后来看一下控制序列又是什么东西。众所周知,现在最先进的汽车也不是自动驾驶的,它通常需要驾驶者输入一些控制参数,譬如档位、油门、离合等。当 然,TeX 引擎不需要输入这些,它只需要你向它提供要排版的文字以及一些控制序列而已。譬如下面这行 TeX 引擎可接受的字串:
这行字串包含了所要排版的文字以及控制序列,其中以“\”作为前缀的单词便构成一个控制序列,比如 "\bf" 和 "\sl"。TeX 在接受该字串之后,它就可以严肃的按照控制序列的指示驱动计算机输出相应的排版结果:
观察这份由 TeX 引擎驱动计算机输出的排版结果,可以看到在控制序列 "\bf" 之后的单词 "bold" 的排版效果是粗体,而控制序列 "\it" 之后的单词 "emphasize" 的排版效果是斜体。即使你现在是第一次听说 TeX,应该也不难猜出 "\it" 和 "\bf" 分别是用来控制文字的粗体和斜体的,以及字串里的 "{...}" 括号是限制控制序列的作用域的(即控制序列只对 "{...}" 所包含的字串有效)。
可以将 TeX 的控制序列看作是由用户发给 TeX 引擎的指令,TeX 引擎会乖乖地按照这些指令去驱使计算机生成用户所期望的排版结果。TeX 控制序列就像对汽车的方向盘、档位、油门、离合、刹车等装置进行操作一样,可以使用它们来控制汽车引擎及其它相关部件的工作状态,从而让汽车按照我们的意 愿行驶在正确的道路上。如果一份文本文件所包含的内容除了控制序列就是所要排版的文字信息,我们可以将该文件称 为 TeX 文稿(主 要是为了叙述上的方便)。
Knuth 在设计 TeX 系统时,为 TeX 引擎定义了 300 多个比较基本的控制序列。TeX 用户只要掌握了这些控制序列的用法,就具备了排版各种类型文档的能力。这种想法很好,但是在实际应用中,这些控制序列与所排版的文字交织在一起,显得非常 不堪,比方说下面这行字串:
看上去很是古怪,实际上它的目的只是对 "TEX" 这三个字母进行稍微特殊一些的排版:
试想,如果一篇很长的 TeX 文稿里到处都是类似的文本, 对于 TeX 引擎而言很是直白,因为它只管机械地处理那些控制序列;对于直接阅读该文稿的我们而言就异常晦涩了,因为我们关注的是文稿中的内容,另外输入那些稀奇古怪 的控制序列也是个很费时间的体力活。
针对这一问题,Knuth 为 TeX 建立了宏扩展机制,允许用户去组合一部分基本的控制序列,从而生成更方 便使用的控制序列。比如上述 "TEX" 的排版语句可以定义成 "\TeX" 控制序列:
这样,在 TeX 文稿中,只要使用 "\TeX" 就可以实现上述 "TEX" 的特殊排版效果,因为 TeX 引擎在遇到 "\TeX" 控制序列时,会自动将其展开为 "T\Mkern {-.1667}\lower .5ex\hbox {E}\Mkern{-.125}X"。
利用宏扩展机制,可以将那些丑陋的 TeX 语句定义为一个高级的控制序列,从而显著改善 TeX 文稿可读性。当 TeX 引擎遇到高级控制序列时,会将高级控制序列展开为基本控制序列组合,前提是 TeX 引擎需要事先知道这些高级控制序列的定义。
一些非常有经验的 TeX 用户(即 TeX 专家)在长期使用 TeX 的过程中,会利用宏扩展机制,逐渐积累出一套自定义的控制序列,他们利用这些控制序列可以快速而优美地实现诸如论文、专著、幻灯片、书信、乐谱、棋谱等文 档的排版。这些由 TeX 专家们自定义的控制序列通常是单独存放到一份或多份文件里,这样就形成了 TeX 宏包。 这些 TeX 宏包大部分都是无偿地提供给普通 TeX 用户使用的。使用方法很简单,比方说我从某处获得了一个名为 xxxx 的宏包,要使用这个宏包,只需要在我的 TeX 文稿的开头,使用 "\input" 控制序列就可以将该宏包装载进来:
然后我就可以在自己的 TeX 文稿里调用 xxxx 宏包中定义的控制序列了。
为了加速 TeX 引擎对这些 TeX 宏包的装载和解析,Knuth 为 TeX 提供了格式生成机制,利用它可以将一份 TeX 宏包转换为 TeX 引擎可以快速载入的二进制文件,这种文件被称为 TeX 格式。也就是说,TeX 格式也是 TeX 宏包,只不过是一种可供 TeX 引擎快速装载和处理的 TeX 宏包。
Knuth 本人也是感觉 TeX 的基本控制序列过于难用,于是提供了一套由他定义的 TeX 格式,叫做 Plain TeX,其中包含了 600 多个控制序列。使用 Plain TeX 定义的控制序列来撰写 TeX 文稿要比直接使用那 300 多个 TeX 基本控制序列来的轻便一些。由于 TeX 的基础控制序列和 Plain TeX 所包含的控制序列皆出自 Knuth 之手,所以 TeX 用户们干脆也就不加以区分了,将它们统称为 Plain TeX,共包含大约 900 个控制序列。
在实际应用中,TeX 用户们对 Plain TeX 显然是不满意的。这主要是因为 Plain TeX 仅仅停留在如何排版的层次上,即便是使用 Plain TeX 来排版一份中规中矩的论文,用户们也不得不同时扮演论文作者和论文排版者双重角色。
Lamport 和 Hans 让 TeX 更好用了
现在,我们从一些比较流行的字处理软件(比如微软 Word、金山 WPS、OpenOffice 等软件)的视角来看,普通用户在写一份文档时,只需要给他提供一份大众化的模板,然后他向里面填写文档内容即可快速有效的完成文稿排版。早期的 TeX 所缺乏的就是类似的便于普通用户使用的文稿模板。这一问题的解决,自然还是要着落在 TeX 的宏扩展机制上。在 Knuth 公开发布 TeX 之后没几年,这个问题就被美国计算机科学家 Leslie Lamport 给解决了。
1984 年前后,Lamport 在使用 Knuth 发明的 plain TeX 排版软件撰写一些并行计算方面的论文,感到用起来不太方便,于是便自己定义了一套比较高级的控制序列,并制作成新的 TeX 格式,命名为 LaTeX。起初 LaTeX 在计算机科学家之间流传,大家觉得 LaTeX 比 plain TeX 使用更方便,就经常通过各种渠道向他索取。
LaTeX 的卓越之处在于提供了一套针对文档逻辑结构的控制序列,将文章的排版设计与文章内容分开处理。比方说一篇科技论文,其逻辑结构主要由标题、作者信息、摘 要、正文、参考文献等部分组成,使用 LaTeX 的控制序列可将其表示为:
\title{ 标题}
\author{ 作者信息}
\begin{ abstract}
... 摘要内容 ...
\end{ abstract}
\begin{ document}
... 正文内容 ...
\bibliography{ 参考文献}
\end{ document}
至于论文的标题、摘要、正文等各部分所使用的字体及其尺寸、文本行距、段落间距等排版参数,LaTeX 均提供了较好的默认设置,通常不需要修改。如果采用 Plain TeX 来排版这样的文档,动用上百个控制序列是家常便饭。这样,用户在使用 LaTeX 来排版自己的文稿时,主要精力通常可以放在文稿的内容上,而不是文稿的版面设计。话又说回来,如果用户必须去调整文稿的排版参数来适应特殊的排版需 求,LaTeX 提供的控制序列对此也是有些力不从心,这时用户就有必要去学习一下 Plain TeX 了。未能为排版参数配置提供统一化的控制序列,这是 LaTeX 最大的缺点,不过在当时终究是瑕不掩瑜。
![]() |
Leslie Lamport |
LaTeX 的出现消除了普通用户对 TeX 的敬畏,普通用户即便不是很了解 TeX,也可以在很短的时间制作出高质量的排版结果,并且对于复杂数学公式排版,LaTeX 表现的也非常出色,因此迅速在计算机科学、数学及相关学科领域得到推广应用,也逐步吸引了许多科学家和 TeX 爱好者不断对 LaTeX 继续进行宏扩展,并将宏扩展以宏包的形式发布,供其他用户使用,这使得 LaTeX 的功能不断地扩充,应用领域也不断地扩大。
Lamport 在 1992 年发布了 LaTeX 2.09 版本之后便退居二线。之后 LaTeX 的开发工作由 Frank Mittelbach 领导的 LaTeX 小组接管。该小组于 1994 年发布了 LaTeX 2ε 版本之后,然后他们就转入 LaTeX 3 版本的开发。迄今,LaTeX 3 仍在在开发中,希望将来会有好的结局。
已经存在了 15 年的 LaTeX 2ε 现在已经成为国际数学排版的事实标准,国外有许多期刊接受甚至只接受 LaTeX 文稿。从这一点来看,LaTeX 项目长期没有太大变化似乎是件好事情,因为这样比较稳定,许多基于 LaTeX 的文档项目或者软件项目不用担心来自底层的动荡。
虽然大多数 TeX 用户对 LaTeX 表示很满意(现在也是如此),但是在上个世纪 80 年代后期,荷兰的一个名字叫做 Pragma 的排版公司里有几个家伙却对 LaTeX 很不满意,其中一个人的名字叫做 Hans Hagen。因为 Hans 是做文档排版服务的专业人员,他的工作就是根据顾客的需求来排版各种样式的文档,因此需要频繁的修改 LaTeX 默认的那些排版参数。
前面已经说过,LaTeX 最大的缺点就是没有为排版参数的设置提供统一化的控制序列,用计算机软件的专业术语来说就是“用户界面不友好”。于是,Hans 尝试对 LaTeX 的控制序列做一些封装(宏扩展),想改善 LaTeX 的用户界面。譬如,他对 LaTeX 的列表项控制序列进行封装后,提供了更为友好的控制序列:
\item 列表项 1
\item 列表项 2
\item 列表项 3
\stopitemize
上述控制序列可以生成如下风格的列表:
如果将 "\startitemize[n]" 的参数由 "n" 改为 "a" 时,即 "\startitemize[a]",那么上述控制序列可以生成如下风格的列表:
如果将 "\startitemize[n]" 的参数由 "a" 改为 "1" 时,即 "\startitemize[1]",那么上述控制序列可以生成如下风格的列表:
从上面这个有关列表排版的示例可以看出,Hans 对 LaTeX 继续封装的主要意图就是:让用户只需为控制序列提供一些很简单 的参数便可以实现最大化地排版控制。在 LaTeX 里,对于上述三种列表项是分别通过几组不同的控制序列来实现的,另外去调整列表的其它排版参数(留白、缩进、行距等)也非常繁琐。
![]() |
Hans Hagen |
但是,Hans 对 LaTeX 的封装工作仅仅开了个头便终止了。因为他当时对 LaTeX 进行了一次版本升级,然后发现他定义的那些控制序列没法正常工作了,估计是积极性被严重打击了。扔掉 LaTeX 之后,Hans 去尝试了当时其它一些 TeX 格式,最后发现 InrsTeX 格式(现在已经是文物了)比较适合 hack,便于用户界面友好方面的改进。Hans 在以后的岁月里不断地对 InrsTeX 进行代码替换和封装,直到最后他意识到自己已经创造了一个新的 TeX 宏包,便将这个宏包命名为 pragmatex,直到 1996年才更名为 ConTeXt,这个名字是个文字游戏,其意可以拆解为 Con-TeX-t,表示 "text with tex"。不得不说,这个名字取的很失败,因为在 Google 里输入 "ConTeXt" 的时候,检索到的大都是跟 ConTeXt 无关的信息。
一开始 ConTeXt 主要是针对 LaTeX 的缺点而开发的,按说它应该可以取代 LaTeX。但是在 ConTeXt 还在逐步完善的时间里,LaTeX 已经在 TeX 用户群中广为流传了 10 多年,期间出现了数以千计的辅助宏包,再加上许多科技期刊和专业排版公司的支持,所以 ConTeXt 一时之间很难撼动 LaTeX 的地位。所以,我们最好还是不要以用户群的多与寡来评判一个工具的好坏。
ConTeXt 还具有一个特点,就是项目开发特别活跃。拿新版本发布来说,有时一天会连续发布多次。把这个特点与 LaTeX 项目长期的不露声色相比,ConTeXt 项目显得很有激情。当然,这不能算是优点。频繁的发布新版本通常也昭示着容易出 bug。但是也不必过于担心,因为频繁发布的新版本只是测试版,ConTeXt 项目组每年都会发布一个稳定版。
在 TeX 发展历程中,TeX 格式可谓千变万化,但是它们都致力于提高 TeX 的易用性,让用户不用去面对晦涩难懂的 Plain TeX 控制序列。现在 LaTeX 和 ConTeXt 好像是 TeX 的左膀和右臂,我们只需抓住它们中的一个,即可与 TeX 共舞。显然,我和这篇文档一起选择了 ConTeXt。
在 ConTeXt 的道路上观看 TeX 奔跑的身影
基于前面的那些知识,应当可以认识到 TeX 格式是与 TeX 引擎密切相关的。ConTeXt 尤为如此,它与 TeX 引擎宛若两根相互缠绕的树藤,沿着岁月的方向蜿蜒前进并且生机盎然。
ConTeXt 目前的版本已进化到 MkIV,在它之前还有两个版本,分别是 ConTeXt MkI 和 ConTeXt MkII。
ConTeXt MkI 是 ConTeXt 的第 1 个版本,所匹配的 TeX 引擎是 Knuth 开发的那个 TeX 引擎。Knuth 的 TeX 引擎的排版输出结果是 dvi 文件格式,这种文件格式通常需要借助 dvi2pdf、dvipdfmx 等程序转换成 ps 或 pdf 文件格式方可用于文档打印或屏幕阅读。我们现在还是把 MkI 和 dvi 放到博物馆里供喜欢历史的人去研究吧。
ConTeXt MkII 是 ConTeXt 的第 2 个版本,所匹配的 TeX 引擎是捷克籍越南人 Hàn Thế Thành (也可写作 Han The Thanh) 由 Knuth TeX 引擎改造而来的 pdfTeX 引擎。pdfTeX 引擎可以直接将排版结果输出为 pdf 文档格式,这样就可以省去 dvi 到 pdf 的转换步骤。ConTeXt MkII 是当前 ConTeXt 格式的稳定版本,但是开发者今后只对其进行 bug 修正,不再为其增加新功能。
ConTeXt MkIV 是 ConTeXt 的第 4 个版本,也是正在开发中的下一代 ConTeXt,所匹配的 TeX 引擎是 Taco Hoekwater 开发的 LuaTeX。LuaTeX 引擎本身也是正处于开发中,目前在功能上已经超越了当前所有的 TeX 引擎。ConTeXt MkIV 的开发工作是与 LuaTeX 的开发工作同步进行的,前者靠后者提供更多的新功能,后者靠前者进行可用性与稳定性测试。
Hans 打算将 MkIII (也就是 ConTeXt 第 3 个版本)这个版本号留给那个可以与 XeTeX 引擎相匹配的 ConTeXt 格式,这是因为 XeTeX 引擎也是正处于开发中,尚未发布正式版本。
目前,Hans 和 Taco 在合作上如胶似漆,两人的开发工作也相得益彰,所以招惹许多 ConTeXt 用户对那个计划在 2012 年正式发布的 MkIV 版本非常期待。
他们想把 TeX 怎么样
这么多年以来,TeX 的引擎一直在不断的改革着,TeX 格式也在不断地改革着,许多 TeX 用户在这众多的改革中有时会晕头转向。为了不迷路,我们还是先在 ConTeXt 格式发展道路上停留片刻,静心看一下 TeX 引擎究竟在向那个方向走去。
前面我们已经知道,最早的 TeX 就是 Knuth TeX。当 Knuth TeX 项目冻结之后,仅仅做bug 修正。但是它提供的宏扩展机制依然无法满足大家的需要,于是就有了一大堆 TeX 的改进版本。
NTS (New Typesetting System) 项目的任务就是要继续扩展 TeX。这个项目由德国 TeX 用户组织于 1992 年发起,后来不知怎么回事一直拖到 1998 年才算是真正地开始,并计划使用 Java 将 Knuth TeX 重新实现与改进(Knuth TeX 是使用 WEB 语言实现的,WEB=Pascal+TeX)。在 1999 年至 2000 年间,NTS 项目的运作比较积极。但是后来又不知怎么回事,这个项目又没有什么动静了。
NTS 项目开始时,有一个叫做 e-TeX (Extension TeX) 的对 TeX 引擎的改进项目,也是由 NTS 项目组开发的,后来由 Peter Breitenlohner 接管。e-TeX 项目的主要任务是对 TeX 进行扩展,在 Knuth TeX 的基础上又增加了许多有用的控制序列。当时,LaTeX 格式中的很多排版功能是基于这些控制序列实现的,后来 ConTeXt 也很快放弃了 Knuth TeX 转而使用 e-TeX。
e-TeX 与 NTS 的区别在于:前者只是对 Knuth TeX 进行修修补补,而后者是计划使用 Java 语言对 TeX 重新实现并加以改进。从我所阅读的材料来看,NTS 项目基本上已经败落,而 e-TeX 则是下文要讲到的 pdfTeX 项目的重要基础。
后来在 2002 年,德国一些专家和开发人员组织成一个小团体,发起了 ExTeX 项目。ExTeX 项目是基于 NTS 项目的,它的理想是实现一个基于 Java 实现一个新的 TeX 引擎,但是这个项目似乎也是挖了个坑,然后就没影了。
![]() |
Han The Thanh |
1997 年,Han The Thanh 基于 Knuth TeX 实现了 pdfTeX 。pdfTeX 在实现上可以分为两个模块:一个模块保留了原先Knuth的所有代码,可以按照 Knuth TeX 那样直接输出 dvi 文件格式;另一个模块主要是实现基于 TeX 源文档直接输出 pdf 文件格式,在该模块的实现中,加入了大量的 C 代码;通过与 C 库的连接,可以处理一些 Knuth TeX 引擎难以解决的问题,比如插入各种格式的图片等。pdfTeX 在排版算法方面也做出了重要改进,可以取得更好的排版效果。后来,pdfTeX 开发人员又将 e-TeX 对 Knuth TeX 的改进部分也合并到 pdfTeX 项目中。由于 pdfTeX 的功能比较强大,在国际 TeX 用户组织 (TUG) 维护的 TeX 系统发行版——TeX Live 中被设定为默认的 TeX 引擎,这标着着 pdfTeX 得到了 TeX 用户广泛认可。
对 TeX 引擎的改造工作除了增强其排版功能之外,还有一个重要的方向就是对多国语言文字的支持。
Knuth 在设计 TeX 引擎时,是以支持英文为出发点考虑的,系统规定的文本输入一律采用 ASCII 字符集。但是世界上被广泛使用的语言文字不止英文一种,很多语言的基本字符数量远远超出 ASCII 字符集所能表示的范围,比如对于中国的汉字而言,常用汉字约有 6000 多,而 ASCII 最多能表示 256 个字符。即便如此,让 TeX 支持各国语言文字也不是很困难。譬如,以 TeX 中文支持问题的解决为例,可以先对中文 TeX 文稿进行预处理,为每个汉字生成多个字节的 ASCII 编码;然后再实现汉字字符编码与字体图形之间的映射,之后的过程交给 TeX 引擎处理即可。这一预处理过程采用 TeX 宏扩展机制即可实现。现在一些 TeX 中文支持宏包,譬如德国人 Werner Lemberg 写的 CJK 宏包、中科院张林波教授开发的 CCT、华东师大陈志杰教授开发的 TyTeX(天元软件包)等,就是按照这一思路实现的。这种解决方案虽然可以比较轻省地实现中文化、日文、韩文等文字语言支持。但是要实现各国语言文字的 支持,基本上对于每一个语种都要为之开发一个 TeX 支持宏包,特别是一份 TeX 文稿需要出现多种语言文字时,问题就变得更加复杂。
计算机软件开发中,对不同语言文字的支持有一股清晰的潮流,那就是让应用程序支持 Unicode 编码,这是目前统一化处理世界各国语言计算机表示的最佳方案,因为 Unicode 编码的字符集可以涵盖目前地球上所有的文字,并且还具备大量的扩展编码空间。很多人都希望 TeX 引擎也能顺应这种潮流,便想方设法改造 TeX 引擎以实现对 Unicode 编码的支持。Omega、XeTeX、LuaTeX 等项目均致力解决这个问题。
Omega 是由 John Plaice 与 Yannis Haralambous 基于 Knuth TeX 引擎最早实现的可以支持 Unicode 编码的 TeX 引擎。在 Omega 中,每个字符都以一个 16 位编码的数据结构表示,这样就可以摆脱 TeX 的 ASCII 编码限制。但是在留下了一堆 bug 之后,Omega 项目就终止了。后来有人将 Omega 项目与 e-TeX 项目合并起来,建立了 Aleph 项目。再后来,Aleph 项目也终止了,其后继者就是下面要介绍的 LuaTeX 项目。
![]() |
Jonathan Kew |
Jonathan Kew 在 Mac OS X 平台上对 e-TeX 进行改造,为其添加 Unicode 编码支持,并基于 Mac OS X 的各种开发技术,创建了 XeTeX 项目。Jonathan Kew 自 2005 年开始发布 XeTeX 的 Windows 和 Linux 版本。值得注意的是,XeTeX 除了可以直接支持 Unicode 编码之外,还可以直接调用那些存在于用户操作系统之内的 TTF 和 OpenType 格式的字体,这极大方便了用户为 TeX 添加自己喜爱的字体(在 Knuth TeX 中增加一款 TTF 或 OpenType 字体简直是一场噩梦)。从 2007 年开始,XeTeX 被 TeX Live 吸纳,标志着它也得到 TeX 用户的广泛认可。现在,XeTeX 还在开发中,但是功能上可提升的空间似乎也很有限了。
现在该轮到 LuaTeX 登场了。LuaTeX 项目是 2006 年春天启动的。当时,美国科罗拉多州立大学的一个研究哲学的教授与国际 TeX 用户组织联合申请到一个叫做“东方 TeX”的项目,目的是为了更好的排版阿拉伯语言的书。Hans Hagen 拿到这个项目的经费之后,就由 Taco Hoekwater 把 LuaTeX 项目做起来了。LuaTeX 和 ConTeXt MkIV 的开发工作很大程度上是为了这个“东方 TeX”的项目,但是也不排除 Hans 要壮大 ConTeXt 的野心。
LuaTeX 项目对 TeX 引擎进行了大刀阔斧地改革,它先是整合了 pdfTeX 和 aleph 项目,然后又将 TeX 世界里一款非常重要的矢量图绘制引擎——MetaPost 改造成一个可以连接的库——MpLib,并将这个库嵌入 LuaTeX 中,这样 LuaTeX 就可以内部直接支持 MetaPost 图绘制了。另外也像 XeTeX 那样,实现了对用户操作系统中 TTF 和 OpenType 字体的直接调用。LuaTeX 最引人注目的地方就是:它把自从 Knuth TeX 开始就一直被沿用的宏扩展机制改造成 Lua 程序扩展机制。这样,将来用户可以使用文法比较友好的 Lua 程序设计语言为 LuaTeX 引擎实现功能扩展,再也不需要面对丑陋并且容易出错的 TeX 宏扩展机制。
![]() |
Taco Hoekwater |
LuaTeX 项目大概要在 2012 年才功德圆满,届时发布 1.0 版本。但是现在的 LuaTeX 引擎已具备可用性,并于 2008 年和 ConTeXt MkIV 一起被 TUG 纳入 TeX Live,作为用户可选的 TeX 引擎。目前,仅有 ConTeXt MkIV 格式可以与 LuaTeX 匹配。
LuaTeX 是 TeX 引擎改革的结束么?也许现在谁也没法说清楚,正所谓江山代有才人出,一代新人换旧人,当年即使 Knuth 也没法预料到现在会有 LuaTeX 的出现。现在,我们也许只能预料到 LuaTeX 可以将 TeX 用户带上一个新的台阶,至于将来在那个新的台阶上又会遇到什么样的困难,我们也没必要替未来的人担忧。
值得注意的是,TeX 引擎之所以能够曲曲折折走到今天,除了凭借自由/开源软件的开发模式以及众多的黑客长期不懈的智力投入与积累之外,也跟 TeX 所面向的领域过于小众化有重要关系。2000 年,一名记者采访 Leslie Lamport 时问:“当前为什么没有高质量的所见即所得 (WYSIWYG) 的排版系统?”Lamport 回答说:“门槛太高了,一个所见即所得的排版系统要做到 LaTeX 当前的水平,工作量之大不是单枪匹马所能完成的。微软这样的大公司可以做,但是市场太小了。”Lamport 算是一语道破了 TeX 虽然历经 30 余年迄今依然生机盎然的秘密。
TeX 不合时宜?
与时下家喻户晓的微软 Word 那种所见即所得的文档排版方式相比,TeX 显得多么的不合时宜。虽然 ConTeXt 在改善 TeX 易用性的工作上要比 LaTeX 走的更远,但是它依然未能摆脱通过控制序列来排版文档的这种“原始方式”。
Knuth 说:我从来也不期盼 TeX 会成为一个万能的排版工具,让大家使用它可以来做一些“快速而脏”的东西;我只是将其视为一种只要你足够用心就能得到最好结果的东西。
那个包含了许多 TeX 引擎、格式、宏包以及辅助程序的东西
其实,我们日常挂在嘴边的“TeX”既不是 TeX 引擎,也不是 TeX 格式,而是一个包含了 TeX 引擎、TeX 格式、宏包以及一些辅助程序的东西,它的学名叫“TeX 发行版”,它的使命是让 TeX 用户们不用四处奔波去寻找自己也不知道究竟是否需要的 TeX 引擎以及那些 TeX 格式、宏包以及一些乱七八糟的辅助程序。为了完成这一使命,TeX 发行版的开发者们就努力地将这个世界上公认的那些很有用的 TeX 引擎、格式、宏包以及一些乱七八糟的辅助程序收集起来,并持续地维护下去。
虽然 TeX 发行版谁都可以做,但是只有 TeX Live、MacTeX、MikTeX 这三个发行版所收集的 TeX 软件比较全面且比较受欢迎,它们好像都是每年发布一个新版本供用户免费下载和使用,其中 TeX Live 主要在类 Unix 系统中运行,当然它也可以在 Windows 系统中运行的也很好,但是 Windows 用户们却很买 MikTeX 的账,至于 MacTeX,顾名思义就是 Mac OS 系统中的 TeX 了。
这些 TeX 发行版通常都是大而全的。以 TeX Live 为例,它几乎包含了前文中所提到的所有 TeX 引擎,像 Plain TeX、LaTeX、ConTeXt 这些 TeX 格式也是照单全收,此外还有数以千计的宏包,还有一些用于字体、图形处理的辅助程序。由于收录的软件包太多,所以这些 TeX 发行版通常都是庞大的怪兽。不过,这些年随着计算机网络的普及,开始流行在线定制安装的形式。用户只需要下载一个很小的安装程序,然后根据自己的需要选择 所安装的软件包集,然后这个安装程序会自动连接提供 TeX 发行版的服务器去下载所需的文件。通常,只需要下载几百兆字节的文件就可以得到一个比较完善的 TeX 环境了。
本篇文档所讲的 TeX 发行版与上面所说的 TeX 发行版略有区别,我们要使用的是 ConTeXt Minimals, 顾名思义,就是专门为 ConTeXt 格式定制的最小化 TeX 发行版,它是由 Hans 所领导的 ConTeXt 项目组发布的,它的任务就是把最稳定和最不稳定的各种版本的 ConTeXt 以及与之配套的 TeX 引擎提供给那些只对 ConTeXt 感兴趣的 TeX 用户们。ConTeXt Minimals 可以跨操作系统平台(Windows、Linux、FreeBSD、Mac OS X、Solaris 等)运行,并且可以与系统中所安装的其它 TeX 发行版互不干扰。
为迎接 ConTeXt 做点准备
从现在开始,我们就不再旁生枝节,只将注意力放到 ConTeXt 格式 上,只关注它的 MkIV 版本(就是搭配 LuaTeX 引擎的那个),并且所使用的 TeX 发行版仅限于 ConTeXt Minimals。下面所有的内容,除非我很巧妙的申明,否则它们 默认都属于这个环境。
在开始学习使用 ConTeXt 来排版文档之前,需要在身体和心理上做点准备,即便你铁了心要跟 ConTeXt 耗下去,也要准备一下。
首先,不要过于奔放的追求新版本。因为 ConTeXt MkIV 及 LuaTeX 都在开发状态中,经常会每天都发布一个“新版本”。这些新版本固然增加了一些新功能或者修复了一些 bug,但是往往又引入了新的 bug。另外,太奔放的追求新版本,容易患上更新综合症,具体症状为:一天不更新点啥,心里不舒坦。
其次,不要苛求完美。因为 ConTeXt MkIV 及 LuaTeX 都在开发状态中,有大量大量的 bug 都是难免的,千万不要为此而郁闷。实在感觉很难受,可以去 ConTeXt 邮件列表里勇敢又巧妙地把 bug 报告给 Hans,并催促他老人家修复。
再次,不要四处乱找 ConTeXt 中文文档,特别是 2008 年之前的那些中文文档,它们大都是针对 ConTeXt MkII 的,而我们这里要学习的是 ConTeXt MkIV,不搭。
最后,如果真的感觉 ConTeXt 很无聊,纯粹是浪费时间,那么最好还是把大好的时间用来陪女朋友逛逛街,做点体育活动,或者用来学习不无聊也不浪费时间的知识。如果只是把节省下来的时间 用 来看看电影,打打游戏,那么我还是很巧妙地建议你继续学习 ConTeXt 吧。因为 ConTeXt 中文用户实在太少了,你不要再让它失去一个。
序幕结束,打算看下一篇“这 就是 ConTeXt Minimals”?