javadoc文档注释 qt文档风格哪个好

如何优雅的分析代码 - 推酷
如何优雅的分析代码
当我们来接手一个别人的工程时,阅读别人的代码是一件很痛苦的事。成千上百的函数,糟糕的代码风格,不知所云的注释,这些都是让人抓狂。那么,问题就来了: 如何优雅地分析别人的代码?
答案就是: Doxygen + Graphviz
整个工作流程很简单,我们在写程序时按照 Doxygen 约定的格式注释代码(不注释也可以),Doxygen 会对代码进行分析,然后列出程序中的变量、类定义、数据结构、函数表用关系等,然后调用 Graphviz 将结果用图形化的形式表现出来。
这个功能在自动生成文档、代码分析时非常强大,下面分别简单介绍一下。
在 Linux 环境下,Vim 有插件 DoxygenToolKIt.vim 可以帮助我们很方便地写出 Doxygen 风格的代码。这里只介绍 Doxygen + Graphviz,DoxygenToolKit.vim 在另外一篇中介绍。
What is Graphviz?
Graphviz is open source graph visualization software. Graph visualization is a way of representing structural information as diagrams of abstract graphs and networks. It has important applications in networking, bioinformatics, software engineering, database and web design, machine learning, and in visual interfaces for other technical domains.
Installation
官方网站上有各个平台(Windows/Unix/Linnux/Mac)的安装文件和源码,在 Ubuntu 13.10 saucy 下,直接使用 apt-get 安装即可:
sudo apt-get install graphviz
更多详细的介绍见官网的 About、Documentation、Wiki、FAQ。
What is Doxygen
Doxygen is the de facto standard tool for generating documentation from annotated C++ sources, but it also supports other popular programming languages such as C, Objective-C, C#, PHP, Java, Python, IDL (Corba, Microsoft, and UNO/OpenOffice flavors), Fortran, VHDL, Tcl, and to some extent D.
简而言之,Doxygen 是一个程序的文件产生工具,可将程序中的特定批注转换成为说明文件。只要我们在写注释的时候按照它制定的规则写,那么它就可以为我们生成漂亮的文档。
Installation
官网上的 Manual 中有详细的介绍,对于不同平台,采用不同的安装方式(从源码编译安装、二进制文件安装),下面仅记录我在 Ubuntu 下使用源码编码的方式安装过程。
下载源代码 git clone https:///doxygen/doxygen.git
cd doxygen
安装 ./configure
make install
安装成功之后,在 /usr/bin/ 或者 /usr/local/bin 目录下可以查看到二进制 doxygen 文件。
若 configure 出错,检查依赖关系,安装需要系统中有 GNU 工具(flex, bison, libiconv and GNU make, and strip)和 Perl 支持。
因为 Doxygen 要调用 Graphviz,所以先安装 Graphviz,然后编译安装 Doxygen
Getting Started
检查 Doxygen 是否支持你项目所使用的语言 Doxygen 支持 C, C++, C#, Objective-C, IDL, Java, VHDL, PHP, Python, Tcl, Fortran, D
创建一个配置文件
Doxygen 使用一个配置文件来工作,,每个项目都应该有一个自己对应的配置文件。我们可以使用 doxygen -g 来让 Doxygen 自动生成一个参考配置文件,然后修改其中个别配置即可.
doxygen -g &config-file& 常用配置:
PROJECT_NAME = &Test Project& 配置项目名称
PROJECT_NUMBER = 1.0 配置项目版本号
OUTPUT_DIRECTORY = ./doxygen-output 配置输出结果目录
OPTIMIZE_OUTPUT_FOR_C = YES 设置针对哪种语言进行优化
EXTRACT_ALL = YES 默认是 NO ,即默认只对有标准注释的文件进行分析。如果我们希望对一个没有按照标准格式注释的项目进行分析,那么就要改为 YES ,这在接手一个旧项目,分析代码时尤其有效。
HAVE_DOT = YES 设置 Doxygen 调用 dot 工具(graphviz 的一部分)
DOT_PATH = /usr/local/graphviz 指定 graphviz 的路径
运行 Doxygen doxygen &config-file&
如果前一步没有指定配置文件的名字的话,直接运行 doxygen 即可。
运行完之后,就可以在指定的输出目录中看到结果,用浏览器可以看到 HTML 版本的结果。
按照 Doxygen 格式注释代码
这一步应该在最前面,即先按照 Doxygen 风格格式注释好代码,然后再进行分析。官网上针对不同的编程语言,有详细的举例说明:
Documenting the code
这部分虽然在最后,事实上应该是第一步,也就是说我们先按照规定添加 Doxygen 风格的注释,然后再配置、调用 Doxygen 来生成文档。
上有详细的注释
,下面是我搬运来学习,自己翻译的。
我们在 C/C++ 风格注释块中加入一些特殊符号,这样 Doxygen 就知道需要把这段注释分析生成在文档中,这样的注释在官网中叫做 Special comment blocks 。下面详细介绍类 C/C++ 语言(C/C++/C#/Objective-C/PHP/Java)的注释,其他语言(Python, VHDL, Fortran, Tcl)见官网。
对于代码中的任何实体( entity ),都有两种注释,它们一起工作,完成注释功能,但至少得有一个:
a brief description :单行的简短注释
a detailed description :多行的详细注释
对于 方法 methods 和 函数 functions ,还有额外的第三种注释:
in body description
对于详细注释(detailed description),可以用以下的几种风格来进行:
JavaDoc Style
即在 C 风格注释块开始使用两个星号 * :
* ... text ...
即在 C 风格注释块开始处添加一个叹号 ! :
* ... text ...
C++ Comment Style
使用连续两个以上的 C++ 注释行组成注释块,并且每行要多写一个 / 或者 ! :
/// ... text ...
/// or //!
//! ... text ...
第四种格式,有的人喜欢让自己的注释更加醒目一些: /////////////////////////////////////////////////
/// ... text ...
/////////////////////////////////////////////////
对于简单注释(brief description),也有以下的几种方案:
可以选用以上其中一种风格,然后加入 \brief 命令来标明 brief 的开始。这种方式以段落的结尾作为结束。所以在 brief 后要写 detailed 的话,需要空一行。
/* \brief Brief description.
Brief description continued.
Detailed description starts here.
如果选择 JavaDoc 的风格,并且在配置文件中设置 JAVADOC_AUTOBRIEF = YES 的话,Doxygen 会自动将第一句话作为 brief description,这个句子以 . + 空格/空行 结束。
/** Brief description which ends at this dot. Details follow
*/ 这种方式对多行的 C++ 特殊注释风格也有效: /// Brief description which ends at this dot. Details follow
第三种方法是使用不多于一行的特殊 C++ 风格注释,下面是两个例子: /// Brief description.
/** Detailed description. */
或者:(这种情况下,必须用空行把 brief 和 detailed 分开,同时 JAVADOC_AUTOBRIEF = NO )
//! Brief description.
//! Detailed description
//! starts here.
Doxygen 和其他的文档系统的一个不同之处就是它允许把注释写在实体的定义(包括全局函数)之前。这样,就可以把注释直接写在源文件里面而不是头文件中,从而使头文件更加紧凑,而且功能的实现人员也更容易阅读注释。 所以,一个折衷方案就是在声明前写 brief description,在定义前写 detailed description。
Putting documentation after members
在注释结构体、类、枚举类型等时,有时习惯将注释写在代码的后面,而不是前面。因为 Doxygen 默认注释是解释后面的代码,所以这时候就需要在注释中添加一个额外的 & 来标明是注释前面的内容。
Qt 风格的注释:
int var; /*!& Detailed description after the member */
int var; /**& Detailed description after the member */
int var; //!& Detailed description after the member
一般来说,我们通常在后面添加的注释都是 brief description 而不是 detailed description,所以更常见的格式如下:
int var; //!& Brief description after the member
int var; ///& Brief description after the member
这种添加 & 的方法只能用在 成员( member )和 参数( parameter )中,不能用在描述文件、类、联合体、名字空间和枚举本身。此外, 在后面提到的结构化命令(如 \class )在这种注释段中是无效的。
官网上提供了一个例子,分别用 Qt 和 JavaDoc 的风格注释一段相同的 C++ 代码:
A test class.
A more elaborate class description.
class Test
//! An enum.
/*! More detailed enum description. */
enum TEnum {
TVal1, /*!& Enum value TVal1. */
TVal2, /*!& Enum value TVal2. */
/*!& Enum value TVal3. */
//! Enum pointer.
/*! Details. */
//! Enum variable.
/*! Details. */
//! A constructor.
A more elaborate description of the constructor.
//! A destructor.
A more elaborate description of the destructor.
//! A normal member taking two arguments and returning an integer value.
\param a an integer argument.
\param s a constant character pointer.
\return The test results
\sa Test(), ~Test(), testMeToo() and publicVar()
int testMe(int a,const char *s);
//! A pure virtual member.
\sa testMe()
\param c1 the first argument.
\param c2 the second argument.
virtual void testMeToo(char c1,char c2) = 0;
//! A public variable.
int publicVar;
//! A function variable.
int (*handler)(int a,int b);
生成的 HTML 网页:http://www.stack.nl/~dimitri/doxygen/manual/examples/qtstyle/html/class_test.html
JavaDoc style:
A test class. A more elaborate class description.
class Test
* An enum.
* More detailed enum description.
enum TEnum {
TVal1, /**& enum value TVal1. */
TVal2, /**& enum value TVal2. */
/**& enum value TVal3. */
*enumPtr, /**& enum pointer. Details. */
/**& enum variable. Details. */
* A constructor.
* A more elaborate description of the constructor.
* A destructor.
* A more elaborate description of the destructor.
* a normal member taking two arguments and returning an integer value.
* @param a an integer argument.
* @param s a constant character pointer.
* @see Test()
* @see ~Test()
* @see testMeToo()
* @see publicVar()
* @return The test results
int testMe(int a,const char *s);
* A pure virtual member.
* @see testMe()
* @param c1 the first argument.
* @param c2 the second argument.
virtual void testMeToo(char c1,char c2) = 0;
* a public variable.
* Details.
int publicVar;
* a function variable.
* Details.
int (*handler)(int a,int b);
生成的 HTML 网页:http://www.stack.nl/~dimitri/doxygen/manual/examples/jdstyle/html/class_test.html
Documentation at other places
我们之前的例子中注释都是在文件、命名空间、类的声明或者定义之前,或者在它们的成员的前/后。虽然一般来说这是很正常的,但是有时候我们需要把代码写在在文档的其他地方。对于文件的注释更是如此,因为对于文件来说,根本就不存在在它之前的地方(&in front of a file&)。
Doxygen 允许你把注释写在任何地方(例外情况是在函数体内 or 在 C 风格注释块内)。你需要付出的代价就是要在注释块内部多写一些结构化命令( structural command )来标明。所以, 一般来说,我们应该尽量避免使用结构化命令,除非是有其他的特殊要求这样做。
结构化命令以一个 \ 或者 @ (JavaDoc 风格)开始,后面接一个命令名字 + 一个(多个)参数。举例如下:
/*! \class Test
\brief A test class.
A more detailed class description.
这个例子中的 \class 指示这个注释块中包含一个 Test 类的文档。其他常用的命名如下:
\structure
\namespace
\interface
完整的命令和说明在这里:
对 C++ 类成员进行注释的时候,必须先注释这个类,对于命名空间来说也是如此。对 C 的全局函数、 typedef、enum、 preprocessor definition 进行注释,必须先注释包含它们的文件(通常是头文件)。
Attention:
在重复一下容易出错的地方: 在注释全局对象时,必须先注释它们所在的文件。 也就是说,必须包含以下两者之一:
/* \file */
/* @file */
下面是官网上的一个 C 头文件的例子:
/*! \file structcmd.h
\brief A Documented file.
/*! \def MAX(a,b)
\brief A macro that returns the maximum of \a a and \a b.
/*! \var typedef unsigned int UINT32
\brief A type definition for a .
/*! \var int errno
\brief Contains the last error code.
\warning Not thread safe!
/*! \fn int open(const char *pathname,int flags)
\brief Opens a file descriptor.
\param pathname The name of the descriptor.
\param flags Opening flags.
/*! \fn int close(int fd)
\brief Closes the file descriptor \a fd.
\param fd The descriptor to close.
/*! \fn size_t write(int fd,const char *buf, size_t count)
\brief Writes \a count bytes from \a buf to the filedescriptor \a fd.
\param fd The descriptor to write to.
\param buf The data buffer to write.
\param count The number of bytes to write.
/*! \fn int read(int fd,char *buf,size_t count)
\brief Read bytes from a file descriptor.
\param fd The descriptor to read from.
\param buf The buffer to read into.
\param count The number of bytes to read.
#define MAX(a,b) (((a)&(b))?(a):(b))
typedef unsigned int UINT32;
int errno;
int open(const char *,int);
int close(int);
size_t write(int,const char *, size_t);
int read(int,char *,size_t);
上面这个例子中的每个注释块都包含了一条结构化命令,所以这些注释可以放在文件的其他位置或者放在其他文件中,不会影响到最终生成的文档。这种方法的坏处在于我们实际上写了两遍原型,当做修改时我们必须同时修改代码和注释。因此,我们在使用前应该仔细考虑是否真的需要结构化命令,并且尽可能避免使用它。一个常见的现象就是在函数前的注释块中包含了 \fn 命令,显然这是冗余的,除了导致错误,这个命令毫无作用。
如果我们对以 .dox, .txt, .doc 结尾的文件注释,那么 Doxygen 会自动忽略这些文件。
如果我们有一个 Doxygen 无法解析的文件,但是仍然像注释它,那么就使用 \verbinclude 这个命令:
/*! \file myscript.sh
Look at this nice srcipt.
\verbinlcude mycript.sh
还要确定在配置文件中 INPUT 变量显式地说明这个脚本文件,或者 FILE_PATTERNS 变量必须包含 .sh 文件扩展名并且可以通过 EXAMPLE_PATH 变量寻找到这个文件。
Anatomy of a comment block
前面介绍了如何对代码进行注释,并且讨论了两种不同的注释:brief 和 detailed,还讨论了如何使用结构化命令。
下面我们分析注释块本身。
Doxygen 支持很多种格式的注释,最简单的就是文本文件,适用于比较短的注释。对于比较长的注释,我们需要清单、表格等更加结构化的元素,对于这种情况,Doxygen 支持 Markdown 语法,可以直接读取 Markdown 文件,详细内容看这里:
(Markdown 源自邮件的文本格式,语法非常简洁,并且功能很强大,这篇文章本书就是用 Markdown 语法写的,语法细节见官网,这里不再赘述。)
找到一篇博客,详细介绍了基于 Doxygen 的 C++ 注释风格:
最后展示一张我的效果图:
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致新手园地& & & 硬件问题Linux系统管理Linux网络问题Linux环境编程Linux桌面系统国产LinuxBSD& & & BSD文档中心AIX& & & 新手入门& & & AIX文档中心& & & 资源下载& & & Power高级应用& & & IBM存储AS400Solaris& & & Solaris文档中心HP-UX& & & HP文档中心SCO UNIX& & & SCO文档中心互操作专区IRIXTru64 UNIXMac OS X门户网站运维集群和高可用服务器应用监控和防护虚拟化技术架构设计行业应用和管理服务器及硬件技术& & & 服务器资源下载云计算& & & 云计算文档中心& & & 云计算业界& & & 云计算资源下载存储备份& & & 存储文档中心& & & 存储业界& & & 存储资源下载& & & Symantec技术交流区安全技术网络技术& & & 网络技术文档中心C/C++& & & GUI编程& & & Functional编程内核源码& & & 内核问题移动开发& & & 移动开发技术资料ShellPerlJava& & & Java文档中心PHP& & & php文档中心Python& & & Python文档中心RubyCPU与编译器嵌入式开发驱动开发Web开发VoIP开发技术MySQL& & & MySQL文档中心SybaseOraclePostgreSQLDB2Informix数据仓库与数据挖掘NoSQL技术IT业界新闻与评论IT职业生涯& & & 猎头招聘IT图书与评论& & & CU技术图书大系& & & Linux书友会二手交易下载共享Linux文档专区IT培训与认证& & & 培训交流& & & 认证培训清茶斋投资理财运动地带快乐数码摄影& & & 摄影器材& & & 摄影比赛专区IT爱车族旅游天下站务交流版主会议室博客SNS站务交流区CU活动专区& & & Power活动专区& & & 拍卖交流区频道交流区
UID空间积分0 积分1994阅读权限30帖子精华可用积分1994 信誉积分178 专家积分0 在线时间334 小时注册时间最后登录
家境小康, 积分 1994, 距离下一级还需 6 积分
帖子主题精华可用积分1994 信誉积分178 专家积分0 在线时间334 小时注册时间最后登录
论坛徽章:0
利用JavaDoc制作windows的CHM文档
使用了开源的一个ruby脚本来利用JavaDoc制作windows的CHM文档。
输出文件编码的时候一定记得选择中文,例如file.puts &Language=0x804 Chinese&。
Ruby代码1.def createProjectFile(prjname, basedir)&&
2.& && &
3.& & packages = scanPackageTree(basedir)&&
4.&&
5.& & createContentsFile(prjname+'.hhc', basedir, packages)&&
6.& & createIndexFile(prjname+'.hhk', basedir, packages)&&
7.& && &
8.& & assetsexplise = /^$/&&
9.& & title = getIndexTitle(basedir)&&
10.& && &
11.& & file = open(prjname+'.hhp', 'w')&&
12.& & file.puts &[OPTIONS]&&&
13.& & file.puts &Compatibility=1.1 or later&&&
14.& & file.puts &Compiled file=#{prjname}.chm&&&
15.& & file.puts &Contents file=#{prjname}.hhc&&&
16.& & file.puts &Default Window=default&&&
17.& & file.puts &Display compile progress=Yes&&&
18.& & file.puts &Default topic=#{basedir}/overview-summary.html&&&
19.& & file.puts &Full-text search=Yes&&&
20.& & file.puts &Index file=#{prjname}.hhk&&&
21.& & # file.puts &Language=0x411 Japanese&&&
22.& & file.puts &Language=0x409 English (U.S.)&&&
23.& & # file.puts &Language=0x804 Chinese&&&
24.& & file.puts &Title=#{title}&&&
25.& & file.puts &&&&
26.& & file.puts &[WINDOWS]&&&
27.& & file.puts &default=\&#{title}\&,\&#{prjname}.hhc\&,\&#{prjname}.hhk\&,\&#{basedir}/overview-summary.html\&,\&#{basedir}/overview-summary.html\&,,,,,0xe,,,,,,,,0&&&
28.& & file.puts &&&&
29.& & file.puts &&&&
30.& & file.puts &[FILES]&&&
31.& & collectAssets(basedir, assetsexplise).each() do |path|&&
32.& && &&&file.puts(path)&&
33.& & end&&
34.& & file.puts &&&&
35.& & file.close()&&
36.end&&
37.&&
38.def getIndexTitle(basedir)&&
39.& & title = &&&&
40.& & open(basedir + '/index.html', 'r') do |fh|&&
41.& && &&&fh.read() =~ /\&title\&\n*(.+?)\n*\&\/title\&/i&&
42.& && &&&title = $1&&
43.& & end&&
44.& & return title&&
45.end&&
46.&&
47.def collectAssets(assetsdir, assetsexplise)&&
48.& & assets = []&&
49.& & Dir.foreach(assetsdir) do |asset|&&
50.& && &&&assetpath = assetsdir + '/' + asset&&
51.& && &&&if File.stat(assetpath).ftype == 'file' then&&
52.& && && && &assets.push(assetpath) unless assetsexplise =~ assetpath&&
53.& && &&&elsif File.stat(assetpath).ftype == 'directory' and asset[0,1] != '.' then&&
54.& && && && &assets.concat(collectAssets(assetpath, assetsexplise))&&
55.& && &&&end&&
56.& & end&&
57.& & return assets&&
58.end&&
59.&&
60.HEADER = '&HTML&&HEAD&&meta name=&GENERATOR& content=&Microsoft& HTML Help Workshop 4.1&&&!-- Sitemap 1.0 --&&/HEAD&&BODY&&OBJECT type=&text/site properties&&&/OBJECT&'&&
61.FOOTER = '&/BODY&&/HTML&'&&
62.&&
63.def createContentsFile(filename, basedir, packages)&&
64.& && &
65.& & file = open(filename, 'w')&&
66.& & file.puts HEADER&&
67.& && &
68.& & file.puts &[list]&&&
69.& & file.puts &\t& + '&LI& &OBJECT type=&text/sitemap&&'&&
70.& & file.puts &\t& * 2 + '&param name=&Name& value=&Overview&&'&&
71.& & file.puts &\t& * 2 + '&param name=&Local& value=&' + basedir + '/overview-summary.html&&'&&
72.& & file.puts &\t& * 2 + '&param name=&ImageNumber& value=&21&&'&&
73.& & file.puts &\t& * 2 + '&/OBJECT&'&&
74.& && &
75.& & packages.each() do |pkg|&&
76.& && &&&file.puts &\t& + formatTopicItem(pkg['name'], basedir+'/'+pkg['file'])&&
77.& && &&&file.puts &\t& * 1 + &[list]&&&
78.& && &&&pkg['classes'].each() do |cls|&&
79.& && && && &file.puts &\t& * 2 + formatTopicItem(cls['name'], basedir+'/'+cls['file'])&&
80.& && && && &file.puts &\t& * 2 + &[list]&&&
81.& && && && &cls['details'].each() do |det|&&
82.& && && && && & file.puts &\t& * 3 + formatTopicItem(det, basedir+'/'+cls['file']+'#'+det)&&
83.& && && && &end&&
84.& && && && &file.puts &\t& * 2 + &[/list]&&&
85.& && &&&end&&
86.& && &&&file.puts &\t& * 1 + &[/list]&&&
87.& & end&&
88.& & file.puts &[/list]&&&
89.& && &
90.& & file.puts FOOTER&&
91.& & file.close()&&
92.end&&
93.&&
94.def createIndexFile(filename, basedir, packages)&&
95.& && &
96.& & file = open(filename, 'w')&&
97.& & file.puts HEADER&&
98.& && &
99.& & indexes = {}&&
100.& & packages.each() do |pkg|&&
101.& && &&&addKeywordToIndex(indexes, pkg['name'], pkg['name'], basedir+'/'+pkg['file'])&&
102.& && &&&pkg['classes'].each() do |cls|&&
103.& && && && &addKeywordToIndex(indexes, cls['name'], pkg['name']+'.'+cls['name'], basedir+'/'+cls['file'])&&
104.& && && && &cls['details'].each() do |det|&&
105.& && && && && & addKeywordToIndex(indexes, det, pkg['name']+'.'+cls['name']+'.'+det, basedir+'/'+cls['file']+'#'+det)&&
106.& && && && &end&&
107.& && &&&end&&
108.& & end&&
109.& && &
110.& & file.puts &[list]&&&
111.& & indexes.keys.sort.each() do |keyword|&&
112.& && &&&file.puts &\t& + formatIndexItem(keyword, indexes[keyword])&&
113.& & end&&
114.& & file.puts &[/list]&&&
115.& && &
116.& & file.puts FOOTER&&
117.& & file.close()&&
118.end&&
119.&&
120.def addKeywordToIndex(indexes, keyword, detail, file)&&
121.& & if indexes[keyword] == nil then indexes[keyword] = {} end&&
122.& & indexes[keyword][detail] = file&&
123.end&&
124.&&
125.&&
126.def scanPackageTree(basedir)&&
127.& & packagelist = []&&
128.& & rxpkg = /\&A\s+HREF\=\&([\w\d\-\/]+?)\/package\-frame\.html\&\s+target\=\&packageFrame\&\&([\w\d\.]+)\&\/A\&/i&&
129.& & rxcls = /\&A\s+HREF\=\&([^\.][\w\d\-\.]+?)\&(\s+title\=\&.+\&)?\s+target\=\&classFrame\&\&(\&I\&)?([\w\d\.]+)(\&\/I\&)?\&\/A\&/i&&
130.& && &
131.& & IO.foreach(basedir + &/overview-frame.html&) do | line |&&
132.& && &&&if (line =~ rxpkg) != nil then&&
133.& && && && &pkgdir = $1&&
134.& && && && &pkgname = $2&&
135.& && && && &print &#{pkgname}\n&&&
136.& && && && &classes = []&&
137.& && && && &IO.foreach(basedir + '/' + pkgdir + '/package-frame.html') do | line |&&
138.& && && && && & if (line =~ rxcls) != nil then&&
139.& && && && && && &&&classfile = $1&&
140.& && && && && && &&&classname = $4&&
141.& && && && && && &&&print &#{pkgname}.#{classname}\n&&&
142.& && && && && && &&&details = scanClassDocument(basedir+'/'+pkgdir+'/'+classfile)&&
143.& && && && && && &&&classes.push({'name'=&classname, 'file'=&pkgdir+'/'+classfile, 'details'=&details})&&
144.& && && && && & end&&
145.& && && && &end&&
146.& && && && &pkgfile = pkgdir + '/package-summary.html'&&
147.& && && && &packagelist.push({'name'=&pkgname, 'file'=&pkgfile, 'classes'=&classes})&&
148.& && &&&end&&
149.& & end&&
150.& & return packagelist&&
151.end&&
152.&&
153.def scanClassDocument(file)&&
154.& & scanstarts = false&&
155.& & anchors = []&&
156.& & IO.foreach(file) do |line|&&
157.& && &&&if (line =~ /\&A\s+NAME\=\&([^\&]+)\&\&/i) != nil then&&
158.& && && && &aname = $1&&
159.& && && && &if (aname =~ /\w+_detail$/i) != nil then&&
160.& && && && && & scanstarts = true&&
161.& && && && &elsif (aname =~ /^navbar_\w+/i) != nil then&&
162.& && && && && & scanstarts = false&&
163.& && && && &else&&
164.& && && && && & if scanstarts then&&
165.& && && && && && &&&anchors.push(aname)&&
166.& && && && && & end&&
167.& && && && &end&&
168.& && &&&end&&
169.& & end&&
170.& & return anchors&&
171.end&&
172.&&
173.def formatTopicItem(name, href)&&
174.& & out = '&LI&&OBJECT type=&text/sitemap&&'&&
175.& & out += sprintf('&param name=&Name& value=&%s&&', name)&&
176.& & if href != nil then&&
177.& && &&&out += sprintf('&param name=&Local& value=&%s&&', href)&&
178.& & end&&
179.& & out += &&/OBJECT&&&&
180.& & return out&&
181.end&&
182.&&
183.def formatIndexItem(name, details)&&
184.& & out = '&LI&&OBJECT type=&text/sitemap&&'&&
185.& & out += sprintf('&param name=&Name& value=&%s&&', name)&&
186.& & details.keys.each() do |det|&&
187.& && &&&out += sprintf('&param name=&Name& value=&%s&&', det)&&
188.& && &&&out += sprintf('&param name=&Local& value=&%s&&', details[det])&&
189.& & end&&
190.& & out += &&/OBJECT&&&&
191.& & return out&&
192.end&&
193.&&
194.createProjectFile(ARGV[0], ARGV[1])&&复制代码将JavaDoc的根目录拷贝到ruby脚本所在的目录下,这样会避免相对路径的问题,脚本里面处理得不好。安装好ruby环境(因为兼容性的问题,推荐使用ruby1.8)之后,执行命令ruby createhhp.rb &help-file-basename& &javadoc-dir&,会在当前目录下生产hhc(目录)、hhk(索引)、hhp(项目)这三个文件。
&&nbsp|&&nbsp&&nbsp|&&nbsp&&nbsp|&&nbsp&&nbsp|&&nbsp
UID空间积分0 积分490阅读权限20帖子精华可用积分490 信誉积分36 专家积分0 在线时间0 小时注册时间最后登录
稍有积蓄, 积分 490, 距离下一级还需 10 积分
帖子主题精华可用积分490 信誉积分36 专家积分0 在线时间0 小时注册时间最后登录
论坛徽章:0

我要回帖

更多关于 qt实现360风格界面 的文章

 

随机推荐