内容

名称

Pod::Man - 将 POD 数据转换为格式化的 *roff 输入

概要

use Pod::Man;
my $parser = Pod::Man->new (release => $VERSION, section => 8);

# Read POD from STDIN and write to STDOUT.
$parser->parse_file (\*STDIN);

# Read POD from file.pod and write to file.1.
$parser->parse_from_file ('file.pod', 'file.1');

描述

Pod::Man 是一个模块,用于将 POD 格式的文档(Perl 文档的首选语言)转换为使用 man 宏集的 *roff 输入。生成的 *roff 代码适合使用 nroff(1)(通常通过 man(1))在终端上显示,或使用 troff(1) 打印。它通常使用驱动脚本 pod2man 调用,但也可以直接使用。

默认情况下(在非 EBCDIC 系统上),Pod::Man 输出 UTF-8。它的输出应该适用于使用 groff(大多数 Linux 发行版)或 mandoc(大多数 BSD 变体)的系统上的 man 程序,但在较旧的 UNIX 系统上可能会导致输出混乱。要在这些系统上选择不同的、可能更向后兼容的输出处理,请将 encoding 选项设置为 roff(早期 Pod::Man 版本中的默认值)。有关更多详细信息,请参阅 encoding 选项和 "ENCODING"

有关 Pod::Man 版本(除了构造函数选项,其版本在下面有记录)的重大向后不兼容更改,以及包含它们的 Perl 版本,请参阅 "COMPATIBILTY"

类方法

new(ARGS)

创建一个新的 Pod::Man 对象。ARGS 应该是一个键值对列表,其中键从以下选项中选择。每个选项都标注了该选项在 Pod::Man 中添加的版本及其当前含义。

center

[1.00] 设置 .TH 宏的居中页面标题。如果未指定此选项,则默认值为 User Contributed Perl Documentation

date

[4.00] 设置 .TH 宏的左侧页脚。如果未设置此选项,则将使用环境变量 POD_MAN_DATE 的内容(如果已设置)。如果失败,则将使用 SOURCE_DATE_EPOCH 的值、输入文件的修改日期或 stat() 无法找到该文件时的当前时间(如果输入来自 STDIN,则会发生这种情况)。如果从除 POD_MAN_DATE(按字面意思使用)以外的任何来源获取,则日期将格式化为 YYYY-MM-DD 并且将基于 UTC(因此输出将与本地时区无关而可重复)。

encoding

[5.00] 指定输出的编码。该值必须是 Encode 模块识别的编码(参见 Encode::Supported),或者特殊值 roffgroff。非 EBCDIC 系统的默认值为 UTF-8。

如果输出包含无法在此编码中表示的字符,则会发生错误,并根据 errors 选项配置进行报告。如果错误处理方式不是 die,则无法表示的字符将被替换为 Encode 替换字符(通常为 ?)。

如果 encoding 选项设置为特殊值 groff(EBCDIC 系统的默认值),或者 Encode 模块不可用且编码设置为除 roff 以外的任何值,Pod::Man 将把所有非 ASCII 字符转换为 \[uNNNN] Unicode 转义序列。这些传统上不属于 *roff 语言的一部分,但受 groffmandoc 支持,因此受当今大多数手册页处理器支持。

如果 encoding 选项设置为特殊值 roff,Pod::Man 将执行其历史上的转换,将 (某些) ISO 8859-1 字符转换为 *roff 转义序列,这些转义序列在 troff 中可能足够,并且在 nroff 中可能可读(即使很丑)。这是 5.00 之前版本的 Pod::Man 的默认行为。使用此编码,所有其他非 ASCII 字符将被替换为 X。对于不支持 UTF-8 的非常旧的 troff 和 nroff 实现,这可能是必需的,但它对任何非 ASCII 字符的表示都非常糟糕,并且通常特定于欧洲语言。

如果输出文件句柄设置了 PerlIO 编码层,则将 encoding 设置为除 groffroff 以外的任何值将被忽略,Pod::Man 不会执行任何编码。它将改为依赖编码层来执行所需的任何输出编码转换。

警告:POD 源的输入编码独立于输出编码,设置此选项不会影响 POD 输入的解释。除非您的 POD 源是 US-ASCII,否则应在源中使用 =encoding 命令声明其编码。如果没有这样做,Pod::Simple 将尝试猜测编码,如果它是 Latin-1 或 UTF-8,则可能成功,但会产生警告。有关更多信息,请参见 perlpod(1)

errors

[2.27] 如何报告错误。die 表示在任何 POD 格式错误时抛出异常。stderr 表示在标准错误上报告错误,但不抛出异常。pod 表示在生成的文档中包含一个 POD ERRORS 部分,总结错误。none 完全忽略 POD 错误,尽可能地做到这一点。

默认值为 pod

fixed

[1.00] 用于逐字文本和代码的固定宽度字体。默认为 CW。某些系统更喜欢 CR。仅对 troff 输出有效。

fixedbold

[1.00] 固定宽度字体的粗体版本。默认为 CB。仅对 troff 输出有效。

fixeditalic

[1.00] 固定宽度字体的斜体版本(有点用词不当,因为大多数固定宽度字体只有倾斜版本,没有斜体版本)。默认为 CI。仅对 troff 输出有效。

fixedbolditalic

[1.00] 固定宽度字体的粗体斜体(理论上,实际上可能是倾斜的)版本。Pod::Man 不假定您有此字体,并默认为 CB。某些系统(例如 Solaris)提供 CX 作为此字体。仅对 troff 输出有效。

guesswork

[5.00] 默认情况下,Pod::Man 会应用一些基于猜测和正则表达式的默认格式化规则,这些规则旨在使编写 Perl 文档更容易,并减少显式标记的需求。这些规则可能并不总是适用,特别是对于与 Perl 无关的文档而言。此选项允许关闭所有或部分规则。

特殊值 all 启用所有猜测。出于向后兼容性的原因,这也是默认值。特殊值 none 禁用所有猜测。否则,此选项的值应为以下一个或多个关键字的逗号分隔列表

functions

将函数引用(如 foo())转换为粗体,即使它们没有标记。函数名称接受函数名称的有效 Perl 字符(包括 :),并且尾随括号必须存在且为空。

manref

即使手册页引用(例如 foo(1))没有标记,也要将引用中括号前的部分(第一部分)加粗。该部分必须是一个单独的数字,后面可以可选地跟小写字母。

quoting

如果未启用猜测功能,则在 nroff(终端)输出中,任何用 C<> 括起来的文本都会用双引号包围,除非内容本身已经用引号包围。当启用猜测功能时,对于 Perl 变量、函数名、函数调用、数字和十六进制常量,引号也会被抑制。

variables

即使 Perl 变量名没有标记,也要将其转换为等宽字体。这种转换只会在 troff 输出或其他支持等宽字体的输出格式(与 nroff 终端输出不同)中显现。

任何未知的猜测名称都会被静默忽略(为了将来可能的兼容性),因此请注意拼写。

language

[5.00] 添加命令告诉 groff 输入文件使用的是哪种语言。此设置的值必须是 groff 提供补充配置的语言缩写,例如 ja(日语)或 zh(中文)。

具体来说,这会添加

.mso <language>.tmac
.hla <language>

到文件开头,这将为指定语言配置正确的断行。如果没有这些命令,如果手册页安装到正常的手册页目录(例如 /usr/share/man),groff 可能不知道如何为中文和日文文本添加正确的断行。

在许多系统上,如果手册页安装到特定语言的手册页目录(例如 /usr/share/man/zh_CN),这将自动完成。在这种情况下,不需要此选项。

不幸的是,使用此选项添加的命令是特定于 groff 的,并且不适用于其他 troffnroff 实现。

lquote
rquote

[4.08] 设置用于包围 C<> 文本的引号。lquote 设置左引号,rquote 设置右引号。两者都可以设置为特殊值 none,在这种情况下,C<> 文本的两侧都不会添加引号(但 troff 输出的字体仍然会改变)。

另请参阅 quotes 选项,它可以用来同时设置两个引号。如果同时设置了 quotes 和其他选项之一,则 lquoterquote 会覆盖 quotes

name

[4.08] 为 .TH 宏设置手册页的名称。如果没有此选项,手册名称将设置为正在转换的文件的基名称的大写形式,除非手册部分为 3,在这种情况下,将解析路径以查看它是否为 Perl 模块路径。如果是,则类似 .../lib/Pod/Man.pm 的路径将转换为类似 Pod::Man 的名称。如果给出此选项,它将覆盖对名称的任何自动确定。

如果从标准输入生成手册页,则如果没有提供此选项,名称将设置为 STDIN。在这种情况下,强烈建议提供此选项以设置有意义的手册页名称。

nourls

[2.27] 通常,带有 URL 但有锚文本的 L<> 格式化代码将被格式化为显示锚文本和 URL。换句话说

L<foo|http://example.com/>

将被格式化为

foo <http://example.com/>

如果将此选项设置为真值,则在给出锚文本时会抑制 URL,因此此示例将仅格式化为 foo。在 URL 不特别重要的情况下,这可以产生更简洁的输出。

quotes

[4.00] 设置用于包围 C<> 文本的引号。如果值为单个字符,则它将用作左引号和右引号。否则,它将被分成两半,字符串的前半部分将用作左引号,后半部分将用作右引号。

这也可以设置为特殊值 none,在这种情况下,不会在 C<> 文本周围添加引号(但字体仍然会为 troff 输出而更改)。

另请参阅 lquoterquote 选项,它们可以用来独立设置左引号和右引号。如果同时设置了 quotes 和其他选项之一,则 lquoterquote 会覆盖 quotes

release

[1.00] 为 .TH 宏设置居中的页脚。默认情况下,这将设置为你在 Pod::Man 下运行的 Perl 版本。将其设置为空字符串将导致某些 *roff 实现使用系统默认值。

请注意,某些系统 an 宏集假设居中的页脚将是修改日期,并将添加类似 Last modified: 的内容。如果你的目标系统是这种情况,你可能希望将 release 设置为最后修改日期,将 date 设置为版本号。

section

[1.00] 为 .TH 宏设置部分。标准部分编号约定是使用 1 表示用户命令,2 表示系统调用,3 表示函数,4 表示设备,5 表示文件格式,6 表示游戏,7 表示杂项信息,8 表示管理员命令。但是,这里有很多变化;一些系统(如 Solaris)使用 4 表示文件格式,5 表示杂项信息,7 表示设备。还有一些系统使用 1m 代替 8,或者两者混合使用。唯一可靠一致的部分编号大约是 1、2 和 3。

默认情况下,将使用部分 1,除非文件以 .pm 结尾,在这种情况下,将选择部分 3。

stderr

[2.19] 如果设置为真值,则将有关无效 POD 的错误消息发送到标准错误,而不是将 POD ERRORS 部分附加到生成的 *roff 输出。这等同于将 errors 设置为 stderr,前提是 errors 尚未设置。

此选项是为了与不支持 errors 的 Pod::Man 版本向后兼容。通常,应使用 errors 选项代替。

utf8

[2.21] 此选项用于将输出编码设置为 UTF-8。由于现在这是默认值,因此它会被忽略并且不会执行任何操作。

实例方法

作为 Pod::Simple 的派生类,Pod::Man 支持相同的方法和接口。有关所有详细信息,请参阅 Pod::Simple。本节总结了最常用的方法以及 Pod::Man 添加的方法。

output_fh(FH)

将 parse_file()、parse_lines() 或 parse_string_document() 的输出定向到文件句柄 FH,而不是 STDOUT

output_string(REF)

将 parse_file()、parse_lines() 或 parse_string_document() 的输出定向到 REF 指向的标量变量,而不是 STDOUT。例如

my $man = Pod::Man->new();
my $output;
$man->output_string(\$output);
$man->parse_file('/some/input/file');

请注意,该变量中的输出将已编码为 UTF-8。

parse_file(PATH)

从 PATH 读取 POD 源代码并对其进行格式化。默认情况下,输出将发送到 STDOUT,但可以使用 output_fh() 或 output_string() 方法更改此设置。

parse_from_file(INPUT, OUTPUT)
parse_from_filehandle(FH, OUTPUT)

从 INPUT 读取 POD 源代码,对其进行格式化,并将结果输出到 OUTPUT。

parse_from_filehandle() 是为了与旧版本的 Pod::Man 向后兼容而提供的。应使用 parse_from_file() 代替。

parse_lines(LINES[, ...[, undef]])

将提供的行解析为 POD 源代码,并将输出写入 STDOUT 或使用 output_fh() 或 output_string() 方法设置的文件句柄。此方法可以重复调用以提供更多输入行。应传递显式 undef 以指示输入结束。

此方法期望的是原始字节,而不是解码后的字符。

parse_string_document(INPUT)

将提供的标量变量解析为 POD 源代码,并将输出写入 STDOUT 或使用 output_fh() 或 output_string() 方法设置的文件句柄。

此方法期望的是原始字节,而不是解码后的字符。

编码

从 Pod::Man 5.00 开始,Pod::Man 的默认输出编码为 UTF-8。这应该在任何使用 groff(大多数 Linux 发行版)或 mandoc(Alpine Linux 和大多数 BSD 变体,包括 macOS)的现代系统上正常工作。

用户可能需要使用 UTF-8 本地化才能看到正确的输出。这可能默认情况下已完成;如果没有,请将 LANG 或 LC_CTYPE 环境变量设置为适当的本地化。如果想要在不更改其他本地化影响的事项(例如排序规则)的情况下获得正确的输出,则大多数系统上都提供本地化 C.UTF-8

通过将 encoding 选项设置为 roff,可以获得 Pod::Man 5.00 之前版本中使用的向后兼容的输出格式。这可能会在不使用 groffmandoc 的旧版 UNIX 版本上产生略微更好的结果,但所有可用选项都无法在这些系统上正确呈现 Unicode 字符。

以下是有关如何做出此选择以及一些替代方案讨论的更多详细信息。

历史

Pod::Man 的默认输出编码一直是一个长期存在的问题。troffnroff 的出现时间远早于 Unicode,并且它们在许多 UNIX 系统上的实现反映了这种遗留问题。Unicode 通常不受任何形式的支持。

因此,5.00 之前的 Pod::Man 版本保留了原始 pod2man 的高度保守输出,该输出使用纯 ASCII 和复杂的宏来模拟在使用 troff 处理时常见的西欧重音字符。nroff 输出很笨拙,有时不正确,并且西欧脚本中未使用的字符被替换为 X。这种选择最大限度地提高了与 mannroff/troff 实现的向后兼容性,但代价是许多 POD 文档(尤其是包含人名的文档)的渲染不正确。

现代实现,groff(用于大多数 Linux 发行版)和 mandoc(用于大多数 BSD 变体),现在支持 Unicode。其他 UNIX 系统通常不支持,但它们现在只是人们日常使用系统中的一小部分。使用 Unicode 字符来创建 POD 文档(而不是使用人们姓名的 ASCII 转换或避免使用非英语文本)越来越普遍(出于非常好的理由),这使得旧输出格式中的限制更加明显。

提出了四种解决方法

Pod::Man 5.00 及更高版本做出了最后一个选择。这可能在使用 troff 将手册页格式化为 PostScript 或 PDF 时会产生更糟糕的输出,但这样做很少见,通常是手动的,因此可以在这些情况下更改编码。通过将 encoding 设置为 roff 可以使用旧的输出编码。

测试结果

以下是测试 utf-8groffencoding 值在各种操作系统上的结果。测试方法是在当前目录中创建 man/man1,将 encoding.utf8encoding.groff 从 podlators 5.00 发行版复制到 man/man1/encoding.1,然后运行

LANG=C.UTF-8 MANPATH=$(pwd)/man man 1 encoding

如果区域设置没有显式设置为包含 UTF-8 的区域设置,则 Unicode 字符通常会被转换为 ASCII(例如,删除重音符号)或删除或替换为 <?>(如果没有转换)。

在 2022-09-25 测试。非常感谢 GCC 编译农场项目提供测试主机。

OS                   UTF-8      groff
------------------   -------    -------
AIX 7.1              no [1]     no [2]
Alpine 3.15.0        yes        yes
CentOS 7.9           yes        yes
Debian 7             yes        yes
FreeBSD 13.0         yes        yes
NetBSD 9.2           yes        yes
OpenBSD 7.1          yes        yes
openSUSE Leap 15.4   yes        yes
Solaris 10           yes        no [2]
Solaris 11           no [3]     no [3]

我没有机会访问 macOS 系统进行测试,但由于它使用 mandoc,因此它的行为可能与 BSD 主机相同。

备注

[1]

Unicode 字符被转换为一个或两个与原始字符无关的随机 ASCII 字符。

[2]

Unicode 字符显示为 groff 转义符的正文,而不是指示的字符(换句话说,类似于 [u00EF] 的文本)。

[3]

Unicode 字符被完全删除,就好像它们不存在一样。使用 nroff -man 而不是 man 来格式化页面显示的结果与 Solaris 10 相同。使用 groff -k -man -Tutf8 来格式化页面产生了正确的输出。

在 Debian 12 系统上使用 groff 生成的 PostScript 和 PDF 输出不支持组合重音符或 SMP 字符,因为默认输出字体不支持。

欢迎在其他平台上进行测试。如果您有其他结果,请告知作者。

诊断

roff 字体应该是 1 或 2 个字符,而不是 "%s"

(F) 您指定了一个 *roff 字体(使用 fixedfixedbold 等),它不是一个或两个字符。Pod::Man 不支持超过两个字符的 *roff 字体,尽管一些 *roff 扩展支持(nrofftroff 的规范版本也不支持)。

无效的错误设置 "%s"

(F) 构造函数的 errors 参数被设置为未知值。

无效的引号规范 "%s"

(F) 给定的引号规范(构造函数的 quotes 选项)无效。引号规范必须是一个字符长或一个偶数(大于一)个字符长。

POD 文档存在语法错误

(F) 正在格式化的 POD 文档存在语法错误,并且 errors 选项被设置为 die

环境

PERL_CORE

如果设置了此环境变量,并且 Encode 不可用,则会静默地回退到 groff 的编码,而不会向标准错误发出抱怨。此环境变量在 Perl 核心构建期间设置,该构建在 podlators 之后构建 Encode。在这种情况下,预计 Encode 不会(尚未)可用。

POD_MAN_DATE

如果设置,这将用作左页脚的值,除非显式设置了date选项,覆盖输入文件的 timestamps 或当前时间。这主要用于确保在给定相同源代码和 Pod::Man 版本的情况下,即使文件 timestamps 可能不一致,也能生成相同输出文件的可重复构建。

SOURCE_DATE_EPOCH

如果设置,并且未设置 POD_MAN_DATE 和date选项,这将用作源文件的修改时间,覆盖输入文件的 timestamps 或当前时间。它应该设置为自 UNIX 纪元以来的所需时间(以秒为单位)。这主要用于确保在给定相同源代码和 Pod::Man 版本的情况下,即使文件 timestamps 可能不一致,也能生成相同输出文件的可重复构建。有关完整规范,请参见 https://reproducible-builds.org/specs/source-date-epoch/

(可以说,根据规范,只有在输入文件的 timestamps 不可用且 Pod::Man 使用当前时间时,才应使用此变量。但是,对于 Debian 中的可重复构建,如果此变量覆盖输入文件的 timestamps,则结果更可靠。)

COMPATIBILITY

Pod::Man 1.02(基于 Pod::Parser)是 Perl 5.6.0 中包含的第一个版本。

基于 Pod::Simple 的当前 API 添加到 Pod::Man 2.00 中。Pod::Man 2.04 包含在 Perl 5.9.3 中,这是第一个包含这些更改的 Perl 版本。这是第一个正确支持所有现代 POD 语法的版本。parse_from_filehandle() 方法在 Pod::Man 2.09 中重新添加以实现向后兼容性,该版本包含在 Perl 5.9.4 中。

对类型为 URL 的 L<> 链接中的锚文本的支持是在 Pod::Man 2.23 中添加的,该版本包含在 Perl 5.11.5 中。

parse_lines()、parse_string_document() 和 parse_file() 从 Pod::Man 2.28 开始,如果尚未设置默认输出文件句柄,则设置为STDOUT,该版本包含在 Perl 5.19.5 中。

Pod::Man 4.00 版本(包含在 Perl 5.23.7 中)添加了对 SOURCE_DATE_EPOCH 和 POD_MAN_DATE 的支持,生成的日期使用 UTC 而不是本地时区。这也是第一个将模块版本与 podlators 分发版本对齐的版本。从现在开始,podlators 中包含的所有模块以及 podlators 分发本身都共享相同的版本号。

Pod::Man 4.10 版本(包含在 Perl 5.27.8 中)更改了手册页引用和函数名的格式,遵循当前的 Linux 手册页标准,使用粗体而不是斜体。

Pod::Man 5.00 版本将默认输出编码更改为 UTF-8,可以通过新的 encoding 选项覆盖。它还修复了使用 C<> 转义时粗体或斜体扩展过远的问题,并开始将 Unicode 零宽度空格 (U+200B) 转换为 \: *roff 转义符。它还放弃了在输出中添加细微格式修正的尝试,这些修正只有在使用 troff 排版时才能看到,而这之前一直是错误的主要来源。

错误

roff 编码中,带重音字符的 nroff 回退存在许多错误和特定于语言的假设。由于这种编码的目的是与早期版本的 Pod::Man 输出向后兼容,并且除了支持旧系统时必要外,它已被弃用,因此这些错误不太可能被修复。

Pod::Man 不处理超过两个字符的字体名称。大多数 troff 实现也不处理,但 groff 作为扩展处理。对于那些想要使用它的人来说,支持它作为一种选择会很好。

注意事项

句子间距

Pod::Man 将输入间距逐字复制到输出 *roff 文档。这意味着您的输出将受到 nroff 通常如何处理句子间距的影响。

nroff 来自一个使用句子后两个空格作为标准的时代,并且在重新排列文本时,始终会在行尾句号(或类似标点符号)后添加两个空格。例如,以下输入

=pod

One sentence.
Another sentence.

当文本重新排列时,句号后将有两个空格。如果您在句子后也使用两个空格,这将是一致的,尽管您必须注意不要以缩写词(如 e.g.Ms.)结尾。如果您使用 *roff 风格指南(以及 XKCD 1285)建议在每个句子后换行,输出也将是一致的,尽管这将始终在每个句子后产生两个空格,这可能不是您想要的。

如果您更喜欢句子后留一个空格(这是更现代的风格),那么您不幸需要确保段落中间的任何一行都不以句号或类似的句子结束符结尾。否则,nroff将在重新排版时在该句子后添加两个空格,导致您的输出文档间距不一致。

连字符

连字符和破折号的处理方式有些脆弱,在某些情况下可能会得到错误的符号。这通常只对断行和可能对 troff 输出有影响。

作者

由 Russ Allbery <[email protected]> 编写,基于 Tom Christiansen <[email protected]> 的原始 pod2man

与 Pod::Simple 而不是 Pod::Parser 一起使用的修改是由 Sean Burke <[email protected]> 贡献的,但我已经将它们修改得面目全非,所有错误都是我的。

版权和许可

版权所有 1999-2010, 2012-2020, 2022 Russ Allbery <[email protected]>

Sean Burke <[email protected]> 做出了重大贡献。

本程序是自由软件;您可以根据与 Perl 本身相同的条款重新发布和/或修改它。

另请参阅

Encode::SupportedPod::Simpleperlpod(1)pod2man(1)nroff(1)troff(1)man(1)man(7)

Ossanna, Joseph F. 和 Brian W. Kernighan。 "Troff 用户手册",计算机科学技术报告第 54 号,AT&T 贝尔实验室。这是标准 nrofftroff 的最佳文档。在撰写本文时,它可在 http://www.troff.org/54.pdf 获取。

记录 man 宏集的联机帮助页可能是 man(5) 而不是 man(7),具体取决于您的系统。

如果您以前没有编写联机帮助页并且不熟悉相关约定,请参阅 perlpodstyle(1) 以获取有关使用 POD 编写联机帮助页的文档。

此模块的当前版本始终可从其网站获取:https://www.eyrie.org/~eagle/software/podlators/。它也是 Perl 核心发行版的一部分,从 5.6.0 版本开始。