為 man 手冊頁編寫解析器的備忘錄
那時候,我非常熟悉手冊頁這個概念,而且使用過很多次,但我知道的僅止於此,我不知道它們是如何生成的,或者是否有一個標準。
-- Roberto Dip(作者)
我一般都很喜歡無所事事,但有時候太無聊了也不行 —— 2015 年的一個星期天下午就是這樣,我決定開始寫一個開源項目來讓我不那麼無聊。
在我尋求創意時,我偶然發現了一個請求,要求構建一個由 Mathias Bynens 提出的「 按 Web 標準構建的 Man 手冊頁查看器 」。沒有考慮太多,我開始使用 JavaScript 編寫一個手冊頁解析器,經過大量的反覆思考,最終做出了一個 Jroff 。
那時候,我非常熟悉手冊頁這個概念,而且使用過很多次,但我知道的僅止於此,我不知道它們是如何生成的,或者是否有一個標準。在經過兩年後,我有了一些關於此事的想法。
man 手冊頁是如何寫的
當時令我感到驚訝的第一件事是,手冊頁的核心只是存儲在系統某處的純文本文件(你可以使用 manpath 命令檢查這些目錄)。
此文件中不僅包含文檔,還包含使用了 20 世紀 70 年代名為 troff 的排版系統的格式化信息。
troff 及其 GNU 實現 groff 是處理文檔的文本描述以生成適合列印的排版版本的程序。它更像是「你所描述的即你得到的」,而不是你所見即所得的。
- 摘自 troff.org
如果你對排版格式毫不熟悉,可以將它們視為 steroids 期刊用的 Markdown,但其靈活性帶來的就是更複雜的語法:
groff-compressor
groff 文件可以手工編寫,也可以使用許多不同的工具從其他格式生成,如 Markdown、Latex、HTML 等。
為什麼 groff 和 man 手冊頁綁在一起是有歷史原因的,其格式 隨時間有變化 ,它的血統由一系列類似命名的程序組成:RUNOFF > roff > nroff > troff > groff。
但這並不一定意味著 groff 與手冊頁有多緊密的關係,它是一種通用格式,已被用於 書籍 ,甚至用於 照相排版 。
此外,值得注意的是 groff 也可以調用後處理器將其中間輸出結果轉換為最終格式,這對於終端顯示來說不一定是 ascii !一些支持的格式是:TeX DVI、HTML、Canon、HP LaserJet4 兼容格式、PostScript、utf8 等等。
宏
該格式的其他很酷的功能是它的可擴展性,你可以編寫宏來增強其基本功能。
鑒於 *nix 系統的悠久歷史,有幾個可以根據你想要生成的輸出而將特定功能組合在一起的宏包,例如 man、mdoc、mom、ms、mm 等等。
手冊頁通常使用 man 和 mdoc 宏包編寫。
區分原生的 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 宏包編寫手冊頁時,你的第一個不是注釋的行必須是這個宏,它接受五個參數:title、section、date、source、manual。
- .BI:粗體加斜體(特別適用於函數格式)
- .BR:粗體加正體(特別適用於參考其他手冊頁)
mdoc 宏包:
- .Dd、.Dt、.Os:類似於 man 宏包需要 .TH,mdoc 宏也需要這三個宏,需要按特定順序使用。它們的縮寫分別代表:文檔日期、文檔標題和操作系統。
- .Bl、.It、.El:這三個宏用於創建列表,它們的名稱不言自明:開始列表、項目和結束列表。
via: https://monades.roperzh.com/memories-writing-parser-man-pages/
作者: Roberto Dip 譯者: wxy 校對: wxy 選題: lujun9972
本文由 LCTT 原創編譯, Linux中國 榮譽推出
點擊「了解更多」可訪問文內鏈接
※Linux 下的進程間通信:套接字和信號
※每日安全資訊:微軟 Azure 雲服務被用於託管惡意軟體
TAG:Linux技術 |