7 个版本

0.1.6 2021年6月26日
0.1.5 2021年6月26日
0.1.4 2021年4月18日

#516 in 命令行界面

26 个月下载量

MIT 许可证

79KB
1.5K SLoC

Parsnip

Rust 的小型 Argparser

// ./prog --arg param1 param2 -a
fn main() {
    let args = args! {
        // define all your args here
        args: vec![arg! {
            name: "arg",
            short: Some("a"),
        }, arg! {
            name: "arg2",
            long: Some("arg2"),
            num_values: NumValues::Between(1, 3),
        }],
        // subcommands (e.g git add)
        subcommands: vec![args! {}],
        // optional, by default parsing will return a "Results" object
        handler: |results| { return results.args.get("arg2"); }
    };
    let results = args.parse(std::env::args());
}

设置

将库添加到您的 Cargo.toml.

[dependencies]
argparsnip = "0.1.5"

功能

  • 自动生成的帮助/版本命令
    • 可以重写
    • [subcommand]* 帮助 & [subcommand]* 版本命令也会生成
    • 名称/版本/关于参数默认使用 Cargo.toml 中的 CARGO_PKG_NAME/CARGO_PKG_VERSION/CARGO_PKG_DESCRIPTION 变量
  • 参数
    • 支持短 -h--help 语法
    • 默认支持 Unicode
    • 支持返回(作为 vec)或因未知参数而失败
    • 标志
      • 支持组合(例如 -rli 等同于 -r -l -i
      • 支持重复,例如 -vvv -v 将被视为出现 4 次的同一标志 v
    • 带有值
      • 支持对参数值的数量进行限制,例如精确地有一个值,有两个到四个值,或任何数量的值。例如 -v foo bar
      • 支持通过 TryInto 特性将值限制为特定的 原始 类型(任何、bool、i32、i64、f32、f64、String)
      • 支持额外的自定义验证(因此您可以编写自己的 sum 类型限制,例如)
      • 支持默认值
    • 组合
      • 可以将解析配置为如果缺少任何必需的参数则失败
      • 支持要求一组参数中的至少一个(例如 A || B || C)
      • 支持要求一组中的所有参数(例如 A && B && C)
      • 支持反转集合(例如 !(A && B))
      • 支持要求多个集合中的任意或所有(例如 (A && B) || (A && C))。这也可以被否定
    • 位置参数
      • 支持 Unix --,即 foo -- -a -b -c 将接收位置参数 ["-a", "-b", "-c"]
      • 将所有不以 --- 开头的参数视为位置参数。
  • 子命令
    • 例如 cargo run 与 cargo test(run/test 是子命令)
    • 子命令可以有它们自己的子命令和参数
    • 为每个子命令生成单独的帮助/版本命令
  • 可选回调支持
    • 而不是返回一个包含 argparsing 结果的结果对象,可以为每个命令/子命令提供一个处理函数 fn(Results) -> T(在使用 serde 时不受支持)。
  • no_std 支持
    • 禁用默认功能以启用 no_std
    • parsnip= {版本= "x",默认-功能= false }
  • serde 支持
    • parsnip= {版本= "x",功能= ["derive"] }
    • 使用任何格式(serde_json、toml 等)的 serde 解析器编写您的参数模式(参见 derive-test 以获取示例)
  • 其他可选功能
    • debug - 启用有关参数解析的日志记录信息
    • macros - 默认启用,我们提供了一些实用宏,以避免在各个地方编写 ..Default::default()

用法

以下是一些快速常见情况。有关更多示例,请参阅 lib.rs 中的测试

文档

https://docs.rs/argparsnip/0.1.5/argparsnip/

示例

最小标志示例

// ./prog --arg
fn main() {
    let args = args! {
        args: vec![arg! {
            name: "arg",
            short: Some("a"),
        }],
    };
    let results = args.parse(std::env::args());
    assert_eq!(1, results.flags("arg"));
}

检查是否给出了标志

// ./prog --arg
fn main() {
    let args = args! {
        args: vec![arg! {
            name: "arg",
            short: Some("a"),
            about: "a flag",
            long: Some("arg"),
            required: true,
        }],
    };
    let results = args.parse(std::env::args());
    assert_eq!(1, results.flags("arg"));
}

获取参数的值

// ./prog -a 1
fn main() {
    let args = args! {
        args: vec![arg! {
            name: "arg",
            short: Some("a"),
            default: Some(|| { Value::From(2) }),
            value_type: Type::Int,
            num_values: NumValues::Fixed(1),
        }],
    };
    let results = args.parse(std::env::args());
    assert_eq!(1, results.params.get("arg")?.try_into());
}

验证参数

// ./prog -a 1 2
fn main() {
    let args = args! {
        args: vec![arg! {
            name: "arg",
            short: Some("a"),
            value_type: Type::Int,
            num_values: NumValues::AtLeast(1),
            validation: |val| {
                let val: &i32 = v.try_into().unwrap();
                if 2 >= *val {
                    Ok(())
                } else {
                    Err("failed validation")
                }
            }
        }],
    };
    let results = args.parse(std::env::args());
    assert_eq!(vec![1, 2], results.params.get("arg")?.try_into());
}

使用子命令

// ./prog sub --arg 
fn main() {
    let args = args! {
        args: vec![arg! {
            name: "arg",
            long: Some("arg"),
            num_values: NumValues::None,
        }],
        subcommands: vec![args! {
            name: "sub",
            path: Some("main/sub"),
            args: vec![arg! {
                name: "arg",
                long: Some("arg"),
                num_values: NumValues::None,
            }],
        }],
    };
    let results = args.parse(std::env::args());
    // this is the unique identifier for the subcommand
    assert_eq!("main/sub", results.path);
    assert_eq!(1, results.flags["arg"]);
}

过滤器

// only supports combinations (--arg && --arg2) or (--arg && --arg3)
// will fail if --arg or --arg2 or --arg3 are passed on their own
fn main() {
    let args = args! {
        args: vec![arg! {
            name: "arg",
            long: Some("arg"),
            num_values: NumValues::None,
        }, arg! {
            name: "arg2",
            long: Some("arg2"),
            num_values: NumValues::None,
        }, arg! {
            name: "arg3",
            long: Some("arg3"),
            num_values: NumValues::None,
        }],
        filters: Filters {
            filters: vec![Filter {
                filter_type: FilterType::All,
                inverse: false,
                args: vec!["arg", "arg2"],
            }, Filter {
                filter_type: FilterType::All,
                inverse: false,
                args: vec!["arg", "arg3"],
            }],
            ..Default::default()
        },
        // this flag means we will fail if we see the same value multiple times
        disable_overrides: true,
    };
    let results = args.parse(std::env::args());
}

开发

待办事项

  • 基准测试
  • 更多测试
  • 功能
    • Bash/Zsh 完成功能
    • 支持禁用位置参数
    • 支持更新重复项,例如 --arg Foo --arg Bar 应该给出 {"arg": ["Foo", "Bar"]}
  • 我的设计可能不是迭代器友好,请尝试使用计数器代替

依赖项

~0.5–1MB
~15K SLoC