中文 | English
Commander-Rust 是一个仿照 commander.js 实现的 Rust 命令行解析库。它提供了简洁的链式 API,用于定义命令、选项和参数,支持子命令、默认值、自动生成帮助信息等功能。
- 链式 API 设计,简洁易用
- 支持选项(布尔值、单值、可选值)
- 支持参数(必需参数、可选参数、多值参数)
- 支持子命令和嵌套命令
- 支持默认值与值类型自动推断(int、float、bool、string)
- 自动生成帮助信息(动态列宽对齐,含完整命令路径)
- 分层错误处理(未知选项 warning,缺少必填值 error)
- 支持选项别名和组合(如
-vd) - 支持通过 JSON 构造命令树
当前仓库尚未发布到 crates.io,可通过本地路径或 Git 依赖使用。
本地路径:
[dependencies]
commander-rust = { path = "/path/to/commander-rust" }Git 依赖:
[dependencies]
commander-rust = { git = "https://github.com/DoYoungDo/commander-rust.git" }use commander_rust::{new, Action, Context, Varaint};
fn main() {
let mut app = new("example");
app.version("1.0.0")
.description("一个示例命令行应用")
.options(
"-n, --name <name>",
"你的名字",
Varaint::from_string("".to_string()),
)
.action(Some(Box::new(|ctx: &mut Context| {
let name = ctx.opt("name").to_string();
if !name.is_empty() {
println!("Hello, {}", name);
} else {
println!("Hello, World!");
}
}) as Action));
let args: Vec<String> = std::env::args().skip(1).collect();
if let Err(err) = app.parse(&args) {
eprintln!("error: {}", err);
std::process::exit(1);
}
}运行示例:
$ cargo run -- -n Alice
Hello, Alice
$ cargo run -- -V
1.0.0
$ cargo run -- --help
Usage: example [options]
一个示例命令行应用
Options:
-h, --help display help for command
-V, --version output the version number
-n, --name <name> 你的名字| 格式 | 说明 |
|---|---|
--option |
布尔选项 |
-o, --option |
带别名的布尔选项 |
--option <value> |
必需值选项 |
--option [value] |
可选值选项 |
| 格式 | 说明 |
|---|---|
<arg> |
必需参数 |
[arg] |
可选参数 |
<arg...> |
多值必需参数 |
[arg...] |
多值可选参数 |
| 格式 | 说明 |
|---|---|
command |
子命令 |
command <arg> |
子命令带一个必需参数 |
command [arg] |
子命令带一个可选参数 |
command <arg...> |
子命令带一个多值必需参数 |
command [arg...] |
子命令带一个多值可选参数 |
let mut app = new("app");
app.options("-v, --verbose", "详细输出", Varaint::from_bool(false))
.options(
"-o, --output <file>",
"输出文件",
Varaint::from_string("".to_string()),
)
.options("-n, --num <n>", "数字", Varaint::from_int(0))
.action(Some(Box::new(|ctx: &mut Context| {
if ctx.opt("verbose").to_bool() {
println!("verbose mode");
}
println!("output: {}", ctx.opt("output").to_string());
println!("num: {}", ctx.opt("num").to_int());
}) as Action));let mut app = new("copy");
app.arguments("<from>", "源文件", Varaint::empty())
.arguments("[to]", "目标文件", Varaint::empty())
.action(Some(Box::new(|ctx: &mut Context| {
println!("from: {}", ctx.args()[0].to_string());
println!("to: {}", ctx.args()[1].to_string());
}) as Action));let mut app = new("git");
app.version("1.0.0").description("Git 命令行工具");
app.command("add", "添加文件到暂存区")
.arguments("<files...>", "文件列表", Varaint::empty())
.options("-f, --force", "强制添加", Varaint::from_bool(false))
.action(Some(Box::new(|ctx: &mut Context| {
println!("add: {:?}", ctx.args());
}) as Action));
app.command("commit", "提交更改")
.options(
"-m, --message <msg>",
"提交信息",
Varaint::from_string("".to_string()),
)
.action(Some(Box::new(|ctx: &mut Context| {
println!("commit: {}", ctx.opt("message").to_string());
}) as Action));支持短选项组合(类似 tar -xzvf):
$ ./app -vdParse 时自动将字符串转换为对应类型:
$ ./app --num 42
$ ./app --rate 1.5
$ ./app --flag true
$ ./app --name hellolet args: Vec<String> = std::env::args().skip(1).collect();
if let Err(err) = app.parse(&args) {
eprintln!("error: {}", err);
std::process::exit(1);
}- 未知选项:打印 warning 到 stderr,继续解析,不影响 action 执行
- 缺少必填选项值:返回 error,终止解析
- 缺少必填参数:返回 error,终止解析
- 使用
parse_strict时,未知选项、未知别名、超出声明的参数都会返回 error
use commander_rust::new_from_json;
let mut app = new_from_json(r#"{
"name": "todo",
"version": "1.0.0",
"description": "todo app",
"arguments": [
{
"name": "filter",
"desc": "filter todos",
"defaultValue": "all",
"valueRequired": false,
"multiValue": false
}
],
"options": [
{
"name": "output",
"alias": "o",
"desc": "output file",
"value": {
"valueName": "file",
"defaultValue": "stdout",
"valueRequired": true
}
}
]
}"#);仓库中提供了两个 todo 示例:
examples/todo.rsexamples/todo/
运行根项目 example:
cargo run --example todo -- --help运行独立示例 crate:
cd examples/todo
cargo run -- --helpcargo test严格检查:
cargo fmt --check
cargo clippy --all-targets --all-features -- -D warningsMIT License