2 个版本
0.1.1 | 2023年7月12日 |
---|---|
0.1.0 | 2023年7月11日 |
#1433 在 解析实现
65KB
1.5K SLoC
codump
一个用于从源文件中导出代码/注释的简单工具。
该工具使用正则表达式进行注释解析,根本不解析语言。因此,不需要指令或编译指令,并且可以在所有源代码上工作,前提是你的代码库有一个文档注释的系统。
为什么
有许多现有的工具可以将代码库中的注释转换为文档。然而,生成的文档质量完全取决于注释的质量。大多数情况下,你最终会得到一份生成的文档,其中90%的页面都是无用的,因为符号要么没有文档说明,要么注释为空/没有说明,就像
/// <summary>
///
/// <summary>
/// <param name="input">the input</param>
public void DoSomething(string input) {
...
}
我发现将这个过程反过来更有用,即我 将代码带到文档中。例如,我的文档可以是一个维基页面,我在其中不仅记录了API和符号,还记录了设计原则、示例等。而文档工具可以生成与维基页面一起使用的代码片段。
这就是背后的故事。这个工具接受一个文件、预置或自定义注释语法和一个搜索路径来查找符号,然后以优雅的格式打印出代码,以便嵌入到文档页面中。
显然,只是将代码打印到控制台并不能使其成为文档。我使用 txtpp 生成包含嵌入式命令的文件。
贡献和问题
欢迎贡献和问题。这是一个个人项目,我在此项目上的带宽有限,但我将对任何建议/评论认真对待。
安装
作为可执行文件
cargo install codump
作为库
cargo add codump
如果您需要从CLI参数解析配置,请添加 cli
功能
cargo add codump --features cli
CLI 使用
A straightforward and flexible code/comment dump tool
Usage: codump [OPTIONS] <FILE> <SEARCH_PATH>...
Arguments:
<FILE>
The input file to parse
<SEARCH_PATH>...
The component search path
Each path is a case-sensitive substring used to search for components at that level. The first line of the code after the doc comments is searched for the substring.
Options:
--outer <OUTER>
Outer single line comment regex
--outer-start <OUTER_START>
Outer multi line comment start regex
--outer-end <OUTER_END>
Outer multi line comment end regex
--inner <INNER>
Inner single line comment regex
--inner-start <INNER_START>
Inner multi line comment start regex
--inner-end <INNER_END>
Inner multi line comment end regex
-i, --ignore <IGNORE>
Pattern for lines that should be ignored
-f, --format <FORMAT>
Format for the output
[default: summary]
Possible values:
- summary: Comments + abbreviated code
- comment: Comment only format
- detail: Comment + all code
-p, --preset <PRESET>
Use a preset configuration
If both presets and individual options are set, the individual options will override the corresponding part of the preset. The rest of the preset will still be used.
Possible values:
- rust: Rust style
- rust-java: Rust style for single line and Java/JS/TS style for multiline
- python: Python style
-c, --context
Print context
Context is the parent components of the found component
-C, --context-comments
Print context comments
Print the comments of the parents along with the context (implies --context)
-h, --help
Print help (see a summary with '-h')
-V, --version
Print version
概念
外部注释
外部注释是指放在它所针对的内容之前的注释。以下是一个Rust风格的示例中的外部注释
/// Do something and returns the result
fn do_something() -> u32 {
todo!();
}
相同的外部注释在JS/TS风格中
/**
Do something and returns the result
*/
export function doSomething(): number {
...
}
在这种注释风格中,注释针对的代码都在注释之后。
内部注释
内部注释是指放在它所针对的内容内部的注释。例如,Rust中的模块注释。
//! This is a module to do things
pub fn do_thing_1() {
...
}
pub fn do_thing_2() {
...
}
另一个例子是Python中的文档注释
def do_something():
"""Do something and returns the result"""
...
区别在于注释所针对的代码的“签名”在注释外部,而细节在注释之后。
组件
在概念上,组件包含其注释和代码。其代码可以包含子组件。
//! imagine this file is example.rs
//! this is the inner comment for that file
// code inside this component, but not a child component
use std;
/// a function is a child component
fn foo() -> u32 {
...
}
/// a nested module is a child component too
mod bar {
//! inner comment (not sure if this is valid rust doc, but valid for this tool)
/// child components can have children too
fn biz() {
...
}
}
此工具根据路径搜索组件。找到组件后,该工具可以打印出其摘要、注释或实现细节。
解析
该工具使用基于行和正则表达式的简单解析风格。
单行和多行注释
该工具支持内部和外部注释的单行和多行注释。然而,对于同一个文档化的组件,单行和多行样式不能混合使用。
例如,你可以这样做
//! Example typescript file
/// Example 1
///
/// This function is documented with rust style single line comments
function foo() { ... }
/**
* Example 2
*
* C/Java/JS style
*/
function bar() { ... }
但这是无效的
/// This is a single line doc comment
/**
which cannot be mixed with multi line
*/
function foo() { ... }
这是为了使解析器保持简单。实际上,你不会希望在同一组件中混合它们。注意,你仍然可以混合子组件内部的注释,这正是示例1所做的事情。
组件结构
解析步骤将行列表转换为用于搜索的组件。组件行将按照以下方式解析:
- 内联注释之前的第一行之前的行。将被忽略。
- 内联注释,可以是
- 匹配内联注释单行正则表达式的连续行,或者
- 匹配内联注释多行开始正则表达式的行,直到包括匹配内联注释多行结束正则表达式的第一行
- 子组件外部注释之前的第一行之前的行(忽略)。
- 重复
- 外部注释,可以是
- 匹配外部注释单行正则表达式的连续行,或者
- 匹配外部注释多行开始正则表达式的行,直到包括匹配外部注释多行结束正则表达式的第一行
- 直到下一个外部注释的第一行的行。
- 外部注释,可以是
嵌套组件
嵌套子组件的解析方式如下
- 通过找到第一个缩进行来确定缩进。只接受由空格或制表符引起的缩进。
- 取消缩进主体行。删除未缩进的行。
- 像常规组件一样解析结果
请注意,这不利于C++命名空间风格,因为在命名空间内部,通常不会缩进。
/// I am a namespace
namespace foo {
/// Why is this not indented
void do_something();
} // end namespace foo
将发生两件(不希望发生的)事情
do_something
不会被处理为foo
的子组件,而是与命名空间处于同一级别。} // end namespace foo
将被处理为do_something
的一部分。
对于2,我们可以通过向要忽略的行的模式中添加^} // end namespace
来解决这个问题。
对于1,我们仍然可以将它作为文件中的组件来处理以找到符号。但是,如果同一个文件中有多个具有完全相同签名(除了命名空间)的函数,则该工具将无法唯一地找到它。
搜索
该工具通过指定文件和一个或多个搜索参数来搜索组件。
每个搜索参数用于搜索下一个嵌套组件。如果嵌套组件不能与搜索项唯一地识别,则工具将出错。
由于工具使用注释来查找组件,因此如果组件没有文档,则不会找到它。
输出格式
该工具支持三种输出格式:组件的summary
、comment
和detail
。
此外,您还可以使用-k/-K
标志来打印父项及其父注释。
摘要(默认)
在摘要模式下,外部和内部注释将按原样打印。只有正文中没有前导空格的行会被打印。缩进块将被替换为 ...
,其缩进与该块的第一个行相同。这也适用于外部和内部注释之间的行。
注释
在注释模式下,只打印外部和内部注释。
详细
在详细模式下,组件的所有内容将按原样打印。
依赖项
~2.2–3.5MB
~59K SLoC