Skip to content

Commit

Permalink
feat(from_usage): adds ability to add value names or num of vals in u…
Browse files Browse the repository at this point in the history
…sage string

Allows new usage strings with value names or number of values. If the
names are consecutive, they are counted to represent the number of
values (if they all have the same name), or if their names are different
they are used as value names.

Closes #98
  • Loading branch information
kbknapp committed May 5, 2015
1 parent a87d970 commit ad55748
Show file tree
Hide file tree
Showing 2 changed files with 249 additions and 16 deletions.
65 changes: 49 additions & 16 deletions src/args/arg.rs
@@ -1,4 +1,5 @@
use std::iter::IntoIterator;
use std::collections::HashSet;

use usageparser::{UsageParser, UsageToken};

Expand Down Expand Up @@ -79,7 +80,7 @@ pub struct Arg<'n, 'l, 'h, 'g, 'p, 'r> {
#[doc(hidden)]
pub group: Option<&'g str>,
#[doc(hidden)]
pub val_names: Option<Vec<&'p str>>,
pub val_names: Option<Vec<&'n str>>,
#[doc(hidden)]
pub num_vals: Option<u8>,
#[doc(hidden)]
Expand Down Expand Up @@ -229,34 +230,57 @@ impl<'n, 'l, 'h, 'g, 'p, 'r> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
let mut required = false;
let mut takes_value = false;
let mut multiple = false;
let mut num_names = 1;
let mut name_first = false;
let mut consec_names = false;
let mut val_names = HashSet::new();

let parser = UsageParser::with_usage(u);
for_match!{ parser,
UsageToken::Name(n, req) => {
if name.is_none() {
if consec_names {
num_names += 1;
}
let mut use_req = false;
let mut use_name = false;
if name.is_none() && long.is_none() && short.is_none() {
name_first = true;
use_name = true;
use_req = true;
} else if let Some(l) = long {
if l == name.unwrap_or("") {
if !name_first {
use_name = true;
use_req = true;
}
}
} else {
// starting with short
if !name_first {
use_name = true;
use_req = true;
}
}
if use_name && !consec_names {
name = Some(n);
}
if use_req && !consec_names {
if let Some(r) = req {
required = r;
}
} else if let Some(l) = long {
if l == name.unwrap() {
if let Some(r) = req {
required = r;
}
name = Some(n);
} else if n != l {
name = Some(n);
}

}
if short.is_some() || long.is_some() {
val_names.insert(n);
takes_value = true;
}
consec_names = true;
},
UsageToken::Short(s) => {
consec_names = false;
short = Some(s);
},
UsageToken::Long(l) => {
consec_names = false;
long = Some(l);
if name.is_none() {
name = Some(l);
Expand All @@ -270,6 +294,15 @@ impl<'n, 'l, 'h, 'g, 'p, 'r> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
}
}

if let Some(l) = long {
val_names.remove(l);
if val_names.len() > 1 {
if name.unwrap() != l && !name_first {
name = Some(l);
}
}
}

Arg {
name: name.unwrap(),
short: short,
Expand All @@ -282,8 +315,8 @@ impl<'n, 'l, 'h, 'g, 'p, 'r> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
possible_vals: None,
blacklist: None,
requires: None,
num_vals: None,
val_names: None,
num_vals: if num_names > 1 { Some(num_names) } else { None },
val_names: if val_names.len() > 1 {Some(val_names.iter().map(|s| *s).collect::<Vec<_>>())}else{None},
max_vals: None,
min_vals: None,
group: None,
Expand Down Expand Up @@ -765,8 +798,8 @@ impl<'n, 'l, 'h, 'g, 'p, 'r> Arg<'n, 'l, 'h, 'g, 'p, 'r> {
/// # ).get_matches();
pub fn value_names<T, I>(mut self, names: I)
-> Arg<'n, 'l, 'h, 'g, 'p, 'r>
where T: AsRef<str> + 'p,
I: IntoIterator<Item=&'p T> {
where T: AsRef<str> + 'n,
I: IntoIterator<Item=&'n T> {
if let Some(ref mut vec) = self.val_names {
names.into_iter().map(|s| vec.push(s.as_ref())).collect::<Vec<_>>();
} else {
Expand Down

0 comments on commit ad55748

Please sign in to comment.