最近因为服务端的一些变故, 需要一份客户端与服务器交互的 api 文档. 首先肯定是要排除掉手写的, api 文档这货肯定是要自动生成啦, 要不以后维护起来得死人的.

项目前端是使用 quick-cocos2d-x 来开发的, 开发语言是 lua, 找了一下 lua 的文档生成工具, 貌似只有 LuaDoc 和 LDoc 可以选. LuaDoc 已经好几年没有人维护了, 加上 LDoc 可以兼容 LuaDoc 的文档, 所以就定了 LDoc.

一. 安装

因为 LDoc 依赖与 penlight 和 lfs , 所以使用 luarocks 来安装是最简单的, 不然自己还得处理依赖. 因此我们需要先安装 luarocks.

1. 安装luarocks

如果已经安装过了的话,可以跳过这一步.

1.1 通过 homebrew 安装

通过 homwbrew 安装是最简单的, 只需要 brew update 和 brew install luarocks 两步就可以啦! 不过 brew update 等待的时间可能会比较久, 耐心不够的话可以尝试从源码安装.

1.2 通过源码安装

1). 从这里下载最新版的 luarocks 源文件, 解压.

2). 打开终端, cd 到刚才解压的目录.

3). 键入 ./configure

这一步的话比较诡异, 我在公司装的时候各种问题, 在家里装就没有问题. 比如出现了这个:

Looking for Lua…
lua not found in $PATH.
You may want to use the flags –with-lua, –with-lua-bin and/or –lua-suffix. See –help.
configure failed.

这是没有找到lua的原因, 确保你安装了lua, 可以通过which lua来找到lua的安装路径. 然后用--with-lua-bin 参数传给configure, 如:

1
./configure --with-lua-bin=/usr/local

Could not find a downloader helper program. Tried: curl wget fetch.
Make sure one of them is installed and available in your PATH.
configure failed.

其实我也不知道为什么会抽这个风, curl 和 wget 我都有安装的, 用 --with-downloader 指定一下就ok了, 如:

1
./configure --with-lua=/usr/local --with-downloader=wget

Could not find a MD5 checksum calculator. Tried: md5sum openssl md5.
Make sure one of them is installed and available in your PATH.
configure failed.

额, 还是指定一下 --with-md5-checker 吧!

1
./configure --with-lua=/usr/local --with-downloader=wget --with-md5-checker=md5

4). 键入 make build

5). 键入 make install

如果一切正常的话, 那么就安装成功了. 可以通过键入 luarocks 来检测.

2. 安装 LDoc

安装好 luarocks 之后, 安装 LDoc 是非常简单的, 只需要:

1
luarocks install ldoc

就可以了, luarocks 会自动帮你安装依赖项. 安装好之后在终端键入 ldoc -h, 如果出现下面这个, 则代表安装成功!

1
ldoc, a documentation generator for Lua, vs 1.4.3
...

二. 概览

让我们先通过一个简单的测试来了解下 ldoc , 先创建一个目录, 在目录下创建一个 test.lua 文件, 将下面的内容复制到里面:

1
--- a test module
-- @module test

local test = {}

--- this is a function
-- @string param1 this is param1
-- @int param2 this is param2
-- @return a string value
function test.my_module_function_1(param1, param2)
	return param1 .. param2
end

return test

然后在这个目录下打开终端, 键入 ldoc test.lua, 一切正常的话, 会在当前目录下生成一个名为 doc 文件夹, 打开 doc/index.html 文件, 会看到下面这样的东西.

虽然很丑陋, 但也还不错, 该有的都有. 我们仔细看一下这个测试, 总体由 test 模块 和 my_module_function_1 函数 2部分组成. 它们都是以 --- 开始的, 这是 ldoc 的一个规则, 只有以 --- 开始的注释才会被 ldoc 解析, 这样就可以排除掉普通的注释信息. @module 是一个特殊的标签, 后面跟着模块的名字, 但其实这个标签是可选的, 没有的话默认会以文件名来定义模块名.

类似的标签还有很多, 我们在下面会一一说明.

三. 详解

1. 标签

  • @module 模块, 一般一个文件就是一个模块.
  • @classmod 和 @module 类似, 但是用来描述 class, 用这个标签后, 生成的文档中 Module 文字会变成 Class.
  • @submodule 如果一个模块的内容被分到了好几个文件中, 那么就可以再其他文件中用 submodule 来定义, 后面跟上master module的名字.
  • @script 和 @module 类似, 生成的文档中 Module 文字会变成 Script.

以上几个标签都是project-level, 意味着每个文件中只能包含它们其中的一个, 否则生成时就会提示 Module already declared! 错误.

  • @author (multiple), @copyright, @license, @release 这几个啥意思就不必说了吧, 值得一提的是它们必须放在project-level,如 @module 标签下.

  • @function, @lfunction. 用来描述函数. @function 一般情况下不用加, 只需要给函数加上---注释就可以. @lfunction 用来表示一个局部函数, 但是ldoc默认是不会导出局部变量和函数的.

  • @param @int, @string, @bool, @func, @tab, @thread 用来描述函数参数, 后面几个指定了参数类型.
  • @return 函数的返回值, 函数的返回值可能有多种, 因此 @return 在一个函数中也是可以多次使用的
  • @raise 这个函数可能抛出的错误
  • @local 最大的作用是使得一个函数不被导出, 除非使用了(unless –all)
  • @see 引用文档的其他内容, 同一模块的话直接 @see xxx, 不同模块的话需要加上模块名 @see xxmodule.xxfunc
  • @usage 给出函数的用例, 可以分多行来写
  • @fixme, @todo 和 @warning , 意思大家应该都懂. 但是必须在函数体内部并且以 --- 开头才能生效.

以上几个标签都是描述function的一些行为的

  • @table 描述一个table, 也可以不加, 只需要给table加上---注释就可以.
  • @field 用来描述table中的一个字段

  • @section 用来把一个模块分隔成好几块

  • @type 和 @class 的作用差不多, 但不能与 @class 同时存在. 一个文件中可以有多处 @type , 会和 @section 似得吧文件分隔成好多份.
  • @within 用来形容函数和table, 指定它们属于哪个section, 可以指定不存在的一个section, 会自动创建一个

哈哈, 以上就是所有的标签啦, 虽然比较多, 但是有很多都不怎么常用, 所以还是很好理解的.

2. 对于函数的一些高级用法

2.1 显示参数的类型

这个前面有提过, @param 是不指明具体类型的, 若想指明的话可以用 @int, @string, @bool, @func, @tab, @thread 几个标签来.

2.2 可选参数与默认值

可选参数的标记是自参数标签后紧跟 [opt] 来标识, 默认值则是 [opt=xx]. 让我们看一个官方的示例:

1
2
3
4
5
6
7
8
9
--- a function with typed args.
-- @string name person's name
-- @int age
-- @string[opt='gregorian'] calender optional calendar
-- @int[opt=0] offset optional offset
-- @treturn string
function one (name,age,...)
end
----> displayed as: one (name, age [, calender='gregorian' [, offset=0]])

2.3 多种返回值

一个函数不同的情况可能返回不同的值, 意义也都不一样, 那么怎么来表示呢? 答案是在 @return 后紧跟 [x](x可以是1,2,3,…) 来标识. 生成出来的文档是用 Or 来列出这些不同的返回值的.

3. config.ld 的字段说明

ldoc 运行时有一堆参数可以传递, 在终端中去做比较麻烦, 修改也不太方便. 因此我们可以创建一个config.ld 配置文件来做这个事情, ldoc . 表示在当前目前下查找 config.ld 文件, ldoc -c path/to/myconfig.ld <file> 读取特殊的目录的配置文件. 其实 config.ld 就是一个lua文件, 填写时需要遵循lua语法.

config.ld 文件中有一大坨的条目可以选择, 我们来看一下他们都是什么意思吧.

  • file 可以是一个文件名或者目录名, 如: file = 'test.lua'. file 也可以是一个table, 这时里面可以填写文件数组或目录数组, 同时也可以包含另一个特殊的数组 exclude, 表明要排除的文件或目录
  • project 项目的名称, 会出现在文档的左上角. 默认为 ldoc
  • title 页面的名称, 默认为 Reference
  • all 导出 local 的 function
  • output 导出 html 的名字, 默认是 index
  • dir 导出目录的名字, 默认是 doc
  • colon 使用冒号风格代替 @ 风格的 tag
  • boilerplate 忽略所有源文件中的首个注释(块), 比如: license 注释.
  • ext 输出文件的后缀(默认为 html)
  • one 文档使用单列的布局
  • style, template 指定模板和样式的目录. 在 config.ld 中它也可以为 true , 表示使用和配置文件同一目录的模板.
  • merge 允许文档从不同的文件合并同名的 module , 而不是产生多个module.

其它可选的参数还有很多, 但是都不常用. 大家可以点击这里跳转到官方文档继续查看.


这篇文章到这里就差不多, ldoc 网上的中文资料不是很多, 加上我使用时遇到了一些问题, 因此我写下这篇文章, 主要是帮大家对 ldoc 形成一个大体的印象, 具体细节或者高级功能可能还是得去看官方的文档.

当然有什么问题也欢迎大家评论指出, 多多交流!

附录:

官方文档: 这里
github地址: 这里