Skip to content

Commit

Permalink
fix(parser): Arg::allow_hyphen_values correctly handles long args in …
Browse files Browse the repository at this point in the history
…first pos

This makes it match up with `Command::allow_hyphen_values` which was the
guiding factor for what the behavior should be.

This supersedes clap-rs#4039

Fixes clap-rs#3880
Fixes clap-rs#1538
  • Loading branch information
emersonford authored and epage committed Sep 7, 2022
1 parent 94a5e7f commit fd9a5a1
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 13 deletions.
16 changes: 16 additions & 0 deletions src/parser/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ impl<'cmd> Parser<'cmd> {
long_arg,
long_value,
&parse_state,
pos_counter,
&mut valid_arg_found,
)?;
debug!(
Expand Down Expand Up @@ -710,11 +711,13 @@ impl<'cmd> Parser<'cmd> {
long_arg: Result<&str, &RawOsStr>,
long_value: Option<&RawOsStr>,
parse_state: &ParseState,
pos_counter: usize,
valid_arg_found: &mut bool,
) -> ClapResult<ParseResult> {
// maybe here lifetime should be 'a
debug!("Parser::parse_long_arg");

#[allow(clippy::blocks_in_if_conditions)]
if matches!(parse_state, ParseState::Opt(opt) | ParseState::Pos(opt) if
self.cmd[opt].is_allow_hyphen_values_set())
{
Expand Down Expand Up @@ -807,6 +810,19 @@ impl<'cmd> Parser<'cmd> {
} else if self.cmd.is_allow_hyphen_values_set() {
debug!("Parser::parse_long_arg: contains non-long flag");
Ok(ParseResult::MaybeHyphenValue)
} else if self
.cmd
.get_keymap()
.get(&pos_counter)
.map_or(false, |arg| {
arg.is_allow_hyphen_values_set() && !arg.is_last_set()
})
{
debug!(
"Parser::parse_long_args: positional at {} allows hyphens",
pos_counter
);
Ok(ParseResult::MaybeHyphenValue)
} else {
Ok(ParseResult::NoMatchingArg {
arg: long_arg.to_owned(),
Expand Down
100 changes: 87 additions & 13 deletions tests/builder/app_settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -519,22 +519,78 @@ fn allow_negative_numbers_fail() {
}

#[test]
fn leading_double_hyphen_trailingvararg() {
let m = Command::new("positional")
.allow_hyphen_values(true)
.arg(arg!([opt] ... "some pos").trailing_var_arg(true))
.try_get_matches_from(vec!["", "--foo", "-Wl", "bar"])
.unwrap();
assert!(m.contains_id("opt"));
assert_eq!(
m.get_many::<String>("opt")
.unwrap()
.map(|v| v.as_str())
.collect::<Vec<_>>(),
&["--foo", "-Wl", "bar"]
fn trailing_var_arg_with_hyphen_values_escape_first() {
assert_trailing_var_args(&["test", "--", "foo", "bar"], Some(&["foo", "bar"]), false);
}

#[test]
fn trailing_var_arg_with_hyphen_values_escape_middle() {
assert_trailing_var_args(
&["test", "foo", "--", "bar"],
Some(&["foo", "--", "bar"]),
false,
);
}

#[test]
fn trailing_var_arg_with_hyphen_values_short_first() {
assert_trailing_var_args(&["test", "-p", "foo", "bar"], Some(&["foo", "bar"]), true);
}

#[test]
fn trailing_var_arg_with_hyphen_values_short_middle() {
assert_trailing_var_args(
&["test", "foo", "-p", "bar"],
Some(&["foo", "-p", "bar"]),
false,
);
}

#[test]
fn trailing_var_arg_with_hyphen_values_long_first() {
assert_trailing_var_args(
&["test", "--prog", "foo", "bar"],
Some(&["foo", "bar"]),
true,
);
}

#[test]
fn trailing_var_arg_with_hyphen_values_long_middle() {
assert_trailing_var_args(
&["test", "foo", "--prog", "bar"],
Some(&["foo", "--prog", "bar"]),
false,
);
}

#[track_caller]
fn assert_trailing_var_args(
input: &[&str],
expected_var_arg: Option<&[&str]>,
expected_flag: bool,
) {
let cmd = Command::new("test").arg(arg!(-p - -prog)).arg(
arg!([opt] ... "some pos")
.trailing_var_arg(true)
.allow_hyphen_values(true),
);
let m = cmd.try_get_matches_from(input);
assert!(
m.is_ok(),
"failed with args {:?}: {}",
input,
m.unwrap_err()
);
let m = m.unwrap();

let actual_var_args = m
.get_many::<String>("opt")
.map(|v| v.map(|s| s.as_str()).collect::<Vec<_>>());
assert_eq!(actual_var_args.as_deref(), expected_var_arg);
assert_eq!(m.get_flag("prog"), expected_flag);
}

#[test]
fn disable_help_subcommand() {
let result = Command::new("disablehelp")
Expand Down Expand Up @@ -829,6 +885,24 @@ fn issue_1437_allow_hyphen_values_for_positional_arg() {
);
}

#[test]
fn issue_3880_allow_long_flag_hyphen_value_for_positional_arg() {
let m = Command::new("prog")
.arg(
Arg::new("pat")
.allow_hyphen_values(true)
.required(true)
.action(ArgAction::Set),
)
.try_get_matches_from(["", "--file"])
.unwrap();

assert_eq!(
m.get_one::<String>("pat").map(|v| v.as_str()),
Some("--file")
);
}

#[test]
fn issue_1093_allow_ext_sc() {
let cmd = Command::new("clap-test")
Expand Down

0 comments on commit fd9a5a1

Please sign in to comment.