1 个不稳定版本
0.1.0 | 2020 年 5 月 2 日 |
---|
#848 在 命令行界面
每月 141 次下载
36KB
370 行
gflags-derive
使用 gflags
从 struct
字段派生命令行参数。
这是 gflags
手册中“定义标志”部分的替代方案。
定义标志
创建一个结构体来包含您库或二进制的配置数据。
例如,这个假设的日志库定义了两个配置选项。
struct Config {
/// True if log messages should also be sent to STDERR
to_stderr: bool,
/// The directory to write log files to
dir: String,
}
通过在结构体上派生 gflags_derive::Gflags
将标志添加到注册表中。
use gflags_derive::GFlags;
#[derive(GFlags)]
struct Config {
/// True if log messages should also be sent to STDERR
to_stderr: bool,
/// The directory to write log files to
dir: String,
}
现在您有两个新的标志,就像您已经写了一样
gflags::define! {
/// True if log messages should also be sent to STDERR
--to_stderr: bool
}
gflags::define! {
/// The directory to write log files to
--dir: &str
}
注意:
- 每个结构体字段的注释也是标志的文档注释,它成为其帮助文本。
--dir
标志的类型已从String
转换为&str
。
定义标志前缀
您可能希望所有标志名称都有相同的前缀,而无需在字段名称中使用该前缀。例如,日志模块可能希望所有标志都从 log-
或 log_
开始。
为此,请使用结构体上的 #[gflags(prefix = "...")]
属性。
use gflags_derive::GFlags;
#[derive(GFlags)]
#[gflags(prefix = "log_")]
struct Config {
/// True if log messages should also be sent to STDERR
to_stderr: bool,
/// The directory to write log files to
dir: String,
}
现在标志定义包含前缀,就像您已经写了一样
gflags::define! {
/// True if log messages should also be sent to STDERR
--log_to_stderr: bool
}
gflags::define! {
/// The directory to write log files to
--log_dir: &str
}
如果标志前缀以 -
结尾,则宏将标志名称转换为 kebab-case 而不是 snake_case。因此,编写
use gflags_derive::GFlags;
#[derive(GFlags)]
#[gflags(prefix = "log-")]
struct Config {
/// True if log messages should also be sent to STDERR
to_stderr: bool,
/// The directory to write log files to
dir: String,
}
生成以下标志
gflags::define! {
/// True if log messages should also be sent to STDERR
--log-to-stderr: bool
}
gflags::define! {
/// The directory to write log files to
--log-dir: &str
}
处理 Option<T>
您的配置 struct
可能包含具有 Option<T>
类型的字段。对于这些字段,gflags_derive
会创建一个内部类型 T
的标志。
自定义默认值
要为标志指定默认值,请向字段添加一个 #[gflags(default = ...)]
属性。
该属性的值是字面值,而不是引用值。只有当字段的类型是字符串或可以从字符串创建时才引用值。
例如,要将 --log-to-stderr
标志的默认值设置为 true
use gflags_derive::GFlags;
#[derive(GFlags)]
#[gflags(prefix = "log-")]
struct Config {
/// True if log messages should also be sent to STDERR
#[gflags(default = true)]
to_stderr: bool,
/// The directory to write log files to
dir: String,
}
使用引号指定,#[gflags(default = "true")]
将导致编译时错误
expected `bool`, found `&str`
重要:这不会改变创建
Config
结构体实例时的默认值。它只改变LOG_TO_STDERR.flag
变量的默认值。
自定义类型
要使用不同类型的字段和命令行标志,请向字段添加一个 #[gflags(type = "...")]
属性。例如,要将日志目录存储为 PathBuf
,但在命令行上接受字符串
use gflags_derive::GFlags;
use std::path::PathBuf;
#[derive(GFlags)]
#[gflags(prefix = "log-")]
struct Config {
/// True if log messages should also be sent to STDERR
to_stderr: bool,
/// The directory to write log files to
#[gflags(type = "&str")]
dir: PathBuf,
}
自定义可见性
要为标志使用不同的可见性,请向字段添加一个 #[gflags(visibility = "...")]
属性,并给出 Rust 可见性指定符。
在此示例中,LOG_DIR
标志变量将在父模块中可见。
use gflags_derive::GFlags;
use std::path::PathBuf;
#[derive(GFlags)]
#[gflags(prefix = "log-")]
struct Config {
/// True if log messages should also be sent to STDERR
to_stderr: bool,
/// The directory to write log files to
#[gflags(visibility = "pub(super)")]
#[gflags(type = "&str")]
dir: PathBuf,
}
指定占位符
为了在标志的 help
输出中显示占位符,请将该字段添加一个 #[gflags(placeholder = "...")]
属性。这将用 <...>
包裹以供显示。
use gflags_derive::GFlags;
use std::path::PathBuf;
#[derive(GFlags)]
#[gflags(prefix = "log-")]
struct Config {
/// True if log messages should also be sent to STDERR
to_stderr: bool,
/// The directory to write log files to
#[gflags(placeholder = "DIR")]
#[gflags(type = "&str")]
dir: PathBuf,
}
在帮助输出中,--log-dir
标志将显示为
--log-dir <DIR>
The directory to write log files to
跳过标志
要跳过一个字段的标志生成,请将该字段添加一个 #[gflags(skip)]
属性。
use gflags_derive::GFlags;
use std::path::PathBuf;
#[derive(GFlags)]
#[gflags(prefix = "log-")]
struct Config {
/// True if log messages should also be sent to STDERR
to_stderr: bool,
/// The directory to write log files to
#[gflags(skip)]
dir: PathBuf,
}
不会生成 --log-dir
标志。
提供多个属性
如果您想在一个字段上提供多个属性,则可以在单个 #[gflags(...)]
属性中指定多个选项,或者指定多个 #[gflags(...)]
属性。以下示例是相同的。
...
/// The directory to write log files to
#[gflags(type = "&str", visibility = "pub(super)")]
dir: PathBuf,
...
...
/// The directory to write log files to
#[gflags(type = "&str")]
#[gflags(visibility = "pub(super)")]
dir: PathBuf,
...
反序列化和合并标志
这支持了一种强大的模式,用于配置由多个crate组成的应用程序,其中每个crate导出一个配置并支持多个标志,而应用程序crate定义了一个配置,该配置导入了组件crate中的配置结构体。
此主配置可以从例如JSON文件中反序列化,然后每个组件crate都有机会使用特定于该crate的命令行标志中的信息覆盖加载的配置。
有关实现此功能的完整应用程序,请参阅 examples/json
目录。
与 prost
一起使用
此宏可用于从使用 prost
和 prost-build
生成的Protobuffer模式生成的 structs
提取标志。
给定此 .proto
文件
syntax = "proto3"
package log.config.v1;
message Config {
// True if log messages should also be sent to STDERR
bool to_stderr = 1;
// The directory to write log files to
string dir = 2;
}
此 build.rs
文件将添加相关属性,添加 log-
前缀并跳过 dir
字段。
fn main() {
let mut config = prost_build::Config::new();
config.type_attribute(".log.config.v1.Config", "#[derive(gflags_derive::GFlags)]");
config.type_attribute(".log.config.v1.Config", "#[gflags(prefix=\"log-\")]");
config.field_attribute(".log.config.v1.Config.dir", "#[gflags(skip)]");
config
.compile_protos(&["proto/log/config/v1/config.proto"], &["proto"])
.unwrap();
}
有关实现此功能的完整应用程序,请参阅 examples/protobuf
目录。
许可:MIT OR Apache-2.0
依赖项
~1.5MB
~37K SLoC