#参数解析器 #命令行 #命令行参数 #解析器 #CLI 解析器 #参数

hp

HashParse 是一个简单、快速且零依赖的命令行解析库

1 个稳定版本

1.0.0 2022 年 8 月 31 日

命令行界面 中排名第 771

每月下载 23

GPL-3.0 许可证

42KB
587 代码行

关于

hpHashParse 是一个快速、简单且完全无依赖的命令行参数解析库。解析过程在 O(n) 时间复杂度内完成,其中 n 是提供的参数数量,实现基于 HashMaps,所有查找应具有 O(1) 的时间复杂度。

最突出的特性包括

  • 自动生成帮助信息。
  • 彩色且详尽的错误报告。
  • 分层命令和子命令。
  • 易于阅读和理解文档。

原理

在过去的几个月里,我的所有Rust项目都是命令行工具。我仍然是一名学生,手头有很多空闲时间,所以我通常的做法,现在大部分时间还是这样做,就是尽可能地使用最少的依赖项,并尝试自己实现大部分需要的功能,这样我可以更好地理解相关的组件,同时将项目的规模和复杂性保持在最低。在编写这些命令行工具时,我意识到我需要一个简单高效的方式来解析命令行参数。在我工作的每一个项目中,我主要使用同一复杂解析器的变体,这总是很麻烦去编写和扩展,添加更多的参数,因为项目在增长。我希望有一个简单、小巧、快速,并且几乎没有依赖的解决方案,它可以提供简单的CLI应用可能需要的所有功能。我了解其他库,如clapstructopt(你最好使用这两个库之一),但我想要编写一个简单的库,提供一些相同的功能,比如自动生成--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缺少什么,请随意提出问题或提交拉取请求。所有贡献和讨论都非常受欢迎!

无运行时依赖