#arguments #command-line-arguments #macro-derive #derive #args #cli

argp

基于 Derive 的参数解析器,优化代码大小

3 个版本 (重大更改)

0.3.0 2023年4月19日
0.2.0 2023年3月26日
0.1.0 2023年2月7日

#444Rust 模式

Download history 118/week @ 2024-03-14 57/week @ 2024-03-21 131/week @ 2024-03-28 42/week @ 2024-04-04 52/week @ 2024-04-11 75/week @ 2024-04-18 173/week @ 2024-04-25 51/week @ 2024-05-02 124/week @ 2024-05-09 522/week @ 2024-05-16 69/week @ 2024-05-23 181/week @ 2024-05-30 202/week @ 2024-06-06 204/week @ 2024-06-13 135/week @ 2024-06-20 64/week @ 2024-06-27

每月下载量 630
4 个crate中使用

BSD-3-Clause

82KB
1K SLoC

Argp 是一个基于 Derive 的参数解析器,优化代码大小和灵活性。

该库的公共 API 主要包括 FromArgs derive 和 parse_args_or_exit 函数,可用于从当前程序的命令行参数生成顶级的 FromArgs 类型。

功能

  • 零运行时依赖。

  • 小尺寸开销 - ~40 kiB [1],这是 比 clap 或 clap_derive 少 10 倍!有关更多详细信息,请参阅 argparse-rosetta-rs

  • 基于 Derive 的 API - 您定义用于解析值的结构和枚举,使用属性来指定它们应该如何被解析,过程宏将在编译时生成解析器。

  • 上下文敏感解析。

  • 支持子命令。

  • 带有 Markdown 支持和基于终端宽度的动态包装的帮助信息生成器。

起源

Argp 最初是从 argh 分支出来的,以使其更无偏见、更 UNIX 风格和更灵活。

与 argh 的显著变化

  • 支持全局选项(即顶层定义的选项可以在子命令中使用)。

  • 支持组合短选项(例如,-ab 被解析为 -a -b-an 5 被解析为 -a -n 5)。

  • 支持非 UTF-8 参数 (OsStr)。

  • from_str_fn 属性也可以包含函数路径,而不仅仅是单个标识符,并且可以返回任何实现了 ToStringErr 类型。

  • 描述不需要以小写字母开头。

  • 帮助信息根据终端宽度动态包装(在 Unix 系统上)。

  • 帮助信息中描述的缩进根据所有元素的宽度动态计算。

  • 即使是在位置参数上,也可以使用 arg_name 属性来自定义在帮助信息中显示参数的方式。

  • 错误使用枚举而不是字符串表示,生成帮助信息的所需信息以部分结构化的形式存储在结构体中;这为消息的定制打开了大门。

  • 专门的examplenoteerror_code属性被单个footer属性替换——您可以用它来做任何您想做的事情。

  • 在用法字符串中的位置参数在选项和开关之后显示,并在选项的描述中显示<arg_name>

  • 允许在-h, --help开关之后使用尾部选项,但仅限于在help子命令之后不允许。

  • from_env函数重命名为parse_args_or_exit,将cargo_from_env重命名为cargo_parse_args_or_exit

  • 已移除redact_arg_values(如果您偶然需要它,请在问题中告诉我)。

基本示例

use argp::FromArgs;

/// Reach new heights.
#[derive(FromArgs)]
struct GoUp {
    /// Whether or not to jump.
    #[argp(switch, short = 'j')]
    jump: bool,

    /// How high to go.
    #[argp(option, arg_name = "meters")]
    height: usize,

    /// An optional nickname for the pilot.
    #[argp(option, arg_name = "name")]
    pilot_nickname: Option<String>,
}

fn main() {
    let up: GoUp = argp::parse_args_or_exit(argp::DEFAULT);
}

./some_bin --help将输出以下内容

Usage: cmdname [-j] --height <meters> [--pilot-nickname <name>]

Reach new heights.

Options:
  -j, --jump                   Whether or not to jump.
      --height <meters>        How high to go.
      --pilot-nickname <name>  An optional nickname for the pilot.
  -h, --help                   Show this help message and exit.

生成的程序可以以以下任何方式使用

  • ./some_bin --height 5

  • ./some_bin -j --height 5

  • ./some_bin --jump --height 5 --pilot-nicknameWes

开关,如jump,是可选的,如果提供,则将其设置为true。

选项,如heightpilot_nickname,可以是必需的、可选的或重复的,具体取决于它们是否包含在OptionVec中。可以使用#[argp(default = "<your_code_here>")]属性提供默认值,在这种情况下,选项被视为可选的。

use argp::FromArgs;

fn default_height() -> usize {
    5
}

/// Reach new heights.
#[derive(FromArgs)]
struct GoUp {
    /// An optional nickname for the pilot.
    #[argp(option)]
    pilot_nickname: Option<String>,

    /// An optional height.
    #[argp(option, default = "default_height()")]
    height: usize,

    /// An optional direction which is "up" by default.
    #[argp(option, default = "String::from(\"only up\")")]
    direction: String,
}

fn main() {
    let up: GoUp = argp::parse_args_or_exit(argp::DEFAULT);
}

只要自定义选项类型实现了FromArgValue特质(对于大多数在std中实现了FromStr特质的标准类型已经实现),就可以反序列化自定义选项类型。如果需要更定制化的解析,您可以使用from_str_fn属性提供一个自定义的fn(&str)Result<T, E>,或使用from_os_str_fn属性提供一个自定义的fn(&OsStr)Result<T, E>,其中E实现了ToString

use argp::FromArgs;
use std::ffi::OsStr;
use std::path::PathBuf;

/// Goofy thing.
#[derive(FromArgs)]
struct FineStruct {
    /// Always five.
    #[argp(option, from_str_fn(always_five))]
    five: usize,

    /// File path.
    #[argp(option, from_os_str_fn(convert_path))]
    path: PathBuf,
}

fn always_five(_value: &str) -> Result<usize, String> {
    Ok(5)
}

fn convert_path(value: &OsStr) -> Result<PathBuf, String> {
    Ok(PathBuf::from("/tmp").join(value))
}

可以使用#[argp(positional)]声明位置参数。这些参数将按照结构体中声明的顺序解析

use argp::FromArgs;

/// A command with positional arguments.
#[derive(FromArgs, PartialEq, Debug)]
struct WithPositional {
    #[argp(positional)]
    first: String,
}

最后一个位置参数可以包含默认值,或者用OptionVec包裹,以表示可选或重复的位置参数。

也支持子命令。要使用子命令,需要为每个子命令声明一个单独的FromArgs类型,以及一个遍历每个命令的枚举。

use argp::FromArgs;

/// Top-level command.
#[derive(FromArgs, PartialEq, Debug)]
struct TopLevel {
    /// Be verbose.
    #[argp(switch, short = 'v', global)]
    verbose: bool,

    #[argp(subcommand)]
    nested: MySubCommandEnum,
}

#[derive(FromArgs, PartialEq, Debug)]
#[argp(subcommand)]
enum MySubCommandEnum {
    One(SubCommandOne),
    Two(SubCommandTwo),
}

/// First subcommand.
#[derive(FromArgs, PartialEq, Debug)]
#[argp(subcommand, name = "one")]
struct SubCommandOne {
    /// How many x.
    #[argp(option)]
    x: usize,
}

/// Second subcommand.
#[derive(FromArgs, PartialEq, Debug)]
#[argp(subcommand, name = "two")]
struct SubCommandTwo {
    /// Whether to fooey.
    #[argp(switch)]
    fooey: bool,
}

有关更多信息,请参阅argp 文档

如何调试 argp 的展开 derive 宏

可以使用cargo-expand 包调试argp::FromArgs derive 宏。

examples/simple_example.rs中展开 derive 宏

请参阅argp/examples/simple_example.rs,以了解我们想要展开的示例结构体。

首先,运行cargo install cargo-expand安装cargo-expand。注意,这需要 Rust 的夜间构建。

安装完成后,在 argp 包中运行cargo expand,你将可以看到展开后的代码。

许可证

本项目受BSD-3-Clause 许可证许可。有关许可证的全文,请参阅LICENSE文件。

  1. 在带有strip = truepanic = "abort"的发布构建中进行了测量。确切的大小取决于多个因素,包括选项和子命令的数量。

依赖关系

~3MB
~59K SLoC