爲 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中國 榮譽推出

相關文章
相關標籤/搜索