为 man 手册页编写解析器的备忘录

我通常都很喜欢无所事事,但有时候太无聊了也不行 —— 2015 年的一个星期天下午就是这样,我决定开始写一个开源项目来让我不那么无聊。html

在我寻求创意时,我偶然发现了一个请求,要求构建一个由 Mathias Bynens 提出的“按 Web 标准构建的 Man 手册页查看器”。没有考虑太多,我开始使用 JavaScript 编写一个手册页解析器,通过大量的反复思考,最终作出了一个 Jrofflinux

那时候,我很是熟悉手册页这个概念,并且使用过不少次,但我知道的仅止于此,我不知道它们是如何生成的,或者是否有一个标准。在通过两年后,我有了一些关于此事的想法。git

man 手册页是如何写的

当时令我感到惊讶的第一件事是,手册页的核心只是存储在系统某处的纯文本文件(你可使用 manpath 命令检查这些目录)。github

此文件中不只包含文档,还包含使用了 20 世纪 70 年代名为 troff 的排版系统的格式化信息。web

troff 及其 GNU 实现 groff 是处理文档的文本描述以生成适合打印的排版版本的程序。它更像是“你所描述的即你获得的”,而不是你所见即所得的。函数

若是你对排版格式绝不熟悉,能够将它们视为 steroids 期刊用的 Markdown,但其灵活性带来的就是更复杂的语法:工具

groff-compressor

groff 文件能够手工编写,也可使用许多不一样的工具从其余格式生成,如 Markdown、Latex、HTML 等。post

为何 groff 和 man 手册页绑在一块儿是有历史缘由的,其格式随时间有变化,它的血统由一系列相似命名的程序组成:RUNOFF > roff > nroff > troff > groff。操作系统

但这并不必定意味着 groff 与手册页有多紧密的关系,它是一种通用格式,已被用于书籍,甚至用于照相排版code

此外,值得注意的是 groff 也能够调用后处理器将其中间输出结果转换为最终格式,这对于终端显示来讲不必定是 ascii !一些支持的格式是:TeX DVI、HTML、Canon、HP LaserJet4 兼容格式、PostScript、utf8 等等。

该格式的其余很酷的功能是它的可扩展性,你能够编写宏来加强其基本功能。

鉴于 *nix 系统的悠久历史,有几个能够根据你想要生成的输出而将特定功能组合在一块儿的宏包,例如 manmdocmommsmm 等等。

手册页一般使用 manmdoc 宏包编写。

区分原生的 groff 命令和宏的方式是经过标准 groff 包大写其宏名称。对于 man 宏包,每一个宏的名称都是大写的,如 .PP.TH.SH 等。对于 mdoc 宏包,只有第一个字母是大写的: .Pp.Dt.Sh

groff-example

挑战

不管你是考虑编写本身的 groff 解析器,仍是只是好奇,这些都是我发现的一些更具挑战性的问题。

上下文敏感的语法

表面上,groff 的语法是上下文无关的,遗憾的是,由于宏描述的是主体不透明的令牌,因此包中的宏集合自己可能不会实现上下文无关的语法。

这致使我在那时作不出来一个解析器生成器(无论好坏)。

嵌套的宏

mdoc 宏包中的大多数宏都是可调用的,这差很少意味着宏能够用做其余宏的参数,例如,你看看这个:

  • Fl(Flag)会在其参数中添加破折号,所以 Fl s 会生成 -s
  • Ar(Argument)提供了定义参数的工具
  • Op(Optional)会将其参数括在括号中,由于这是将某些东西定义为可选的标准习惯用法
  • 如下组合 .Op Fl s Ar file 将生成 [-s file],由于 Op 宏能够嵌套。

缺少适合初学者的资源

让我感到困惑的是缺少一个规范的、定义明确的、清晰的来源,网上有不少信息,这些信息对读者来讲很重要,须要时间来掌握。

有趣的宏

总结一下,我会向你提供一个很是简短的宏列表,我在开发 jroff 时发现它颇有趣:

man 宏包:

  • .TH:用 man 宏包编写手册页时,你的第一个不是注释的行必须是这个宏,它接受五个参数:titlesectiondatesourcemanual
  • .BI:粗体加斜体(特别适用于函数格式)
  • .BR:粗体加正体(特别适用于参考其余手册页)

mdoc 宏包:

  • .Dd.Dt.Os:相似于 man 宏包须要 .THmdoc 宏也须要这三个宏,须要按特定顺序使用。它们的缩写分别表明:文档日期、文档标题和操做系统。
  • .Bl.It.El:这三个宏用于建立列表,它们的名称不言自明:开始列表、项目和结束列表。

via: monades.roperzh.com/memories-wr…

做者:Roberto Dip 译者:wxy 校对:wxy 选题:lujun9972

本文由 LCTT 原创编译,Linux中国 荣誉推出

相关文章
相关标签/搜索