#[cfg(feature = "yaml")]
use std::collections::BTreeMap;
use std::fmt::{Debug, Formatter, Result};
#[cfg(feature = "yaml")]
use yaml_rust::Yaml;
pub struct ArgGroup<'n, 'ar> {
#[doc(hidden)]
pub name: &'n str,
#[doc(hidden)]
pub args: Vec<&'ar str>,
#[doc(hidden)]
pub required: bool,
#[doc(hidden)]
pub requires: Option<Vec<&'ar str>>,
#[doc(hidden)]
pub conflicts: Option<Vec<&'ar str>>,
}
impl<'n, 'ar> ArgGroup<'n, 'ar> {
pub fn with_name(n: &'n str) -> Self {
ArgGroup {
name: n,
required: false,
args: vec![],
requires: None,
conflicts: None,
}
}
#[cfg(feature = "yaml")]
pub fn from_yaml<'y>(y: &'y BTreeMap<Yaml, Yaml>) -> ArgGroup<'y, 'y> {
let name_yml = y.keys().nth(0).unwrap();
let name_str = name_yml.as_str().unwrap();
let mut a = ArgGroup::with_name(name_str);
let group_settings = y.get(name_yml).unwrap().as_hash().unwrap();
for (k, v) in group_settings.iter() {
a = match k.as_str().unwrap() {
"required" => a.required(v.as_bool().unwrap()),
"args" => {
for ys in v.as_vec().unwrap() {
if let Some(s) = ys.as_str() {
a = a.add(s);
}
}
a
}
"requires" => {
for ys in v.as_vec().unwrap() {
if let Some(s) = ys.as_str() {
a = a.requires(s);
}
}
a
}
"conflicts_with" => {
for ys in v.as_vec().unwrap() {
if let Some(s) = ys.as_str() {
a = a.conflicts_with(s);
}
}
a
}
s => panic!("Unknown ArgGroup setting '{}' in YAML file for \
ArgGroup '{}'",
s,
name_str),
}
}
a
}
pub fn add(mut self, n: &'ar str) -> Self {
assert!(self.name != n,
"ArgGroup '{}' can not have same name as arg inside it",
self.name);
self.args.push(n);
self
}
pub fn add_all(mut self, ns: &[&'ar str]) -> Self {
for n in ns {
self = self.add(n);
}
self
}
pub fn required(mut self, r: bool) -> Self {
self.required = r;
self
}
pub fn requires(mut self, n: &'ar str) -> Self {
if let Some(ref mut reqs) = self.requires {
reqs.push(n);
} else {
self.requires = Some(vec![n]);
}
self
}
pub fn requires_all(mut self, ns: &[&'ar str]) -> Self {
for n in ns {
self = self.requires(n);
}
self
}
pub fn conflicts_with(mut self, n: &'ar str) -> Self {
if let Some(ref mut confs) = self.conflicts {
confs.push(n);
} else {
self.conflicts = Some(vec![n]);
}
self
}
pub fn conflicts_with_all(mut self, ns: &[&'ar str]) -> Self {
for n in ns {
self = self.conflicts_with(n);
}
self
}
}
impl<'n, 'ar> Debug for ArgGroup<'n, 'ar> {
fn fmt(&self, f: &mut Formatter) -> Result {
write!(f,
"{{
name:{:?},
args: {:?},
required: {:?},
requires: {:?},
conflicts: {:?},
}}",
self.name,
self.args,
self.required,
self.requires,
self.conflicts)
}
}
#[cfg(test)]
mod test {
use super::ArgGroup;
#[test]
fn groups() {
let g = ArgGroup::with_name("test")
.add("a1")
.add_all(&["a2", "a3"])
.add("a4")
.required(true)
.conflicts_with("c1")
.conflicts_with_all(&["c2", "c3"])
.conflicts_with("c4")
.requires("r1")
.requires_all(&["r2", "r3"])
.requires("r4");
let args = vec!["a1", "a2", "a3", "a4"];
let reqs = vec!["r1", "r2", "r3", "r4"];
let confs = vec!["c1", "c2", "c3", "c4"];
assert_eq!(g.args, args);
assert_eq!(g.requires.unwrap(), reqs);
assert_eq!(g.conflicts.unwrap(), confs);
}
}