第二十六章 简单旧文档
优质
小牛编辑
135浏览
2023-12-01
设计 Perl 的一个原则是简单的事情应该简单,而难的事情应该有可能简单。文档应该简单。 Perl 支持一种叫 pod 的简单文本标记格式,它可以独立存在或者自由地与你的源代码混合 在一起形成嵌入的文档。Pod 可以转换成许多其他格式,用于查阅或者打印,或者你也可以 直接阅读它,因为它很简单。 Pod 不象 XML,LatEx,troff(1) 那样富于表现力,甚至连 HTML 都不如。这么做是 故意的:我们为了简单和方便牺牲了表现力。有些文本标记语言让作者写的标记比文本还多, 这样就把写作变得比原来还要复杂,而阅读则几乎是不可能的。一个好的格式应该象好的电影 乐曲那样,隐藏在后台而不会让观众的注意力分散。 让程序员写文档几乎和让他们打领带一样困难。Pod 的设计让写文档非常容易,甚至一个程序 员都可以写——并且愿意写。我们可没有说 pod 胜任写一本书——尽管它足够写我们这本。
26.1 pod in a NutShell?
大多数文档格式要求整个文档都是用该格式写的。Pod 更宽容:你可以在任何文件里嵌入 pod, 然后依靠 pod 翻译器抽取 pod。有些文件包含 100% 纯 pod。但是其他文件,尤其是 Perl 程序和模块,可能只包含若干团 pod,散布在作者认为合适的地方。当 Perl 分析该文件准备 执行的时候,它只是简单地忽略 pod 文本。 如果某一句话是用一个等于号和一个标识符开的头(象下面这样),而不是普通的一句程序, 那么 Perl 的词法分析器就会知道忽略这一句话:=head1 Here There Be Pods!从这段文本开始,一直到一个以 =cut 开头的行为止,中间的所有文本(包括两端的行)都会 被忽略。这样你就可以自由地把你的程序和文档混合在一起,比如:
=item snazzle The snazzle() function will behave in the most spectacular form that you can possibly imagine, not even excepting cybernetic pyrotechnics. =cut sub snazzle { my $arg = shift; .... } =item razzle The razzle() function enables autodidactic epistemology generation. =cut sub razzle { print "Epistemology generation unimplemented on this platform.\n"; }如果需要更多的例子,请参阅标准的或者 CPAN Perl 模块。除了极个别的以外,它们很可能都 随身带着 pod, 因为 Perl 词法器可以识别 pod 并且会把它抛弃,所以你还可以使用合适的 pod 指示符快速 地注释掉大块的程序代码。使用 =for pod 块注释掉一个段落,或者一个 =begin/=end 对 注释一个段落。我们稍后将介绍这些 pod 指示符。不过,请记住,在两种情况下,你仍然都是 在 pod 模式下的,因此你需要 =cut 回到编译器。
print "got 1\n"; =for commentary This paragraph alone is ignored by anyone except the mythical "commentary" translator. When it's over, you're still in pod mode, not program mode. print "got 2\n"; =cut # ok, real program again print "got 3\n"; =begin comment print "got 4\n"; all of this stuff here will be ignored by everyone print "got 5\n"; =end comment =cut print "got 6\n";这段代码将单引出得到 1,3,和 6。请注意这些 pod 指示符并不是哪里都能去。你必须把 它们放到分析器预计会看到一行新语句的地方,而不是在一个表达式的中间或者其他任意的 地方。 从 Perl 的观点来看,所有 pod 标记都被抛弃,但是从 pod 翻译器的观点来看,抛弃的是 代码。pod 翻译器把余下的文本当作一系列用空白行分隔的段落。所有现代的 pod 翻译器都 用同样的方法分析 pod:使用标准的 Pod::Parser 模块。它们的区别只是输出,因为每种 翻译器都专门生成一种输出格式。 目前有三种段落:字面段落,命令段落,和散文段落。
26.1.1. 字面段落
字面段落用于那些你想表现为文本的文字,比如一小段代码。字面段落必须是缩进的,也就是 说,它必须用空格或者水平制表符字符开头。翻译器会准确地重现它的格式——通常是用一种 固定宽度的字体,并且假定水平制表符为八个空格宽。字面段落里面没有什么特殊的格式化 逃逸,所以,你不能使用斜体或者宽体的字体。< 字符的意思就是文本 <,不是别的什么 东西。26.1.2. pod 指示符
所有 pod 指示符都是以 = 开头后面跟着一个标识符。它后面可以跟指示符愿意的任意数量的 任意文本。唯一的语法要求就是这些文本必须都在同一个段落里。目前翻译器可以识别的 指示符是(有时候我们把它们称做 pod 命令):- =head1
- =head2
- ...
- =head1,=head2,...指示符生成指定的标题。余下的文本会被当作标题描述看待。 这些指示符类似 man(7) 里的 .SH 和 .SS 段子段标题,或者 HTML 里的
...
和...
标记。实际上,这些标记就是翻译器转换出来的指示符。
- =head1,=head2,...指示符生成指定的标题。余下的文本会被当作标题描述看待。 这些指示符类似 man(7) 里的 .SH 和 .SS 段子段标题,或者 HTML 里的
- =cut
- =cut 指示符标识一片 pod 的结尾。(在文档的后面可能还有更多 pod,但是如果有的话,那么它们会由另外的 pod 指示符引入。)
- =pod
- =pod 指示符什么也不干,只是告诉编译器停止分析代码,直到下一个 =cut。如果你混合了大量的代码和 pod,那么用它向文档中增加一段会比较方便。
- =over NUMBER
- =item SYMBOL
- =back
- =over 打开一个段落,这个段落是专门为使用 =item 指示符生成的列表使用的。在你的列表的最后,你要用 =back 结束它。如果提供了 NUMBER,那么就是暗示格式化输出器缩进多少空格。有些格式化输出器特性不够丰富,不能支持这个参数,而其他的 特性又丰富了,目前看来,如果我们使用比例字体的话,那么我们很难仅仅依靠空格来对齐各行。(不过,四个空格通常也足够存放数字和圆点了。)这个列表的实际类型是用独立的项的 SYMBOL 来标识的。下面就是一个圆点列表:
=over 4 =item * Mithril armor =item * Elven cloak =back 和一个编号了的列表: =over 4 =item 1. First, speck "friend". =item 2. Second, enter Moria. =back 和一个命名的列表: =over 4 =item armor() Description of the armor() function =item chant() Description of the chant() function =back你可以把相同的或不同的列表嵌套在一起,但是要遵守一些基本的规则:不要在 =over/=back 块之外使用 =item;在 =over/=back 块里至少要使用一个 =item; 并且可能最重要的是,在一个列表里,保持项(item)类型的一致性。要么就是给每个 项都用 =item *,生成一个圆点列表,要么用 =item 1.,=item 2.,等等生成一个 序号列表,或者使用 =item foo, =item bar,等等生成一个命名列表。如果你以 句点或者序号开头,那么要一直保持,因为格式化输出器是可以使用第一个 =item 类型来判断如何格式化该列表的。 和 pod 其他方面一样,结果的质量取决于翻译器。有些翻译器注意跟在 =item 后面的特殊的数字(或者字母,或者罗马数字),而其他的却不注意。比如,目前的 pod2html 翻译器就相当懒惰:它把序号指示符完全剥离,根本不从这些指示符中推断 你使用的是什么序号,然后把整个列表都包装在
- 和
- =for TRANSLATOR
- =begin TRANSLATOR
- =end TRANSLATOR
- =for,=begin,和 =end 可以让你包含特殊的段落,这些段落只能由特殊的格式化输出器处理,而在其他格式化输出器里则可以毫发未损的通过。那些在 TRANSLATOR 里的识别这些标识符或者它们的别名的格式化输出器才会注意它们;任何其他的格式化输出器都完全不理会这些标识符。=for 标识符说明只有本段落余下的部分才是专门由特定的翻译器翻译的。
- =for html
- *|*
用斜体字输出文本,用于强调,书的标题,船的名字,以及手册页引用,比如"perlpod(1)”。 - *B*
用宽体输出文本,几乎总是用于命令行开关,以及有时候用于程序名字。 - *C*
字面代码,可能是在一种类似 Courier 这样的固定宽度的字体里。在那些翻译器可以推断出代码的简单项目上可以不用,但是你还是应该用它。 - *S*
带有不可分隔的空格的文本。通常包围其他序列。 - L
一个名字的交叉引用(链接):- L手册页
- L手册页里的项目
- L在其他手册页里的节(段)
- L 着本手册页里的节(段),引号是可选的。
- L同上。
- ; END
- Set MYTITLE = 简单的旧文档
- 标记中,这样, 浏览器就会把它们当作一个排了序的列表显示在 HTML 里。这可不是一个分析出来的 特性;我们将来可能要把这个修补一下。
成对的 =begin 和 =end 标识符的功能类似 =for,不过它们不只是接受一个段落, 而是把在 =begin 和 =end 之间的所有文本交给特定的翻译器处理。一些例子:This is rawHTMLparagraph
=begin html格式化输出器通常可以接受的 TRANSLATOR 的值有 roff,man,troff,nroff,tbl,eqn,latex,tex,html, 和 text。有些格式化输出器会把这些词中的一些看作同义词。没有哪个格式化输出器接受 comment——它只是一个客户化的词,表示一些任何人都可以忽略的东西。任何不能识别的词都会起这个作用。在我们写本书的时候,我们常用 =for later 指示符给我们自己留一些注意信息。 请注意 =begin 和 =end 可以嵌套,但是只有在下面的情况下才有效:那就是最外层的一对把它们中间的所有 东西都变成了非 pod,就算这里面碰巧有 =word 指示符也如此。也就是说,一旦格式化输出器看到了 =begin foo,那么它要么忽略要么处理直到对应 =end foo 标记中间的所有内容。
Figure 1.
=end html =begin text --------------- | foo | | bar | --------------- ^^^^ Figure 1. ^^^^ =end text