第 19 章 文件產生器 (ocamldoc)

本章介紹 OCamldoc,這是一個從嵌入在原始碼檔案中的特殊註解產生文件的工具。OCamldoc 使用的註解格式為 (***),並遵循 19.2 節中描述的格式。

OCamldoc 可以產生多種格式的文件:HTML、LATEX、TeXinfo、Unix man pages 和 dot 相依性圖。此外,使用者可以新增自己的自訂產生器,如 19.3 節中所述。

在本章中,我們使用元素一詞來指稱 OCaml 原始碼檔案的下列任何部分:型別宣告、值、模組、例外、模組型別、型別建構子、記錄欄位、類別、類別型別、類別方法、類別值或類別繼承子句。

1 用法

1.1 呼叫

OCamldoc 是透過 ocamldoc 命令呼叫,如下所示

        ocamldoc options sourcefiles

選擇輸出格式的選項

以下選項決定產生的文件格式。

-html
以 HTML 預設格式產生文件。產生的 HTML 頁面儲存在目前目錄或使用 -d 選項指定的目錄中。您可以透過編輯產生的 style.css 檔案,或使用 -css-style 選項提供自己的樣式表,來自訂產生頁面的樣式。如果 style.css 檔案已存在或已使用 -css-style,則不會產生該檔案。
-latex
以 LATEX 預設格式產生文件。產生的 LATEX 文件會儲存於 ocamldoc.out 檔案中,或使用 -o 選項指定的檔案中。該文件使用樣式檔案 ocamldoc.sty。當使用 -latex 選項時,如果該檔案不存在,則會產生此檔案。您可以變更此檔案來自訂 LATEX 文件的樣式。
-texi
以 TeXinfo 預設格式產生文件。產生的 LATEX 文件會儲存於 ocamldoc.out 檔案中,或使用 -o 選項指定的檔案中。
-man
以一組 Unix man 頁面形式產生文件。產生的頁面會儲存在目前目錄或使用 -d 選項指定的目錄中。
-dot
以適合 dot 顯示和處理的格式,產生頂層模組的相依性圖。dot 工具可從 https://graphviz.dev.org.tw/ 取得。圖形的文字表示形式會寫入 ocamldoc.out 檔案或使用 -o 選項指定的檔案中。使用 dot ocamldoc.out 來顯示它。
-g file.cm[o,a,xs]
動態載入指定的檔案,其中定義了自訂文件產生器。請參閱 19.4.1 節。此選項由 ocamldoc 命令 (用於載入 .cmo.cma 檔案) 及其原生碼版本 ocamldoc.opt (用於載入 .cmxs 檔案) 支援。如果指定的檔案是簡單的檔案,且不存在於目前目錄中,則 ocamldoc 會在自訂產生器預設目錄中,以及使用選用的 -i 選項指定的目錄中尋找它。
-customdir
顯示自訂產生器預設目錄。
-i directory
將指定的目錄新增至尋找自訂產生器的路徑中。

一般選項

-d dir
在目錄 dir 中產生檔案,而不是在目前目錄中。
-dump file
將收集的資訊傾印到 file 中。此資訊可在後續呼叫 ocamldoc 時使用 -load 選項讀取。
-hide modules
在產生的文件中隱藏給定的完整模組名稱。modules 是以「,」分隔的完整模組名稱清單,不含空格。例如:Stdlib,M2.M3
-inv-merge-ml-mli
合併時反轉實作和介面的優先順序。保留實作檔案中的所有元素,並且 -m 選項會指出介面檔案中的哪些註解部分與實作檔案中的註解合併。
-keep-code
在可用時,始終保留值、方法和實例變數的原始碼。
-load file
file 載入資訊,該檔案已由 ocamldoc -dump 產生。可以提供多個 -load 選項。
-m flags
指定介面和實作之間的合併選項。(詳細資訊請參閱 19.1.2 節)。flags 可以是以下一個或多個字元
d
合併描述
a
合併 @author
v
合併 @version
l
合併 @see
s
合併 @since
b
合併 @before
o
合併 @deprecated
p
合併 @param
e
合併 @raise
r
合併 @return
A
合併所有內容
-no-custom-tags
不允許自訂 @ 標籤 (請參閱 19.2.5 節)。
-no-stop
保留放在 (**/**) 特殊註解之後/之間的元素 (請參閱 19.2 節)。
-o file
將產生的文件輸出到 file,而不是 ocamldoc.out。此選項僅在與 -latex-texi-dot 選項結合使用時才有意義。
-pp command
透過預處理器 command 傳輸原始碼。
-impl filename
將檔案 filename 視為實作檔案處理,即使其副檔名不是 .ml
-intf filename
將檔案 filename 視為介面檔案處理,即使其副檔名不是 .mli
-text filename
將檔案 filename 視為文字檔案處理,即使其副檔名不是 .txt
-sort
在產生文件之前,排序頂層模組的清單。
-stars
移除註解每行中第一個星號 ('*') 之前的所有空白字元。
-t title
使用 title 作為產生文件的標題。
-intro file
使用 file 的內容作為 ocamldoc 文字以用作簡介 (僅限 HTML、LATEX 和 TeXinfo)。對於 HTML,該檔案用於建立整個 index.html 檔案。
-v
詳細模式。顯示進度資訊。
-version
列印版本字串並結束。
-vnum
列印簡短版本號碼並結束。
-warn-error
將 Ocamldoc 警告視為錯誤。
-hide-warnings
不印出 OCamldoc 警告。
-help--help
顯示簡短的使用摘要並結束。

型別檢查選項

OCamldoc 會呼叫 OCaml 型別檢查器以取得型別資訊。以下選項會影響型別檢查階段。它們與 ocamlcocamlopt 命令的意義相同。

-I 目錄
目錄 加入搜尋已編譯介面檔案(.cmi 檔案)的目錄清單中。
-H 目錄
-I 類似,但 -H 目錄會在最後搜尋,且程式可能無法直接參照以這種方式加入搜尋路徑的模組。
-nolabels
忽略型別中非可選的標籤。
-rectypes
允許任意遞迴型別。(請參閱 ocamlc-rectypes 選項。)

產生 HTML 頁面的選項

以下選項與 -html 選項一起使用

-all-params
顯示函數和方法的完整參數清單。
-charset 字元集
加入字元編碼為 字元集 的相關資訊(預設值為 iso-8859-1)。
-colorize-code
使用顏色來強調關鍵字等,將以 [ ]{[ ]} 括起來的 OCaml 程式碼著色。如果程式碼片段在語法上不正確,則不會加入顏色。
-css-style 檔名
使用 檔名 作為串聯樣式表檔案。
-index-only
只產生索引檔案。
-short-functors
使用簡短形式顯示函式子
module M : functor (A:Module) -> functor (B:Module2) -> sig .. end
顯示為
module M (A:Module) (B:Module2) : sig .. end

產生 LATEX 檔案的選項

以下選項與 -latex 選項一起使用

-latex-value-prefix 前綴
為產生的 LATEX 文件中值的標籤提供一個前綴。預設前綴為空字串。您也可以使用 -latex-type-prefix-latex-exception-prefix-latex-module-prefix-latex-module-type-prefix-latex-class-prefix-latex-class-type-prefix-latex-attribute-prefix-latex-method-prefix 選項。

當您有一個型別和一個同名的值時,這些選項非常有用。如果您未指定前綴,LATEX 將會抱怨重複定義的標籤。

-latextitle n,樣式
將樣式數字 n 與給定的 LATEX 分節命令 樣式 建立關聯,例如 sectionsubsection。(僅限 LATEX。)當在給定的分節層級將產生的文件包含在另一個 LATEX 文件中時,這非常有用。預設關聯是:section 為 1,subsection 為 2,subsubsection 為 3,paragraph 為 4,而 subparagraph 為 5。
-noheader
在產生的文件中隱藏標頭。
-notoc
不產生目錄。
-notrailer
在產生的文件中隱藏結尾。
-sepfiles
每個頂層模組產生一個 .tex 檔案,而不是全域的 ocamldoc.out 檔案。

產生 TeXinfo 檔案的選項

以下選項與 -texi 選項一起使用

-esc8
在 Info 檔案中跳脫重音字元。
-info-entry
指定 Info 目錄項目。
-info-section
指定 Info 目錄區段。
-noheader
在產生的文件中隱藏標頭。
-noindex
不為 Info 檔案建置索引。
-notrailer
在產生的文件中隱藏結尾。

產生 dot 圖表的選項

以下選項與 -dot 選項一起使用

-dot-colors 顏色
指定在產生的 dot 程式碼中使用的顏色。當產生模組相依性時,ocamldoc 會根據模組所在的目錄使用不同的顏色。當產生型別相依性時,ocamldoc 會根據定義型別的模組使用不同的顏色。顏色 是以「,」分隔的顏色名稱清單,如 Red,Blue,Green。可用的顏色是 dot 工具支援的顏色。
-dot-include-all
dot 輸出中包含所有模組,而不僅僅是命令列上給定的模組或使用 -load 選項載入的模組。
-dot-reduce
在輸出 dot 程式碼之前,執行相依性圖的遞移約簡。如果有很多雜亂圖表的遞移相依性,這會很有用。
-dot-types
輸出 dot 程式碼,描述型別相依性圖,而不是模組相依性圖。

產生 man 檔案的選項

以下選項與 -man 選項一起使用

-man-mini
僅為模組、模組型別、類別和類別型別產生 man 頁面,而不是所有元素的頁面。
-man-suffix 字尾
設定用於產生的 man 檔案名的字尾。預設值為 '3o',如 List.3o
-man-section 區段
設定用於產生的 man 檔案名的區段號碼。預設值為 '3'。

1.2 模組資訊的合併

模組的資訊可以從 .mli.ml 檔案中提取,或同時從兩者提取,具體取決於命令列上給定的檔案。當給定同一模組的 .mli.ml 檔案時,根據以下規則合併從這些檔案提取的資訊

1.3 程式碼撰寫規則

必須遵守以下規則,以避免名稱衝突導致交叉參照錯誤

2 文件註解的語法

包含文件資料的註解稱為特殊註解,並寫在 (***) 之間。特殊註解必須完全以 (** 開頭。以 ( 開頭且超過兩個 * 的註解會被忽略。

2.1 文件註解的位置

OCamldoc 可以將註解與原始碼檔案中遇到的一些語言元素關聯。這種關聯是根據註解相對於語言元素的位置來建立的。.mli.ml 檔案中註解的位置是不同的。

.mli 檔案中的註解

如果特殊註解放在元素之前或之後,則該註解會與該元素關聯。
如果符合以下條件,則元素之前的特殊註解會與該元素關聯:

如果特殊註解和元素之間沒有空白行或註解,則元素之後的特殊註解會與該元素關聯。

有兩個例外:對於類型定義中的建構函式和記錄欄位,關聯的註解只能放在建構函式或欄位定義之後,且它們之間不能有空白行或其他註解。如果建構函式之後還有另一個建構函式,則該建構函式的特殊註解必須放在分隔兩個建構函式的「|」字元之前。

以下範例介面檔案 foo.mli 說明了 .mli 檔案中註解的放置規則。

(** 檔案中的第一個特殊註解是與整個模組關聯的註解。*) (** 特殊註解可以放在元素之間,並且會被 OCamldoc 工具保留,但不會與任何元素關聯。這些註解中的 @-tag 會被忽略。*) (*******************************************************************) (** 像上面這樣的註解,如果星號超過兩個,則會被忽略。*) (** 函式 f 的註解。*) val f : int -> int -> int (** 函式 f 註解的延續。*) (** 例外 My_exception 的註解,即使在特殊註解和例外之間有簡單的註解。*) (* 您好,我是一個簡單的註解 :-) *) exception My_exception of (int -> int) * int (** 類型 weather 的註解 *) type weather = | Rain of int (** 建構函式 Rain 的註解 *) | Sun (** 建構函式 Sun 的註解 *) (** 類型 weather2 的註解 *) type weather2 = | Rain of int (** 建構函式 Rain 的註解 *) | Sun (** 建構函式 Sun 的註解 *) (** 我可以在這裡繼續類型 weather2 的註解,因為已經有註解與最後一個建構函式關聯。*) (** 類型 my_record 的註解 *) type my_record = { foo : int ; (** 欄位 foo 的註解 *) bar : string ; (** 欄位 bar 的註解 *) } (** 類型 my_record 註解的延續 *) (** foo 的註解 *) val foo : string (** 此註解與 foo 關聯,而不是 bar。*) val bar : string (** 此註解與 bar 關聯。*) (** 類別 my_class 的註解 *) class my_class : object (** 用於描述從 cl 繼承的註解 *) inherit cl (** 屬性 tutu 的註解 *) val mutable tutu : string (** 屬性 toto 的註解。*) val toto : int (** 此註解未附加到 titi,因為 titi 前面有空白行,但會保留為類別中的註解。*) val titi : string (** 方法 toto 的註解 *) method toto : string (** 方法 m 的註解 *) method m : float -> int end (** 類別類型 my_class_type 的註解 *) class type my_class_type = object (** 變數 x 的註解。*) val mutable x : int (** 方法 m 的註解。*) method m : int -> int end (** 模組 Foo 的註解 *) module Foo : sig (** x 的註解 *) val x : int (** 一個特殊註解,會被保留,但不與任何元素關聯 *) end (** 模組類型 my_module_type 的註解。*) module type my_module_type = sig (** 值 x 的註解。*) val x : int (** 模組 M 的註解。*) module M : sig (** 值 y 的註解。*) val y : int (* ... *) end end

.ml 檔案中的註解

如果特殊註解放在元素之前,且註解和元素之間沒有空白行,則該註解會與該元素關聯。同時,特殊註解和元素之間可以有簡單的註解。有兩個例外,對於類型定義中的建構函式和記錄欄位,關聯的註解必須放在建構函式或欄位定義之後,且它們之間不能有空白行。如果建構函式之後還有另一個建構函式,則該建構函式的特殊註解必須放在分隔兩個建構函式的「|」字元之前。

以下 toto.ml 檔案的範例說明如何在 .ml 檔案中放置註解。

(** 檔案中的第一個特殊註解是與整個模組關聯的註解。*) (** 函式 f 的註解 *) let f x y = x + y (** 此註解未附加到任何元素,因為下一個元素之前還有另一個特殊註解。*) (** 例外 My_exception 的註解,即使在特殊註解和例外之間有簡單的註解。*) (* 一個簡單的註解。*) exception My_exception of (int -> int) * int (** 類型 weather 的註解 *) type weather = | Rain of int (** 建構函式 Rain 的註解 *) | Sun (** 建構函式 Sun 的註解 *) (** 類型 my_record 的註解 *) type my_record = { foo : int ; (** 欄位 foo 的註解 *) bar : string ; (** 欄位 bar 的註解 *) } (** 類別 my_class 的註解 *) class my_class = object (** 用於描述從 cl 繼承的註解 *) inherit cl (** 實例變數 tutu 的註解 *) val mutable tutu = "tutu" (** toto 的註解 *) val toto = 1 val titi = "titi" (** 方法 toto 的註解 *) method toto = tutu ^ "!" (** 方法 m 的註解 *) method m (f : float) = 1 end (** 類別類型 my_class_type 的註解 *) class type my_class_type = object (** 實例變數 x 的註解。*) val mutable x : int (** 方法 m 的註解。*) method m : int -> int end (** 模組 Foo 的註解 *) module Foo = struct (** x 的註解 *) let x = 0 (** 類別中的一個特殊註解,但不與任何元素關聯。*) end (** 模組類型 my_module_type 的註解。*) module type my_module_type = sig (* 值 x 的註解。*) val x : int (* ... *) end

2.2 Stop 特殊註解

特殊註解 (**/**) 會告知 OCamldoc 捨棄此註解之後的元素,直到目前類別、類別類型、模組或模組類型的結尾,或直到下一個 stop 註解。例如:

class type foo = object (** 方法 m 的註解 *) method m : string (**/**) (** 這個方法不會出現在文件中 *) method bar : int end (** 這個值會出現在文件中,因為類別中的 Stop 特殊註解不會影響類別的父模組。*) val foo : string (**/**) (** 值 bar 不會出現在文件中。*) val bar : string (**/**) (** 類型 t 會出現在文件中,因為前一個 stop 註解關閉了「無文件模式」。*) type t = string

使用 ocamldoc-no-stop 選項會導致 Stop 特殊註解被忽略。

2.3 文件註解的語法

文件註解 (***) 的內部包含自由格式的文字,以及選擇性的格式註解,後面接著選擇性的標籤,提供有關參數、版本、作者等的更具體資訊。標籤以 @ 字元開頭。因此,文件註解的形狀如下:

(** The comment begins with a description, which is text formatted
   according to the rules described in the next section.
   The description continues until the first non-escaped '@' character.
   @author Mr Smith
   @param x description for parameter x
*)

某些元素僅支援所有 @-tag 的子集。與文件化的元素無關的標籤會被直接忽略。例如,在文件化類型建構函式、記錄欄位和類別繼承子句時,會忽略所有標籤。同樣地,類別實例變數上的 @param 標籤也會被忽略。

最後,(**) 是空的文件註解。

2.4 文字格式化

以下是 BNF 文法,用於格式化文字描述的簡單標記語言。

text::= {text-element}+
 
inline-text::= {inline-text-element}+
 
text-element::=
inline-text-element 
blank-line強制換行。


inline-text-element::=
{ { 09 }+ 行內文字 }文字 格式化為章節標題;{ 後面的整數表示章節層級。
{ { 09 }+ : 標籤 行內文字 }相同,但同時將名稱 標籤 與目前位置關聯。此位置可像其他元素一樣,在 {! 命令中使用其完整限定的標籤來參考。
{b 行內文字 }文字 設定為粗體。
{i 行內文字 }文字 設定為斜體。
{e 行內文字 }強調 文字
{C 行內文字 }文字 置中對齊。
{L 行內文字 }文字 靠左對齊。
{R 行內文字 }文字 靠右對齊。
{ul 列表 }建立一個列表。
{ol 列表 }建立一個編號列表。
{{: 字串 } 行內文字 }在指定的 文字 上放置一個指向給定地址(以 字串 形式給出)的連結。
[ 字串 ]將給定的 字串 設定為原始碼樣式。
{[ 字串 ]}將給定的 字串 設定為預格式化原始碼樣式。
{v 字串 v}將給定的 字串 設定為逐字樣式。
{% 字串 %}特定目標的內容(預設為 LATEX 程式碼,詳情請參閱 19.2.4.4
{! 字串 }插入一個對元素的交叉引用(有關交叉引用的語法,請參閱 19.2.4.2 節)。
{{! 字串 } 行內文字 }插入一個帶有給定文字的交叉引用。
{!modules: 字串 字串 ... }為給定的模組名稱插入索引表。僅在 HTML 中使用。
{!indexlist} 插入一個指向各個索引(類型、值、模組等)的連結表。僅在 HTML 中使用。
{^ 行內文字 }將文字設定為上標。
{_ 行內文字 }將文字設定為下標。
跳脫字串按原樣排版給定的字串;特殊字元(’{’、’}’、’[’、’]’ 和 ’@’)必須使用 ’\’ 跳脫


2.4.1 列表格式

列表::= 
  { {-行內文字} }+
  { {li行內文字} }+

列表和編號列表存在快捷語法

(** Here is a {b list}
- item 1
- item 2
- item 3

The list is ended by the blank line.*)

等同於

(** Here is a {b list}
{ul {- item 1}
{- item 2}
{- item 3}}
The list is ended by the blank line.*)

編號列表可以使用相同的快捷方式,使用 ’+’ 而不是 ’-’。請注意,在巢狀列表中,只能使用此快捷方式定義一個列表。

2.4.2 交叉引用格式

交叉引用是完整限定的元素名稱,如範例 {!Foo.Bar.t} 所示。這是一個模糊的引用,因為它可能表示類型名稱、值名稱、類別名稱等。可以使用 {!type:Foo.Bar.t} 來明確表示預期的語法類別,以指定類型,並使用 {!val:Foo.Bar.t} 來表示同名的值。

可能的語法類別列表如下

標籤語法類別
模組模組
模組類型模組類型
類別類別
類別類型類別類型
類型類型
例外例外
屬性屬性
方法類別方法
章節ocamldoc 章節
常數變體建構子
記錄欄位記錄欄位

對於變體建構子或記錄欄位,建構子或欄位名稱之前應加上對應的類型名稱,以避免多個類型具有相同建構子名稱的歧義。例如,類型為 tree 的建構子 Node 將被引用為 {!tree.Node}{!const:tree.Node},或者可能從模組外部引用為 {!Mod1.Mod2.tree.Node}

2.4.3 首句

在值、類型、例外、模組、模組類型、類別或類別類型的描述中,*首句* 有時用於索引,或當只需要部分描述時。首句由描述的第一個字元組成,直到

在下列文字格式設定之外:{ul 列表 }{ol 列表 }[ 字串 ]{[ 字串 ]}{v 字串 v}{% 字串 %}{! 字串 }{^ 文字 }{_ 文字 }

2.4.4 特定目標格式

{%foo: ... %} 內的內容是特定於目標的,並且僅由後端 foo 解釋,而其他後端則忽略。發行版的後端為 latexhtmlteximan。如果未指定目標(語法 {% ... %}),則預設選擇 latex。自訂產生器可以支援其自己的目標前綴。

2.4.5 可辨識的 HTML 標籤

可以使用 HTML 標籤 <b>..</b><code>..</code><i>..</i><ul>..</ul><ol>..</ol><li>..</li><center>..</center><h[0-9]>..</h[0-9]>,分別代替 {b ..}[..]{i ..}{ul ..}{ol ..}{li ..}{C ..}{[0-9] ..}

2.5 文件標籤 (@-tags)

預定義標籤

下表列出預定義的 @-tags 及其語法和含義。

@author 字串元素的作者。每個 @author 標籤一個作者。同一個元素可以有多個 @author 標籤。
@deprecated 文字文字 應描述元素何時被棄用、要使用什麼替代方案,以及可能被棄用的原因。
@param id 文字將給定的描述(文字)與給定的參數名稱 id 關聯。此標籤用於函式、方法、類別和函子。
@raise Exc 文字說明元素可能會引發例外 Exc
@return 文字描述傳回值及其可能的值。此標籤用於函式和方法。
@see < URL > 文字新增一個對 URL 的參考,並以給定的 文字 作為註解。
@see '檔案名稱' 文字新增一個對給定檔案名稱(寫在單引號之間)的參考,並以給定的 文字 作為註解。
@see "document-name" text新增一個參照至指定文件名稱(寫在雙引號之間)的連結,並以指定的 text 作為註解。
@since string指出該元素是在何時被引入的。
@before version text將給定的描述 (text) 與給定的 version 關聯,以記錄相容性問題。
@version string該元素的版本號。

自訂標籤

你可以在文件註解中使用自訂標籤,但如果所使用的產生器無法處理它們,則它們不會有任何作用。要使用自訂標籤,例如 foo,只需在註解中加入 @foo 並帶有一些文字,如下所示:

(** My comment to show you a custom tag.
@foo this is the text argument to the [foo] custom tag.
*)

若要處理自訂標籤,您需要定義一個自訂產生器,如第 19.3.2 節所述。

3 自訂產生器

OCamldoc 的運作分為兩個步驟:

  1. 分析原始碼檔案;
  2. 透過文件產生器產生文件,該產生器是 Odoc_args.class_generator 類別的物件。

使用者可以提供他們自己的文件產生器,在步驟 2 中使用,而不是預設的產生器。在分析步驟中檢索的所有資訊都可以透過 Odoc_info 模組取得,該模組可以存取所有表示給定模組中找到的元素及其相關描述的類型和函式。

您可以用來定義自訂產生器的檔案安裝在 OCaml 標準程式庫的 ocamldoc 子目錄中。

3.1 產生器模組

產生器模組的類型取決於產生的文件類型。以下是產生器模組類型的清單,以及模組中產生器類別的名稱:

也就是說,要定義一個新的產生器,必須實作一個具有預期簽名的模組,以及給定的產生器類別,並提供 generate 方法作為入口點,以便讓產生器為給定的模組列表產生文件。

        method generate : Odoc_info.Module.t_module list -> unit

此方法將使用已分析並可能合併的 Odoc_info.t_module 結構列表來呼叫。

建議繼承與您要定義的產生器相同種類的當前產生器。這樣做,就可以載入各種自訂產生器,以結合每個產生器帶來的改進。

這是使用 first class modules(請參閱 12.5 章節)完成的。

定義自訂產生器最簡單的方法是遵循以下範例,這裡擴展了目前的 HTML 產生器。我們不必知道這是 ocamldoc 中定義的原始 HTML 產生器,還是已經被先前載入的自訂產生器擴展過。

module Generator (G : Odoc_html.Html_generator) =
struct
  class html =
    object(self)
      inherit G.html as html
      (* ... *)

      method generate module_list =
        (* ... *)
        ()

      (* ... *)
  end
end;;

let _ = Odoc_args.extend_html_generator (module Generator : Odoc_gen.Html_functor);;

要了解要覆寫哪些方法和/或哪些方法可用,請查看不同的基礎實作,具體取決於您要擴展的產生器種類:

3.2 處理自訂標籤

讓自訂產生器處理自訂標籤(請參閱 19.2.5)非常簡單。

適用於 HTML

以下是如何開發一個處理自訂標籤的 HTML 產生器。

Odoc_html.Generator.html 類別繼承自 Odoc_html.info 類別,其中包含一個名為 tag_functions 的欄位,該欄位是一個由自訂標籤(例如 "foo")和一個接受 text 並傳回 HTML 程式碼(類型為 string)的函式組成的配對列表。要處理一個新的標籤 bar,請擴展目前的 HTML 產生器並完成 tag_functions 欄位。

module Generator (G : Odoc_html.Html_generator) =
struct
  class html =
    object(self)
      inherit G.html

      (** Return HTML code for the given text of a bar tag. *)
      method html_of_bar t = (* your code here *)

      initializer
        tag_functions <- ("bar", self#html_of_bar) :: tag_functions
  end
end
let _ = Odoc_args.extend_html_generator (module Generator : Odoc_gen.Html_functor);;

Odoc_html.info 類別的另一個方法將尋找與自訂標籤相關聯的函式,並將其應用於給定標籤的文字。如果沒有函式與自訂標籤相關聯,則該方法會在 stderr 上印出警告訊息。

適用於其他產生器

您可以使用相同的方式處理其他種類的產生器。

4 新增命令列選項

命令列分析會在載入包含文件產生器的模組之後執行,因此允許將命令列選項新增至現有的選項列表中。可以使用以下函式新增選項:

        Odoc_args.add_option : string * Arg.spec * string -> unit

注意:可以使用此函式重新定義現有的命令列選項。

4.1 編譯與使用

在一個檔案中定義自訂產生器類別

假設 custom.ml 是定義新產生器類別的檔案。custom.ml 的編譯可以透過以下命令執行:

        ocamlc -I +ocamldoc -c custom.ml

建立檔案 custom.cmo,並可透過以下方式使用:

        ocamldoc -g custom.cmo other-options source-files

選擇 ocamldoc 的內建產生器的選項(例如 -html)如果使用 -g 提供相同種類的自訂產生器,則不起作用。如果種類不符,則使用選定的內建產生器,而忽略自訂產生器。

在多個檔案中定義自訂產生器類別

可以在多個模組中定義產生器類別,這些模組定義在多個檔案 file1.ml[i]、file2.ml[i]、...、filen.ml[i] 中。必須建立一個 .cma 程式庫檔案,其中包含所有這些檔案。

以下命令會從檔案 file1.ml[i]、...、filen.ml[i] 建立 custom.cma 檔案:

ocamlc -I +ocamldoc -c file1.ml[i]
ocamlc -I +ocamldoc -c file2.ml[i]
...
ocamlc -I +ocamldoc -c filen.ml[i]
ocamlc -o custom.cma -a file1.cmo file2.cmo ... filen.cmo

然後,以下命令會使用 custom.cma 作為自訂產生器:

        ocamldoc -g custom.cma other-options source-files