16个版本

0.3.12 2022年12月18日
0.3.11 2022年1月22日
0.3.10 2021年12月23日
0.3.9 2021年11月10日
0.1.0 2018年12月27日

#24 in #central

Download history 284/week @ 2024-04-07 263/week @ 2024-04-14 587/week @ 2024-04-21 354/week @ 2024-04-28 158/week @ 2024-05-05 43/week @ 2024-05-12 158/week @ 2024-05-19 662/week @ 2024-05-26 864/week @ 2024-06-02 1161/week @ 2024-06-09 1090/week @ 2024-06-16 745/week @ 2024-06-23 833/week @ 2024-06-30 472/week @ 2024-07-07 86/week @ 2024-07-14 57/week @ 2024-07-21

1,472 monthly downloads
3 个crate中使用 (通过 gflags)

MIT/Apache

14KB
402

gflags

github crates.io docs.rs build status

类似gflags (原Google命令行标志)的命令行标志库。

[dependencies]
gflags = "0.3"

支持rustc 1.37+


直接引用C++ gflags文档中的内容,因为概念是相同的

命令行标志是用户在运行可执行文件时在命令行中指定的标志。在命令

fgrep -l -f /var/tmp/foo johannes brahms

-l-f /var/tmp/foo 是两个命令行标志。 (johannesbrahms,不以短横线开头,是 命令行参数。)

通常,应用程序会列出允许用户传递的标志和它们接受的参数 -- 在此示例中,-l 不接受任何参数,而 -f 接受一个字符串(特别是,一个文件名)作为参数。用户可以使用库来帮助解析命令行并将标志存储在某种数据结构中。

Google内部使用的命令行标志库gflags与其他库(如 getopt())不同,因为标志定义可以分散在源代码中,而不仅仅是列在一个地方,如 main()。在实践中,这意味着单个源代码文件将定义和使用对该文件有意义的标志。任何链接到该文件的程序都将获得这些标志,gflags库将自动适当地处理这些标志。

由于这种技术,在灵活性和代码重用方面有显著的收益。

这种标志注册方式比维护单个中央标志列表更适合大规模开发,因为中央列表会变成在数百名开发者同时开发的应用程序中不断产生合并冲突的源头。

定义标志

标志可以通过gflags::define!宏在任意源文件中定义。应用程序的所有标志没有中央列表。(这就是gflags与其他标志库相比在大型开发中的优势所在。)

gflags::define! {
    /// Include 'advanced' options in the menu listing.
    --big_menu = true
}

gflags::define! {
    /// Comma-separated list of languages to offer in the 'lang' menu.
    -l, --language <LANG> = "english,french,german"
}

标志必须有一个长名称(如--verbose),可以可选地有一个短名称(如-v)。标志必须有一个确切的长名称,最多有一个短名称;不支持同一标志的多个不同别名。

除了bool类型以外的标志可以有可选的值占位符,如<LANG>。这是可选的,纯粹为了美观。它出现在帮助文本中。

访问标志

在您的应用程序中某个早期位置,调用gflags::parse()来解析命令行。此调用返回一个包含所有不在标志中的命令行内容的Vec<&str>(这些有时被称为位置参数)的向量。

在调用gflags::parse()之后,每个标志的值都可在标志的长名称的.flag字段中找到。

gflags::define! {
    --print-args = false
}

fn main() {
    let args = gflags::parse();

    if PRINT_ARGS.flag {
        println!("args = {:?}", args);
    }
}

如这个片段所示,标志名称可以包含短横线,在这种情况下,可以通过标志值访问的变量在短横线位置使用下划线代替。

此外,每个标志提供了一个方法.is_present()来查询该标志是否在命令行中提供。当使用未提供默认值的标志时,务必检查.is_present(),因为当标志不存在时访问.flag会导致恐慌。注意,没有默认值的标志必须指定它们的数据类型,如下所示。

use std::path::Path;

gflags::define! {
    /// Search for patterns from the given file, with one pattern per line.
    -f, --file: &Path
}

fn main() {
    let patterns = gflags::parse();

    if FILE.is_present() {
        let path = FILE.flag;
        println!("searching for patterns from file: {}", path.display());
    } else {
        println!("searching for patterns given on command line: {:?}", patterns);
    }
}

打印帮助

没有内置的-h标志用于帮助,但您可以定义自己的,并调用gflags::print_help_and_exit()来渲染所有标志的文档。

gflags::define! {
    -h, --help = false
}

fn main() {
    gflags::parse();
    if HELP.flag {
        gflags::print_help_and_exit(0);
    }

    /* ... */
}

对于本文档中显示的一些标志定义,帮助文本将按以下方式渲染。

        --big_menu
            Include 'advanced' options in the menu listing.

    -f, --file
            Search for patterns from the given file, with one pattern per line.

    -l, --language <LANG>
            Comma-separated list of languages to offer in the 'lang' menu.

标志按长名称的字母顺序列出。

您可能希望在此打印自己的内容,包括应用程序名称、版本、作者、简介说明和使用字符串。

自定义数据类型

gflags::define! 宏可以通过提供一个为你的数据类型实现的 gflags::custom::Value 来扩展到自定义数据类型。

use gflags::custom::{Arg, Error, Result, Value};

gflags::define! {
    --color <WHEN>: Color = Color::Auto
}

enum Color {
    Never,
    Always,
    Auto,
}

impl Value for Color {
    fn parse(arg: Arg) -> Result<Self> {
        match arg.get_str() {
            "never" => Ok(Color::Never),
            "always" => Ok(Color::Always),
            "auto" => Ok(Color::Auto),
            _ => Err(Error::new("invalid color")),
        }
    }
}

许可协议

根据你的选择,此软件受 Apache License, Version 2.0MIT 许可协议 许可。
除非你明确说明,否则你提交给此软件包的任何贡献,根据 Apache-2.0 许可协议定义,应按上述方式双重许可,不附加任何额外的条款或条件。

依赖关系

约 1.5MB
约 35K SLoC