mirror of
https://github.com/clap-rs/clap
synced 2024-12-13 14:22:34 +00:00
feat(clap_derive): Add default_values_t
and default_values_os_t
This commit is contained in:
parent
732a21b1bf
commit
04e0ed7474
7 changed files with 406 additions and 0 deletions
|
@ -516,6 +516,81 @@ impl Attrs {
|
||||||
self.methods.push(Method::new(raw_ident, val));
|
self.methods.push(Method::new(raw_ident, val));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DefaultValuesT(ident, expr) => {
|
||||||
|
let ty = if let Some(ty) = self.ty.as_ref() {
|
||||||
|
ty
|
||||||
|
} else {
|
||||||
|
abort!(
|
||||||
|
ident,
|
||||||
|
"#[clap(default_values_t)] (without an argument) can be used \
|
||||||
|
only on field level";
|
||||||
|
|
||||||
|
note = "see \
|
||||||
|
https://github.com/clap-rs/clap/blob/master/examples/derive_ref/README.md#magic-attributes")
|
||||||
|
};
|
||||||
|
|
||||||
|
let container_type = Ty::from_syn_ty(ty);
|
||||||
|
if *container_type != Ty::Vec {
|
||||||
|
abort!(
|
||||||
|
ident,
|
||||||
|
"#[clap(default_values_t)] can be used only on Vec types";
|
||||||
|
|
||||||
|
note = "see \
|
||||||
|
https://github.com/clap-rs/clap/blob/master/examples/derive_ref/README.md#magic-attributes")
|
||||||
|
}
|
||||||
|
let inner_type = inner_type(ty);
|
||||||
|
|
||||||
|
// Use `Borrow<#inner_type>` so we accept `&Vec<#inner_type>` and
|
||||||
|
// `Vec<#inner_type>`.
|
||||||
|
let val = if parsed.iter().any(|a| matches!(a, ValueEnum(_))) {
|
||||||
|
quote_spanned!(ident.span()=> {
|
||||||
|
{
|
||||||
|
fn iter_to_vals<T>(iterable: impl IntoIterator<Item = T>) -> Vec<&'static str>
|
||||||
|
where
|
||||||
|
T: ::std::borrow::Borrow<#inner_type>
|
||||||
|
{
|
||||||
|
iterable
|
||||||
|
.into_iter()
|
||||||
|
.map(|val| {
|
||||||
|
clap::ValueEnum::to_possible_value(val.borrow()).unwrap().get_name()
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEFAULT_VALUES: clap::__macro_refs::once_cell::sync::Lazy<Vec<&str>> = clap::__macro_refs::once_cell::sync::Lazy::new(|| {
|
||||||
|
iter_to_vals(#expr)
|
||||||
|
});
|
||||||
|
&*DEFAULT_VALUES.as_slice()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
quote_spanned!(ident.span()=> {
|
||||||
|
{
|
||||||
|
fn iter_to_vals<T>(iterable: impl IntoIterator<Item = T>) -> Vec<String>
|
||||||
|
where
|
||||||
|
T: ::std::borrow::Borrow<#inner_type>
|
||||||
|
{
|
||||||
|
iterable.into_iter().map(|val| val.borrow().to_string()).collect()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEFAULT_STRINGS: clap::__macro_refs::once_cell::sync::Lazy<Vec<::std::string::String>> = clap::__macro_refs::once_cell::sync::Lazy::new(|| {
|
||||||
|
iter_to_vals(#expr)
|
||||||
|
});
|
||||||
|
|
||||||
|
static DEFAULT_VALUES: clap::__macro_refs::once_cell::sync::Lazy<Vec<&str>> = clap::__macro_refs::once_cell::sync::Lazy::new(|| {
|
||||||
|
DEFAULT_STRINGS.iter().map(::std::string::String::as_str).collect()
|
||||||
|
});
|
||||||
|
&*DEFAULT_VALUES.as_slice()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
self.methods
|
||||||
|
.push(Method::new(Ident::new("default_values", ident.span()), val));
|
||||||
|
}
|
||||||
|
|
||||||
DefaultValueOsT(ident, expr) => {
|
DefaultValueOsT(ident, expr) => {
|
||||||
let ty = if let Some(ty) = self.ty.as_ref() {
|
let ty = if let Some(ty) = self.ty.as_ref() {
|
||||||
ty
|
ty
|
||||||
|
@ -556,6 +631,84 @@ impl Attrs {
|
||||||
self.methods.push(Method::new(raw_ident, val));
|
self.methods.push(Method::new(raw_ident, val));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DefaultValuesOsT(ident, expr) => {
|
||||||
|
let ty = if let Some(ty) = self.ty.as_ref() {
|
||||||
|
ty
|
||||||
|
} else {
|
||||||
|
abort!(
|
||||||
|
ident,
|
||||||
|
"#[clap(default_values_os_t)] (without an argument) can be used \
|
||||||
|
only on field level";
|
||||||
|
|
||||||
|
note = "see \
|
||||||
|
https://github.com/clap-rs/clap/blob/master/examples/derive_ref/README.md#magic-attributes")
|
||||||
|
};
|
||||||
|
|
||||||
|
let container_type = Ty::from_syn_ty(ty);
|
||||||
|
if *container_type != Ty::Vec {
|
||||||
|
abort!(
|
||||||
|
ident,
|
||||||
|
"#[clap(default_values_os_t)] can be used only on Vec types";
|
||||||
|
|
||||||
|
note = "see \
|
||||||
|
https://github.com/clap-rs/clap/blob/master/examples/derive_ref/README.md#magic-attributes")
|
||||||
|
}
|
||||||
|
let inner_type = inner_type(ty);
|
||||||
|
|
||||||
|
// Use `Borrow<#inner_type>` so we accept `&Vec<#inner_type>` and
|
||||||
|
// `Vec<#inner_type>`.
|
||||||
|
let val = if parsed.iter().any(|a| matches!(a, ValueEnum(_))) {
|
||||||
|
quote_spanned!(ident.span()=> {
|
||||||
|
{
|
||||||
|
fn iter_to_vals<T>(iterable: impl IntoIterator<Item = T>) -> Vec<&'static ::std::ffi::OsStr>
|
||||||
|
where
|
||||||
|
T: ::std::borrow::Borrow<#inner_type>
|
||||||
|
{
|
||||||
|
iterable
|
||||||
|
.into_iter()
|
||||||
|
.map(|val| {
|
||||||
|
clap::ValueEnum::to_possible_value(val.borrow()).unwrap().get_name()
|
||||||
|
})
|
||||||
|
.map(::std::ffi::OsStr::new)
|
||||||
|
.collect()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEFAULT_VALUES: clap::__macro_refs::once_cell::sync::Lazy<Vec<&::std::ffi::OsStr>> = clap::__macro_refs::once_cell::sync::Lazy::new(|| {
|
||||||
|
iter_to_vals(#expr)
|
||||||
|
});
|
||||||
|
&*DEFAULT_VALUES.as_slice()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
quote_spanned!(ident.span()=> {
|
||||||
|
{
|
||||||
|
fn iter_to_vals<T>(iterable: impl IntoIterator<Item = T>) -> Vec<::std::ffi::OsString>
|
||||||
|
where
|
||||||
|
T: ::std::borrow::Borrow<#inner_type>
|
||||||
|
{
|
||||||
|
iterable.into_iter().map(|val| val.borrow().into()).collect()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEFAULT_OS_STRINGS: clap::__macro_refs::once_cell::sync::Lazy<Vec<::std::ffi::OsString>> = clap::__macro_refs::once_cell::sync::Lazy::new(|| {
|
||||||
|
iter_to_vals(#expr)
|
||||||
|
});
|
||||||
|
|
||||||
|
static DEFAULT_VALUES: clap::__macro_refs::once_cell::sync::Lazy<Vec<&::std::ffi::OsStr>> = clap::__macro_refs::once_cell::sync::Lazy::new(|| {
|
||||||
|
DEFAULT_OS_STRINGS.iter().map(::std::ffi::OsString::as_os_str).collect()
|
||||||
|
});
|
||||||
|
&*DEFAULT_VALUES.as_slice()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
self.methods.push(Method::new(
|
||||||
|
Ident::new("default_values_os", ident.span()),
|
||||||
|
val,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
NextDisplayOrder(ident, expr) => {
|
NextDisplayOrder(ident, expr) => {
|
||||||
self.next_display_order = Some(Method::new(ident, quote!(#expr)));
|
self.next_display_order = Some(Method::new(ident, quote!(#expr)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,9 @@ pub enum ClapAttr {
|
||||||
// ident = arbitrary_expr
|
// ident = arbitrary_expr
|
||||||
NameExpr(Ident, Expr),
|
NameExpr(Ident, Expr),
|
||||||
DefaultValueT(Ident, Option<Expr>),
|
DefaultValueT(Ident, Option<Expr>),
|
||||||
|
DefaultValuesT(Ident, Expr),
|
||||||
DefaultValueOsT(Ident, Option<Expr>),
|
DefaultValueOsT(Ident, Option<Expr>),
|
||||||
|
DefaultValuesOsT(Ident, Expr),
|
||||||
NextDisplayOrder(Ident, Expr),
|
NextDisplayOrder(Ident, Expr),
|
||||||
NextHelpHeading(Ident, Expr),
|
NextHelpHeading(Ident, Expr),
|
||||||
HelpHeading(Ident, Expr),
|
HelpHeading(Ident, Expr),
|
||||||
|
@ -120,7 +122,9 @@ impl Parse for ClapAttr {
|
||||||
Ok(expr) => match &*name_str {
|
Ok(expr) => match &*name_str {
|
||||||
"skip" => Ok(Skip(name, Some(expr))),
|
"skip" => Ok(Skip(name, Some(expr))),
|
||||||
"default_value_t" => Ok(DefaultValueT(name, Some(expr))),
|
"default_value_t" => Ok(DefaultValueT(name, Some(expr))),
|
||||||
|
"default_values_t" => Ok(DefaultValuesT(name, expr)),
|
||||||
"default_value_os_t" => Ok(DefaultValueOsT(name, Some(expr))),
|
"default_value_os_t" => Ok(DefaultValueOsT(name, Some(expr))),
|
||||||
|
"default_values_os_t" => Ok(DefaultValuesOsT(name, expr)),
|
||||||
"next_display_order" => Ok(NextDisplayOrder(name, expr)),
|
"next_display_order" => Ok(NextDisplayOrder(name, expr)),
|
||||||
"next_help_heading" => Ok(NextHelpHeading(name, expr)),
|
"next_help_heading" => Ok(NextHelpHeading(name, expr)),
|
||||||
"help_heading" => Ok(HelpHeading(name, expr)),
|
"help_heading" => Ok(HelpHeading(name, expr)),
|
||||||
|
|
|
@ -223,9 +223,15 @@
|
||||||
//! - `default_value_t [= <expr>]`: [`Arg::default_value`][crate::Arg::default_value] and [`Arg::required(false)`][crate::Arg::required]
|
//! - `default_value_t [= <expr>]`: [`Arg::default_value`][crate::Arg::default_value] and [`Arg::required(false)`][crate::Arg::required]
|
||||||
//! - Requires `std::fmt::Display` or `#[clap(value_enum)]`
|
//! - Requires `std::fmt::Display` or `#[clap(value_enum)]`
|
||||||
//! - Without `<expr>`, relies on `Default::default()`
|
//! - Without `<expr>`, relies on `Default::default()`
|
||||||
|
//! - `default_values_t = <expr>`: [`Arg::default_values`][crate::Arg::default_values] and [`Arg::required(false)`][crate::Arg::required]
|
||||||
|
//! - Requires field arg to be of type `Vec<T>` and `T` to implement `std::fmt::Display` or `#[clap(value_enum)]`
|
||||||
|
//! - `<expr>` must implement `IntoIterator<T>`
|
||||||
//! - `default_value_os_t [= <expr>]`: [`Arg::default_value_os`][crate::Arg::default_value_os] and [`Arg::required(false)`][crate::Arg::required]
|
//! - `default_value_os_t [= <expr>]`: [`Arg::default_value_os`][crate::Arg::default_value_os] and [`Arg::required(false)`][crate::Arg::required]
|
||||||
//! - Requires `std::convert::Into<OsString>` or `#[clap(value_enum)]`
|
//! - Requires `std::convert::Into<OsString>` or `#[clap(value_enum)]`
|
||||||
//! - Without `<expr>`, relies on `Default::default()`
|
//! - Without `<expr>`, relies on `Default::default()`
|
||||||
|
//! - `default_values_os_t = <expr>`: [`Arg::default_values_os`][crate::Arg::default_values_os] and [`Arg::required(false)`][crate::Arg::required]
|
||||||
|
//! - Requires field arg to be of type `Vec<T>` and `T` to implement `std::convert::Into<OsString>` or `#[clap(value_enum)]`
|
||||||
|
//! - `<expr>` must implement `IntoIterator<T>`
|
||||||
//!
|
//!
|
||||||
//! ### Value Enum Attributes
|
//! ### Value Enum Attributes
|
||||||
//!
|
//!
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use clap::{CommandFactory, Parser};
|
use clap::{CommandFactory, Parser};
|
||||||
|
|
||||||
use crate::utils;
|
use crate::utils;
|
||||||
|
@ -44,6 +46,124 @@ fn auto_default_value_t() {
|
||||||
assert!(help.contains("[default: 0]"));
|
assert!(help.contains("[default: 0]"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_values_t() {
|
||||||
|
#[derive(Parser, PartialEq, Debug)]
|
||||||
|
struct Opt {
|
||||||
|
#[clap(default_values_t = vec![1, 2, 3])]
|
||||||
|
arg1: Vec<i32>,
|
||||||
|
|
||||||
|
#[clap(long, default_values_t = &[4, 5, 6])]
|
||||||
|
arg2: Vec<i32>,
|
||||||
|
|
||||||
|
#[clap(long, default_values_t = [7, 8, 9])]
|
||||||
|
arg3: Vec<i32>,
|
||||||
|
|
||||||
|
#[clap(long, default_values_t = 10..=12)]
|
||||||
|
arg4: Vec<i32>,
|
||||||
|
|
||||||
|
#[clap(long, default_values_t = vec!["hello".to_string(), "world".to_string()])]
|
||||||
|
arg5: Vec<String>,
|
||||||
|
|
||||||
|
#[clap(long, default_values_t = &vec!["foo".to_string(), "bar".to_string()])]
|
||||||
|
arg6: Vec<String>,
|
||||||
|
}
|
||||||
|
assert_eq!(
|
||||||
|
Opt {
|
||||||
|
arg1: vec![1, 2, 3],
|
||||||
|
arg2: vec![4, 5, 6],
|
||||||
|
arg3: vec![7, 8, 9],
|
||||||
|
arg4: vec![10, 11, 12],
|
||||||
|
arg5: vec!["hello".to_string(), "world".to_string()],
|
||||||
|
arg6: vec!["foo".to_string(), "bar".to_string()],
|
||||||
|
},
|
||||||
|
Opt::try_parse_from(&["test"]).unwrap()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Opt {
|
||||||
|
arg1: vec![1],
|
||||||
|
arg2: vec![4, 5, 6],
|
||||||
|
arg3: vec![7, 8, 9],
|
||||||
|
arg4: vec![10, 11, 12],
|
||||||
|
arg5: vec!["hello".to_string(), "world".to_string()],
|
||||||
|
arg6: vec!["foo".to_string(), "bar".to_string()],
|
||||||
|
},
|
||||||
|
Opt::try_parse_from(&["test", "1"]).unwrap()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Opt {
|
||||||
|
arg1: vec![1, 2, 3],
|
||||||
|
arg2: vec![4, 5, 6],
|
||||||
|
arg3: vec![7, 8, 9],
|
||||||
|
arg4: vec![42, 15],
|
||||||
|
arg5: vec!["baz".to_string()],
|
||||||
|
arg6: vec!["foo".to_string(), "bar".to_string()],
|
||||||
|
},
|
||||||
|
Opt::try_parse_from(&["test", "--arg4", "42", "--arg4", "15", "--arg5", "baz"]).unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let help = utils::get_long_help::<Opt>();
|
||||||
|
assert!(help.contains("[default: 1 2 3]"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_value_os_t() {
|
||||||
|
#[derive(Parser, PartialEq, Debug)]
|
||||||
|
struct Opt {
|
||||||
|
#[clap(default_value_os_t = PathBuf::from("abc.def"))]
|
||||||
|
arg: PathBuf,
|
||||||
|
}
|
||||||
|
assert_eq!(
|
||||||
|
Opt {
|
||||||
|
arg: PathBuf::from("abc.def")
|
||||||
|
},
|
||||||
|
Opt::try_parse_from(&["test"]).unwrap()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Opt {
|
||||||
|
arg: PathBuf::from("ghi")
|
||||||
|
},
|
||||||
|
Opt::try_parse_from(&["test", "ghi"]).unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let help = utils::get_long_help::<Opt>();
|
||||||
|
assert!(help.contains("[default: abc.def]"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_values_os_t() {
|
||||||
|
#[derive(Parser, PartialEq, Debug)]
|
||||||
|
struct Opt {
|
||||||
|
#[clap(
|
||||||
|
default_values_os_t = vec![PathBuf::from("abc.def"), PathBuf::from("123.foo")]
|
||||||
|
)]
|
||||||
|
arg1: Vec<PathBuf>,
|
||||||
|
|
||||||
|
#[clap(
|
||||||
|
long,
|
||||||
|
default_values_os_t = &[PathBuf::from("bar.baz")]
|
||||||
|
)]
|
||||||
|
arg2: Vec<PathBuf>,
|
||||||
|
}
|
||||||
|
assert_eq!(
|
||||||
|
Opt {
|
||||||
|
arg1: vec![PathBuf::from("abc.def"), PathBuf::from("123.foo")],
|
||||||
|
arg2: vec![PathBuf::from("bar.baz")]
|
||||||
|
},
|
||||||
|
Opt::try_parse_from(&["test"]).unwrap()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Opt {
|
||||||
|
arg1: vec![PathBuf::from("ghi")],
|
||||||
|
arg2: vec![PathBuf::from("baz.bar"), PathBuf::from("foo.bar")]
|
||||||
|
},
|
||||||
|
Opt::try_parse_from(&["test", "ghi", "--arg2", "baz.bar", "--arg2", "foo.bar"]).unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let help = utils::get_long_help::<Opt>();
|
||||||
|
assert!(help.contains("[default: abc.def 123.foo]"));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn detect_os_variant() {
|
fn detect_os_variant() {
|
||||||
#![allow(unused_parens)] // needed for `as_ref` call
|
#![allow(unused_parens)] // needed for `as_ref` call
|
||||||
|
|
|
@ -78,6 +78,108 @@ fn default_value() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn vec_for_default_values_t() {
|
||||||
|
#[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
|
||||||
|
enum ArgChoice {
|
||||||
|
Foo,
|
||||||
|
Bar,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Parser, PartialEq, Debug)]
|
||||||
|
struct Opt {
|
||||||
|
#[clap(value_enum, default_values_t = vec![ArgChoice::Foo, ArgChoice::Bar])]
|
||||||
|
arg1: Vec<ArgChoice>,
|
||||||
|
|
||||||
|
#[clap(
|
||||||
|
long,
|
||||||
|
value_enum,
|
||||||
|
default_values_t = clap::ValueEnum::value_variants()
|
||||||
|
)]
|
||||||
|
arg2: Vec<ArgChoice>,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
Opt {
|
||||||
|
arg1: vec![ArgChoice::Foo],
|
||||||
|
arg2: vec![ArgChoice::Foo, ArgChoice::Bar]
|
||||||
|
},
|
||||||
|
Opt::try_parse_from(&["", "foo"]).unwrap()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Opt {
|
||||||
|
arg1: vec![ArgChoice::Bar],
|
||||||
|
arg2: vec![ArgChoice::Foo, ArgChoice::Bar]
|
||||||
|
},
|
||||||
|
Opt::try_parse_from(&["", "bar"]).unwrap()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Opt {
|
||||||
|
arg1: vec![ArgChoice::Foo, ArgChoice::Bar],
|
||||||
|
arg2: vec![ArgChoice::Foo, ArgChoice::Bar]
|
||||||
|
},
|
||||||
|
Opt::try_parse_from(&[""]).unwrap()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Opt {
|
||||||
|
arg1: vec![ArgChoice::Foo, ArgChoice::Bar],
|
||||||
|
arg2: vec![ArgChoice::Foo]
|
||||||
|
},
|
||||||
|
Opt::try_parse_from(&["", "--arg2", "foo"]).unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn vec_for_default_values_os_t() {
|
||||||
|
#[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
|
||||||
|
enum ArgChoice {
|
||||||
|
Foo,
|
||||||
|
Bar,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Parser, PartialEq, Debug)]
|
||||||
|
struct Opt {
|
||||||
|
#[clap(value_enum, default_values_os_t = vec![ArgChoice::Foo, ArgChoice::Bar])]
|
||||||
|
arg: Vec<ArgChoice>,
|
||||||
|
|
||||||
|
#[clap(
|
||||||
|
long,
|
||||||
|
value_enum,
|
||||||
|
default_values_os_t = clap::ValueEnum::value_variants()
|
||||||
|
)]
|
||||||
|
arg2: Vec<ArgChoice>,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
Opt {
|
||||||
|
arg: vec![ArgChoice::Foo],
|
||||||
|
arg2: vec![ArgChoice::Foo, ArgChoice::Bar]
|
||||||
|
},
|
||||||
|
Opt::try_parse_from(&["", "foo"]).unwrap()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Opt {
|
||||||
|
arg: vec![ArgChoice::Bar],
|
||||||
|
arg2: vec![ArgChoice::Foo, ArgChoice::Bar]
|
||||||
|
},
|
||||||
|
Opt::try_parse_from(&["", "bar"]).unwrap()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Opt {
|
||||||
|
arg: vec![ArgChoice::Foo, ArgChoice::Bar],
|
||||||
|
arg2: vec![ArgChoice::Foo, ArgChoice::Bar]
|
||||||
|
},
|
||||||
|
Opt::try_parse_from(&[""]).unwrap()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Opt {
|
||||||
|
arg: vec![ArgChoice::Foo, ArgChoice::Bar],
|
||||||
|
arg2: vec![ArgChoice::Foo]
|
||||||
|
},
|
||||||
|
Opt::try_parse_from(&["", "--arg2", "foo"]).unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn multi_word_is_renamed_kebab() {
|
fn multi_word_is_renamed_kebab() {
|
||||||
#[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
|
#[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
|
||||||
|
|
13
tests/derive_ui/default_values_t_invalid.rs
Normal file
13
tests/derive_ui/default_values_t_invalid.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
use clap::Parser;
|
||||||
|
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
#[clap(name = "basic")]
|
||||||
|
struct Opt {
|
||||||
|
#[clap(default_values_t = [1, 2, 3])]
|
||||||
|
value: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let opt = Opt::parse();
|
||||||
|
println!("{:?}", opt);
|
||||||
|
}
|
8
tests/derive_ui/default_values_t_invalid.stderr
Normal file
8
tests/derive_ui/default_values_t_invalid.stderr
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
error: #[clap(default_values_t)] can be used only on Vec types
|
||||||
|
|
||||||
|
= note: see https://github.com/clap-rs/clap/blob/master/examples/derive_ref/README.md#magic-attributes
|
||||||
|
|
||||||
|
--> tests/derive_ui/default_values_t_invalid.rs:6:12
|
||||||
|
|
|
||||||
|
6 | #[clap(default_values_t = [1, 2, 3])]
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
Loading…
Reference in a new issue