#flags #command-line #list #central #command-line-arguments #require #parse

gflags

不依赖于中央列表的所有标志的命令行标志库

15个版本

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日

命令行界面 中排名第 642

Download history 223/week @ 2024-03-14 206/week @ 2024-03-21 185/week @ 2024-03-28 230/week @ 2024-04-04 330/week @ 2024-04-11 376/week @ 2024-04-18 460/week @ 2024-04-25 287/week @ 2024-05-02 41/week @ 2024-05-09 99/week @ 2024-05-16 403/week @ 2024-05-23 957/week @ 2024-05-30 870/week @ 2024-06-06 1245/week @ 2024-06-13 878/week @ 2024-06-20 712/week @ 2024-06-27

每月下载量 3,893
2 crate 中使用

MIT/Apache

46KB
642 代码行

gflags

github crates.io docs.rs build status

类似于 gflags(原Google Commandline Flags) 风格的命令行标志库。

[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许可协议定义,您有意提交以包含在此包中的任何贡献,将以上述方式双许可,不附加任何额外条款或条件。

依赖项

~340–790KB
~18K SLoC