4个版本 (2个破坏性更新)
0.3.0 | 2023年1月16日 |
---|---|
0.2.1 | 2022年7月10日 |
0.2.0 | 2021年10月23日 |
0.1.0 | 2021年7月16日 |
#37 in 命令行界面
每月下载量112,957
在 87 个crate中使用 (直接使用67个)
71KB
1K SLoC
Lexopt
Lexopt 是一个 Rust 的参数解析器。它试图拥有最简单可能的设计同时保持正确性。它的简单性使得使用起来略显繁琐。
Lexopt 是
- 小巧:单一文件,无依赖,无宏。易于审计或定制。
- 正确:支持标准约定并避免歧义。经过测试和模糊测试。
- 严谨:参数以
OsString
的形式返回,迫使您显式地进行转换。这使得您能够处理错误编码的文件名。 - 命令式:选项按找到的顺序返回,事先没有声明任何内容。
- 简约:只提供基本功能。
- 不友好:没有帮助生成,错误消息通常缺乏上下文。
示例
struct Args {
thing: String,
number: u32,
shout: bool,
}
fn parse_args() -> Result<Args, lexopt::Error> {
use lexopt::prelude::*;
let mut thing = None;
let mut number = 1;
let mut shout = false;
let mut parser = lexopt::Parser::from_env();
while let Some(arg) = parser.next()? {
match arg {
Short('n') | Long("number") => {
number = parser.value()?.parse()?;
}
Long("shout") => {
shout = true;
}
Value(val) if thing.is_none() => {
thing = Some(val.string()?);
}
Long("help") => {
println!("Usage: hello [-n|--number=NUM] [--shout] THING");
std::process::exit(0);
}
_ => return Err(arg.unexpected()),
}
}
Ok(Args {
thing: thing.ok_or("missing argument THING")?,
number,
shout,
})
}
fn main() -> Result<(), lexopt::Error> {
let args = parse_args()?;
let mut message = format!("Hello {}", args.thing);
if args.shout {
message = message.to_uppercase();
}
for _ in 0..args.number {
println!("{}", message);
}
Ok(())
}
让我们来看看这个
- 我们使用
Parser::from_env()
开始解析。 - 我们通过循环调用
parser.next()
来获取所有参数,直到它们耗尽。 - 我们对参数进行匹配。
Short
和Long
指示一个选项。 - 要获取属于选项的值(如
10
在-n 10
中),我们调用parser.value()
。- 这返回一个标准的
OsString
。 - 为了方便,使用
use lexopt::prelude::*
会添加一个.parse()
方法,类似于str::parse
。 - 调用
parser.value()
是告诉Parser
-n
需要一个值的。
- 这返回一个标准的
Value
表示一个独立的参数。if thing.is_none()
是处理位置参数的有用模式。如果我们已经找到了thing
,我们将其传递给另一个情况。- 它还包含一个
OsString
。.string()
方法将其解码为普通的String
。
- 如果我们不知道如何处理一个参数,我们使用
return Err(arg.unexpected())
将其转换为错误信息。 - 字符串可以被提升为错误,用于自定义错误信息。
这涵盖了库中的大部分功能。Lexopt 为你做了非常少的事情。
有关具有有用模式的更大示例,请参阅 examples/cargo.rs
。
命令行语法
以下约定得到支持
- 短选项(
-q
) - 长选项(
--verbose
) --
用于标记选项的结束=
用于分隔选项和值(--option=value
,-o=value
)- 空格用于分隔选项和值(
--option value
,-o value
) - 未分隔的短选项(
-ovalue
) - 组合短选项(
-abc
表示-a -b -c
) - 带有可选参数的选项(类似于 GNU sed 的
-i
,它可以独立使用,也可以作为-iSUFFIX
)(Parser::optional_value()
) - 带有多个参数的选项(
Parser::values()
)
这些不支持
- 单划线长选项(如 find 的
-name
) - 缩写长选项(GNU 的 getopt 允许你写出
--num
而不是--number
,如果它可以无歧义地展开)
Parser::raw_args()
和 Parser::try_raw_args()
提供了一种消费原始命令行参数的逃生门。请参阅 examples/nonstandard.rs
,了解解析非标准选项语法的示例。
Unicode
此库支持 Unicode,同时容忍非 Unicode 参数。
短选项可以是 Unicode,但只能是一个码点(一个 char
)。
选项可以与非 Unicode 参数结合使用。也就是说,--option=���
不会导致错误或损坏值。
如果选项本身不是有效的 Unicode,则它们将被 String::from_utf8_lossy
进行修补。这意味着您可能会在稍后它们未被识别时引发错误。
为什么?
对于特定的应用程序,我在寻找一个小的、严格正确的解析器。有其他紧凑的参数解析库,但我找不到一个能够处理 OsString
并忠实实现参数语法的所有繁琐细节的库。
如果需要大量的控制,如当精确的参数顺序很重要或不是所有选项都预先知道时,此库也可能很有用。它更像是词法分析器而不是解析器。
为什么不呢?
如果以下情况,此库可能不值得使用:
- 您不关心非 Unicode 参数
- 您不关心精确的兼容性和正确性
- 您不关心代码大小
- 您非常关心出色的错误消息
- 您讨厌模板代码
另请参阅
- 参数解析 crate 的收集基准.
- libc 的
getopt
。 - Plan 9 的 arg(3) 宏。