#[macro_export]
macro_rules! crate_name {
() => {
option_env!("CARGO_PKG_NAME").expect("package `name` is not defined")
};
}
#[macro_export]
macro_rules! crate_description {
() => {
option_env!("CARGO_PKG_DESCRIPTION").expect("package `description` is not defined")
};
}
#[macro_export]
macro_rules! crate_version {
() => {
option_env!("CARGO_PKG_VERSION").expect("package `version` is not defined")
};
}
#[macro_export]
macro_rules! app {
(=> $($rest:tt)*) => {{
$crate::CommandLine::new(
$crate::app!{
@command ($crate::Command::root()) $($rest)*
}
)
}};
($command_name:ident => $($rest:tt)*) => {{
$crate::CommandLine::new(
$crate::app!{
@command ($crate::Command::new(stringify!($command_name))) $($rest)*
}
)
}};
($command_name:expr => $($rest:tt)*) => {{
$crate::CommandLine::new(
$crate::app!{
@command ($crate::Command::new($command_name)) $($rest)*
}
)
}};
(@command ($builder:expr)) => { $builder };
(@command ($builder:expr) (description => $description:expr) $($tt:tt)*) => {
$crate::app!{
@command ($builder.description($description)) $($tt)*
}
};
(@command ($builder:expr) (usage => $usage:expr) $($tt:tt)*) => {
$crate::app!{
@command ($builder.usage($usage)) $($tt)*
}
};
(@command ($builder:expr) (help => $help:expr) $($tt:tt)*) => {
$crate::app!{
@command ($builder.help($help)) $($tt)*
}
};
(@command ($builder:expr) (version => $version:expr) $($tt:tt)*) => {
$crate::app!{
@command ($builder.version($version)) $($tt)*
}
};
(@command ($builder:expr) (hidden => $hidden:expr) $($tt:tt)*) => {
$crate::app!{
@command ($builder.hidden($hidden)) $($tt)*
}
};
(@command ($builder:expr) (handler ($options:ident, $arguments:ident) => $block:block) $($tt:tt)*) => {
$crate::app!{
@command ($builder.handler(|$options, $arguments|{
$block
Ok(())
})) $($tt)*
}
};
(@command ($builder:expr) (handler ($options:ident, $arguments:ident) => $expr:expr) $($tt:tt)*) => {
$crate::app!{
@command ($builder.handler(|$options, $arguments|{
$expr;
Ok(())
})) $($tt)*
}
};
(@command ($builder:expr) (handler (...$($arg_name:ident: $arg_type:ty),+) => $block:block) $($tt:tt)*) => {
$crate::app!{
@command ($builder.handler(|options, arguments|{
$(
let $arg_name : $arg_type = $crate::declare_argument_var!(arguments, $arg_name: $arg_type);
)+
$block
Ok(())
})) $($tt)*
}
};
(@command ($builder:expr) (handler (...$($arg_name:ident: $arg_type:ty),+) => $expr:expr) $($tt:tt)*) => {
$crate::app!{
@command ($builder.handler(|options, arguments|{
$(
let $arg_name : $arg_type = $crate::declare_argument_var!(arguments, $arg_name: $arg_type);
)+
$expr;
Ok(())
})) $($tt)*
}
};
(@command ($builder:expr) (handler ($($name:ident : $ty:ty),+ $(,...$($arg_name:ident: $arg_type:ty),+)?) => $block:block) $($tt:tt)*) => {
$crate::app!{
@command ($builder.handler(|options, arguments|{
#[cfg(debug_assertions)]
#[allow(unused_variables)]
fn assert_non_duplicate_arguments($($name: $ty),+ $(,$($arg_name: $arg_type),+)?){}
$(
let $name : $ty = $crate::declare_option_var!(options, $name: $ty);
)+
$(
$(
let $arg_name : $arg_type = $crate::declare_argument_var!(arguments, $arg_name: $arg_type);
)+
)?
$block
Ok(())
})) $($tt)*
}
};
(@command ($builder:expr) (handler ($($name:ident : $ty:ty),+ $(,...$($arg_name:ident: $arg_type:ty),+)?) => $expr:expr) $($tt:tt)*) => {
$crate::app!{
@command ($builder.handler(|options, arguments|{
#[cfg(debug_assertions)]
#[allow(unused_variables)]
fn assert_non_duplicate_arguments($($name: $ty),+ $(,$($arg_name: $arg_type),+)?){}
$(
let $name : $ty = $crate::declare_option_var!(options, $name: $ty);
)+
$(
$(
let $arg_name : $arg_type = $crate::declare_argument_var!(arguments, $arg_name: $arg_type);
)+
)?
$expr;
Ok(())
})) $($tt)*
}
};
(@command ($builder:expr) (handler () => $block:block) $($tt:tt)*) => {
$crate::app!{
@command ($builder.handler(|_options, _arguments|{
$block
Ok(())
})) $($tt)*
}
};
(@command ($builder:expr) (handler () => $expr:expr) $($tt:tt)*) => {
$crate::app!{
@command ($builder.handler(|_options, _arguments|{
$expr;
Ok(())
})) $($tt)*
}
};
(@command ($builder:expr) (handler => $block:block) $($tt:tt)*) => {
$crate::app!{
@command ($builder.handler(|_options, _arguments|{
$block
Ok(())
})) $($tt)*
}
};
(@command ($builder:expr) (handler => $expr:expr) $($tt:tt)*) => {
$crate::app!{
@command ($builder.handler(|_options, _arguments|{
$expr;
Ok(())
})) $($tt)*
}
};
(@command ($builder:expr) (@subcommand $command_name:ident $(=> $($rest:tt)+)?) $($tt:tt)*) => {
$crate::app!{
@command
($builder.subcommand(
$crate::app!{ @command ($crate::Command::new(stringify!($command_name))) $($($rest)+)? }
)) $($tt)*
}
};
(@command ($builder:expr) (@subcommand $command_name:expr $(=> $($rest:tt)+)?) $($tt:tt)*) => {
$crate::app!{
@command
($builder.subcommand(
$crate::app!{ @command ($crate::Command::new($command_name)) $($($rest)+)? }
)) $($tt)*
}
};
(@command ($builder:expr) (@option $option_name:ident $(=> $($rest:tt)+)?) $($tt:tt)*) => {
$crate::app!{
@command
($builder.option(
$crate::app!{ @option ($crate::CommandOption::new(stringify!($option_name))) $($($rest)+)? }
)) $($tt)*
}
};
(@command ($builder:expr) (@option $option_name:expr $(=> $($rest:tt)+)?) $($tt:tt)*) => {
$crate::app!{
@command
($builder.option(
$crate::app!{ @option ($crate::CommandOption::new($option_name)) $($($rest)+)? }
)) $($tt)*
}
};
(@option ($option_builder:expr)) => { $option_builder };
(@option ($option_builder:expr) (@arg $arg_name:ident $(=> $($rest:tt)+)?) $($tt:tt)*) => {
$crate::app!{
@option
($option_builder.arg(
$crate::app!{ @arg ($crate::Argument::with_name(stringify!($arg_name))) $($($rest)+)? }
)) $($tt)*
}
};
(@option ($option_builder:expr) (@arg $arg_name:expr $(=> $($rest:tt)+)?) $($tt:tt)*) => {
$crate::app!{
@option
($option_builder.arg(
$crate::app!{ @arg ($crate::Argument::with_name($arg_name)) $($($rest)+)? }
)) $($tt)*
}
};
(@option ($option_builder:expr) (@arg $(=> $($rest:tt)+)?) $($tt:tt)*) => {
$crate::app!{
@option
($option_builder.arg(
$crate::app!{ @arg ($crate::Argument::new()) $($($rest)+)? }
)) $($tt)*
}
};
(@option ($option_builder:expr) (description => $description:expr) $($tt:tt)*) => {
$crate::app!{
@option ($option_builder.description($description)) $($tt)*
}
};
(@option ($option_builder:expr) (required => $required:expr) $($tt:tt)*) => {
$crate::app!{
@option ($option_builder.required($required)) $($tt)*
}
};
(@option ($option_builder:expr) (multiple => $multiple:expr) $($tt:tt)*) => {
$crate::app!{
@option ($option_builder.multiple($multiple)) $($tt)*
}
};
(@option ($option_builder:expr) (hidden => $hidden:expr) $($tt:tt)*) => {
$crate::app!{
@option ($option_builder.hidden($hidden)) $($tt)*
}
};
(@option ($option_builder:expr) (requires_assign => $requires_assign:expr) $($tt:tt)*) => {
$crate::app!{
@option ($option_builder.requires_assign($requires_assign)) $($tt)*
}
};
(@option ($option_builder:expr) (alias => $($alias:expr),+) $($tt:tt)*) => {
$crate::app!{
@option
($option_builder$(.alias($alias))+) $($tt)*
}
};
(@option ($option_builder:expr) (alias => $($literal:expr),+) $($tt:tt)*) => {
$crate::app!{
@option
($option_builder$(.global($literal))+) $($tt)*
}
};
(@command ($builder:expr) (@arg $arg_name:ident $(=> $($rest:tt)+)?) $($tt:tt)*) => {
$crate::app!{
@command
($builder.arg(
$crate::app!{ @arg ($crate::Argument::with_name(stringify!($arg_name))) $($($rest)+)? }
)) $($tt)*
}
};
(@command ($builder:expr) (@arg $arg_name:expr $(=> $($rest:tt)+)?) $($tt:tt)*) => {
$crate::app!{
@command
($builder.arg(
$crate::app!{ @arg ($crate::Argument::with_name($arg_name)) $($($rest)+)? }
)) $($tt)*
}
};
(@arg ($arg_builder:expr)) => { $arg_builder };
(@arg ($arg_builder:expr) (count => $count:expr) $($tt:tt)*) => {
$crate::app!{
@arg ($arg_builder.values_count($count)) $($tt)*
}
};
(@arg ($arg_builder:expr) (description => $description:expr) $($tt:tt)*) => {
$crate::app!{
@arg ($arg_builder.description($description)) $($tt)*
}
};
(@arg ($arg_builder:expr) (values => $($valid_values:expr),+) $($tt:tt)*) => {
$crate::app!{
@arg ($arg_builder.valid_values(&[$($valid_values),+])) $($tt)*
}
};
(@arg ($arg_builder:expr) (default => $($default_values:expr),+) $($tt:tt)*) => {
$crate::app!{
@arg ($arg_builder.defaults(&[$($default_values),+])) $($tt)*
}
};
(@arg ($arg_builder:expr) (validator => $validator:expr) $($tt:tt)*) => {
$crate::app!{
@arg ($arg_builder.validator($validator)) $($tt)*
}
};
(@arg ($arg_builder:expr) (type => $ty:ty) $($tt:tt)*) => {
$crate::app!{
@arg ($arg_builder.validator($crate::validator::validate_type::<$ty>())) $($tt)*
}
};
(@arg ($arg_builder:expr) (error => $error:expr) $($tt:tt)*) => {
$crate::app!{
@arg ($arg_builder.validation_error($error)) $($tt)*
}
};
(@@command => $($rest:tt)+) => {{
$crate::app!{
@command ($crate::Command::root()) $($rest)+
}
}};
(@@command $command_name:ident => $($rest:tt)+) => {{
$crate::app!{
@command ($crate::Command::new(stringify!($command_name))) $($rest)+
}
}};
(@@command $command_name:expr => $($rest:tt)+) => {{
$crate::app!{
@command ($crate::Command::new($command_name)) $($rest)+
}
}};
}
#[macro_export]
macro_rules! run_app {
( => $($rest:tt)+) => {
$crate::app!( => $($rest)+)
.use_default_suggestions()
.use_default_help()
.run()
};
($name:ident => $($rest:tt)+) => {
$crate::app!($name => $($rest)+)
.use_default_suggestions()
.use_default_help()
.run()
};
($name:expr => $($rest:tt)+) => {
$crate::app!($name => $($rest)+)
.use_default_suggestions()
.use_default_help()
.run()
};
}
#[macro_export]
macro_rules! crate_app {
($($rest:tt)*) => {{
$crate::CommandLine::new(
$crate::app!{
@command
(
$crate::Command::new($crate::package_name!())
.description($crate::package_description!())
.subcommand(Command::new("version")
.handler(|_, _| {
println!("{}", $crate::package_version!());
Ok(())
})
)
) $($rest)*
}
)
}};
}
#[macro_export]
macro_rules! run_crate_app {
($($rest:tt)*) => {{
$crate::CommandLine::new(
$crate::app!{
@command
(
$crate::Command::new($crate::package_name!())
.description($crate::package_description!())
.subcommand(Command::new("version")
.handler(|_, _| {
println!("{}", $crate::package_version!());
Ok(())
})
)
) $($rest)*
}
)
.use_default_help()
.use_default_suggestions()
.run()
}};
}