6个版本 (重大更新)

0.5.0 2024年8月11日
0.4.0 2024年8月4日
0.3.0 2024年7月22日
0.2.0 2024年6月17日
0.0.0 2024年5月27日

#134 in 命令行界面

Download history 117/week @ 2024-05-23 22/week @ 2024-05-30 147/week @ 2024-06-06 138/week @ 2024-06-13 20/week @ 2024-06-20 6/week @ 2024-06-27 27/week @ 2024-07-04 98/week @ 2024-07-18 24/week @ 2024-07-25 121/week @ 2024-08-01 108/week @ 2024-08-08

每月下载量 351

MIT 许可证

410KB
9K SLoC

cliargs-rust crate.io doc.rs CI Status MIT License

一个用于解析命令行参数并打印帮助信息的Rust库。

此库提供以下功能

  • 支持POSIX和GNU类似的短选项和长选项。
    • 此库支持--选项。
    • 此库不支持数字短选项。
    • 此库支持不是-ofoo而是-o=foo作为短选项的替代方案。
  • 支持使用选项配置进行解析。
  • 支持使用结构体字段和属性创建的选项配置进行解析,并将选项值设置到它们中。
  • 支持解析包括子命令的命令行参数。
  • 从选项配置生成帮助文本。

安装

Cargo.toml中,将此crate作为依赖项写入。

[dependencies]
cliargs = "0.5.0"

用法

此crate提供了Cmd结构体来解析命令行参数。此Cmd结构体的使用方法如下

创建一个Cmd实例

Cmd::new 函数使用原始命令行参数创建一个 Cmd 实例。此函数使用 std::env::args_osOsString#into_string 读取命令行参数,以避免用户无法控制的 panic! 调用。

use cliargs::Cmd;
use cliargs::errors::InvalidOsArg;

let cmd = match Cmd::new() {
    Ok(cmd) => cmd,
    Err(InvalidOsArg::OsArgsContainInvalidUnicode { index, os_arg }) => {
        panic!("Invalid Unicode data: {:?} (index: {})", os_arg, index);
    }
};

使用指定的 String 数组创建 Cmd 实例

Cmd::with_strings 函数使用指定的 String 数组创建一个 Cmd 实例。

use cliargs::Cmd;
use std::env;

let cmd = Cmd::with_strings(env::args());

使用指定的 OsString 数组创建 Cmd 实例

Cmd::with_os_strings 函数使用指定的 OsString 数组创建一个 Cmd 实例。

use cliargs::Cmd;
use cliargs::errors::InvalidOsArg;
use std::env;

let cmd = match Cmd::with_os_strings(env::args_os()) {
    Ok(cmd) => cmd,
    Err(InvalidOsArg::OsArgsContainInvalidUnicode { index, os_arg }) => {
        panic!("Invalid Unicode data: {:?} (index: {})", os_arg, index);
    }
};

无配置解析

Cmd 结构体有一个方法,可以在不配置的情况下解析命令行参数。此方法会自动将命令行参数分割为命令参数、选项和选项参数。

--- 开头的命令行参数是选项,其余的是命令参数。如果您想为选项指定一个值,请在选项后跟 "=" 和选项后的值,例如 foo=123

所有在 -- 之后的所有命令行参数都是命令参数,即使它们以 --- 开头。

use cliargs::Cmd;
use cliargs::errors::InvalidOption;

let mut cmd = Cmd::with_strings(vec![ /* ... */ ]);
match cmd.parse() {
    Ok(_) => { /* ... */ },
    Err(InvalidOption::OptionContainsInvalidChar { option }) => {
        panic!("Option contains invalid character: {option}");
    },
    Err(err) => panic!("Invalid option: {}", err.option()),
}

带配置解析

Cmd 结构体有一个 parse_with 方法,该方法在配置下解析命令行参数。此方法接受一个选项配置数组:OptCfg,并根据此配置将命令行参数分割为选项和命令参数。

选项配置具有以下字段:store_keynameshas_argis_arraydefaultsdescarg_in_helpvalidator

store_key 字段指定将选项值存储到 Cmd 实例中的选项映射中的键名。如果此字段未指定,则使用 names 字段的第一个元素。

names 字段是一个字符串数组,指定了选项名称,包括长选项和短选项。该字段中元素的顺序用于帮助文本。如果您想在帮助文本中优先显示短选项名,例如:-f, --foo-bar,但使用长选项名作为选项映射的键,请按照以下方式编写 store_keynames 字段:OptCfg::with([store_key("foo-bar"), names(&["f", "foo-bar"])]).

has_arg 字段指示选项需要一个或多个值。 is_array 字段指示选项可以具有多个值。 defaults 字段是一个字符串数组,用作未指定选项时的默认一个或多个选项参数。 desc 是用于帮助文本的选项描述。 arg_n_help 字段是在帮助文本中作为选项值输出的文本,紧跟在选项名和别名之后。

validator 字段用于设置一个函数指针,该指针验证选项参数。此crate提供了验证器 cliargs::validators::validate_number<T>,该验证器验证选项参数是否为有效的数字格式。

此方法将作为参数传递的选项配置向量所有权移动到该方法,并将其设置为 Cmd 实例的公共字段 cfgs。如果您在解析后想访问选项配置,请从该字段获取它们。

此外,使用 Help 生成 OptCfg 数组的帮助打印。

use cliargs::{Cmd, OptCfg};
use cliargs::OptCfgParam::{names, has_arg, defaults, validator, desc, arg_in_help};
use cliargs::validators::validate_number;
use cliargs::errors::InvalidOption;

let mut cmd = Cmd::with_strings(vec![ /* ... */ ]);
let opt_cfgs = vec![
    OptCfg::with([
        names(&["foo-bar"]),
        desc("This is description of foo-bar."),
    ]),
    OptCfg::with([
        names(&["baz", "z"]),
        has_arg(true),
        defaults(&["1"]),
        desc("This is description of baz."),
        arg_in_help("<num>"),
        validator(validate_number::<u32>),
    ]),
];

match cmd.parse_with(opt_cfgs) {
    Ok(_) => { /* ... */ },
    Err(InvalidOption::OptionContainsInvalidChar { option }) => { /* ... */ },
    Err(InvalidOption::UnconfiguredOption { option }) => { /* ... */ },
    Err(InvalidOption::OptionNeedsArg { option, .. }) => { /* ... */ },
    Err(InvalidOption::OptionTakesNoArg { option, .. }) => { /* ... */ },
    Err(InvalidOption::OptionIsNotArray { option, .. }) => { /* ... */ },
    Err(InvalidOption::OptionArgIsInvalid { option, opt_arg, details, .. }) => { /* ... */ },
    Err(err) => panic!("Invalid option: {}", err.option()),
}

let opt_cfgs = cmd.opt_cfgs();

let mut help = Help::new();
help.add_text("This is the usage description.".to_string());
help.add_opts_with_margins(opt_cfgs, 2, 0);
help.print();

// (stdout)
// This is the usage description.
//   --foo-bar, -f    This is description of foo-bar.
//   --bar, -z <num>  This is description of baz.

解析 OptStore 结构体

Cmd 结构体具有 parse_for 方法,该方法解析命令行参数并将它们的选项值设置到作为参数传递的选项存储中。

此方法将命令行参数分为命令参数和选项,然后设置每个选项值到选项存储的相应字段。

在此方法中,从选项存储的字段创建一个 OptCfg 向量。此 OptCfg 向量被设置为 Cmd 实例的公共字段 cfgs。如果您想访问此选项配置,请从该字段获取它们。

根据选项存储的字段类型和 opt 字段属性确定与选项存储每个字段对应的选项配置。如果类型是 bool,则选项不取参数。如果类型是整数、浮点数或字符串,则选项可以取单个选项参数,因此它可以在命令行参数中出现一次。如果类型是向量,则选项可以取多个选项参数,因此它可以在命令行参数中出现多次。

字段属性 opt 可以有以下名称和值对:一个是 cfg,用于指定 OptCfg 结构体的 namesdefaults 字段;另一个是 desc,用于指定 desc 字段;还有一个是 arg,用于指定 arg_in_help 字段。

cfg 的格式如下:cfg="f,foo=123"。等号左边是选项名称,右边是默认值。如果没有等号,则表示只指定了选项名称。如果需要指定多个选项名称,请用逗号分隔。如果需要指定多个默认值,请用逗号分隔,并用方括号括起来,如 [1,2,3]。如果您想使用您喜欢的分隔符,可以在左方括号左侧放置它,如 /[1/2/3]

注意:字段属性中空字符串数组选项的默认值是 [],如 #[opt(cfg="=[]")],但它并不表示只包含一个空字符串的数组。如果您想指定只包含一个空字符串的数组,请在等号符号后不写任何内容,如 #[opt(cfg="=")]

use cliargs::Cmd;
use cliargs::errors::InvalidOption;

#[derive(cliargs::OptStore)]
struct MyOptions {
    #[opt(cfg = "f,foo-bar", desc="The description of foo_bar.")]
    foo_bar: bool,
    #[opt(cfg = "b,baz", desc="The description of baz.", arg="<s>")]
    baz: String,
}
let mut my_options = MyOptions::with_defaults();

let mut cmd = Cmd::with_strings(vec![ /* ... */ ]);
match cmd.parse_for(&mut my_options) {
    Ok(_) => { /* ... */ },
    Err(InvalidOption::OptionContainsInvalidChar { option }) => { /* ... */ },
    Err(InvalidOption::UnconfiguredOption { option }) => { /* ... */ },
    Err(InvalidOption::OptionNeedsArg { option, .. }) => { /* ... */ },
    Err(InvalidOption::OptionTakesNoArg { option, .. }) => { /* ... */ },
    Err(InvalidOption::OptionIsNotArray { option, .. }) => { /* ... */ },
    Err(InvalidOption::OptionArgIsInvalid { option, opt_arg, details, .. }) => { /* ... */ },
    Err(err) => panic!("Invalid option: {}", err.option()),
}

let opt_cfgs = cmd.opt_cfgs();

let mut help = Help::new();
help.add_text("This is the usage description.".to_string());
help.add_opts_with_margins(opt_cfgs, 2, 0);
help.print();

// (stdout)
// This is the usage description.
//   -f, --foo-bar  This is description of foo_bar.
//   -z, --baz <s>  This is description of baz.

支持解析包括子命令的命令行参数

此库提供用于解析包括子命令的命令行参数的方法 Cmd#parse_until_sub_cmdCmd#parse_until_sub_cmd_withCmd#parse_until_sub_cmd_for

这些方法分别对应于 Cmd#parseCmd#parse_withCmd#parse_for,行为相同,只是它们在第一个命令参数(子命令)之前停止解析,并返回一个包含从子命令开始的参数的 Cmd 实例。

以下是一个使用 Cmd#parse_until_sub_cmd 的示例代码

use cliargs::Cmd;
use cliargs::errors::InvalidOption;

let mut cmd = Cmd::with_strings([ /* ... */ ]);

match cmd.parse_until_sub_cmd() {
    Ok(Some(mut sub_cmd)) => {
        let sub_cmd_name = sub_cmd.name();
        match sub_cmd.parse() {
            Ok(_) => { /* ... */ },
            Err(err) => panic!("Invalid option: {}", err.option()),
        }
    },
    Ok(None) => { /* ... */ },
    Err(InvalidOption::OptionContainsInvalidChar { option }) => {
        panic!("Option contains invalid character: {option}");
    },
    Err(err) => panic!("Invalid option: {}", err.option()),
}

支持的 Rust 版本

此库支持 Rust 1.74.1 或更高版本。

% cargo msrv --no-check-feedback
Fetching index
Determining the Minimum Supported Rust Version (MSRV) for toolchain x86_64-apple-darwin
Using check command cargo check
   Finished The MSRV is: 1.74.1   ████████████████████████████████████████████ 00:00:04

许可证

版权(C)2024 Takayuki Sato

本程序是在 MIT 许可证下提供的自由软件。
有关详细信息,请参阅本分布中的 LICENSE 文件。

依赖项

~12–36MB
~505K SLoC