From e6ee585a4b36d540e19f741b680bc944912aa3c2 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 4 Jan 2022 09:00:13 -0600 Subject: [PATCH 1/2] fix: Clarify short rejection in debug --- src/lib.rs | 2 ++ src/parse/parser.rs | 33 +++++++++++++++++++++++---------- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 02b4d682..fcc7b4fa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,6 +19,8 @@ // HACK https://github.com/rust-lang/rust-clippy/issues/7290 #![allow(clippy::single_component_path_imports)] #![allow(clippy::branches_sharing_code)] +// Doesn't allow for debug statements, etc to be unique +#![allow(clippy::if_same_then_else)] #[cfg(not(feature = "std"))] compile_error!("`std` feature is currently required to build `clap`"); diff --git a/src/parse/parser.rs b/src/parse/parser.rs index d490f851..d7598963 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -1181,17 +1181,30 @@ impl<'help, 'app> Parser<'help, 'app> { debug!("Parser::parse_short_arg: short_arg={:?}", short_arg); let arg = short_arg.to_str_lossy(); - if (self.is_set(AS::AllowNegativeNumbers) && arg.parse::().is_ok()) - || (self.is_set(AS::AllowHyphenValues) - && arg.chars().any(|c| !self.app.contains_short(c))) - || matches!(parse_state, ParseState::Opt(opt) | ParseState::Pos(opt) - if self.app[opt].is_set(ArgSettings::AllowHyphenValues)) - || self - .app - .args - .get(&pos_counter) - .map_or(false, |arg| arg.is_set(ArgSettings::AllowHyphenValues)) + #[allow(clippy::blocks_in_if_conditions)] + if self.is_set(AS::AllowNegativeNumbers) && arg.parse::().is_ok() { + debug!("Parser::parse_short_arg: negative number"); + return ParseResult::MaybeHyphenValue; + } else if self.is_set(AS::AllowHyphenValues) + && arg.chars().any(|c| !self.app.contains_short(c)) { + debug!("Parser::parse_short_args: contains non-short flag"); + return ParseResult::MaybeHyphenValue; + } else if matches!(parse_state, ParseState::Opt(opt) | ParseState::Pos(opt) + if self.app[opt].is_set(ArgSettings::AllowHyphenValues)) + { + debug!("Parser::parse_short_args: prior arg accepts hyphenated values",); + return ParseResult::MaybeHyphenValue; + } else if self + .app + .args + .get(&pos_counter) + .map_or(false, |arg| arg.is_set(ArgSettings::AllowHyphenValues)) + { + debug!( + "Parser::parse_short_args: positional at {} allows hyphens", + pos_counter + ); return ParseResult::MaybeHyphenValue; } From 15704dcaff585cae96fd7781912df5c4b6f6b244 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 4 Jan 2022 09:04:31 -0600 Subject: [PATCH 2/2] fix(parser): Ignore Last when checking Hyphe Values This was found with #3249 --- src/parse/parser.rs | 9 +++------ tests/builder/positionals.rs | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/parse/parser.rs b/src/parse/parser.rs index d7598963..10e9b624 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -1195,12 +1195,9 @@ impl<'help, 'app> Parser<'help, 'app> { { debug!("Parser::parse_short_args: prior arg accepts hyphenated values",); return ParseResult::MaybeHyphenValue; - } else if self - .app - .args - .get(&pos_counter) - .map_or(false, |arg| arg.is_set(ArgSettings::AllowHyphenValues)) - { + } else if self.app.args.get(&pos_counter).map_or(false, |arg| { + arg.is_set(ArgSettings::AllowHyphenValues) && !arg.is_set(ArgSettings::Last) + }) { debug!( "Parser::parse_short_args: positional at {} allows hyphens", pos_counter diff --git a/tests/builder/positionals.rs b/tests/builder/positionals.rs index 6452aac2..e7f1a6d4 100644 --- a/tests/builder/positionals.rs +++ b/tests/builder/positionals.rs @@ -287,3 +287,24 @@ fn positional_arg_with_short() { .arg(Arg::new("arg").index(1).short('a')) .try_get_matches(); } + +#[test] +fn ignore_hyphen_values_on_last() { + let app = clap::App::new("foo") + .arg( + clap::Arg::new("cmd") + .multiple_values(true) + .last(true) + .allow_hyphen_values(true), + ) + .arg( + clap::Arg::new("name") + .long("name") + .short('n') + .takes_value(true) + .required(false), + ); + + let matches = app.try_get_matches_from(["test", "-n", "foo"]).unwrap(); + assert_eq!(matches.value_of("name"), Some("foo")); +}