Ddoc文档注释学习笔记

Ddoc学习笔记

ddoc的英文文档在:
http://www.digitalmars.com/d/ddoc.html

D语言可以在代码中嵌入文档注释(以下称文档)。
它不仅仅是注释,而且还是一段可供阅读的文档。
这样做的好处是,在开发、维护代码的时候,就能同时维护文档。
对于程序员,写文档比写代码还痛苦;写注释倒是一个大家还可以接受的事情。
在写代码的时候,顺便把文档写了,也许能改善一下文档不全的问题。
个人挺喜欢这样方式的。至于太团队项目开发中有没有效果。
因为还没有实践过,不敢乱做评判。


文档有以下几个步骤处理:
[list=1]
[*]词法 文档注释被 附加的记号 标识..
[*]解析 文档注释 被关联到 特殊的定义和组合
[*]段落 每个文档注释 被 分解到一个段落的序列
[*]处理特定的节.
[*]非特殊的段落完成后高亮显示.
[*]合并模块中的所有段落.
[*]在最终结果执行宏文本替换.
[/list]

下面按照这个顺序来展开;

推荐先熟悉文档的写法,一般编译方法,常用节;和学习使用Candydoc;
其他内容可以后期在看;


[b][size=14]文档的语法[/size][/b]

从一个最简单的程序开始吧:

[code]
/**
* 这个一个Ddoc文档例子
*
* Authors: Dehong Liu
* Date: 2007年8月13日
*/

void main()
{
}
[/code]
注意注释符号 /**,和单词Authors/Date。

编译这个文件(a1.d),并且生成文档doc1/a1.html
[code]
dmd -Dddoc1 a1.d # -DdXXX 指定文档生成路径为XXX
[/code]
用浏览器打开这个html文件,看起来像下面这样【见附件 doc1/a1.html】:
[code]
a1

void main();
这个一个Ddoc文档例子

Authors:
Dehong Liu

Date:
2007年8月13日

-------------------------------------------------------------
Page generated by Ddoc.
[/code]
看着很奇怪?这只是个开始。至少明白了哪些写法会变成文档,表现形式和怎么生成。

现在一个个开始解释。
文档有下面三种写法:
[code]
/** ... */ / 后面两个*
/++ ... +/ / 后面两个+
/// 三个 /
[/code]

下面有一个完整的文档写法例子(a2.d):
[code]
/// 这是一个行文档注释

/** 这也是 */

/++ 同样 +/

/**
这是一个摘要文档
*/

/**
* 开头的* 不是文档的一部分
*/

/*********************************
在 /** 后面的连续的*,
不是文档的一部分
*/

/++
这也是一个摘要文档
+/

/++
+ 开头的+ 不是文档的一部分
+/

/+++++++++++++++++++++++++++++++++
在 /++ 后面的连续的+,
不是文档的一部分
上面的斜杠是中文符号,避免语法错误

换行:注意上面的空行
+/

/*********** 前面连续的*号不是,这部分*****是文档,后面的又不是 *****************/

module a2;

[/code]

输出的html结果【见附件 doc1/a2.html】:
[code]
a2
这是一个行文档注释

这也是

同样


这是一个摘要文档


开头的* 不是文档的一部分


在 /** 后面的连续的*, 不是文档的一部分


这也是一个摘要文档


开头的+ 不是文档的一部分


在 /++ 后面的连续的+, 不是文档的一部分 上面的斜杠是中文符号,避免语法错误

换行:注意上面的空行

前面连续的*号不是,这部分*****是文档,后面的又不是
[/code]


[b][size=14]文档和申明关联[/size][/b]

每一个文档都和一个申明(declaration)相关联:
[quote]
1. 如果某单行文档的最左边是空格,它就和下面的申明关联
2. 多个关联到同一个申明的文档会被连接在一起
3. 没有关联到申明的文档会被忽略
4. 在module申明前的所有文档会被应用到整个模块
5. 如果文档出现在申明的右边,则关联到它
6. 如果文档只是ditto,则应用上一个申明的文档
7. 如果一个申明没有文档,则不会出现在html输出中,要出现,可以写一个空的文档,如 ///
[/quote]

看一个例子吧:
[code]
/**
* 整个模块的文档
*/

module a3;

int a; /// a;的文档,b没有文档
int b;

/** c和d的文档 */
/** 再添加些c和d的文档的文档 */
int c;
/** ditto */
int d;

/** e和f的文档 */ int e;
int f; /// ditto

/** g的文档 */
int g; /// 在添加点g的文档

/// C和D的文档
class C
{
int x; /// C.x的文档

/** C.y 和 C.z的文档 */
int y;
int z; /// ditto
}

/// ditto
class D
{
}

int h; // 只有注释,没有文档,不会出现在html中

// 下面是空文档
int j; ///

/// 被忽略的文档
[/code]

看起来像这样【见附件 doc1/a3.html】
[code]
a3
整个模块的文档

int a;
a;的文档,b没有文档

int c;
int d;
c和d的文档

再添加些c和d的文档的文档

int e;
int f;
e和f的文档

int g;
g的文档

在添加点g的文档

class C;
class D;
C和D的文档

int x;
C.x的文档

int y;
int z;
C.y 和 C.z的文档

int j;
[/code]


[b][size=14]文档的节[/size][/b]

a1.d例子中的Authors / Date 就是节(Sections)。
节由 "非空格字符" + ":" 组成,其中标识符部分叫节名,它不区分大小写

[b]概要(Summary):[/b]
第一个节就是概要,它没有节名;
它是第一个段落,遇到空行或者节名结束;
可以把概要写成多行,但写成一行比较好
概要节是可选的

[b]描述(Description):[/b]
第二个没有名字的节 是描述
遇到一个节名或者到文档的结束

给个例子(a4.d):
[code]
/***********************************
* 这是一个概要(Brief summary)
* 描述myfunch函数的使用;这两行形成一个概要节
*
* 描述节的第一个段落
*
* 还是描述节:
* 可以写更多内容
*/

void myfunc() { }
[/code]
html输出【见附件 doc1/a4.html】:
[code]
void myfunc();
这是一个概要(Brief summary) 描述myfunch函数的使用;这两行形成一个概要节

描述节的第一个段落

还是描述节: 可以写更多内容
[/code]


[b][size=14]标准节[/size][/b]

有一些预定义好了的节,看看它们的意思:
[list]
[*][b]Authors:[/b] 列出作者名字
[*][b]Bugs:[/b] 列出已知BUG
[*][b]Date:[/b] 列出当前修订的时间,应当是 std.date 能解析的形式
[*][b]Deprecated:[/b] 做 "抗议"标记(?弃用标记)--最好给出理由和纠正的方法
[*][b]Examples:[/b] 例子
[*][b]History:[/b] 修订历史
[*][b]License:[/b] 版权申明
[*][b]Returns:[/b] 解释函数的返回值;如果返回void,就不要写在文档中了
[*][b]See_Also:[/b] 列出相关符号,或者URL链接
[*][b]Standards:[/b] 如果申明涉及到某个标准,在此描述
[*][b]Throws:[/b] 列出在哪些环境下会抛出异常
[*][b]Version:[/b] 指定当前申明的版本号
[*][b]See_Also:[/b] 列出相关符号,或者链接
[*][b]See_Also:[/b] 列出相关符号,或者链接
[/list]

特殊节:一些有特殊含义和语法的节
[list]
[*][b]Copyright:[/b] 版权申明。如果是在module申明中,该节会被COPYRIGHT宏替换;
[*][b]Params:[/b] 函数的参数描述文档;
"标识符 =' 开始一个新的参数描述;它可以跨越多行
[*][b]Macros:[/b] 和Params节有类似的语法;它是一系列 NAME=value 组成
NAME 是宏名,VALUE是要替换成的文字
[/list]

全部列出来看看:
[code]
/** Copyright: Public Domain */

module a5;

/**
* Authors: Melvin D. Nerd, melvin@mailinator.com
*
* Bugs: Doesn't work for negative values.
*
* Date: March 14, 2003
*/

void foo1() {}

/**
* Deprecated: superseded by function bar().
*/

deprecated void foo2() { }

/**
* Examples:
* --------------------
* writefln("3"); // writes '3' to stdout
* --------------------
*
* History:
* V1 is initial version
*
* V2 added feature X
*
* License: use freely for any purpose
*/

void bar() { }

/**
* Read the file.
* Returns: The contents of the file.
*/

void[] readFile(char[] filename) { return "filename"; }

/**
* See_Also:
* foo, bar, http://www.digitalmars.com/d/phobos/index.html
*
* Standards: Conforms to DSPEC-1234
*
* Throws: WriteException on failure.
*
* Version: 1.6a
*/

void writeFile(char[] filename) { }

// 特殊节

/***********************************
* foo does this.
* Params:
* x = is for this
* and not for that
* y = is for that
*/

void foo(int x, int y)
{
}

/**
* Macros:
* FOO = now is the time for
* all good men
* BAR = bar
* MAGENTA = <font color=magenta></font>
* COPYRIGHT = 版权归热爱地球的火星人所有
*/

/**
* Foo: $(FOO)
* Bar: $(BAR)
* MAGENTA: $(MAGENTA)
* Copyright: Public Domain
*/
void foo3() { }

[/code]
输出效果是【见附件doc1/a5.html】:
[code]
a5

void foo1();
Authors:
Melvin D. Nerd, melvin@mailinator.com

BUGS:
Doesn't work for negative values.

Date:
March 14, 2003

deprecated void foo2();
Deprecated:
superseded by function bar().

void bar();
Examples:

writefln("3"); // writes '3' to stdout


History:
V1 is initial version

V2 added feature X

License:
use freely for any purpose

void[] readFile(char[] filename);
Read the file.

Returns:
The contents of the file.

void writeFile(char[] filename);
See Also:
foo, bar, http://www.digitalmars.com/d/phobos/index.html

Standards:
Conforms to DSPEC-1234

Throws:
WriteException on failure.

Version:
1.6a

void foo(int x, int y);
foo does this.

Params:
int x is for this and not for that
int y is for that

void foo3();
Foo:
now is the time for all good men

Bar:
bar

MAGENTA:
<font color=magenta></font>

Copyright:
Public Domain

Page generated by Ddoc. 版权归热爱地球的火星人所有
[/code]

上面的例子都还好理解,把不容易理解的说说:
/** Copyright: Public Domain */ 在module申明前和后的效果不一样;
前者的效果在哪里?看页面的最后一行

代码的文档是这么写的:
[code]
* Examples:
* --------------------
* writefln("3"); // writes '3' to stdout
* --------------------
[/code]
代码的上下有一条分割线:至少三个连字符(-)

[b][size=14]文档的高亮处理[/size][/b]

[b]内嵌注释 Embedded Comments[/b]
不懂

[b]内嵌代码 Embedded Code[/b]
上面已经演示了

[b]内嵌的HTML Embedded HTML[/b]
内嵌的HTML代码不会被转译,直接输出给html文件
虽然如此,基于某些原因(我没看懂),还是最好不要用html
[code]
/** Example of embedded HTML:
*
* <li> <a href="http://www.digitalmars.com">Digital Mars</a> </li>
* <li> <a href="http://www.classicempire.com">Empire</a> </li>
*/
[/code]

[b]强调 Emphasis[/b]
函数参数等标识符会被以斜体,粗体,超链接等形式强调处理;具体形式文档没有说

[b]特殊符号Character Entities[/b]
< > & 有特殊含义,如果要使用这3个符号,换成相应的:< > &
以下情况除外:在代码节中;不是立即跟一个 # 或 字母

[b][size=14]文档的宏[/size][/b]

宏来自于下面这些地方,并按照特定步骤处理:
[list=1]
[*]预定义宏
[*]sc.ini配置文件中的DDOCFILE项指定的文件
[*]命令行指定的*.ddoc文件
[*]Ddoc运行时产生的定义,如BODY,TITLE
[*]文件中的宏节
[/list]

宏主要用在对文档格式的自定义上。
通过修改宏,能自定义HTML输出格式。

[b][size=14]CandyDoc的使用[/size][/b]

dmd默认的格式很简单,可以使用CandyDoc来美化文档格式和增强功能。
使用方法很简单:(.ddoc是宏文件的后缀)
下载CandyDoc程序
主页:http://www.dsource.org/projects/helix/wiki/CandyDoc
下载:http://svn.dsource.org/projects/helix/downloads/candydoc-0.80.zip

假设要编译: a5.d doc2/candydoc
[code]
dmd -c -Dddoc2 a5.d doc2/candydoc/*.ddoc
[/code]
生成的a5.html文件在 doc2/目录下,和candydoc一个目录,如果不是同一目录,会显示不正常;

candydoc有2个.ddoc文件:candy.ddoc modules.ddoc
如果要定义样式,在candy.ddoc中定义,一般不改;
modules.ddoc 要修改成自己的模块,默认是:
[code]
MODULES =
$(MODULE helix.basic)
$(MODULE helix.color)
$(MODULE helix.config)
$(MODULE helix.linalgebra)
[/code]

以上面的5个程序为例:
[code]
MODULES =
$(MODULE a.a1)
$(MODULE a.a2)
$(MODULE a.a3)
$(MODULE a.a4)
$(MODULE a.a5)
[/code]
编译之:
[code]
dmd -c -Dddoc2 a1 a2 a3 a4 a5.d doc2/candydoc/*.ddoc
[/code]

如果要用Candydoc替换默认的文档格式,这么做:
修改dmd.conf文件,添加一行:
DDOCFILE=candy.ddoc
看起来像这样
[code]
[Environment]
DFLAGS=-I%@P%/../src/phobos -L-L%@P%/../lib -L-L/usr/lib -L-L/usr/local/lib -version=Phobos
DDOCFILE=candy.ddoc
[/code]

上面的配置只写了candy.ddoc文件,没有写module.ddoc。所以编译的时候要添加module.ddoc,这样做很不爽;
我的办法是自己写一个.ddoc文件--proj.ddoc
把candydoc.ddoc和 module.ddoc两个文件合并在一起

[模块部分的导航要求所有的html都在一个目录下,这点还没有仔细研究,回头再写]

注意,如果没有效果,检查:
1. Linux是修改dmd.conf文件;Windows是修改sc.ini文件;不要弄错了
2. dmd.conf 可能在多个地方:/etc 或 dmd命令所在目录等
3. candy.doc是相对于当前目录而已,不是dmd.conf文件;请按照实际情况设定路径


文档用起来还算简单,开始会不习惯,慢慢就习惯了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值