為 man 手冊頁編寫解析器的備忘錄
我一般都很喜歡無所事事,但有時候太無聊了也不行 —— 2015 年的一個星期天下午就是這樣,我決定開始寫一個開源專案來讓我不那麼無聊。
在我尋求創意時,我偶然發現了一個請求,要求構建一個由 Mathias Bynens 提出的“按 Web 標準構建的 Man 手冊頁檢視器”。沒有考慮太多,我開始使用 JavaScript 編寫一個手冊頁解析器,經過大量的反覆思考,最終做出了一個 Jroff。
那時候,我非常熟悉手冊頁這個概念,而且使用過很多次,但我知道的僅止於此,我不知道它們是如何生成的,或者是否有一個標準。在經過兩年後,我有了一些關於此事的想法。
man 手冊頁是如何寫的
當時令我感到驚訝的第一件事是,手冊頁的核心只是儲存在系統某處的純文字檔案(你可以使用 manpath
命令檢查這些目錄)。
此檔案中不僅包含文件,還包含使用了 20 世紀 70 年代名為 troff
的排版系統的格式化資訊。
troff 及其 GNU 實現 groff 是處理文件的文字描述以生成適合列印的排版版本的程式。它更像是“你所描述的即你得到的”,而不是你所見即所得的。
- 摘自 troff.org
如果你對排版格式毫不熟悉,可以將它們視為 steroids 期刊用的 Markdown,但其靈活性帶來的就是更復雜的語法:
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
解析器,還是隻是好奇,這些都是我發現的一些更具挑戰性的問題。
上下文敏感的語法
表面上,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
訂閱“Linux 中國”官方小程式來檢視
相關文章
- Bash的基礎知識man手冊
- PostgreSQL 速查、備忘手冊 | PostgreSQL Quick Find and TutorialSQLUI
- 行為型模式:備忘錄模式模式
- 備忘錄
- 【備忘錄】
- 翻譯:man getopt(1)中文手冊
- 備忘錄模式模式
- iOS備忘錄iOS
- JUnit備忘錄
- CSS備忘錄CSS
- RabbitMQ備忘錄MQ
- Linux的bash shell與man檢視手冊Linux
- 如何備份iPhone手機備忘錄到電腦上iPhone
- 手寫一個解析器
- Python 備忘錄Python
- Java備忘錄《集合》Java
- 網站備忘錄網站
- rman命令備忘錄
- Eigen備忘錄
- 萌新(我)的Git備忘錄Git
- 初學Java的備忘錄Java
- 如何為OSX備忘錄新增密碼保護?密碼
- 手寫javascript json解析器JavaScriptJSON
- 移動端HTML5頁面開發備忘錄HTML
- [備忘]沒有為副檔名“.cshtml”註冊的生成提供程式HTML
- 備忘錄模式(Memento)模式
- Java備忘錄《“==” 和 “equals”》Java
- Dart 學習備忘錄Dart
- linux 備忘記錄Linux
- JavaMementoPattern(備忘錄模式)Java模式
- 19_備忘錄模式模式
- 開發 備忘錄 - 雜
- python編譯備忘Python編譯
- 簡易表示式解析器編寫
- 行為型設計模式 - 備忘錄模式詳解設計模式
- 設計模式--備忘錄模式Memento(行為型)設計模式
- 用jQuery-Easy-UI編寫註冊頁面jQueryUI
- IPTABLES-SAVE手冊頁&IPTABLES-RESTORE手冊頁REST