1 个稳定版本
1.0.0 | 2022 年 8 月 31 日 |
---|
在 命令行界面 中排名第 771
每月下载 23 次
42KB
587 代码行
关于
hp
或 HashParse
是一个快速、简单且完全无依赖的命令行参数解析库。解析过程在 O(n)
时间复杂度内完成,其中 n
是提供的参数数量,实现基于 HashMaps,所有查找应具有 O(1)
的时间复杂度。
最突出的特性包括
- 自动生成帮助信息。
- 彩色且详尽的错误报告。
- 分层命令和子命令。
- 易于阅读和理解文档。
原理
在过去的几个月里,我的所有Rust项目都是命令行工具。我仍然是一名学生,手头有很多空闲时间,所以我通常的做法,现在大部分时间还是这样做,就是尽可能地使用最少的依赖项,并尝试自己实现大部分需要的功能,这样我可以更好地理解相关的组件,同时将项目的规模和复杂性保持在最低。在编写这些命令行工具时,我意识到我需要一个简单高效的方式来解析命令行参数。在我工作的每一个项目中,我主要使用同一复杂解析器的变体,这总是很麻烦去编写和扩展,添加更多的参数,因为项目在增长。我希望有一个简单、小巧、快速,并且几乎没有依赖的解决方案,它可以提供简单的CLI应用可能需要的所有功能。我了解其他库,如clap
或structopt
(你最好使用这两个库之一),但我想要编写一个简单的库,提供一些相同的功能,比如自动生成--help
帮助信息、良好的错误报告方式,最重要的是,能够快速添加新命令和子命令。因此,在几天的时间里,我编写并记录了高性能、无依赖的命令行解析库hp
的大部分内容。我仍然想要改变和改进一些东西,但现在它应该处于良好和可工作的状态。
extern crate hp;
use hp::{Parser, Template};
use std::process::exit;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a new parser and set the necessary fields for the `--help` command.
let mut parser = Parser::new()
.with_description("An example program.")
.with_author("Me")
.with_program_name("myprog");
// Add a top level `command template` that will look for `--say` in the command line arguments.
// The command takes 1 value that is not optional, it is required.
// The third function argument is the help string which will be printed by the `--help`
// command.
parser.add("--say", 1, "Print the command line argument value supplied.");
// For finer control, a user might want to use the `Template` structure for a better
// control over the added Template.
parser.add_template(Template::new()
.matches("--new")
.matches("-n")
.number_of_values(2)
.optional_values(true)
.with_help("Do some amazing thing here please!"));
// Each added `Template` returns an ID.
// This ID can than be used to create subcommands for that given command.
let id = parser.add("-c", 0, "Count something based on the subcommands supplied.");
parser.add_subcommand(id, "--add", 2, "Perform addition on two numbers.");
// $ myprog --add
// ERROR: Out of context argument, because '--add' is a subcommand of
// '-c' and '-c' is not present in the command.
//
// $ myprog -c --add 2 2
// 4
// Call closures instantly, when an argument is parsed.
//
// Normally when using the `has()` and `get()` interface on the `ParsedAruguments` struct,
// upon parsing multiple arguments matching the same `Template` only the last instance of
// the argument is stored in the parsed result.
//
// The closure passed to `on_parse()` is called during parsing on every instance of the
// argument matching the same template. This means that the code meant for that template
// can be run on every value of every occurrence of the parsed template.
parser.add_subcommand_template(id, Template::new()
.matches("--sub")
.number_of_values(2)
.on_parse(|values| {
let (a, b): (i32, i32) = (values[0].parse().unwrap(), values[1].parse().unwrap());
println!("{}", a - b);
}));
let presult = parser.parse(None);
if let Some(err) = presult.as_ref().err() {
println!("{err}");
exit(1);
}
let presult = presult.unwrap();
if presult.has("--say") {
println!("Saying: {}", presult.get("--say").unwrap().values()[0]);
}
Ok(())
}
示例
大多数函数都有一些简单的代码示例。还有一个examples
目录,目前包含一个工作的计算器CLI应用。
贡献与修复
如果你觉得hp
缺少什么,请随意提出问题或提交拉取请求。所有贡献和讨论都非常受欢迎!