Skip to content

DoYoungDo/commander-rust

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Commander-Rust

中文 | 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...] 子命令带一个多值可选参数

详细用法

1. 定义选项

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));

2. 定义参数

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));

3. 定义子命令

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));

4. 选项别名组合

支持短选项组合(类似 tar -xzvf):

$ ./app -vd

5. 值类型自动推断

Parse 时自动将字符串转换为对应类型:

$ ./app --num 42
$ ./app --rate 1.5
$ ./app --flag true
$ ./app --name hello

6. 错误处理

let 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

从 JSON 构造命令

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.rs
  • examples/todo/

运行根项目 example:

cargo run --example todo -- --help

运行独立示例 crate:

cd examples/todo
cargo run -- --help

测试

cargo test

严格检查:

cargo fmt --check
cargo clippy --all-targets --all-features -- -D warnings

许可证

MIT License

About

Commander-Rust is a Rust command-line parsing library inspired by commander.js.

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages