Skip to content

Commit ab06454

Browse files
committed
feat(AppSettings): adds new setting AllowNegativeNumbers
One can now use `AppSettings::AllowNegativeNumbers` which functions similar to `AllowLeadingHyphen` with the exception that only unknown numbers are allowed have a preceding hyphen character. See the documentation for details and examples. Closes #696
1 parent 5702657 commit ab06454

File tree

1 file changed

+22
-31
lines changed

1 file changed

+22
-31
lines changed

src/app/parser.rs

+22-31
Original file line numberDiff line numberDiff line change
@@ -566,45 +566,30 @@ impl<'a, 'b> Parser<'a, 'b>
566566
// Is this a new argument, or values from a previous option?
567567
debug!("Starts new arg...");
568568
let starts_new_arg = if arg_os.starts_with(b"-") {
569-
sdebugln!("Yes");
569+
sdebugln!("Maybe");
570+
// a singe '-' by itself is a value and typically means "stdin" on unix systems
570571
!(arg_os.len_() == 1)
571572
} else {
572573
sdebugln!("No");
573574
false
574575
};
575576

576-
// Has the user already passed '--'?
577+
// Has the user already passed '--'? Meaning only positional args follow
577578
if !self.trailing_vals {
578579
// Does the arg match a subcommand name, or any of it's aliases (if defined)
579-
let pos_sc = self.subcommands
580-
.iter()
581-
.any(|s| {
582-
&s.p.meta.name[..] == &*arg_os ||
583-
(s.p.meta.aliases.is_some() &&
584-
s.p
585-
.meta
586-
.aliases
587-
.as_ref()
588-
.unwrap()
589-
.iter()
590-
.any(|&(a, _)| a == &*arg_os))
591-
});
592-
if (!starts_new_arg || self.is_set(AppSettings::AllowLeadingHyphen)) && !pos_sc {
580+
let pos_sc = self.possible_subcommand(&arg_os);
581+
582+
// If the arg doesn't start with a `-` (except numbers, or AllowLeadingHyphen) and
583+
// isn't a subcommand
584+
if (!starts_new_arg ||
585+
(self.is_set(AppSettings::AllowLeadingHyphen) ||
586+
self.is_set(AppSettings::AllowNegativeNumbers))) &&
587+
!pos_sc {
593588
// Check to see if parsing a value from an option
594-
if let Some(nvo) = needs_val_of {
589+
if let Some(arg) = needs_val_of {
595590
// get the OptBuilder so we can check the settings
596-
if let Some(opt) = self.opts
597-
.iter()
598-
.find(|o| {
599-
&o.name == &nvo ||
600-
(o.aliases.is_some() &&
601-
o.aliases
602-
.as_ref()
603-
.unwrap()
604-
.iter()
605-
.any(|&(a, _)| a == &*nvo))
606-
}) {
607-
needs_val_of = try!(self.add_val_to_arg(opt, &arg_os, matcher));
591+
if let Some(ref opt) = self.get_opt(&arg) {
592+
needs_val_of = try!(self.add_val_to_arg(*opt, &arg_os, matcher));
608593
// get the next value from the iterator
609594
continue;
610595
}
@@ -752,7 +737,8 @@ impl<'a, 'b> Parser<'a, 'b>
752737
name: sc_name,
753738
matches: sc_m.into(),
754739
});
755-
} else if !self.settings.is_set(AppSettings::AllowLeadingHyphen) {
740+
} else if !(self.is_set(AppSettings::AllowLeadingHyphen) ||
741+
self.is_set(AppSettings::AllowNegativeNumbers)) {
756742
return Err(Error::unknown_argument(&*arg_os.to_string_lossy(),
757743
"",
758744
&*self.create_current_usage(matcher),
@@ -1262,6 +1248,10 @@ impl<'a, 'b> Parser<'a, 'b>
12621248
return Ok(None);
12631249
} else if self.is_set(AppSettings::AllowLeadingHyphen) {
12641250
return Ok(None);
1251+
} else if self.is_set(AppSettings::AllowNegativeNumbers) &&
1252+
(arg.to_string_lossy().parse::<i64>().is_ok() ||
1253+
arg.to_string_lossy().parse::<f64>().is_ok()) {
1254+
return Ok(None);
12651255
}
12661256

12671257
debugln!("Didn't match anything");
@@ -1319,7 +1309,8 @@ impl<'a, 'b> Parser<'a, 'b>
13191309
// Handle conflicts, requirements, overrides, etc.
13201310
// Must be called here due to mutablilty
13211311
arg_post_processing!(self, flag, matcher);
1322-
} else if !self.is_set(AppSettings::AllowLeadingHyphen) {
1312+
} else if !(self.is_set(AppSettings::AllowLeadingHyphen) ||
1313+
self.is_set(AppSettings::AllowNegativeNumbers)) {
13231314
let mut arg = String::new();
13241315
arg.push('-');
13251316
arg.push(c);

0 commit comments

Comments
 (0)