From 008579cf4150a100d003874b65d3336fcf47bfde Mon Sep 17 00:00:00 2001 From: Evgeniy Terekhin Date: Fri, 6 May 2022 16:02:30 +0200 Subject: [PATCH 1/2] add support for dashed arg names and values in arg! macro --- src/macros.rs | 56 ++++++++++++++++++++++++++++++++++++++ tests/builder/arg_name.rs | 14 ++++++++++ tests/builder/arg_value.rs | 39 ++++++++++++++++++++++++++ tests/builder/main.rs | 2 ++ 4 files changed, 111 insertions(+) create mode 100644 tests/builder/arg_name.rs create mode 100644 tests/builder/arg_value.rs 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/builder/arg_name.rs b/tests/builder/arg_name.rs new file mode 100644 index 00000000000..9f3b71f3321 --- /dev/null +++ b/tests/builder/arg_name.rs @@ -0,0 +1,14 @@ +use clap::{arg, Arg, Command}; + +#[test] +fn arg_name_dashed() { + let arg = arg!(["some-arg"] "some arg"); + assert_eq!(arg, Arg::new("some-arg").help("some arg")); + + let m = 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"); +} diff --git a/tests/builder/arg_value.rs b/tests/builder/arg_value.rs new file mode 100644 index 00000000000..e24089eb1aa --- /dev/null +++ b/tests/builder/arg_value.rs @@ -0,0 +1,39 @@ +use clap::{arg, Arg, Command}; + +#[test] +fn arg_value_dashed_with_short() { + let arg = arg!(-a <"some-val"> "some arg"); + assert_eq!( + arg, + Arg::new("some-val") + .short('a') + .long("arg") + .value_name("some-val") + ); + + let m = 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] +fn arg_value_dashed_with_long() { + let arg = arg!(-a --arg <"some-val"> "some arg"); + assert_eq!( + arg, + Arg::new("arg") + .short('a') + .long("arg") + .value_name("some-val") + ); + + let m = 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"); +} diff --git a/tests/builder/main.rs b/tests/builder/main.rs index 124111f1011..d92d4e84873 100644 --- a/tests/builder/main.rs +++ b/tests/builder/main.rs @@ -3,7 +3,9 @@ mod app_settings; mod arg_aliases; mod arg_aliases_short; mod arg_matcher_assertions; +mod arg_name; mod arg_settings; +mod arg_value; mod borrowed; mod cargo; mod command; From e4e34522ffd0733a93b73c1f02e9c01b2d82962d Mon Sep 17 00:00:00 2001 From: Evgeniy Terekhin Date: Fri, 6 May 2022 17:05:04 +0200 Subject: [PATCH 2/2] move tests --- tests/builder/arg_name.rs | 14 ---------- tests/builder/arg_value.rs | 39 -------------------------- tests/builder/main.rs | 2 -- tests/macros.rs | 56 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 55 deletions(-) delete mode 100644 tests/builder/arg_name.rs delete mode 100644 tests/builder/arg_value.rs diff --git a/tests/builder/arg_name.rs b/tests/builder/arg_name.rs deleted file mode 100644 index 9f3b71f3321..00000000000 --- a/tests/builder/arg_name.rs +++ /dev/null @@ -1,14 +0,0 @@ -use clap::{arg, Arg, Command}; - -#[test] -fn arg_name_dashed() { - let arg = arg!(["some-arg"] "some arg"); - assert_eq!(arg, Arg::new("some-arg").help("some arg")); - - let m = 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"); -} diff --git a/tests/builder/arg_value.rs b/tests/builder/arg_value.rs deleted file mode 100644 index e24089eb1aa..00000000000 --- a/tests/builder/arg_value.rs +++ /dev/null @@ -1,39 +0,0 @@ -use clap::{arg, Arg, Command}; - -#[test] -fn arg_value_dashed_with_short() { - let arg = arg!(-a <"some-val"> "some arg"); - assert_eq!( - arg, - Arg::new("some-val") - .short('a') - .long("arg") - .value_name("some-val") - ); - - let m = 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] -fn arg_value_dashed_with_long() { - let arg = arg!(-a --arg <"some-val"> "some arg"); - assert_eq!( - arg, - Arg::new("arg") - .short('a') - .long("arg") - .value_name("some-val") - ); - - let m = 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"); -} diff --git a/tests/builder/main.rs b/tests/builder/main.rs index d92d4e84873..124111f1011 100644 --- a/tests/builder/main.rs +++ b/tests/builder/main.rs @@ -3,9 +3,7 @@ mod app_settings; mod arg_aliases; mod arg_aliases_short; mod arg_matcher_assertions; -mod arg_name; mod arg_settings; -mod arg_value; mod borrowed; mod cargo; mod command; 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"); + } }