1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use crate::map::MapPropertySource;
use crate::*;
#[cfg(feature = "enable_clap")]
use clap::{App, Arg};
#[cfg(feature = "enable_clap")]
use regex::Regex;
use std::collections::HashMap;
#[cfg(feature = "enable_clap")]
const NOT_POSSIBLE: &'static str = "Not possible";
pub enum SysArgsMode {
#[cfg(feature = "enable_clap")]
#[cfg_attr(docsrs, doc(cfg(feature = "enable_clap")))]
Auto(SysArgsParam),
Custom(Vec<(String, Property)>),
}
#[cfg(feature = "enable_clap")]
#[cfg_attr(docsrs, doc(cfg(feature = "enable_clap")))]
pub struct SysArgsParam {
pub name: &'static str,
pub version: &'static str,
pub author: Option<&'static str>,
pub about: Option<&'static str>,
}
#[macro_export]
#[cfg(feature = "enable_clap")]
#[cfg_attr(docsrs, doc(cfg(feature = "enable_clap")))]
macro_rules! auto_read_sys_args_param {
() => {
args::SysArgsParam {
name: env!("CARGO_PKG_NAME"),
version: env!("CARGO_PKG_VERSION"),
author: option_env!("CARGO_PKG_AUTHORS"),
about: option_env!("CARGO_PKG_DESCRIPTION"),
}
};
}
pub(crate) struct SysArgs(pub(crate) MapPropertySource);
impl SysArgs {
pub fn new(args: SysArgsMode) -> Self {
let args = match args {
#[cfg(feature = "enable_clap")]
SysArgsMode::Auto(arg) => Self::new_default_args(arg),
SysArgsMode::Custom(arg) => arg,
};
let mut map = HashMap::new();
for (k, v) in args {
map.insert(k, v);
}
SysArgs(MapPropertySource::new("SystemArguments".to_owned(), map))
}
#[cfg(feature = "enable_clap")]
fn new_default_args(param: SysArgsParam) -> Vec<(String, Property)> {
let mut app = App::new(param.name).version(param.version);
if let Some(a) = param.author {
app = app.author(a);
}
if let Some(a) = param.about {
app = app.about(a);
}
let matches = app
.arg(
Arg::with_name("property")
.short("P")
.long("property")
.value_name("KEY=VALUE")
.multiple(true)
.number_of_values(1)
.takes_value(true)
.help("Set properties"),
)
.get_matches();
lazy_static::lazy_static! {
static ref RE: Regex = Regex::new(
r"^([^=]+)=(.+)$"
)
.expect(NOT_POSSIBLE);
}
matches
.values_of_lossy("property")
.unwrap_or(vec![])
.iter()
.flat_map(|k| match RE.captures(&k) {
Some(ref v) => Some((
v.get(1).unwrap().as_str().to_owned(),
Property::Str(v.get(2).unwrap().as_str().to_owned()),
)),
_ => None,
})
.collect()
}
}
#[cfg(feature = "enable_clap")]
#[cfg_attr(docsrs, doc(cfg(feature = "enable_clap")))]
impl Default for SysArgs {
fn default() -> Self {
SysArgs::new(SysArgsMode::Auto(auto_read_sys_args_param!()))
}
}
#[cfg(test)]
mod tests {
#[test]
#[cfg(feature = "enable_clap")]
fn test_auto_read_sys_args_param() {
use crate::args;
let m = auto_read_sys_args_param!();
assert_eq!("salak", m.name);
}
}