Skip to content

Commit

Permalink
fix(Multiple Values): fixes bug where number_of_values wasnt respected
Browse files Browse the repository at this point in the history
i.e. assume, option -O set to multiple, and number_of_values(1)
set. And assume a *required* positional argument is also set.

-O some -O other pos

Would fail with pos arg not supplied.

Relates to #415
  • Loading branch information
kbknapp committed Feb 5, 2016
1 parent 106a13d commit 72c387d
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 26 deletions.
28 changes: 2 additions & 26 deletions src/app/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -986,7 +986,7 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
// Increment or create the group "args"
self.groups_for_arg(opt.name).and_then(|vec| Some(matcher.inc_occurrences_of(&*vec)));

if val.is_none() || opt.is_set(ArgSettings::Multiple) {
if val.is_none() || (opt.is_set(ArgSettings::Multiple) && matcher.needs_more_vals(opt)) {
return Ok(Some(opt.name));
}
Ok(None)
Expand Down Expand Up @@ -1054,31 +1054,7 @@ impl<'a, 'b> Parser<'a, 'b> where 'a: 'b {
return Err(Error::value_validation(e));
}
}
let vals = matcher.get(&*arg.name())
.expect(INTERNAL_ERROR_MSG)
.vals.len();
if let Some(max) = arg.max_vals() {
if (vals as u64) < max {
return Ok(Some(arg.name()));
} else {
return Ok(None);
}
}
if let Some(..) = arg.min_vals() {
return Ok(Some(arg.name()));
}
if let Some(num) = arg.num_vals() {
if arg.is_set(ArgSettings::Multiple) {
if (vals as u64) < num {
return Ok(Some(arg.name()));
}
} else {
if (vals as u64 % num) != 0 {
return Ok(Some(arg.name()));
}
}
}
if arg.is_set(ArgSettings::Multiple) {
if matcher.needs_more_vals(arg) {
return Ok(Some(arg.name()));
}
Ok(None)
Expand Down
21 changes: 21 additions & 0 deletions src/args/arg_matcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use std::ops::Deref;
use vec_map::VecMap;

use args::{ArgMatches, MatchedArg, SubCommand};
use args::settings::ArgSettings;
use args::AnyArg;

#[doc(hidden)]
pub struct ArgMatcher<'a>(pub ArgMatches<'a>);
Expand Down Expand Up @@ -91,6 +93,25 @@ impl<'a> ArgMatcher<'a> {
let len = ma.vals.len() + 1;
ma.vals.insert(len, val.to_owned());
}

pub fn needs_more_vals<'b, A>(&self, o: &A) -> bool
where A: AnyArg<'a, 'b> {
if let Some(ma) = self.get(o.name()) {
if let Some(num) = o.num_vals() {
return if o.is_set(ArgSettings::Multiple) {
((ma.vals.len() as u64) % num) != 0
} else {
num != (ma.vals.len() as u64)
};
} else if let Some(num) = o.max_vals() {
return !((ma.vals.len() as u64) > num);
} else if let Some(num) = o.min_vals() {
return (ma.vals.len() as u64) < num;
}
return o.is_set(ArgSettings::Multiple);
}
true
}
}

impl<'a> Into<ArgMatches<'a>> for ArgMatcher<'a> {
Expand Down

0 comments on commit 72c387d

Please sign in to comment.