3个版本 (破坏性)
0.3.0 | 2023年4月19日 |
---|---|
0.2.0 | 2023年3月26日 |
0.1.0 | 2023年2月7日 |
#86 in #optimized
每月645次下载
在5个crate中使用(通过argp)
88KB
2K SLoC
Argp是一个基于派生的参数解析器,针对代码大小和灵活性进行优化。
该库的公共API主要由FromArgs
派生和parse_args_or_exit
函数组成,可以使用它们从当前程序的命令行参数生成顶级FromArgs
类型。
特性
-
无运行时依赖。
-
小尺寸开销 - ~40 kiB [1],这是比clap或clap_derive低10倍!有关更多详细信息,请参阅argparse-rosetta-rs。
-
基于派生的API - 您定义用于解析值的结构和枚举,使用属性指定如何解析,过程派生宏将在编译时生成解析器。
-
上下文敏感解析。
-
支持子命令。
-
带有Markdown支持的帮助信息生成器,以及基于终端宽度的动态换行。
起源
Argp最初是argh的一个分支,目的是使其更具UNIX风格、更灵活。
与argh的显著变化
-
支持全局选项(即顶层定义的选项可以在子命令中使用)。
-
支持组合短选项(例如,
-ab
被解析为-a -b
,-an 5
被解析为-a -n 5
)。 -
支持非UTF8参数(OsStr)。
-
from_str_fn
属性还可以包含函数路径,而不仅仅是单个标识符,并且可以返回任何实现了ToString
的Err
类型。 -
对描述以小写字母开头没有严格的限制。
-
帮助信息根据终端宽度动态包装(在Unix系统上)。
-
帮助信息中描述的缩进是根据所有元素的宽度动态计算的。
-
即使在位置参数上,也可以使用
arg_name
属性来自定义在帮助信息中显示参数的方式。 -
错误使用枚举而不是字符串来表示,生成帮助信息所使用的信息以部分结构化的形式存储在结构体中;这为消息的定制打开了大门。
-
将专门的
example
、note
和error_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。
选项,如 height
和 pilot_nickname
,可以是必需的、可选的或重复的,具体取决于它们是否包含在 Option
或 Vec
中。可以使用 #[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,
}
最后一个位置参数可以包含默认值,或者用 Option
或 Vec
包装,以表示可选或重复的位置参数。
也支持子命令。要使用子命令,为每个子命令声明一个单独的 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 crate 调试 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 文件。
- 在带有
strip = true
和panic = "abort"
的发布构建中进行了测量。确切的大小取决于多个因素,包括选项和子命令的数量。
依赖关系
~3MB
~59K SLoC