Skip to content

Commit

Permalink
feat(Options): adds the ability to require the equals syntax with opt…
Browse files Browse the repository at this point in the history
…ions --opt=val

Closes #833
  • Loading branch information
kbknapp committed Feb 21, 2017
1 parent e0f7722 commit f002693
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 20 deletions.
20 changes: 14 additions & 6 deletions src/app/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1387,7 +1387,7 @@ impl<'a, 'b> Parser<'a, 'b>
if let Some(opt) = find_by_long!(self, &arg, opts) {
debugln!("Parser::parse_long_arg: Found valid opt '{}'", opt.to_string());
self.valid_arg = true;
let ret = try!(self.parse_opt(val, opt, matcher));
let ret = try!(self.parse_opt(val, opt, val.is_some(), matcher));
arg_post_processing!(self, opt, matcher);

return Ok(ret);
Expand Down Expand Up @@ -1469,7 +1469,7 @@ impl<'a, 'b> Parser<'a, 'b>
};

// Default to "we're expecting a value later"
let ret = try!(self.parse_opt(val, opt, matcher));
let ret = try!(self.parse_opt(val, opt, false, matcher));

arg_post_processing!(self, opt, matcher);

Expand Down Expand Up @@ -1501,17 +1501,19 @@ impl<'a, 'b> Parser<'a, 'b>
fn parse_opt(&self,
val: Option<&OsStr>,
opt: &OptBuilder<'a, 'b>,
had_eq: bool,
matcher: &mut ArgMatcher<'a>)
-> ClapResult<Option<&'a str>> {
debugln!("Parser::parse_opt;");
debugln!("Parser::parse_opt; opt={}, val={:?}", opt.b.name, val);
debugln!("Parser::parse_opt; opt.settings={:?}", opt.b.settings);
validate_multiples!(self, opt, matcher);
let mut has_eq = false;

debug!("Parser::parse_optChecking for val...");
debug!("Parser::parse_opt; Checking for val...");
if let Some(fv) = val {
has_eq = fv.starts_with(&[b'=']);
has_eq = fv.starts_with(&[b'=']) || had_eq;
let v = fv.trim_left_matches(b'=');
if !opt.is_set(ArgSettings::EmptyValues) && v.len_() == 0 {
if !opt.is_set(ArgSettings::EmptyValues) && (v.len_() == 0 || (opt.is_set(ArgSettings::RequireEquals) && !has_eq)) {
sdebugln!("Found Empty - Error");
return Err(Error::empty_value(opt,
&*self.create_current_usage(matcher, None),
Expand All @@ -1520,6 +1522,12 @@ impl<'a, 'b> Parser<'a, 'b>
sdebugln!("Found - {:?}, len: {}", v, v.len_());
debugln!("Parser::parse_opt: {:?} contains '='...{:?}", fv, fv.starts_with(&[b'=']));
try!(self.add_val_to_arg(opt, v, matcher));
} else if opt.is_set(ArgSettings::RequireEquals) && !opt.is_set(ArgSettings::EmptyValues) {
sdebugln!("None, but requires equals...Error");
return Err(Error::empty_value(opt,
&*self.create_current_usage(matcher, None),
self.color()));

} else {
sdebugln!("None");
}
Expand Down
35 changes: 21 additions & 14 deletions src/args/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,20 @@ use std::str::FromStr;

bitflags! {
flags Flags: u16 {
const REQUIRED = 0b0000000000001,
const MULTIPLE = 0b0000000000010,
const EMPTY_VALS = 0b0000000000100,
const GLOBAL = 0b0000000001000,
const HIDDEN = 0b0000000010000,
const TAKES_VAL = 0b0000000100000,
const USE_DELIM = 0b0000001000000,
const NEXT_LINE_HELP = 0b0000010000000,
const R_UNLESS_ALL = 0b0000100000000,
const REQ_DELIM = 0b0001000000000,
const DELIM_NOT_SET = 0b0010000000000,
const HIDE_POS_VALS = 0b0100000000000,
const ALLOW_TAC_VALS = 0b1000000000000,
const REQUIRED = 0b00000000000001,
const MULTIPLE = 0b00000000000010,
const EMPTY_VALS = 0b00000000000100,
const GLOBAL = 0b00000000001000,
const HIDDEN = 0b00000000010000,
const TAKES_VAL = 0b00000000100000,
const USE_DELIM = 0b00000001000000,
const NEXT_LINE_HELP = 0b00000010000000,
const R_UNLESS_ALL = 0b00000100000000,
const REQ_DELIM = 0b00001000000000,
const DELIM_NOT_SET = 0b00010000000000,
const HIDE_POS_VALS = 0b00100000000000,
const ALLOW_TAC_VALS = 0b01000000000000,
const REQUIRE_EQUALS = 0b10000000000000,
}
}

Expand All @@ -40,7 +41,8 @@ impl ArgFlags {
RequireDelimiter => REQ_DELIM,
ValueDelimiterNotSet => DELIM_NOT_SET,
HidePossibleValues => HIDE_POS_VALS,
AllowLeadingHyphen => ALLOW_TAC_VALS
AllowLeadingHyphen => ALLOW_TAC_VALS,
RequireEquals => REQUIRE_EQUALS
}
}

Expand Down Expand Up @@ -78,6 +80,8 @@ pub enum ArgSettings {
HidePossibleValues,
/// Allows vals that start with a '-'
AllowLeadingHyphen,
/// Require options use `--option=val` syntax
RequireEquals,
#[doc(hidden)]
RequiredUnlessAll,
#[doc(hidden)]
Expand All @@ -101,6 +105,7 @@ impl FromStr for ArgSettings {
"valuedelimiternotset" => Ok(ArgSettings::ValueDelimiterNotSet),
"hidepossiblevalues" => Ok(ArgSettings::HidePossibleValues),
"allowleadinghyphen" => Ok(ArgSettings::AllowLeadingHyphen),
"requireequals" => Ok(ArgSettings::RequireEquals),
_ => Err("unknown ArgSetting, cannot convert from str".to_owned()),
}
}
Expand Down Expand Up @@ -138,6 +143,8 @@ mod test {
ArgSettings::UseValueDelimiter);
assert_eq!("valuedelimiternotset".parse::<ArgSettings>().unwrap(),
ArgSettings::ValueDelimiterNotSet);
assert_eq!("requireequals".parse::<ArgSettings>().unwrap(),
ArgSettings::RequireEquals);
assert!("hahahaha".parse::<ArgSettings>().is_err());
}
}

0 comments on commit f002693

Please sign in to comment.