diff --git a/src/macros.rs b/src/macros.rs index f43573b42ef..13921b1474a 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -512,6 +512,32 @@ macro_rules! arg_impl { $($tail)* } }; + ( + @arg + ($arg:expr) + <$value_name:literal> + $($tail:tt)* + ) => { + $crate::arg_impl! { + @arg + ({ + debug_assert!(!$arg.is_multiple_occurrences_set(), "Values should precede `...`"); + debug_assert_eq!($arg.get_value_names(), None, "Multiple values not yet supported"); + + let mut arg = $arg; + + arg = arg.required(true); + arg = arg.takes_value(true); + + let value_name = $crate::arg_impl! { @string $value_name }; + if arg.get_id().is_empty() { + arg = arg.id(value_name); + } + arg.value_name(value_name) + }) + $($tail)* + } + }; ( @arg ($arg:expr) @@ -542,6 +568,36 @@ macro_rules! arg_impl { $($tail)* } }; + ( + @arg + ($arg:expr) + [$value_name:literal] + $($tail:tt)* + ) => { + $crate::arg_impl! { + @arg + ({ + debug_assert!(!$arg.is_multiple_occurrences_set(), "Values should precede `...`"); + debug_assert_eq!($arg.get_value_names(), None, "Multiple values not yet supported"); + + let mut arg = $arg; + + if arg.get_long().is_none() && arg.get_short().is_none() { + arg = arg.required(false); + } else { + arg = arg.min_values(0).max_values(1); + } + arg = arg.takes_value(true); + + let value_name = $crate::arg_impl! { @string $value_name }; + if arg.get_id().is_empty() { + arg = arg.id(value_name); + } + arg.value_name(value_name) + }) + $($tail)* + } + }; ( @arg ($arg:expr) diff --git a/tests/macros.rs b/tests/macros.rs index 075724b9c60..caa7b270fbd 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -469,4 +469,60 @@ mod arg_impl { let actual = clap::arg_impl! { @char 'o' }; assert_eq!(actual, expected); } + + #[test] + // allow double quoted dashed arg name in square brackets (e.g ["some-arg"]) + fn arg_name_dashed() { + let arg = clap::arg!(["some-arg"] "some arg"); + assert_eq!(arg, clap::Arg::new("some-arg").help("some arg")); + + let m = clap::Command::new("flag") + .arg(arg) + .try_get_matches_from(vec!["", "some-val"]) + .unwrap(); + assert!(m.is_present("some-arg")); + assert_eq!(m.value_of("some-arg").unwrap(), "some-val"); + } + + #[test] + // allow double quoted dashed arg value in triangle brackets (e.g <"some-val">) + // test in combination with short argument name (e.g. -v) + fn arg_value_dashed_with_short_arg() { + let arg = clap::arg!(-a <"some-val"> "some arg"); + assert_eq!( + arg, + clap::Arg::new("some-val") + .short('a') + .long("arg") + .value_name("some-val") + ); + + let m = clap::Command::new("cmd") + .arg(arg) + .try_get_matches_from(vec!["", "-a", "val"]) + .unwrap(); + assert!(m.is_present("some-val")); + assert_eq!(m.value_of("some-val").unwrap(), "val"); + } + + #[test] + // allow double quoted dashed arg value in triangle brackets (e.g <"some-val">) + // test in combination with long argument name (e.g. --value) + fn arg_value_dashed_with_long_arg() { + let arg = clap::arg!(-a --arg <"some-val"> "some arg"); + assert_eq!( + arg, + clap::Arg::new("arg") + .short('a') + .long("arg") + .value_name("some-val") + ); + + let m = clap::Command::new("cmd") + .arg(arg) + .try_get_matches_from(vec!["", "--arg", "some-val"]) + .unwrap(); + assert!(m.is_present("arg")); + assert_eq!(m.value_of("arg").unwrap(), "some-val"); + } }