第 19 章 文档生成器 (ocamldoc)

本章介绍 OCamldoc,它是一个从源文件中嵌入的特殊注释生成文档的工具。OCamldoc 使用的注释格式为 (***),其格式如第 19.2 节所述。

OCamldoc 可以生成多种格式的文档:HTML、LATEX、TeXinfo、Unix 手册页和 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 显示和处理。您可以从 https://graphviz.cpp.org.cn/ 获取 dot 工具。图的文本表示形式写入 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 directory
directory 添加到用于搜索已编译接口文件 (.cmi 文件) 的目录列表中。
-H directory
-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 工具保留,但与任何元素都不关联。 这些注释中的 @-tags 将被忽略。 *) (*******************************************************************) (** 像上面的注释,带有两个以上星号的注释将被忽略。 *) (** 函数 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 停止特殊注释

特殊注释 (**/**) 告诉 OCamldoc 丢弃此注释之后的元素,直到当前类、类类型、模块或模块类型的结束,或直到下一个停止注释。 例如

class type foo = object (** 方法 m 的注释 *) method m : string (**/**) (** 此方法不会出现在文档中 *) method bar : int end (** 此值出现在文档中,因为类中的停止特殊注释不会影响类的父模块。 *) val foo : string (**/**) (** 值 bar 不会出现在文档中。 *) val bar : string (**/**) (** 类型 t 出现,因为在文档中,因为前面的停止注释关闭了“无文档模式”。 *) type t = string

ocamldoc-no-stop 选项会导致忽略停止特殊注释。

2.3 文档注释的语法

文档注释 (***) 的内部包含自由格式的文本,其中包含可选的格式化注释,后跟可选的 _tags_,这些 _tags_ 提供有关参数、版本、作者等的更具体信息。 _tags_ 由前导的 @ 字符区分。 因此,文档注释具有以下形状

(** 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
*)

某些元素仅支持所有 @-tags 的子集。 与所记录元素无关的 _tags_ 将被简单地忽略。 例如,在记录类型构造函数、记录字段和类继承子句时,所有 _tags_ 都将被忽略。 同样,类实例变量上的 @param _tag_ 将被忽略。

最后,(**) 是空的文档注释。

2.4 文本格式

以下是用于格式化文本描述的简单标记语言的 BNF 语法。

text::= {text-element}+
 
inline-text::= {inline-text-element}+
 
text-element::=
inline-text-element 
blank-line强制换行。


inline-text-element::=
{ { 09 }+ inline-text }text 格式化为节标题;紧随 { 后的整数表示节的级别。
{ { 09 }+ : label inline-text }相同,但还将名称 label 与当前点相关联。 此点可以通过其完全限定的标签在 {! 命令中引用,就像任何其他元素一样。
{b inline-text }text 设置为粗体。
{i inline-text }text 设置为斜体。
{e inline-text }强调 text
{C inline-text }居中 text
{L inline-text }左对齐 text
{R inline-text }右对齐 text
{ul list }创建一个列表。
{ol list }创建一个编号列表。
{{: string } inline-text }在给定的 text 上添加一个指向给定地址(以 string 格式给出)的链接。
[ string ]将给定的 string 设置为源代码样式。
{[ string ]}将给定的 string 设置为预格式化的源代码样式。
{v string v}将给定的 string 设置为逐字显示样式。
{% string %}目标特定内容(默认情况下为 LATEX 代码,详情请参见 19.2.4.4
{! string }插入对元素的交叉引用(有关交叉引用的语法,请参见 19.2.4.2 节)。
{{! string } inline-text }插入带有给定文本的交叉引用。
{!modules: string string ... }插入给定模块名称的索引表。仅在 HTML 中使用。
{!indexlist} 插入指向各种索引(类型、值、模块等)的链接的表。仅在 HTML 中使用。
{^ inline-text }将文本设置为上标。
{_ inline-text }将文本设置为下标。
escaped-string按原样排版给定的字符串;特殊字符(’{’,’}’,’[’,’]’ 和 ’@’)必须通过 ’\’ 转义。


2.4.1 列表格式

list::= 
  { {-inline-text} }+
  { {liinline-text} }+

列表和编号列表存在快捷语法

(** 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} 来指定具有相同名称的值,以明确所需的语法类别。

可能的语法类别的列表如下

tag语法类别
modulemodule
modtype模块类型
classclass
classtype类类型
valvalue
typetype
exceptionexception
attributeattribute
method类方法
sectionocamldoc section
const变体构造函数
recfield记录字段

在变体构造函数或记录字段的情况下,构造函数或字段名称应以相应类型的名称为前缀,以避免多个类型具有相同构造函数名称的歧义。例如,类型 tree 的构造函数 Node 将被引用为 {!tree.Node}{!const:tree.Node},或者可能从模块外部引用为 {!Mod1.Mod2.tree.Node}

2.4.3 首句

在对值、类型、异常、模块、模块类型、类或类类型的描述中,首句 有时用于索引,或者在只需要描述的一部分时使用。首句由描述的第一个字符组成,直到

在以下文本格式之外:{ul list }{ol list }[ string ]{[ string ]}{v string v}{% string %}{! string }{^ text }{_ text }

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 string元素的作者。每个 @author 标签对应一个作者。同一个元素可能有多个 @author 标签。
@deprecated texttext 应描述元素何时被弃用,使用什么作为替代,以及可能的原因。
@param id text将给定的描述(text)与给定的参数名称 id 关联。此标签用于函数、方法、类和函子。
@raise Exc text解释元素可能会引发异常 Exc
@return text描述返回值及其可能的值。此标签用于函数和方法。
@see < URL > text添加指向 URL 的引用,并使用给定的 text 作为注释。
@see 'filename' text添加指向给定文件名(用单引号括起来)的引用,并使用给定的 text 作为注释。
@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 结构列表进行调用。

建议从与要定义的相同类型的当前生成器继承。这样做,可以加载各种自定义生成器,以结合每个生成器带来的改进。

这是使用一等模块完成的(参见第 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

如果使用 -g 提供了相同类型的自定义生成器,则选择内置生成器的选项(例如 -html)将不起作用。如果类型不匹配,则使用所选的内置生成器,而忽略自定义生成器。

在多个文件中定义自定义生成器类

可以在多个模块中定义生成器类,这些模块定义在多个文件 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