mirror of
https://github.com/clap-rs/clap
synced 2024-11-10 23:04:23 +00:00
imp(macros): Support shorthand syntax for ArgGroups
Fixes https://github.com/kbknapp/clap-rs/issues/1231.
This commit is contained in:
parent
41e29417b5
commit
36815fec59
2 changed files with 121 additions and 1 deletions
|
@ -626,6 +626,12 @@ macro_rules! app_from_crate {
|
|||
/// `Arg::conflicts_with("FOO")`, `Arg::conflicts_with("BAR")`, and `Arg::conflicts_with("BAZ")`
|
||||
/// (note the lack of quotes around the values in the macro)
|
||||
///
|
||||
/// # Shorthand Syntax for Groups
|
||||
///
|
||||
/// * There are short hand syntaxes for `ArgGroup` methods that accept booleans
|
||||
/// * A plus sign will set that method to `true` such as `+required` = `ArgGroup::required(true)`
|
||||
/// * An exclamation will set that method to `false` such as `!required` = `ArgGroup::required(false)`
|
||||
///
|
||||
/// [`Arg::short`]: ./struct.Arg.html#method.short
|
||||
/// [`Arg::long`]: ./struct.Arg.html#method.long
|
||||
/// [`Arg::multiple(true)`]: ./struct.Arg.html#method.multiple
|
||||
|
@ -657,7 +663,7 @@ macro_rules! clap_app {
|
|||
$($tt)*
|
||||
}
|
||||
};
|
||||
// Treat the application builder as an argument to set it's attributes
|
||||
// Treat the application builder as an argument to set its attributes
|
||||
(@app ($builder:expr) (@attributes $($attr:tt)*) $($tt:tt)*) => {
|
||||
clap_app!{ @app (clap_app!{ @arg ($builder) $($attr)* }) $($tt)* }
|
||||
};
|
||||
|
@ -667,6 +673,18 @@ macro_rules! clap_app {
|
|||
$($tt)*
|
||||
}
|
||||
};
|
||||
(@app ($builder:expr) (@group $name:ident !$ident:ident => $($tail:tt)*) $($tt:tt)*) => {
|
||||
clap_app!{ @app
|
||||
(clap_app!{ @group ($builder, $crate::ArgGroup::with_name(stringify!($name)).$ident(false)) $($tail)* })
|
||||
$($tt)*
|
||||
}
|
||||
};
|
||||
(@app ($builder:expr) (@group $name:ident +$ident:ident => $($tail:tt)*) $($tt:tt)*) => {
|
||||
clap_app!{ @app
|
||||
(clap_app!{ @group ($builder, $crate::ArgGroup::with_name(stringify!($name)).$ident(true)) $($tail)* })
|
||||
$($tt)*
|
||||
}
|
||||
};
|
||||
// Handle subcommand creation
|
||||
(@app ($builder:expr) (@subcommand $name:ident => $($tail:tt)*) $($tt:tt)*) => {
|
||||
clap_app!{ @app
|
||||
|
@ -687,6 +705,7 @@ macro_rules! clap_app {
|
|||
|
||||
// Add members to group and continue argument handling with the parent builder
|
||||
(@group ($builder:expr, $group:expr)) => { $builder.group($group) };
|
||||
// Treat the group builder as an argument to set its attributes
|
||||
(@group ($builder:expr, $group:expr) (@attributes $($attr:tt)*) $($tt:tt)*) => {
|
||||
clap_app!{ @group ($builder, clap_app!{ @arg ($group) (-) $($attr)* }) $($tt)* }
|
||||
};
|
||||
|
|
101
tests/macros.rs
101
tests/macros.rs
|
@ -1,6 +1,8 @@
|
|||
#[macro_use]
|
||||
extern crate clap;
|
||||
|
||||
use clap::ErrorKind;
|
||||
|
||||
#[test]
|
||||
fn basic() {
|
||||
clap_app!(claptests =>
|
||||
|
@ -151,6 +153,105 @@ fn quoted_arg_name() {
|
|||
assert!(matches.is_present("option2"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn group_macro() {
|
||||
let app = clap_app!(claptests =>
|
||||
(version: "0.1")
|
||||
(about: "tests clap library")
|
||||
(author: "Kevin K. <kbknapp@gmail.com>")
|
||||
(@group difficulty =>
|
||||
(@arg hard: -h --hard "Sets hard mode")
|
||||
(@arg normal: -n --normal "Sets normal mode")
|
||||
(@arg easy: -e --easy "Sets easy mode")
|
||||
)
|
||||
);
|
||||
|
||||
let result = app.get_matches_from_safe(vec!["bin_name", "--hard"]);
|
||||
assert!(result.is_ok());
|
||||
let matches = result.expect("Expected to successfully match the given args.");
|
||||
assert!(matches.is_present("difficulty"));
|
||||
assert!(matches.is_present("hard"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn group_macro_set_multiple() {
|
||||
let app = clap_app!(claptests =>
|
||||
(version: "0.1")
|
||||
(about: "tests clap library")
|
||||
(author: "Kevin K. <kbknapp@gmail.com>")
|
||||
(@group difficulty +multiple =>
|
||||
(@arg hard: -h --hard "Sets hard mode")
|
||||
(@arg normal: -n --normal "Sets normal mode")
|
||||
(@arg easy: -e --easy "Sets easy mode")
|
||||
)
|
||||
);
|
||||
|
||||
let result = app.get_matches_from_safe(vec!["bin_name", "--hard", "--easy"]);
|
||||
assert!(result.is_ok());
|
||||
let matches = result.expect("Expected to successfully match the given args.");
|
||||
assert!(matches.is_present("difficulty"));
|
||||
assert!(matches.is_present("hard"));
|
||||
assert!(matches.is_present("easy"));
|
||||
assert!(!matches.is_present("normal"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn group_macro_set_not_multiple() {
|
||||
let app = clap_app!(claptests =>
|
||||
(version: "0.1")
|
||||
(about: "tests clap library")
|
||||
(author: "Kevin K. <kbknapp@gmail.com>")
|
||||
(@group difficulty !multiple =>
|
||||
(@arg hard: -h --hard "Sets hard mode")
|
||||
(@arg normal: -n --normal "Sets normal mode")
|
||||
(@arg easy: -e --easy "Sets easy mode")
|
||||
)
|
||||
);
|
||||
|
||||
let result = app.get_matches_from_safe(vec!["bin_name", "--hard", "--easy"]);
|
||||
assert!(result.is_err());
|
||||
let err = result.unwrap_err();
|
||||
assert_eq!(err.kind, ErrorKind::ArgumentConflict);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn group_macro_set_required() {
|
||||
let app = clap_app!(claptests =>
|
||||
(version: "0.1")
|
||||
(about: "tests clap library")
|
||||
(author: "Kevin K. <kbknapp@gmail.com>")
|
||||
(@group difficulty +required =>
|
||||
(@arg hard: -h --hard "Sets hard mode")
|
||||
(@arg normal: -n --normal "Sets normal mode")
|
||||
(@arg easy: -e --easy "Sets easy mode")
|
||||
)
|
||||
);
|
||||
|
||||
let result = app.get_matches_from_safe(vec!["bin_name"]);
|
||||
assert!(result.is_err());
|
||||
let err = result.unwrap_err();
|
||||
assert_eq!(err.kind, ErrorKind::MissingRequiredArgument);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn group_macro_set_not_required() {
|
||||
let app = clap_app!(claptests =>
|
||||
(version: "0.1")
|
||||
(about: "tests clap library")
|
||||
(author: "Kevin K. <kbknapp@gmail.com>")
|
||||
(@group difficulty !required =>
|
||||
(@arg hard: -h --hard "Sets hard mode")
|
||||
(@arg normal: -n --normal "Sets normal mode")
|
||||
(@arg easy: -e --easy "Sets easy mode")
|
||||
)
|
||||
);
|
||||
|
||||
let result = app.get_matches_from_safe(vec!["bin_name"]);
|
||||
assert!(result.is_ok());
|
||||
let matches = result.expect("Expected to successfully match the given args.");
|
||||
assert!(!matches.is_present("difficulty"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arg_enum() {
|
||||
arg_enum!{
|
||||
|
|
Loading…
Reference in a new issue