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
use std::collections::HashMap;
use crate::{derive::KeyDescs, KeyDesc, PropertyError};
#[derive(Debug)]
#[cfg_attr(docsrs, doc(cfg(feature = "args")))]
pub struct AppInfo<'a> {
pub name: &'a str,
pub version: &'a str,
pub author: Option<&'a str>,
pub about: Option<&'a str>,
}
#[macro_export]
#[cfg_attr(docsrs, doc(cfg(feature = "args")))]
macro_rules! app_info {
() => {
AppInfo {
name: std::env!("CARGO_PKG_NAME"),
version: std::env!("CARGO_PKG_VERSION"),
author: std::option_env!("CARGO_PKG_AUTHORS"),
about: std::option_env!("CARGO_PKG_DESCRIPTION"),
}
};
}
fn parse(s: String) -> Result<(String, String), PropertyError> {
if let Some(usize) = s.find("=") {
return Ok((s[..usize - 1].to_string(), s[usize..].to_string()));
}
Err(PropertyError::parse_fail("Invalid arguments"))
}
#[cfg_attr(docsrs, doc(cfg(feature = "args")))]
pub fn from_args(
desc: Vec<KeyDesc>,
info: AppInfo<'_>,
) -> Result<HashMap<String, String>, PropertyError> {
let help = format!("KEYS:\n{}\n", &KeyDescs(desc));
let mut app = clap::App::new(info.name)
.version(info.version)
.arg(
clap::Arg::with_name("property")
.long("property")
.short("P")
.value_name("KEY=VALUE")
.multiple(true)
.help("Set properties."),
)
.after_help(help.as_str());
if let Some(v) = info.author {
app = app.author(v);
}
if let Some(v) = info.about {
app = app.about(v);
}
Ok(app
.get_matches()
.values_of_lossy("property")
.unwrap_or(vec![])
.into_iter()
.map(|f| parse(f))
.collect::<Result<Vec<(String, String)>, PropertyError>>()?
.into_iter()
.collect::<HashMap<String, String>>())
}