什么是 GNU: Texinfo

作者:Arnold Robbins

我们将只介绍 Texinfo 的要点。有一份完整的手册(约 200 页)详细描述了 Texinfo。如果您打算实际编写手册,或对现有手册进行重大修改,那么首先阅读 Texinfo 手册将是值得的。(可以从自由软件基金会购买精美印刷和装订的 Texinfo 手册版本。这样做不仅可以节省激光打印机的磨损,并为您提供一本精美的装订书,还可以直接为更多自由软件的生产做出贡献。)

Texinfo 包含在自由软件基金会的 texinfo-3.1.tar.gz 软件发行版中(站点是 ftp://prep.ai.mit.edu/pub/gnu)。它包含了使用 Texinfo 所需的所有软件(除了 TeX)。

处理 Texinfo 文件

Texinfo 被设计为由两组(实际上是三组)不同的程序处理。第一组是 TeX,这是由 Donald Knuth 编写的文本处理系统。TeX 是一个免费提供的、相当庞大的软件包。如果您购买了 CD-ROM Linux 发行版,那么 TeX 可能已经为您设置好了。文件 texinfo.tex 是一系列 TeX 宏,它告诉 TeX 如何格式化 Texinfo 文件,并且必须安装在 TeX 宏目录中。

Texinfo 允许您生成几种纸张尺寸的输出:6 x 9.25 英寸(普通书籍)、8.5 x 11 英寸(标准美国纸张)或 A4(标准欧洲纸张)。

第二个程序称为 makeinfo。此程序读取您的 Texinfo 文件并生成格式化的 Info 文件或多个文件。然后可以使用 Info 查看器查看这些文件。如果您是 GNU Emacs 用户,那么您还有第三个选项,即 Emacs 中的 texinfo-format-buffer。它也会生成格式化的 Info 文件。首选 makeinfo 程序;它是用 C 语言编写的,比 texinfo-format-buffer 更快。它也更智能一些,并且不需要 Emacs 作为底层支持。

要查看 Info 文档,您需要一个 Info 查看器。有两种选择,GNU Emacs 中的 Info 模式,或 Texinfo 发行版附带的独立 info 查看器。我们稍后将讨论查看。

编写 Texinfo 文档时,要记住的重要一点是,您是为两个受众编写的;使用 info 的人和阅读印刷书籍的人。文档的这种双重性质对 Texinfo 语言的设计产生了强烈的影响;有许多构造用于一种情况,而另一种情况则忽略它们。互联网上的许多 WWW 站点都在使用 Info 到 HTML 的转换器,并且 makeinfo 正在增强以直接生成 HTML,尽管此版本的 makeinfo 尚无发布日期。

什么是 Texinfo?

Texinfo 文档的结构类似于传统的书籍,包含章节、节、小节和子小节。(最多可以有四个级别,但这几乎总是超出您的需求。)每个章节、节等等都称为“节点”。实际上,这种结构实际上是计算机科学家喜欢称之为树的结构。文档的“根”是一个名为“顶层”节点的特殊节点。计算机科学家从顶部开始绘制树,然后向下生长。**********此处放置图形

Texinfo 文档的基本结构

我们将简要浏览一下 Texinfo 文档。

\input texinfo  @c -*-texinfo-*-
@c %**start of header (This is for running texinfo on a region.)
@setfilename Foogol.info
@settitle Foogol Language Programming
@c %**end of header (This is for running texinfo on a region.)

这是文档的开头。它读取 Texinfo 宏,并设置 Info 文件名和页眉中使用的标题。@c 启动注释。此处显示的是使 GNU Emacs 感到高兴的魔法注释(%**start of header 等等)。这些注释是样板;只需将它们放在那里,不必担心它们的含义(我不知道;我不是 Emacs 用户)。

@ignore
@ifinfo
@format
START-INFO-DIR-ENTRY
* Foogol: (foogol.info).   A Wonderful Programming Language.
END-INFO-DIR-ENTRY
@end format
@end ifinfo
@end ignore

这是 /usr/local/info 目录中 dir 文件的条目。info 就是通过这种方式知道哪些 Info 文件可用。中间行周围的大部分文本是为了让单独的 shell 脚本可以找到并提取此行,并将其添加到 dir 文件中。不幸的是,FSF 尚未分发这些脚本。简而言之,这更多的是样板;中间行是重要的。它在一行中描述您的文档。目前,当在 /usr/local/info 目录中安装新的 Info 文件时,您必须手动更新 dir 文件。

这显示了关于 Texinfo 的许多内容。首先,@ 是命令字符。Texinfo 中的所有特殊构造都以 @ 开头。(使用 @@ 获取真正的“@”。)其次,许多构造以成对形式出现,@foo ... @end foo@ignore@end ignore 之间的内容会被所有 Texinfo 处理器跳过。

@ifinfo ... @end ifinfo 行将文本括起来,这些文本仅用于 Info 文件,而不用于印刷的 TeX 文档。还有一个对应的 @iftex ... @end iftex 构造,用于仅应出现在印刷文档中而不应出现在 Info 文件中的内容。

@format@end format 括起不缩进的示例文本。(在这种情况下,由于它被忽略了,因此没有任何效果。)

(关于 dir 行的整个事情有点不寻常。它是一个过渡中的功能,最终将成为 Texinfo 语言的主流部分。目前,它是按所示方式完成的,所有内容都被 Texinfo 处理器忽略。您不必在 Texinfo 文档中执行此操作,但这样做也没什么坏处。)

接下来是描述所文档化的内容、文档版本以及正在文档化的程序版本的信息。之后是版权信息和许可声明。

@ifinfo
This file documents @code{foogool}, a programming language that does
really neat things.
This is Edition 1.23 of @cite{The Foogol Language}, for the 3.21 version
of the GNU implementation of FOOGOL.@refill
Copyright (C) ...
Permission is granted ...
@end ifinfo

完整的权限在任何 FSF 手册和 Texinfo 文档中都有记录。为了简洁起见,此处省略了它们。在此示例中,我们还看到了 Texinfo 如何进行内联字体更改。@code{xxx} 将 “xxx” 放入固定宽度字体,例如 xxx。在 Info 中,文本被引用。@cite{} 用于引用标题;它将括起来的文本设置为斜体。

接下来是标题页。几乎所有内容都是样板;必须按一定顺序存在的事物,您可以在其中填写适用于您正在编写的内容的值。

@titlepage
@title The FOOGOL Language
@subtitle A User's Guide for GNU FOOGOL
@subtitle Edition 1.23
@subtitle July, 1994
@author Arnold D. Robbins

这启动了实际的标题页,列出了文档的标题、副标题和作者。标题页仅适用于印刷材料。

@c Include the Distribution inside the titlepage
@c environment so that headings are turned off.
@c Headings on and off do not work.
@page
@vskip 0pt plus 1filll
Copyright @copyright{} 1994 Free Software Foundation, Inc.
@sp 2
This is Edition 1.23 of @cite{The FOOGOL Language}, @* for the 3.21
version of the GNU implementation of FOOGOL.
@sp 2
Published by the Free Software Foundation @*
675 Massachusetts Avenue @*
Cambridge, MA 02139-3309 USA @*
Phone: +1-617-876-3296 @*
Printed copies are available for $20 each.
Permission is granted ...
@end titlepage

这是标题页的背面,称为版权页。它列出了版权信息、版本信息、关于出版商的信息以及复制权限。同样,Texinfo 手册中有完整的详细信息。此示例假设为 GNU 手册,但当然,如果您正在编写手册,则您或您的公司是出版商。@* 强制换行,以便 Texinfo 源文件中的每一行都将打印在印刷版和 Info 版本中的单独行上。

@ifinfo
@node Top, Preface, (dir), (dir)
@top General Introduction
@c Preface or Licensing nodes should come right
@c after the Top node, in `unnumbered' sections,
@c then the chapter, `What is foogol'.
This file documents @code{foogol}, a programming language that does
really neat things.
This is Edition 1.23 of @cite{The Foogol Language}, for the 3.21 version
of the GNU implementation of FOOGOL.@refill
@end ifinfo

这是特殊的“顶层”节点。它应该仅出现在 Info 文件中,这就是为什么它被括在 @ifinfo@end ifinfo 中。它简要描述了 Info 文件文档化的内容。

在这里,我们第一次看到了实际的 @node 语句。@node 按顺序列表列出了此节点的名称、其后继节点、其前任节点以及“上层”节点。后继节点和前任节点通常是树中同一级别的节点;上层节点是父节点。对于顶层节点,它有点不同。后继节点是文档中的第一个子节点(章节),前任节点和上层节点都是代表 dir 文件的特殊 (dir) 节点。

任何带有子节点的节点之后都是一个菜单。菜单列出了所有节点的子节点(通常按顺序),并简要描述了每个节点描述的内容。

@menu
* Preface::        What this Info file is about; brief
                  history and acknowledgements.
* Copying::        Your right to copy and distribute @code{foogol}.
* What Is Foogol:: What is the @code{foogol} language;
                  using this Info file.
* Getting Started:: A basic introduction to using @code{foogol}.
                   How to run a @code{foogol} program.
                   Command line syntax.
.....
* Index::          Concept and Variable Index.
@end menu

顶层节点的菜单称为“主菜单”。它至少包含文件中所有章节级别节点的条目。更常见的是,它包含文件中每个节点的条目,几乎按顺序排列。通常,所有章节级别节点都排在最前面,然后所有“内部”节点都排在后面,顺序与它们在书中的顺序相同。在所有前面的内容之后,您只需安顿下来并编写您的文档。每个节点都有一个唯一的名称。在 makeinfo 中,节点名称中的大小写被忽略,而在 TeX 中则不然,因此为了获得最佳结果,请保持节点名称的所有实例中的大小写相同。

每个 @node 语句之后都跟着一个分节命令。

@node Introduction, Syntax, Preface, Top
@chapter Introduction To Foogol
The @code{Foogol} language was invented in 1897. ...

还有对应的 @section@subsection@subsubsection 命令。还有用于未编号章节和节的命令,@unnumbered@unnumberedsec@unnumberedsubsec@unnumberedsubsubsec,以及类似的用于附录的命令,@appendix@appendixsec 等等。甚至还有用于不会出现在目录中的标题的命令:@heading@subheading 等等,尽管这些仍然需要单独的节点名称和菜单条目。

您可以想象,在编写文档时保持 “next”、“previous” 和 “up” 指针同步有点痛苦。幸运的是,只要您具有正确的分节命令,并且每个带有子节点的节点都有正确的菜单,makeinfo 就会为您计算出指针。在实践中,这意味着您可以忽略它们。TeX 对节点不太在意,尽管它并没有完全忽略它们,我们稍后会看到。

GNU Emacs 中的 Texinfo 主要模式将为您构建菜单,并自动更新 “next”、“previous” 和 “up” 指针。如果您不使用 Emacs,则必须手动执行此操作,或编写单独的程序来执行此操作(这就是我使用 gawk 所做的)。

在文档末尾,您需要打印目录。Texinfo 提供了 “summary” 内容页和完整目录页。

@summarycontents
@contents
@bye

@bye 结束处理。您可以在 @bye 之后的文件中放置给自己的注释;我在 The GAWK Manual 中使用它来保存我的 “待办事项” 列表。

索引

Texinfo 维护六个预定义的索引;概念、变量、函数、按键、程序和数据类型索引。例如,要添加到概念索引,请使用

@cindex History of @code{Foogol}
@cindex @code{Foogol}, History of

变量索引使用 @vindex,函数索引使用 @findex,依此类推。

您可以创建自己的索引,也可以合并索引;例如,将变量、函数和概念都放在同一个索引中。这些通常在文档末尾、目录之前打印,使用 @printindex 命令。

内联字体更改

我们已经看到了 @code,它将文本设置为等宽或 Courier 字体。还有其他几个命令可以为不同的项目提供特殊的输出。

@samp   - for in-line code fragments
@file   - for file names
@var    - things that can vary, parameters, values, and so on
@emph   - emphasizes something, using italics
@strong - makes a strong point, using bold
@r      - force roman (normal) text
@i      - force italic text
@b      - force bold text

后三个命令用于偶尔使用,通常其他命令就足够了。

表格和列表

Texinfo 允许您轻松编写列表和简单表格。

@enumerate A @c A list "numbered" A, B, C ...
@item
First item here
@item
Second item here
....
@end enumerate

省略 “A” 将生成一个编号列表,使用小写 “a” 将使用小写字母。带有减号或项目符号的简单列表将写成

@itemize @bullet
@item
First item here
@item
Second item here
....
@end itemize

这将生成一个列表,每个项目都有项目符号。使用 @minus 将生成一个减号。(排版时,减号和破折号是不同的字符;减号更长。)

有几种表格。每种表格都采用格式代码,用于描述如何格式化各个项目。例如,命令行选项列表将使用 @samp。

The list of @code{foogol} command line arguments are:
@table @samp
@item -f @var{filename}
Use @var{filename} as the source file.
@item -o @var{prog}
Use @var{prog} as the executable program.
@item -d
Print the date, time of day, and current phase of the moon.
...
@end table

另外两个类似的命令是 @vtable ... @end vtable@ftable ... @end ftable。这些命令与 @table 完全相同,但它们会自动在变量和函数索引中为每个项目创建一个条目,这可以节省您一些打字时间。

示例

有几个命令用于格式化以特殊方式标记的文本,例如示例、引文等等。主要的命令是 @example ... @end example,通常用于程序或其他计算机输入和输出。文本将以 Courier 字体缩进打印,并且不会以其他方式填充或调整。

@format ... @end format 类似于 @example,但不进行缩进。您可以使用 @quotation ... @end quotation 将引文括起来以引用扩展的文本段落。

在示例之后,通常会继续思考,而无需开始新段落。为防止后续文本像新段落一样缩进,请在其前面加上 @noindent

此示例显示了运行我们程序的结果

@example
$ make_money
Congratulations! You are a rich   Memory fault - core dumped
$
@end example
@noindent
As we can see, there is a small problem somewhere.
...
交叉引用

Texinfo 文档的一个显着特点是它们充满了交叉引用。有几种类型的交叉引用语句,所有语句都至少以节点名称作为参数。

@xref{Introduction}, for a description of the
history of @code{Foogol}.

还有更长的形式,可以采用节点的完整标题(例如来自 @chapter 命令)。在 TeX 中,交叉引用将生成典型的交叉引用,包括页码。

See [Introduction], page 12, for a description of the history of Foogol.

在 Info 文件中,交叉引用命令将交叉引用放入文本中。交叉引用看起来像这样

*Note Introduction, for a description of the
history of `Foogol'.

当使用查看器读取 Info 文件时,您可以发出一个简单的命令,指示查看器跟随交叉引用。正是交叉引用为在线 Info 阅读器提供了 “超文本” 感觉。交叉引用通常是对当前文档中其他节点的引用,但它们不必如此!可以跟随对另一个 Texinfo 文档中节点的交叉引用,Info 阅读器会像访问当前文档中的节点一样轻松地访问它。

Info 查看器

有两种方法可以查看 Info 文件。(请记住,在查看 texinfo 文件之前,您必须使用 makeinfotexinfo-format-buffer.texi 文件创建它。)第一种是独立的 info 查看器。这是一个相当出色的程序,具有菜单完成功能、拆分屏幕以查看多个节点的功能等等。

它需要具有光标移动功能的终端或终端仿真器。如果您可以在窗口或屏幕上运行 vi 或 Emacs,那么您可以运行 info。第二种是 GNU Emacs 中的 Info 主要模式。Emacs Info 查看器几乎具有独立 info 查看器的所有功能,除了拆分屏幕和查看多个节点的功能。

如前所述,info 还可以跟随无限的交叉引用链,让您可以尽情浏览文档。

其他命令

还有几个其他功能应该提及。首先,您可以使用 @footnote{...} 编写脚注。这会使用 TeX 创建真实的脚注,并在 Info 中在节点末尾创建一个脚注集合。如果您绝对必须使用花哨的 TeX 功能,那么您可以使用 @tex@end tex 将文本括起来,从而进入纯 TeX 模式。在这两个语句之间,您必须使用纯 TeX 编写,使用反斜杠作为转义字符等等。

请注意,@tex@end tex 与前面提到的 @iftex ... @end iftex 命令不同,后者有条件地将文本包含到印刷文档中。

最后,Texinfo 中有一个简单的宏工具。可以使用 @set 设置宏。

@set EDITION 1.23

可以使用 @value 检索值

This is Edition @value{EDITION} of ...

宏也可以用作标志,例如指示版本是否为草稿。可以使用 @ifset ... @end ifset@ifclear ... @end ifclear 测试标志,它们分别测试宏是否已设置。

@set DRAFT
@ifset DRAFT
@b{This is just a draft, please mark it up and send it back.}
@end ifset
@ifclear DRAFT
Welcome to Edition @value{EDITION} of ....
@end ifclear

宏工具对于文档开头附近标题、版本号和程序版本号重复出现的多种情况特别有用。通过在所有这些位置使用 @value,您可以使用 @set 设置标题、版本和版本号,并且只需更新一次数字。这确实可以节省时间。

获取印刷文档

要生成印刷文档,您需要在系统上安装 TeX。texinfo.tex 宏需要位于 TeX 的宏目录中。您还需要将名为 texindex 的程序(随 Texinfo 发行版一起提供)安装到公共 bin 目录中,以便每个人都可以访问它。

Texinfo 文件通常具有 .texi 扩展名。当 TeX 运行时,它会生成未排序的索引。未排序索引的文件名与 Texinfo 文件的名称匹配,.texi 替换为索引的两个字母名称。例如,foogol.texi 的概念索引将为 foogol.cp。未排序的索引不是很有用。texindex 程序将索引排序到新文件中,这些新文件的名称与索引文件的名称相同,末尾带有 s,例如 foogol.cps。如果这些文件存在,texinfo.tex 将在再次运行 TeX 时包含它们。

典型的顺序是运行 TeX 三次,每次运行之间都运行 texindex。

$ tex foogol.texi
$ texindex foogol.??
$ tex foogol.texi
$ texindex foogol.??
$ tex foogol.texi

第一次运行生成未排序的索引,并创建 foogol.aux,其中列出了节点的页码。此信息用于填写交叉引用。第二次运行生成完整的 DVI 文件,但不幸的是,其中的交叉引用可能偏差一页左右。第三次运行使一切正确,此时您可以安排打印文件。通常,这是使用 dvips 完成的,以生成 PostScript。

$ dvips foogol.dvi -o foogol.ps
$ lpr foogol.ps       # or however you print

Texinfo 发行版附带一个名为 texi2dvi 的 shell 脚本,它将计算出应运行 TeX 的次数。如果已安装,则它可能是最容易使用的工具。

如果您没有 TeX,另一种选择是使用一个名为 texi2roff 的单独软件包。它读取 Texinfo 文件并生成可以使用 GNU Troff (groff) 处理的 Troff 输入。您可以选择 Troff 宏包,-me-ms-mm

texi2roff 相比,TeX 是首选,但至少后者是一个选项。生成的 Troff 可能需要手动润色,但在其他方面应该相当可用。不幸的是,最新版本的 texi2roff 被认为是过时的,并且不再由 FSF 分发。

还值得注意的是一个名为 LaTexinfo 的软件包,它是一组 LaTeX 宏和修改版本的 makeinfo,用于执行与 texinfo.tex 和常规 makeinfo 相同的事情。不幸的是,Texinfo 文件与 LaTexinfo 不兼容。如果您更喜欢使用 LaTeX,请使用 archie 查找 LaTexinfo 的最新副本。

总结

Texinfo 提供了一种简洁的输入语言,其中包含生成美观的印刷文档和高度可用的在线超文本帮助所需的一切。info 查看器为阅读在线 Info 文件提供了友好的界面。

我发现 Texinfo 最好的地方在于您无需了解 TeX 即可使用它。我很高兴地使用 Texinfo 写作了大约七年,并且实际上不需要学习 TeX。即使 Texinfo 拥有超过 160 个命令,我在本文中介绍的内容也占大多数人日常使用的 95%。

我还建议从 FSF 购买并阅读 Texinfo 手册。它写得很好而且很详尽。如果您计划编写大型 Texinfo 文件,无论如何您都需要这样做,因为本文只是触及了皮毛。Texinfo 手册随 Texinfo 发行版一起提供,当然是用 Texinfo 编写的;这提供了一个很好的示例,其中使用了 Texinfo 的所有功能。

致谢

感谢 Miriam Robbins 让我澄清了本文中的许多要点,并感谢 FSF 的 Robert J. Chassell(Texinfo 手册的主要作者)的评论。

Arnold Robbins 是一位专业程序员和半专业作家。自 1987 年以来,他一直在为 GNU 项目做志愿者工作,自 1981 年以来一直从事 Unix 和类 Unix 系统的工作。

加载 Disqus 评论