mirror of
https://github.com/clap-rs/clap
synced 2024-11-10 06:44:16 +00:00
fix!: Remove unstable-v4
feature gate
This commit is contained in:
parent
982d4ca361
commit
01a3ea425f
94 changed files with 271 additions and 6072 deletions
|
@ -7,8 +7,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||
|
||||
## 4.0.0 - Upcoming
|
||||
|
||||
_gated behind `unstable-v4`_
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
- `Error::EmptyValue` replaced with `Error::InvalidValue`
|
||||
|
|
|
@ -79,8 +79,8 @@ unicode = ["textwrap/unicode-width", "unicase"] # Support for unicode character
|
|||
# In-work features
|
||||
unstable-replace = []
|
||||
unstable-grouped = []
|
||||
# note: this will always enable clap_derive, change this to `clap_derive?/unstable-v4` when MSRV is bigger than 1.60
|
||||
unstable-v4 = ["clap_derive/unstable-v4", "deprecated"]
|
||||
# note: this will always enable clap_derive, change this to `clap_derive?/unstable-v5` when MSRV is bigger than 1.60
|
||||
unstable-v5 = ["clap_derive/unstable-v5", "deprecated"]
|
||||
|
||||
[lib]
|
||||
bench = false
|
||||
|
|
2
Makefile
2
Makefile
|
@ -17,7 +17,7 @@ _FEATURES_minimal = --no-default-features --features "std"
|
|||
_FEATURES_default =
|
||||
_FEATURES_wasm = --features "deprecated derive cargo env unicode unstable-replace unstable-grouped"
|
||||
_FEATURES_full = --features "deprecated derive cargo env unicode unstable-replace unstable-grouped wrap_help"
|
||||
_FEATURES_next = ${_FEATURES_full} --features unstable-v4
|
||||
_FEATURES_next = ${_FEATURES_full} --features unstable-v5
|
||||
_FEATURES_debug = ${_FEATURES_full} --features debug
|
||||
_FEATURES_release = ${_FEATURES_full} --release
|
||||
|
||||
|
|
|
@ -49,6 +49,6 @@ proc-macro-error = "1"
|
|||
[features]
|
||||
default = []
|
||||
debug = []
|
||||
unstable-v4 = ["deprecated"]
|
||||
unstable-v5 = ["deprecated"]
|
||||
deprecated = []
|
||||
raw-deprecated = ["deprecated"]
|
||||
|
|
|
@ -750,16 +750,10 @@ impl Attrs {
|
|||
quote!( #(#next_help_heading)* #(#help_heading)* )
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
pub fn id(&self) -> TokenStream {
|
||||
self.name.clone().raw()
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "unstable-v4"))]
|
||||
pub fn id(&self) -> TokenStream {
|
||||
self.cased_name()
|
||||
}
|
||||
|
||||
pub fn cased_name(&self) -> TokenStream {
|
||||
self.name.clone().translate(*self.casing)
|
||||
}
|
||||
|
@ -780,7 +774,7 @@ impl Attrs {
|
|||
let inner_type = inner_type(field_type);
|
||||
let span = action.span();
|
||||
default_value_parser(inner_type, span)
|
||||
} else if !self.ignore_parser() || cfg!(not(feature = "unstable-v4")) {
|
||||
} else if !self.ignore_parser() {
|
||||
self.parser(field_type).value_parser()
|
||||
} else {
|
||||
let inner_type = inner_type(field_type);
|
||||
|
@ -802,7 +796,7 @@ impl Attrs {
|
|||
if let Some(value_parser) = self.value_parser.as_ref() {
|
||||
let span = value_parser.span();
|
||||
default_action(field_type, span)
|
||||
} else if !self.ignore_parser() || cfg!(not(feature = "unstable-v4")) {
|
||||
} else if !self.ignore_parser() {
|
||||
self.parser(field_type).action()
|
||||
} else {
|
||||
let span = self
|
||||
|
@ -815,16 +809,10 @@ impl Attrs {
|
|||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
pub fn ignore_parser(&self) -> bool {
|
||||
self.parser.is_none()
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "unstable-v4"))]
|
||||
pub fn ignore_parser(&self) -> bool {
|
||||
self.value_parser.is_some() || self.action.is_some()
|
||||
}
|
||||
|
||||
pub fn explicit_parser(&self) -> bool {
|
||||
self.parser.is_some()
|
||||
}
|
||||
|
@ -1200,7 +1188,6 @@ pub enum Name {
|
|||
}
|
||||
|
||||
impl Name {
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
pub fn raw(self) -> TokenStream {
|
||||
match self {
|
||||
Name::Assigned(tokens) => tokens,
|
||||
|
|
|
@ -484,17 +484,9 @@ fn gen_from_arg_matches(
|
|||
Unnamed(..) => abort_call_site!("{}: tuple enums are not supported", variant.ident),
|
||||
};
|
||||
|
||||
if cfg!(feature = "unstable-v4") {
|
||||
quote! {
|
||||
if #sub_name == #subcommand_name_var && !#sub_arg_matches_var.contains_id("") {
|
||||
return ::std::result::Result::Ok(#name :: #variant_name #constructor_block)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
if #sub_name == #subcommand_name_var {
|
||||
return ::std::result::Result::Ok(#name :: #variant_name #constructor_block)
|
||||
}
|
||||
quote! {
|
||||
if #sub_name == #subcommand_name_var && !#sub_arg_matches_var.contains_id("") {
|
||||
return ::std::result::Result::Ok(#name :: #variant_name #constructor_block)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -528,7 +520,7 @@ fn gen_from_arg_matches(
|
|||
.chain(
|
||||
#sub_arg_matches_var
|
||||
.remove_many::<#str_ty>("")
|
||||
.into_iter().flatten() // `""` isn't present, bug in `unstable-v4`
|
||||
.unwrap()
|
||||
.map(#str_ty::from)
|
||||
)
|
||||
.collect::<::std::vec::Vec<_>>()
|
||||
|
|
|
@ -40,7 +40,7 @@ SUBCOMMANDS:
|
|||
stash
|
||||
|
||||
$ git-derive help add
|
||||
git-derive[EXE]-add
|
||||
git-add
|
||||
adds things
|
||||
|
||||
USAGE:
|
||||
|
@ -58,7 +58,7 @@ A basic argument:
|
|||
```console
|
||||
$ git-derive add
|
||||
? failed
|
||||
git-derive[EXE]-add
|
||||
git-add
|
||||
adds things
|
||||
|
||||
USAGE:
|
||||
|
@ -78,7 +78,7 @@ Adding ["Cargo.toml", "Cargo.lock"]
|
|||
Default subcommand:
|
||||
```console
|
||||
$ git-derive stash -h
|
||||
git-derive[EXE]-stash
|
||||
git-stash
|
||||
|
||||
USAGE:
|
||||
git-derive[EXE] stash [OPTIONS]
|
||||
|
@ -95,7 +95,7 @@ SUBCOMMANDS:
|
|||
push
|
||||
|
||||
$ git-derive stash push -h
|
||||
git-derive[EXE]-stash-push
|
||||
git-stash-push
|
||||
|
||||
USAGE:
|
||||
git-derive[EXE] stash push [OPTIONS]
|
||||
|
@ -105,7 +105,7 @@ OPTIONS:
|
|||
-m, --message <MESSAGE>
|
||||
|
||||
$ git-derive stash pop -h
|
||||
git-derive[EXE]-stash-pop
|
||||
git-stash-pop
|
||||
|
||||
USAGE:
|
||||
git-derive[EXE] stash pop [STASH]
|
||||
|
|
|
@ -38,7 +38,7 @@ SUBCOMMANDS:
|
|||
stash
|
||||
|
||||
$ git help add
|
||||
git[EXE]-add
|
||||
git-add
|
||||
adds things
|
||||
|
||||
USAGE:
|
||||
|
@ -56,7 +56,7 @@ A basic argument:
|
|||
```console
|
||||
$ git add
|
||||
? failed
|
||||
git[EXE]-add
|
||||
git-add
|
||||
adds things
|
||||
|
||||
USAGE:
|
||||
|
@ -76,7 +76,7 @@ Adding ["Cargo.toml", "Cargo.lock"]
|
|||
Default subcommand:
|
||||
```console
|
||||
$ git stash -h
|
||||
git[EXE]-stash
|
||||
git-stash
|
||||
|
||||
USAGE:
|
||||
git[EXE] stash [OPTIONS]
|
||||
|
@ -93,7 +93,7 @@ SUBCOMMANDS:
|
|||
push
|
||||
|
||||
$ git stash push -h
|
||||
git[EXE]-stash-push
|
||||
git-stash-push
|
||||
|
||||
USAGE:
|
||||
git[EXE] stash push [OPTIONS]
|
||||
|
@ -103,7 +103,7 @@ OPTIONS:
|
|||
-m, --message <MESSAGE>
|
||||
|
||||
$ git stash pop -h
|
||||
git[EXE]-stash-pop
|
||||
git-stash-pop
|
||||
|
||||
USAGE:
|
||||
git[EXE] stash pop [STASH]
|
||||
|
|
|
@ -52,7 +52,7 @@ SUBCOMMANDS:
|
|||
sync -S --sync Synchronize packages.
|
||||
|
||||
$ pacman -S -h
|
||||
pacman[EXE]-sync
|
||||
pacman-sync
|
||||
Synchronize packages.
|
||||
|
||||
USAGE:
|
||||
|
|
|
@ -15,7 +15,7 @@ SUBCOMMANDS:
|
|||
help Print this message or the help of the given subcommand(s)
|
||||
|
||||
$ 03_04_subcommands help add
|
||||
03_04_subcommands[EXE]-add [..]
|
||||
clap-add 3.2.14
|
||||
Adds files to myapp
|
||||
|
||||
USAGE:
|
||||
|
|
|
@ -15,7 +15,7 @@ SUBCOMMANDS:
|
|||
help Print this message or the help of the given subcommand(s)
|
||||
|
||||
$ 03_04_subcommands help add
|
||||
03_04_subcommands[EXE]-add [..]
|
||||
clap-add 3.2.14
|
||||
Adds files to myapp
|
||||
|
||||
USAGE:
|
||||
|
@ -59,6 +59,6 @@ $ 03_04_subcommands --version
|
|||
clap [..]
|
||||
|
||||
$ 03_04_subcommands add --version
|
||||
03_04_subcommands[EXE]-add [..]
|
||||
03_04_subcommands-add [..]
|
||||
|
||||
```
|
||||
|
|
|
@ -23,4 +23,4 @@
|
|||
//!
|
||||
//! * **unstable-replace**: Enable [`Command::replace`](https://github.com/clap-rs/clap/issues/2836)
|
||||
//! * **unstable-grouped**: Enable [`ArgMatches::grouped_values_of`](https://github.com/clap-rs/clap/issues/2924)
|
||||
//! * **unstable-v4**: Preview features which will be stable on the v4.0 release
|
||||
//! * **unstable-v5**: Preview features which will be stable on the v5.0 release
|
||||
|
|
|
@ -186,14 +186,7 @@ impl<'help> Arg<'help> {
|
|||
#[inline]
|
||||
#[must_use]
|
||||
pub fn long(mut self, l: &'help str) -> Self {
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
{
|
||||
self.long = Some(l);
|
||||
}
|
||||
#[cfg(not(feature = "unstable-v4"))]
|
||||
{
|
||||
self.long = Some(l.trim_start_matches(|c| c == '-'));
|
||||
}
|
||||
self.long = Some(l);
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
@ -2273,14 +2273,7 @@ impl<'help> Command<'help> {
|
|||
/// [`Arg::long`]: Arg::long()
|
||||
#[must_use]
|
||||
pub fn long_flag(mut self, long: &'help str) -> Self {
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
{
|
||||
self.long_flag = Some(long);
|
||||
}
|
||||
#[cfg(not(feature = "unstable-v4"))]
|
||||
{
|
||||
self.long_flag = Some(long.trim_start_matches(|c| c == '-'));
|
||||
}
|
||||
self.long_flag = Some(long);
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -4674,10 +4667,9 @@ impl<'help> Command<'help> {
|
|||
v.long_help.is_some()
|
||||
|| v.is_hide_long_help_set()
|
||||
|| v.is_hide_short_help_set()
|
||||
|| cfg!(feature = "unstable-v4")
|
||||
&& v.get_possible_values()
|
||||
.iter()
|
||||
.any(PossibleValue::should_show_help)
|
||||
|| v.get_possible_values()
|
||||
.iter()
|
||||
.any(PossibleValue::should_show_help)
|
||||
};
|
||||
|
||||
// Subcommands aren't checked because we prefer short help for them, deferring to
|
||||
|
|
|
@ -27,9 +27,6 @@ pub(crate) fn assert_app(cmd: &Command) {
|
|||
.get_arguments()
|
||||
.filter(|x| {
|
||||
let action_set = matches!(x.get_action(), ArgAction::Version);
|
||||
#[cfg(not(feature = "unstable-v4"))]
|
||||
let provider_set = matches!(x.provider, ArgProvider::GeneratedMutated);
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
let provider_set = matches!(
|
||||
x.provider,
|
||||
ArgProvider::User | ArgProvider::GeneratedMutated
|
||||
|
@ -54,10 +51,7 @@ pub(crate) fn assert_app(cmd: &Command) {
|
|||
}
|
||||
|
||||
if let Some(l) = sc.get_long_flag().as_ref() {
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
{
|
||||
assert!(!l.starts_with('-'), "Command {}: long_flag {:?} must not start with a `-`, that will be handled by the parser", sc.get_name(), l);
|
||||
}
|
||||
assert!(!l.starts_with('-'), "Command {}: long_flag {:?} must not start with a `-`, that will be handled by the parser", sc.get_name(), l);
|
||||
long_flags.push(Flag::Command(format!("--{}", l), sc.get_name()));
|
||||
}
|
||||
|
||||
|
@ -85,10 +79,7 @@ pub(crate) fn assert_app(cmd: &Command) {
|
|||
}
|
||||
|
||||
if let Some(l) = arg.long.as_ref() {
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
{
|
||||
assert!(!l.starts_with('-'), "Argument {}: long {:?} must not start with a `-`, that will be handled by the parser", arg.name, l);
|
||||
}
|
||||
assert!(!l.starts_with('-'), "Argument {}: long {:?} must not start with a `-`, that will be handled by the parser", arg.name, l);
|
||||
long_flags.push(Flag::Arg(format!("--{}", l), &*arg.name));
|
||||
}
|
||||
|
||||
|
@ -161,14 +152,11 @@ pub(crate) fn assert_app(cmd: &Command) {
|
|||
}
|
||||
|
||||
for req in &arg.r_ifs {
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
{
|
||||
assert!(
|
||||
!arg.is_required_set(),
|
||||
"Argument {}: `required` conflicts with `required_if_eq*`",
|
||||
arg.name
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
!arg.is_required_set(),
|
||||
"Argument {}: `required` conflicts with `required_if_eq*`",
|
||||
arg.name
|
||||
);
|
||||
assert!(
|
||||
cmd.id_exists(&req.0),
|
||||
"Command {}: Argument or group '{:?}' specified in 'required_if_eq*' for '{}' does not exist",
|
||||
|
@ -179,14 +167,11 @@ pub(crate) fn assert_app(cmd: &Command) {
|
|||
}
|
||||
|
||||
for req in &arg.r_ifs_all {
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
{
|
||||
assert!(
|
||||
!arg.is_required_set(),
|
||||
"Argument {}: `required` conflicts with `required_if_eq_all`",
|
||||
arg.name
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
!arg.is_required_set(),
|
||||
"Argument {}: `required` conflicts with `required_if_eq_all`",
|
||||
arg.name
|
||||
);
|
||||
assert!(
|
||||
cmd.id_exists(&req.0),
|
||||
"Command {}: Argument or group '{:?}' specified in 'required_if_eq_all' for '{}' does not exist",
|
||||
|
@ -197,14 +182,11 @@ pub(crate) fn assert_app(cmd: &Command) {
|
|||
}
|
||||
|
||||
for req in &arg.r_unless {
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
{
|
||||
assert!(
|
||||
!arg.is_required_set(),
|
||||
"Argument {}: `required` conflicts with `required_unless*`",
|
||||
arg.name
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
!arg.is_required_set(),
|
||||
"Argument {}: `required` conflicts with `required_unless*`",
|
||||
arg.name
|
||||
);
|
||||
assert!(
|
||||
cmd.id_exists(req),
|
||||
"Command {}: Argument or group '{:?}' specified in 'required_unless*' for '{}' does not exist",
|
||||
|
@ -215,14 +197,11 @@ pub(crate) fn assert_app(cmd: &Command) {
|
|||
}
|
||||
|
||||
for req in &arg.r_unless_all {
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
{
|
||||
assert!(
|
||||
!arg.is_required_set(),
|
||||
"Argument {}: `required` conflicts with `required_unless*`",
|
||||
arg.name
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
!arg.is_required_set(),
|
||||
"Argument {}: `required` conflicts with `required_unless*`",
|
||||
arg.name
|
||||
);
|
||||
assert!(
|
||||
cmd.id_exists(req),
|
||||
"Command {}: Argument or group '{:?}' specified in 'required_unless*' for '{}' does not exist",
|
||||
|
@ -680,16 +659,13 @@ fn assert_arg(arg: &Arg) {
|
|||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
{
|
||||
let num_vals = arg.get_num_vals().unwrap_or(usize::MAX);
|
||||
let num_val_names = arg.get_value_names().unwrap_or(&[]).len();
|
||||
if num_vals < num_val_names {
|
||||
panic!(
|
||||
"Argument {}: Too many value names ({}) compared to number_of_values ({})",
|
||||
arg.name, num_val_names, num_vals
|
||||
);
|
||||
}
|
||||
let num_vals = arg.get_num_vals().unwrap_or(usize::MAX);
|
||||
let num_val_names = arg.get_value_names().unwrap_or(&[]).len();
|
||||
if num_vals < num_val_names {
|
||||
panic!(
|
||||
"Argument {}: Too many value names ({}) compared to number_of_values ({})",
|
||||
arg.name, num_val_names, num_vals
|
||||
);
|
||||
}
|
||||
|
||||
assert_arg_flags(arg);
|
||||
|
|
|
@ -153,7 +153,6 @@ impl<'help> PossibleValue<'help> {
|
|||
/// Get the help specified for this argument, if any and the argument
|
||||
/// value is not hidden
|
||||
#[inline]
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
pub(crate) fn get_visible_help(&self) -> Option<&'help str> {
|
||||
if !self.hide {
|
||||
self.help
|
||||
|
|
|
@ -28,7 +28,6 @@ pub(crate) struct Help<'help, 'cmd, 'writer> {
|
|||
|
||||
// Public Functions
|
||||
impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
const DEFAULT_TEMPLATE: &'static str = "\
|
||||
{before-help}{name} {version}\n\
|
||||
{author-with-newline}{about-with-newline}\n\
|
||||
|
@ -36,27 +35,12 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
|
|||
\n\
|
||||
{all-args}{after-help}\
|
||||
";
|
||||
#[cfg(not(feature = "unstable-v4"))]
|
||||
const DEFAULT_TEMPLATE: &'static str = "\
|
||||
{before-help}{bin} {version}\n\
|
||||
{author-with-newline}{about-with-newline}\n\
|
||||
{usage-heading}\n {usage}\n\
|
||||
\n\
|
||||
{all-args}{after-help}\
|
||||
";
|
||||
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
const DEFAULT_NO_ARGS_TEMPLATE: &'static str = "\
|
||||
{before-help}{name} {version}\n\
|
||||
{author-with-newline}{about-with-newline}\n\
|
||||
{usage-heading}\n {usage}{after-help}\
|
||||
";
|
||||
#[cfg(not(feature = "unstable-v4"))]
|
||||
const DEFAULT_NO_ARGS_TEMPLATE: &'static str = "\
|
||||
{before-help}{bin} {version}\n\
|
||||
{author-with-newline}{about-with-newline}\n\
|
||||
{usage-heading}\n {usage}{after-help}\
|
||||
";
|
||||
|
||||
/// Create a new `Help` instance.
|
||||
pub(crate) fn new(
|
||||
|
@ -477,7 +461,6 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
|
|||
self.none(part)?;
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
if let Some(arg) = arg {
|
||||
const DASH_SPACE: usize = "- ".len();
|
||||
const COLON_SPACE: usize = ": ".len();
|
||||
|
@ -663,9 +646,7 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
|
|||
let possible_vals = a.get_possible_values();
|
||||
if !(a.is_hide_possible_values_set()
|
||||
|| possible_vals.is_empty()
|
||||
|| cfg!(feature = "unstable-v4")
|
||||
&& self.use_long
|
||||
&& possible_vals.iter().any(PossibleValue::should_show_help))
|
||||
|| self.use_long && possible_vals.iter().any(PossibleValue::should_show_help))
|
||||
{
|
||||
debug!("Help::spec_vals: Found possible vals...{:?}", possible_vals);
|
||||
|
||||
|
|
|
@ -31,16 +31,6 @@ impl ArgMatcher {
|
|||
},
|
||||
#[cfg(debug_assertions)]
|
||||
valid_subcommands: _cmd.get_subcommands().map(|sc| sc.get_id()).collect(),
|
||||
// HACK: Allow an external subcommand's ArgMatches be a stand-in for any ArgMatches
|
||||
// since users can't detect it and avoid the asserts.
|
||||
//
|
||||
// See clap-rs/clap#3263
|
||||
#[cfg(debug_assertions)]
|
||||
#[cfg(not(feature = "unstable-v4"))]
|
||||
disable_asserts: _cmd.is_allow_external_subcommands_set(),
|
||||
#[cfg(debug_assertions)]
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
disable_asserts: false,
|
||||
..Default::default()
|
||||
},
|
||||
pending: None,
|
||||
|
|
|
@ -67,8 +67,6 @@ pub struct ArgMatches {
|
|||
pub(crate) valid_args: Vec<Id>,
|
||||
#[cfg(debug_assertions)]
|
||||
pub(crate) valid_subcommands: Vec<Id>,
|
||||
#[cfg(debug_assertions)]
|
||||
pub(crate) disable_asserts: bool,
|
||||
pub(crate) args: IndexMap<Id, MatchedArg>,
|
||||
pub(crate) subcommand: Option<Box<SubCommand>>,
|
||||
}
|
||||
|
@ -685,7 +683,7 @@ impl ArgMatches {
|
|||
#[cfg(debug_assertions)]
|
||||
{
|
||||
let id = Id::from(_id);
|
||||
self.disable_asserts || id == Id::empty_hash() || self.valid_args.contains(&id)
|
||||
id == Id::empty_hash() || self.valid_args.contains(&id)
|
||||
}
|
||||
#[cfg(not(debug_assertions))]
|
||||
{
|
||||
|
@ -890,7 +888,7 @@ impl ArgMatches {
|
|||
#[cfg(debug_assertions)]
|
||||
{
|
||||
let id = Id::from(_id);
|
||||
self.disable_asserts || id == Id::empty_hash() || self.valid_subcommands.contains(&id)
|
||||
id == Id::empty_hash() || self.valid_subcommands.contains(&id)
|
||||
}
|
||||
#[cfg(not(debug_assertions))]
|
||||
{
|
||||
|
@ -1066,7 +1064,7 @@ impl ArgMatches {
|
|||
fn verify_arg(&self, _arg: &Id) -> Result<(), MatchesError> {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
if self.disable_asserts || *_arg == Id::empty_hash() || self.valid_args.contains(_arg) {
|
||||
if *_arg == Id::empty_hash() || self.valid_args.contains(_arg) {
|
||||
} else if self.valid_subcommands.contains(_arg) {
|
||||
debug!(
|
||||
"Subcommand `{:?}` used where an argument or group name was expected.",
|
||||
|
@ -1091,7 +1089,7 @@ impl ArgMatches {
|
|||
fn get_arg(&self, arg: &Id) -> Option<&MatchedArg> {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
if self.disable_asserts || *arg == Id::empty_hash() || self.valid_args.contains(arg) {
|
||||
if *arg == Id::empty_hash() || self.valid_args.contains(arg) {
|
||||
} else if self.valid_subcommands.contains(arg) {
|
||||
panic!(
|
||||
"Subcommand `{:?}` used where an argument or group name was expected.",
|
||||
|
@ -1115,10 +1113,7 @@ impl ArgMatches {
|
|||
fn get_subcommand(&self, id: &Id) -> Option<&SubCommand> {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
if self.disable_asserts
|
||||
|| *id == Id::empty_hash()
|
||||
|| self.valid_subcommands.contains(id)
|
||||
{
|
||||
if *id == Id::empty_hash() || self.valid_subcommands.contains(id) {
|
||||
} else if self.valid_args.contains(id) {
|
||||
panic!(
|
||||
"Argument or group `{:?}` used where a subcommand name was expected.",
|
||||
|
|
|
@ -431,9 +431,7 @@ impl<'help, 'cmd> Parser<'help, 'cmd> {
|
|||
|
||||
// Collect the external subcommand args
|
||||
let mut sc_m = ArgMatcher::new(self.cmd);
|
||||
if cfg!(feature = "unstable-v4") || !raw_args.is_end(&args_cursor) {
|
||||
sc_m.start_occurrence_of_external(self.cmd);
|
||||
}
|
||||
sc_m.start_occurrence_of_external(self.cmd);
|
||||
|
||||
for raw_val in raw_args.remaining(&mut args_cursor) {
|
||||
let val = external_parser.parse_ref(self.cmd, None, raw_val)?;
|
||||
|
|
|
@ -890,27 +890,6 @@ fn issue_1093_allow_ext_sc() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(feature = "unstable-v4"))]
|
||||
fn allow_ext_sc_empty_args() {
|
||||
let res = Command::new("clap-test")
|
||||
.version("v1.4.8")
|
||||
.allow_external_subcommands(true)
|
||||
.allow_invalid_utf8_for_external_subcommands(true)
|
||||
.try_get_matches_from(vec!["clap-test", "external-cmd"]);
|
||||
|
||||
assert!(res.is_ok(), "{}", res.unwrap_err());
|
||||
|
||||
match res.unwrap().subcommand() {
|
||||
Some((name, args)) => {
|
||||
assert_eq!(name, "external-cmd");
|
||||
assert!(args.get_many::<OsString>("").is_none());
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
fn allow_ext_sc_empty_args() {
|
||||
let res = Command::new("clap-test")
|
||||
.version("v1.4.8")
|
||||
|
|
|
@ -190,21 +190,6 @@ For more information try --help
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(feature = "unstable-v4"))]
|
||||
fn leading_dash_stripped() {
|
||||
let cmd = Command::new("mycat").arg(
|
||||
Arg::new("filename")
|
||||
.long("--filename")
|
||||
.action(ArgAction::SetTrue),
|
||||
);
|
||||
let matches = cmd.try_get_matches_from(["mycat", "--filename"]).unwrap();
|
||||
assert!(*matches
|
||||
.get_one::<bool>("filename")
|
||||
.expect("defaulted by clap"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
#[cfg(debug_assertions)]
|
||||
#[should_panic = "Argument filename: long \"--filename\" must not start with a `-`, that will be handled by the parser"]
|
||||
fn leading_dash_stripped() {
|
||||
|
|
|
@ -942,7 +942,6 @@ OPTIONS:
|
|||
#[test]
|
||||
#[cfg(all(feature = "wrap_help"))]
|
||||
fn possible_value_wrapped_help() {
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
static WRAPPED_HELP: &str = "test
|
||||
|
||||
USAGE:
|
||||
|
@ -971,18 +970,6 @@ OPTIONS:
|
|||
- name: Short enough help message with no wrapping
|
||||
- second: short help
|
||||
";
|
||||
#[cfg(not(feature = "unstable-v4"))]
|
||||
static WRAPPED_HELP: &str = r#"test
|
||||
|
||||
USAGE:
|
||||
test [OPTIONS]
|
||||
|
||||
OPTIONS:
|
||||
-h, --help Print help information
|
||||
--possible-values <possible_values> [possible values: short_name, second]
|
||||
--possible-values-with-new-line <possible_values_with_new_line> [possible values: "long enough name to trigger new line", second]
|
||||
--possible-values-without-new-line <possible_values_without_new_line> [possible values: name, second]
|
||||
"#;
|
||||
let cmd = Command::new("test")
|
||||
.term_width(67)
|
||||
.arg(
|
||||
|
@ -1100,7 +1087,6 @@ fn hide_single_possible_val() {
|
|||
|
||||
#[test]
|
||||
fn possible_vals_with_help() {
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
static POS_VALS_HELP: &str = "ctest 0.1
|
||||
|
||||
USAGE:
|
||||
|
@ -1122,18 +1108,6 @@ OPTIONS:
|
|||
|
||||
-V, --version
|
||||
Print version information
|
||||
";
|
||||
#[cfg(not(feature = "unstable-v4"))]
|
||||
static POS_VALS_HELP: &str = "ctest 0.1
|
||||
|
||||
USAGE:
|
||||
ctest [OPTIONS]
|
||||
|
||||
OPTIONS:
|
||||
-c, --cafe <FILE> A coffeehouse, coffee shop, or café.
|
||||
-h, --help Print help information
|
||||
-p, --pos <VAL> Some vals [possible values: fast, slow]
|
||||
-V, --version Print version information
|
||||
";
|
||||
let app = Command::new("ctest")
|
||||
.version("0.1")
|
||||
|
@ -2603,22 +2577,6 @@ OPTIONS:
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(feature = "unstable-v4"))]
|
||||
fn too_many_value_names_panics() {
|
||||
Command::new("test")
|
||||
.arg(
|
||||
Arg::new("foo")
|
||||
.long("foo")
|
||||
.required(true)
|
||||
.takes_value(true)
|
||||
.number_of_values(1)
|
||||
.value_names(&["one", "two"]),
|
||||
)
|
||||
.debug_assert()
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
#[should_panic = "Argument foo: Too many value names (2) compared to number_of_values (1)"]
|
||||
fn too_many_value_names_panics() {
|
||||
Command::new("test")
|
||||
|
|
|
@ -19,7 +19,6 @@ use clap::Parser;
|
|||
fn required_argument() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_parser)]
|
||||
arg: i32,
|
||||
}
|
||||
assert_eq!(
|
||||
|
@ -34,7 +33,7 @@ fn required_argument() {
|
|||
fn argument_with_default() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_parser, default_value = "42")]
|
||||
#[clap(default_value = "42")]
|
||||
arg: i32,
|
||||
}
|
||||
assert_eq!(
|
||||
|
@ -49,7 +48,6 @@ fn argument_with_default() {
|
|||
fn auto_value_name() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_parser)]
|
||||
my_special_arg: i32,
|
||||
}
|
||||
|
||||
|
@ -69,7 +67,7 @@ fn auto_value_name() {
|
|||
fn explicit_value_name() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_parser, value_name = "BROWNIE_POINTS")]
|
||||
#[clap(value_name = "BROWNIE_POINTS")]
|
||||
my_special_arg: i32,
|
||||
}
|
||||
|
||||
|
@ -90,7 +88,6 @@ fn explicit_value_name() {
|
|||
fn option_type_is_optional() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_parser)]
|
||||
arg: Option<i32>,
|
||||
}
|
||||
assert_eq!(
|
||||
|
@ -105,7 +102,6 @@ fn option_type_is_optional() {
|
|||
fn vec_type_is_multiple_values() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_parser)]
|
||||
arg: Vec<i32>,
|
||||
}
|
||||
assert_eq!(
|
||||
|
|
|
@ -18,7 +18,7 @@ use clap::Parser;
|
|||
fn basic() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short = 'a', long = "arg", value_parser)]
|
||||
#[clap(short = 'a', long = "arg")]
|
||||
arg: i32,
|
||||
}
|
||||
assert_eq!(
|
||||
|
@ -31,7 +31,7 @@ fn basic() {
|
|||
fn update_basic() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short = 'a', long = "arg", value_parser)]
|
||||
#[clap(short = 'a', long = "arg")]
|
||||
single_value: i32,
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@ enum Sub {
|
|||
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Ext {
|
||||
#[clap(value_parser)]
|
||||
arg: u32,
|
||||
}
|
||||
|
||||
|
|
|
@ -21,19 +21,19 @@ use std::path::PathBuf;
|
|||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct PathOpt {
|
||||
#[clap(short, long, value_parser)]
|
||||
#[clap(short, long)]
|
||||
path: PathBuf,
|
||||
|
||||
#[clap(short, default_value = "../", value_parser)]
|
||||
#[clap(short, default_value = "../")]
|
||||
default_path: PathBuf,
|
||||
|
||||
#[clap(short, value_parser, multiple_occurrences(true))]
|
||||
#[clap(short, multiple_occurrences(true))]
|
||||
vector_path: Vec<PathBuf>,
|
||||
|
||||
#[clap(short, value_parser)]
|
||||
#[clap(short)]
|
||||
option_path_1: Option<PathBuf>,
|
||||
|
||||
#[clap(short = 'q', value_parser)]
|
||||
#[clap(short = 'q')]
|
||||
option_path_2: Option<PathBuf>,
|
||||
}
|
||||
|
||||
|
@ -134,10 +134,10 @@ struct DefaultedOpt {
|
|||
#[clap(short, parse(from_str))]
|
||||
bytes: Bytes,
|
||||
|
||||
#[clap(short, value_parser)]
|
||||
#[clap(short)]
|
||||
integer: u64,
|
||||
|
||||
#[clap(short, value_parser)]
|
||||
#[clap(short)]
|
||||
path: PathBuf,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use clap::{CommandFactory, Parser};
|
||||
|
||||
use crate::utils;
|
||||
|
@ -8,7 +6,7 @@ use crate::utils;
|
|||
fn default_value() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_parser, default_value = "3")]
|
||||
#[clap(default_value = "3")]
|
||||
arg: i32,
|
||||
}
|
||||
assert_eq!(Opt { arg: 3 }, Opt::try_parse_from(&["test"]).unwrap());
|
||||
|
@ -22,7 +20,7 @@ fn default_value() {
|
|||
fn default_value_t() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_parser, default_value_t = 3)]
|
||||
#[clap(default_value_t = 3)]
|
||||
arg: i32,
|
||||
}
|
||||
assert_eq!(Opt { arg: 3 }, Opt::try_parse_from(&["test"]).unwrap());
|
||||
|
@ -36,7 +34,7 @@ fn default_value_t() {
|
|||
fn auto_default_value_t() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_parser, default_value_t)]
|
||||
#[clap(default_value_t)]
|
||||
arg: i32,
|
||||
}
|
||||
assert_eq!(Opt { arg: 0 }, Opt::try_parse_from(&["test"]).unwrap());
|
||||
|
@ -46,37 +44,13 @@ fn auto_default_value_t() {
|
|||
assert!(help.contains("[default: 0]"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_value_os_t() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_parser, 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 detect_os_variant() {
|
||||
#![allow(unused_parens)] // needed for `as_ref` call
|
||||
|
||||
#[derive(clap::Parser)]
|
||||
pub struct Options {
|
||||
#[clap(value_parser, default_value_os = ("123".as_ref()))]
|
||||
#[clap(default_value_os = ("123".as_ref()))]
|
||||
x: String,
|
||||
}
|
||||
Options::command().debug_assert();
|
||||
|
|
|
@ -23,7 +23,7 @@ fn doc_comments() {
|
|||
struct LoremIpsum {
|
||||
/// Fooify a bar
|
||||
/// and a baz
|
||||
#[clap(short, long, action)]
|
||||
#[clap(short, long)]
|
||||
foo: bool,
|
||||
}
|
||||
|
||||
|
@ -39,12 +39,7 @@ fn help_is_better_than_comments() {
|
|||
#[clap(name = "lorem-ipsum", about = "Dolor sit amet")]
|
||||
struct LoremIpsum {
|
||||
/// Fooify a bar
|
||||
#[clap(
|
||||
short,
|
||||
long,
|
||||
help = "DO NOT PASS A BAR UNDER ANY CIRCUMSTANCES",
|
||||
action
|
||||
)]
|
||||
#[clap(short, long, help = "DO NOT PASS A BAR UNDER ANY CIRCUMSTANCES")]
|
||||
foo: bool,
|
||||
}
|
||||
|
||||
|
@ -76,11 +71,11 @@ fn field_long_doc_comment_both_help_long_help() {
|
|||
/// Dot is removed from multiline comments.
|
||||
///
|
||||
/// Long help
|
||||
#[clap(long, action)]
|
||||
#[clap(long)]
|
||||
foo: bool,
|
||||
|
||||
/// Dot is removed from one short comment.
|
||||
#[clap(long, action)]
|
||||
#[clap(long)]
|
||||
bar: bool,
|
||||
}
|
||||
|
||||
|
@ -111,7 +106,7 @@ fn top_long_doc_comment_both_help_long_help() {
|
|||
///
|
||||
/// Or something else
|
||||
Foo {
|
||||
#[clap(value_parser, help = "foo")]
|
||||
#[clap(help = "foo")]
|
||||
bars: String,
|
||||
},
|
||||
}
|
||||
|
@ -146,7 +141,7 @@ fn verbatim_doc_comment() {
|
|||
#[derive(Parser, Debug)]
|
||||
#[clap(verbatim_doc_comment)]
|
||||
struct SeeFigure1 {
|
||||
#[clap(long, action)]
|
||||
#[clap(long)]
|
||||
foo: bool,
|
||||
}
|
||||
|
||||
|
@ -176,10 +171,10 @@ fn verbatim_doc_comment_field() {
|
|||
#[derive(Parser, Debug)]
|
||||
struct Command {
|
||||
/// This help ends in a period.
|
||||
#[clap(long, verbatim_doc_comment, action)]
|
||||
#[clap(long, verbatim_doc_comment)]
|
||||
foo: bool,
|
||||
/// This help does not end in a period.
|
||||
#[clap(long, action)]
|
||||
#[clap(long)]
|
||||
bar: bool,
|
||||
}
|
||||
|
||||
|
@ -196,7 +191,7 @@ fn multiline_separates_default() {
|
|||
/// Multiline
|
||||
///
|
||||
/// Doc comment
|
||||
#[clap(long, default_value = "x", value_parser)]
|
||||
#[clap(long, default_value = "x")]
|
||||
x: String,
|
||||
}
|
||||
|
||||
|
@ -234,10 +229,7 @@ fn doc_comment_about_handles_both_abouts() {
|
|||
/// Sub doc comment body
|
||||
#[derive(Parser, PartialEq, Eq, Debug)]
|
||||
pub enum Sub {
|
||||
Compress {
|
||||
#[clap(value_parser)]
|
||||
output: String,
|
||||
},
|
||||
Compress { output: String },
|
||||
}
|
||||
|
||||
let cmd = Opts::command();
|
||||
|
|
|
@ -6,7 +6,7 @@ use clap::Parser;
|
|||
fn explicit_short_long_no_rename() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short = '.', long = ".foo", value_parser)]
|
||||
#[clap(short = '.', long = ".foo")]
|
||||
foo: String,
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ fn explicit_short_long_no_rename() {
|
|||
fn explicit_name_no_rename() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(name = ".options", value_parser)]
|
||||
#[clap(name = ".options")]
|
||||
foo: String,
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ use clap::Parser;
|
|||
fn bool_type_is_flag() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short, long, action)]
|
||||
#[clap(short, long)]
|
||||
alice: bool,
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,7 @@ fn non_bool_type_flag() {
|
|||
fn mixed_type_flags() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short, long, action)]
|
||||
#[clap(short, long)]
|
||||
alice: bool,
|
||||
#[clap(short, long, action = clap::ArgAction::Count)]
|
||||
bob: u8,
|
||||
|
@ -181,7 +181,6 @@ fn ignore_qualified_bool_type() {
|
|||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(action)]
|
||||
arg: inner::bool,
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@ use clap::{Args, Parser, Subcommand};
|
|||
fn flatten() {
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Common {
|
||||
#[clap(value_parser)]
|
||||
arg: i32,
|
||||
}
|
||||
|
||||
|
@ -45,7 +44,6 @@ fn flatten() {
|
|||
fn flatten_twice() {
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Common {
|
||||
#[clap(value_parser)]
|
||||
arg: i32,
|
||||
}
|
||||
|
||||
|
@ -64,13 +62,12 @@ fn flatten_twice() {
|
|||
fn flatten_in_subcommand() {
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Common {
|
||||
#[clap(value_parser)]
|
||||
arg: i32,
|
||||
}
|
||||
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Add {
|
||||
#[clap(short, action)]
|
||||
#[clap(short)]
|
||||
interactive: bool,
|
||||
#[clap(flatten)]
|
||||
common: Common,
|
||||
|
@ -79,7 +76,7 @@ fn flatten_in_subcommand() {
|
|||
#[derive(Parser, PartialEq, Debug)]
|
||||
enum Opt {
|
||||
Fetch {
|
||||
#[clap(short, action)]
|
||||
#[clap(short)]
|
||||
all: bool,
|
||||
#[clap(flatten)]
|
||||
common: Common,
|
||||
|
@ -108,7 +105,6 @@ fn flatten_in_subcommand() {
|
|||
fn update_args_with_flatten() {
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Common {
|
||||
#[clap(value_parser)]
|
||||
arg: i32,
|
||||
}
|
||||
|
||||
|
@ -138,15 +134,13 @@ enum BaseCli {
|
|||
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Command1 {
|
||||
#[clap(value_parser)]
|
||||
arg1: i32,
|
||||
#[clap(value_parser)]
|
||||
|
||||
arg2: i32,
|
||||
}
|
||||
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Command2 {
|
||||
#[clap(value_parser)]
|
||||
arg2: i32,
|
||||
}
|
||||
|
||||
|
@ -199,7 +193,6 @@ fn flatten_with_doc_comment() {
|
|||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Common {
|
||||
/// This is an arg. Arg means "argument". Command line argument.
|
||||
#[clap(value_parser)]
|
||||
arg: i32,
|
||||
}
|
||||
|
||||
|
@ -227,7 +220,7 @@ fn docstrings_ordering_with_multiple_clap() {
|
|||
/// This is the docstring for Flattened
|
||||
#[derive(Args)]
|
||||
struct Flattened {
|
||||
#[clap(long, action)]
|
||||
#[clap(long)]
|
||||
foo: bool,
|
||||
}
|
||||
|
||||
|
@ -248,7 +241,7 @@ fn docstrings_ordering_with_multiple_clap_partial() {
|
|||
/// This is the docstring for Flattened
|
||||
#[derive(Args)]
|
||||
struct Flattened {
|
||||
#[clap(long, action)]
|
||||
#[clap(long)]
|
||||
foo: bool,
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ use clap::{Args, Parser};
|
|||
fn generic_struct_flatten() {
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Inner {
|
||||
#[clap(value_parser)]
|
||||
pub answer: isize,
|
||||
}
|
||||
|
||||
|
@ -26,7 +25,6 @@ fn generic_struct_flatten() {
|
|||
fn generic_struct_flatten_w_where_clause() {
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Inner {
|
||||
#[clap(value_parser)]
|
||||
pub answer: isize,
|
||||
}
|
||||
|
||||
|
@ -51,7 +49,6 @@ fn generic_struct_flatten_w_where_clause() {
|
|||
fn generic_enum() {
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Inner {
|
||||
#[clap(value_parser)]
|
||||
pub answer: isize,
|
||||
}
|
||||
|
||||
|
@ -71,7 +68,6 @@ fn generic_enum() {
|
|||
fn generic_enum_w_where_clause() {
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Inner {
|
||||
#[clap(value_parser)]
|
||||
pub answer: isize,
|
||||
}
|
||||
|
||||
|
@ -100,7 +96,6 @@ fn generic_w_fromstr_trait_bound() {
|
|||
T: FromStr + Send + Sync + Clone + 'static,
|
||||
<T as FromStr>::Err: std::error::Error + Sync + Send + 'static,
|
||||
{
|
||||
#[clap(value_parser)]
|
||||
answer: T,
|
||||
}
|
||||
|
||||
|
@ -116,7 +111,6 @@ fn generic_wo_trait_bound() {
|
|||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt<T> {
|
||||
#[clap(value_parser)]
|
||||
answer: isize,
|
||||
#[clap(skip)]
|
||||
took: Option<T>,
|
||||
|
@ -141,7 +135,6 @@ fn generic_where_clause_w_trailing_comma() {
|
|||
T: FromStr + Send + Sync + Clone + 'static,
|
||||
<T as FromStr>::Err: std::error::Error + Sync + Send + 'static,
|
||||
{
|
||||
#[clap(value_parser)]
|
||||
pub answer: T,
|
||||
}
|
||||
|
||||
|
|
|
@ -4,36 +4,26 @@ use clap::{AppSettings, Args, CommandFactory, Parser, Subcommand};
|
|||
fn arg_help_heading_applied() {
|
||||
#[derive(Debug, Clone, Parser)]
|
||||
struct CliOptions {
|
||||
#[clap(long, value_parser)]
|
||||
#[clap(long)]
|
||||
#[clap(help_heading = Some("HEADING A"))]
|
||||
should_be_in_section_a: u32,
|
||||
|
||||
#[clap(long, value_parser)]
|
||||
#[clap(long)]
|
||||
no_section: u32,
|
||||
}
|
||||
|
||||
let cmd = CliOptions::command();
|
||||
|
||||
let should_be_in_section_a = if cfg!(feature = "unstable-v4") {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_section_a")
|
||||
.unwrap()
|
||||
} else {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should-be-in-section-a")
|
||||
.unwrap()
|
||||
};
|
||||
let should_be_in_section_a = cmd
|
||||
.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_section_a")
|
||||
.unwrap();
|
||||
assert_eq!(should_be_in_section_a.get_help_heading(), Some("HEADING A"));
|
||||
|
||||
let should_be_in_section_b = if cfg!(feature = "unstable-v4") {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "no_section")
|
||||
.unwrap()
|
||||
} else {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "no-section")
|
||||
.unwrap()
|
||||
};
|
||||
let should_be_in_section_b = cmd
|
||||
.get_arguments()
|
||||
.find(|a| a.get_id() == "no_section")
|
||||
.unwrap();
|
||||
assert_eq!(should_be_in_section_b.get_help_heading(), None);
|
||||
}
|
||||
|
||||
|
@ -42,36 +32,26 @@ fn app_help_heading_applied() {
|
|||
#[derive(Debug, Clone, Parser)]
|
||||
#[clap(next_help_heading = "DEFAULT")]
|
||||
struct CliOptions {
|
||||
#[clap(long, value_parser)]
|
||||
#[clap(long)]
|
||||
#[clap(help_heading = Some("HEADING A"))]
|
||||
should_be_in_section_a: u32,
|
||||
|
||||
#[clap(long, value_parser)]
|
||||
#[clap(long)]
|
||||
should_be_in_default_section: u32,
|
||||
}
|
||||
|
||||
let cmd = CliOptions::command();
|
||||
|
||||
let should_be_in_section_a = if cfg!(feature = "unstable-v4") {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_section_a")
|
||||
.unwrap()
|
||||
} else {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should-be-in-section-a")
|
||||
.unwrap()
|
||||
};
|
||||
let should_be_in_section_a = cmd
|
||||
.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_section_a")
|
||||
.unwrap();
|
||||
assert_eq!(should_be_in_section_a.get_help_heading(), Some("HEADING A"));
|
||||
|
||||
let should_be_in_default_section = if cfg!(feature = "unstable-v4") {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_default_section")
|
||||
.unwrap()
|
||||
} else {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should-be-in-default-section")
|
||||
.unwrap()
|
||||
};
|
||||
let should_be_in_default_section = cmd
|
||||
.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_default_section")
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
should_be_in_default_section.get_help_heading(),
|
||||
Some("DEFAULT")
|
||||
|
@ -94,21 +74,21 @@ fn app_help_heading_flattened() {
|
|||
#[clap(subcommand)]
|
||||
sub_a: SubA,
|
||||
|
||||
#[clap(long, value_parser)]
|
||||
#[clap(long)]
|
||||
should_be_in_default_section: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Args)]
|
||||
#[clap(next_help_heading = "HEADING A")]
|
||||
struct OptionsA {
|
||||
#[clap(long, value_parser)]
|
||||
#[clap(long)]
|
||||
should_be_in_section_a: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Args)]
|
||||
#[clap(next_help_heading = "HEADING B")]
|
||||
struct OptionsB {
|
||||
#[clap(long, value_parser)]
|
||||
#[clap(long)]
|
||||
should_be_in_section_b: u32,
|
||||
}
|
||||
|
||||
|
@ -121,7 +101,6 @@ fn app_help_heading_flattened() {
|
|||
SubAOne,
|
||||
#[clap(next_help_heading = "SUB A")]
|
||||
SubATwo {
|
||||
#[clap(value_parser)]
|
||||
should_be_in_sub_a: u32,
|
||||
},
|
||||
}
|
||||
|
@ -129,100 +108,58 @@ fn app_help_heading_flattened() {
|
|||
#[derive(Debug, Clone, Subcommand)]
|
||||
enum SubB {
|
||||
#[clap(next_help_heading = "SUB B")]
|
||||
SubBOne {
|
||||
#[clap(value_parser)]
|
||||
should_be_in_sub_b: u32,
|
||||
},
|
||||
SubBOne { should_be_in_sub_b: u32 },
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Subcommand)]
|
||||
enum SubC {
|
||||
#[clap(next_help_heading = "SUB C")]
|
||||
SubCOne {
|
||||
#[clap(value_parser)]
|
||||
should_be_in_sub_c: u32,
|
||||
},
|
||||
SubCOne { should_be_in_sub_c: u32 },
|
||||
}
|
||||
|
||||
let cmd = CliOptions::command();
|
||||
|
||||
let should_be_in_section_a = if cfg!(feature = "unstable-v4") {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_section_a")
|
||||
.unwrap()
|
||||
} else {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should-be-in-section-a")
|
||||
.unwrap()
|
||||
};
|
||||
let should_be_in_section_a = cmd
|
||||
.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_section_a")
|
||||
.unwrap();
|
||||
assert_eq!(should_be_in_section_a.get_help_heading(), Some("HEADING A"));
|
||||
|
||||
let should_be_in_section_b = if cfg!(feature = "unstable-v4") {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_section_b")
|
||||
.unwrap()
|
||||
} else {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should-be-in-section-b")
|
||||
.unwrap()
|
||||
};
|
||||
let should_be_in_section_b = cmd
|
||||
.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_section_b")
|
||||
.unwrap();
|
||||
assert_eq!(should_be_in_section_b.get_help_heading(), Some("HEADING B"));
|
||||
|
||||
let should_be_in_default_section = if cfg!(feature = "unstable-v4") {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_default_section")
|
||||
.unwrap()
|
||||
} else {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should-be-in-default-section")
|
||||
.unwrap()
|
||||
};
|
||||
let should_be_in_default_section = cmd
|
||||
.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_default_section")
|
||||
.unwrap();
|
||||
assert_eq!(should_be_in_default_section.get_help_heading(), None);
|
||||
|
||||
let sub_a_two = cmd.find_subcommand("sub-a-two").unwrap();
|
||||
|
||||
let should_be_in_sub_a = if cfg!(feature = "unstable-v4") {
|
||||
sub_a_two
|
||||
.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_sub_a")
|
||||
.unwrap()
|
||||
} else {
|
||||
sub_a_two
|
||||
.get_arguments()
|
||||
.find(|a| a.get_id() == "should-be-in-sub-a")
|
||||
.unwrap()
|
||||
};
|
||||
let should_be_in_sub_a = sub_a_two
|
||||
.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_sub_a")
|
||||
.unwrap();
|
||||
assert_eq!(should_be_in_sub_a.get_help_heading(), Some("SUB A"));
|
||||
|
||||
let sub_b_one = cmd.find_subcommand("sub-b-one").unwrap();
|
||||
|
||||
let should_be_in_sub_b = if cfg!(feature = "unstable-v4") {
|
||||
sub_b_one
|
||||
.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_sub_b")
|
||||
.unwrap()
|
||||
} else {
|
||||
sub_b_one
|
||||
.get_arguments()
|
||||
.find(|a| a.get_id() == "should-be-in-sub-b")
|
||||
.unwrap()
|
||||
};
|
||||
let should_be_in_sub_b = sub_b_one
|
||||
.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_sub_b")
|
||||
.unwrap();
|
||||
assert_eq!(should_be_in_sub_b.get_help_heading(), Some("SUB B"));
|
||||
|
||||
let sub_c = cmd.find_subcommand("sub-c").unwrap();
|
||||
let sub_c_one = sub_c.find_subcommand("sub-c-one").unwrap();
|
||||
|
||||
let should_be_in_sub_c = if cfg!(feature = "unstable-v4") {
|
||||
sub_c_one
|
||||
.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_sub_c")
|
||||
.unwrap()
|
||||
} else {
|
||||
sub_c_one
|
||||
.get_arguments()
|
||||
.find(|a| a.get_id() == "should-be-in-sub-c")
|
||||
.unwrap()
|
||||
};
|
||||
let should_be_in_sub_c = sub_c_one
|
||||
.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_sub_c")
|
||||
.unwrap();
|
||||
assert_eq!(should_be_in_sub_c.get_help_heading(), Some("SUB C"));
|
||||
}
|
||||
|
||||
|
@ -237,21 +174,16 @@ fn flatten_field_with_help_heading() {
|
|||
|
||||
#[derive(Debug, Clone, Args)]
|
||||
struct OptionsA {
|
||||
#[clap(long, value_parser)]
|
||||
#[clap(long)]
|
||||
should_be_in_section_a: u32,
|
||||
}
|
||||
|
||||
let cmd = CliOptions::command();
|
||||
|
||||
let should_be_in_section_a = if cfg!(feature = "unstable-v4") {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_section_a")
|
||||
.unwrap()
|
||||
} else {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should-be-in-section-a")
|
||||
.unwrap()
|
||||
};
|
||||
let should_be_in_section_a = cmd
|
||||
.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_section_a")
|
||||
.unwrap();
|
||||
assert_eq!(should_be_in_section_a.get_help_heading(), Some("HEADING A"));
|
||||
}
|
||||
|
||||
|
@ -264,7 +196,7 @@ fn derive_generated_error_has_full_context() {
|
|||
#[derive(Debug, Parser)]
|
||||
#[clap(subcommand_negates_reqs = true)]
|
||||
struct Opts {
|
||||
#[clap(long, value_parser)]
|
||||
#[clap(long)]
|
||||
req_str: String,
|
||||
|
||||
#[clap(subcommand)]
|
||||
|
@ -286,8 +218,7 @@ fn derive_generated_error_has_full_context() {
|
|||
result.unwrap()
|
||||
);
|
||||
|
||||
if cfg!(feature = "unstable-v4") {
|
||||
let expected = r#"error: The following required argument was not provided: req_str
|
||||
let expected = r#"error: The following required argument was not provided: req_str
|
||||
|
||||
USAGE:
|
||||
clap --req-str <REQ_STR>
|
||||
|
@ -295,18 +226,7 @@ USAGE:
|
|||
|
||||
For more information try --help
|
||||
"#;
|
||||
assert_eq!(result.unwrap_err().to_string(), expected);
|
||||
} else {
|
||||
let expected = r#"error: The following required argument was not provided: req-str
|
||||
|
||||
USAGE:
|
||||
clap --req-str <REQ_STR>
|
||||
clap <SUBCOMMAND>
|
||||
|
||||
For more information try --help
|
||||
"#;
|
||||
assert_eq!(result.unwrap_err().to_string(), expected);
|
||||
}
|
||||
assert_eq!(result.unwrap_err().to_string(), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -339,10 +259,10 @@ OPTIONS:
|
|||
#[clap(next_display_order = 10000)]
|
||||
struct A {
|
||||
/// second flag
|
||||
#[clap(long, action)]
|
||||
#[clap(long)]
|
||||
flag_a: bool,
|
||||
/// second option
|
||||
#[clap(long, value_parser)]
|
||||
#[clap(long)]
|
||||
option_a: Option<String>,
|
||||
}
|
||||
|
||||
|
@ -350,10 +270,10 @@ OPTIONS:
|
|||
#[clap(next_display_order = 10)]
|
||||
struct B {
|
||||
/// first flag
|
||||
#[clap(long, action)]
|
||||
#[clap(long)]
|
||||
flag_b: bool,
|
||||
/// first option
|
||||
#[clap(long, value_parser)]
|
||||
#[clap(long)]
|
||||
option_b: Option<String>,
|
||||
}
|
||||
|
||||
|
@ -397,20 +317,20 @@ OPTIONS:
|
|||
#[derive(Args, Debug)]
|
||||
struct A {
|
||||
/// second flag
|
||||
#[clap(long, action)]
|
||||
#[clap(long)]
|
||||
flag_a: bool,
|
||||
/// second option
|
||||
#[clap(long, value_parser)]
|
||||
#[clap(long)]
|
||||
option_a: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
struct B {
|
||||
/// first flag
|
||||
#[clap(long, action)]
|
||||
#[clap(long)]
|
||||
flag_b: bool,
|
||||
/// first option
|
||||
#[clap(long, value_parser)]
|
||||
#[clap(long)]
|
||||
option_b: Option<String>,
|
||||
}
|
||||
|
||||
|
@ -453,20 +373,20 @@ OPTIONS:
|
|||
#[derive(Args, Debug)]
|
||||
struct A {
|
||||
/// first flag
|
||||
#[clap(long, action)]
|
||||
#[clap(long)]
|
||||
flag_a: bool,
|
||||
/// first option
|
||||
#[clap(long, value_parser)]
|
||||
#[clap(long)]
|
||||
option_a: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
struct B {
|
||||
/// second flag
|
||||
#[clap(long, action)]
|
||||
#[clap(long)]
|
||||
flag_b: bool,
|
||||
/// second option
|
||||
#[clap(long, value_parser)]
|
||||
#[clap(long)]
|
||||
option_b: Option<String>,
|
||||
}
|
||||
|
||||
|
@ -480,7 +400,6 @@ OPTIONS:
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
fn derive_possible_value_help() {
|
||||
static HELP: &str = "clap
|
||||
Application help
|
||||
|
@ -505,7 +424,7 @@ OPTIONS:
|
|||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Args {
|
||||
/// Argument help
|
||||
#[clap(value_enum, value_parser)]
|
||||
#[clap(value_enum)]
|
||||
arg: ArgChoice,
|
||||
}
|
||||
|
||||
|
|
|
@ -9,9 +9,9 @@ fn issue_151_groups_within_subcommands() {
|
|||
#[derive(Args, Debug)]
|
||||
#[clap(group = ArgGroup::new("verb").required(true).multiple(true))]
|
||||
struct Opt {
|
||||
#[clap(long, group = "verb", value_parser)]
|
||||
#[clap(long, group = "verb")]
|
||||
foo: Option<String>,
|
||||
#[clap(long, group = "verb", value_parser)]
|
||||
#[clap(long, group = "verb")]
|
||||
bar: Option<String>,
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,6 @@ fn issue_418() {
|
|||
#[clap(visible_alias = "ret")]
|
||||
Reticulate {
|
||||
/// How many splines
|
||||
#[clap(value_parser)]
|
||||
num_splines: u8,
|
||||
},
|
||||
/// Frobnicate the rest
|
||||
|
@ -122,9 +121,8 @@ fn issue_490() {
|
|||
|
||||
#[derive(Parser, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_parser)]
|
||||
opt_vec: Vec<u16>,
|
||||
#[clap(long, value_parser)]
|
||||
#[clap(long)]
|
||||
opt_opt_vec: Option<Vec<u16>>,
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ fn use_option() {
|
|||
($name:ident: $ty:ty) => {
|
||||
#[derive(Parser)]
|
||||
struct Outer {
|
||||
#[clap(short, long, value_parser)]
|
||||
#[clap(short, long)]
|
||||
#[allow(dead_code)]
|
||||
$name: $ty,
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#![cfg(feature = "derive")]
|
||||
|
||||
mod next;
|
||||
|
||||
mod app_name;
|
||||
mod arguments;
|
||||
mod author_version_about;
|
||||
|
|
|
@ -5,7 +5,7 @@ fn test_standalone_long_generates_kebab_case() {
|
|||
#[derive(Parser, Debug, PartialEq)]
|
||||
#[allow(non_snake_case)]
|
||||
struct Opt {
|
||||
#[clap(long, action)]
|
||||
#[clap(long)]
|
||||
FOO_OPTION: bool,
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ fn test_standalone_long_generates_kebab_case() {
|
|||
fn test_custom_long_overwrites_default_name() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(long = "foo", action)]
|
||||
#[clap(long = "foo")]
|
||||
foo_option: bool,
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ fn test_custom_long_overwrites_default_name() {
|
|||
fn test_standalone_long_uses_previous_defined_custom_name() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(name = "foo", long, action)]
|
||||
#[clap(name = "foo", long)]
|
||||
foo_option: bool,
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ fn test_standalone_long_uses_previous_defined_custom_name() {
|
|||
fn test_standalone_long_ignores_afterwards_defined_custom_name() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(long, name = "foo", action)]
|
||||
#[clap(long, name = "foo")]
|
||||
foo_option: bool,
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,7 @@ fn test_standalone_short_generates_kebab_case() {
|
|||
#[derive(Parser, Debug, PartialEq)]
|
||||
#[allow(non_snake_case)]
|
||||
struct Opt {
|
||||
#[clap(short, action)]
|
||||
#[clap(short)]
|
||||
FOO_OPTION: bool,
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,7 @@ fn test_standalone_short_generates_kebab_case() {
|
|||
fn test_custom_short_overwrites_default_name() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(short = 'o', action)]
|
||||
#[clap(short = 'o')]
|
||||
foo_option: bool,
|
||||
}
|
||||
|
||||
|
@ -90,7 +90,7 @@ fn test_custom_short_overwrites_default_name() {
|
|||
fn test_standalone_short_uses_previous_defined_custom_name() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(name = "option", short, action)]
|
||||
#[clap(name = "option", short)]
|
||||
foo_option: bool,
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,7 @@ fn test_standalone_short_uses_previous_defined_custom_name() {
|
|||
fn test_standalone_short_ignores_afterwards_defined_custom_name() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(short, name = "option", action)]
|
||||
#[clap(short, name = "option")]
|
||||
foo_option: bool,
|
||||
}
|
||||
|
||||
|
@ -118,7 +118,7 @@ fn test_standalone_short_ignores_afterwards_defined_custom_name() {
|
|||
fn test_standalone_long_uses_previous_defined_casing() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(rename_all = "screaming_snake", long, action)]
|
||||
#[clap(rename_all = "screaming_snake", long)]
|
||||
foo_option: bool,
|
||||
}
|
||||
|
||||
|
@ -132,7 +132,7 @@ fn test_standalone_long_uses_previous_defined_casing() {
|
|||
fn test_standalone_short_uses_previous_defined_casing() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(rename_all = "screaming_snake", short, action)]
|
||||
#[clap(rename_all = "screaming_snake", short)]
|
||||
foo_option: bool,
|
||||
}
|
||||
|
||||
|
@ -147,7 +147,7 @@ fn test_standalone_long_works_with_verbatim_casing() {
|
|||
#[derive(Parser, Debug, PartialEq)]
|
||||
#[allow(non_snake_case)]
|
||||
struct Opt {
|
||||
#[clap(rename_all = "verbatim", long, action)]
|
||||
#[clap(rename_all = "verbatim", long)]
|
||||
_fOO_oPtiON: bool,
|
||||
}
|
||||
|
||||
|
@ -161,7 +161,7 @@ fn test_standalone_long_works_with_verbatim_casing() {
|
|||
fn test_standalone_short_works_with_verbatim_casing() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(rename_all = "verbatim", short, action)]
|
||||
#[clap(rename_all = "verbatim", short)]
|
||||
_foo: bool,
|
||||
}
|
||||
|
||||
|
@ -176,7 +176,7 @@ fn test_rename_all_is_propagated_from_struct_to_fields() {
|
|||
#[derive(Parser, Debug, PartialEq)]
|
||||
#[clap(rename_all = "screaming_snake")]
|
||||
struct Opt {
|
||||
#[clap(long, action)]
|
||||
#[clap(long)]
|
||||
foo: bool,
|
||||
}
|
||||
|
||||
|
@ -197,7 +197,7 @@ fn test_rename_all_is_not_propagated_from_struct_into_flattened() {
|
|||
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Foo {
|
||||
#[clap(long, action)]
|
||||
#[clap(long)]
|
||||
foo: bool,
|
||||
}
|
||||
|
||||
|
@ -213,7 +213,7 @@ fn test_rename_all_is_not_propagated_from_struct_into_flattened() {
|
|||
fn test_lower_is_renamed() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(rename_all = "lower", long, action)]
|
||||
#[clap(rename_all = "lower", long)]
|
||||
foo_option: bool,
|
||||
}
|
||||
|
||||
|
@ -227,7 +227,7 @@ fn test_lower_is_renamed() {
|
|||
fn test_upper_is_renamed() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(rename_all = "upper", long, action)]
|
||||
#[clap(rename_all = "upper", long)]
|
||||
foo_option: bool,
|
||||
}
|
||||
|
||||
|
@ -241,10 +241,7 @@ fn test_upper_is_renamed() {
|
|||
fn test_single_word_enum_variant_is_default_renamed_into_kebab_case() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
enum Opt {
|
||||
Command {
|
||||
#[clap(value_parser)]
|
||||
foo: u32,
|
||||
},
|
||||
Command { foo: u32 },
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
|
@ -257,10 +254,7 @@ fn test_single_word_enum_variant_is_default_renamed_into_kebab_case() {
|
|||
fn test_multi_word_enum_variant_is_renamed() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
enum Opt {
|
||||
FirstCommand {
|
||||
#[clap(value_parser)]
|
||||
foo: u32,
|
||||
},
|
||||
FirstCommand { foo: u32 },
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
|
@ -281,7 +275,7 @@ fn test_rename_all_is_not_propagated_from_struct_into_subcommand() {
|
|||
#[derive(Parser, Debug, PartialEq)]
|
||||
enum Foo {
|
||||
Command {
|
||||
#[clap(long, action)]
|
||||
#[clap(long)]
|
||||
foo: bool,
|
||||
},
|
||||
}
|
||||
|
@ -301,7 +295,7 @@ fn test_rename_all_is_propagated_from_enum_to_variants() {
|
|||
enum Opt {
|
||||
FirstVariant,
|
||||
SecondVariant {
|
||||
#[clap(long, value_parser)]
|
||||
#[clap(long)]
|
||||
foo: String,
|
||||
},
|
||||
}
|
||||
|
@ -319,7 +313,7 @@ fn test_rename_all_is_propagated_from_enum_to_variant_fields() {
|
|||
enum Opt {
|
||||
FirstVariant,
|
||||
SecondVariant {
|
||||
#[clap(long, value_parser)]
|
||||
#[clap(long)]
|
||||
foo: String,
|
||||
},
|
||||
}
|
||||
|
@ -339,11 +333,11 @@ fn test_rename_all_is_propagation_can_be_overridden() {
|
|||
enum Opt {
|
||||
#[clap(rename_all = "kebab_case")]
|
||||
FirstVariant {
|
||||
#[clap(long, action)]
|
||||
#[clap(long)]
|
||||
foo_option: bool,
|
||||
},
|
||||
SecondVariant {
|
||||
#[clap(rename_all = "kebab_case", long, action)]
|
||||
#[clap(rename_all = "kebab_case", long)]
|
||||
foo_option: bool,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ use clap::{Parser, Subcommand};
|
|||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short, long, action)]
|
||||
#[clap(short, long)]
|
||||
force: bool,
|
||||
#[clap(short, long, action = clap::ArgAction::Count)]
|
||||
verbose: u8,
|
||||
|
@ -32,7 +32,7 @@ enum Sub {
|
|||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt2 {
|
||||
#[clap(short, long, action)]
|
||||
#[clap(short, long)]
|
||||
force: bool,
|
||||
#[clap(short, long, action = clap::ArgAction::Count)]
|
||||
verbose: u8,
|
||||
|
@ -109,7 +109,7 @@ fn test_badinput() {
|
|||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt3 {
|
||||
#[clap(short, long, action)]
|
||||
#[clap(short, long)]
|
||||
all: bool,
|
||||
#[clap(subcommand)]
|
||||
cmd: Sub2,
|
||||
|
@ -118,7 +118,6 @@ struct Opt3 {
|
|||
#[derive(Subcommand, PartialEq, Debug)]
|
||||
enum Sub2 {
|
||||
Foo {
|
||||
#[clap(value_parser)]
|
||||
file: String,
|
||||
#[clap(subcommand)]
|
||||
cmd: Sub3,
|
||||
|
@ -159,16 +158,8 @@ enum SubSubCmdWithOption {
|
|||
}
|
||||
#[derive(Subcommand, PartialEq, Debug)]
|
||||
enum Remote {
|
||||
Add {
|
||||
#[clap(value_parser)]
|
||||
name: String,
|
||||
#[clap(value_parser)]
|
||||
url: String,
|
||||
},
|
||||
Remove {
|
||||
#[clap(value_parser)]
|
||||
name: String,
|
||||
},
|
||||
Add { name: String, url: String },
|
||||
Remove { name: String },
|
||||
}
|
||||
|
||||
#[derive(Subcommand, PartialEq, Debug)]
|
||||
|
|
|
@ -1,97 +0,0 @@
|
|||
use clap::CommandFactory;
|
||||
use clap::Parser;
|
||||
#[test]
|
||||
fn app_name_in_short_help_from_struct() {
|
||||
#[derive(Parser)]
|
||||
#[clap(name = "my-cmd")]
|
||||
struct MyApp {}
|
||||
|
||||
let mut help = Vec::new();
|
||||
MyApp::command().write_help(&mut help).unwrap();
|
||||
let help = String::from_utf8(help).unwrap();
|
||||
|
||||
assert!(help.contains("my-cmd"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn app_name_in_long_help_from_struct() {
|
||||
#[derive(Parser)]
|
||||
#[clap(name = "my-cmd")]
|
||||
struct MyApp {}
|
||||
|
||||
let mut help = Vec::new();
|
||||
MyApp::command().write_long_help(&mut help).unwrap();
|
||||
let help = String::from_utf8(help).unwrap();
|
||||
|
||||
assert!(help.contains("my-cmd"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn app_name_in_short_help_from_enum() {
|
||||
#[derive(Parser)]
|
||||
#[clap(name = "my-cmd")]
|
||||
enum MyApp {}
|
||||
|
||||
let mut help = Vec::new();
|
||||
MyApp::command().write_help(&mut help).unwrap();
|
||||
let help = String::from_utf8(help).unwrap();
|
||||
|
||||
assert!(help.contains("my-cmd"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn app_name_in_long_help_from_enum() {
|
||||
#[derive(Parser)]
|
||||
#[clap(name = "my-cmd")]
|
||||
enum MyApp {}
|
||||
|
||||
let mut help = Vec::new();
|
||||
MyApp::command().write_long_help(&mut help).unwrap();
|
||||
let help = String::from_utf8(help).unwrap();
|
||||
|
||||
assert!(help.contains("my-cmd"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn app_name_in_short_version_from_struct() {
|
||||
#[derive(Parser)]
|
||||
#[clap(name = "my-cmd")]
|
||||
struct MyApp {}
|
||||
|
||||
let version = MyApp::command().render_version();
|
||||
|
||||
assert!(version.contains("my-cmd"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn app_name_in_long_version_from_struct() {
|
||||
#[derive(Parser)]
|
||||
#[clap(name = "my-cmd")]
|
||||
struct MyApp {}
|
||||
|
||||
let version = MyApp::command().render_long_version();
|
||||
|
||||
assert!(version.contains("my-cmd"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn app_name_in_short_version_from_enum() {
|
||||
#[derive(Parser)]
|
||||
#[clap(name = "my-cmd")]
|
||||
enum MyApp {}
|
||||
|
||||
let version = MyApp::command().render_version();
|
||||
|
||||
assert!(version.contains("my-cmd"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn app_name_in_long_version_from_enum() {
|
||||
#[derive(Parser)]
|
||||
#[clap(name = "my-cmd")]
|
||||
enum MyApp {}
|
||||
|
||||
let version = MyApp::command().render_long_version();
|
||||
|
||||
assert!(version.contains("my-cmd"));
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
|
||||
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
|
||||
// Ana Hobden (@hoverbear) <operator@hoverbear.org>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
//
|
||||
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
|
||||
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
|
||||
// MIT/Apache 2.0 license.
|
||||
|
||||
use clap::CommandFactory;
|
||||
use clap::Parser;
|
||||
|
||||
#[test]
|
||||
fn required_argument() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
arg: i32,
|
||||
}
|
||||
assert_eq!(
|
||||
Opt { arg: 42 },
|
||||
Opt::try_parse_from(&["test", "42"]).unwrap()
|
||||
);
|
||||
assert!(Opt::try_parse_from(&["test"]).is_err());
|
||||
assert!(Opt::try_parse_from(&["test", "42", "24"]).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn argument_with_default() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(default_value = "42")]
|
||||
arg: i32,
|
||||
}
|
||||
assert_eq!(
|
||||
Opt { arg: 24 },
|
||||
Opt::try_parse_from(&["test", "24"]).unwrap()
|
||||
);
|
||||
assert_eq!(Opt { arg: 42 }, Opt::try_parse_from(&["test"]).unwrap());
|
||||
assert!(Opt::try_parse_from(&["test", "42", "24"]).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn auto_value_name() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
my_special_arg: i32,
|
||||
}
|
||||
|
||||
let mut help = Vec::new();
|
||||
Opt::command().write_help(&mut help).unwrap();
|
||||
let help = String::from_utf8(help).unwrap();
|
||||
|
||||
assert!(help.contains("MY_SPECIAL_ARG"));
|
||||
// Ensure the implicit `num_vals` is just 1
|
||||
assert_eq!(
|
||||
Opt { my_special_arg: 10 },
|
||||
Opt::try_parse_from(&["test", "10"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn explicit_value_name() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_name = "BROWNIE_POINTS")]
|
||||
my_special_arg: i32,
|
||||
}
|
||||
|
||||
let mut help = Vec::new();
|
||||
Opt::command().write_help(&mut help).unwrap();
|
||||
let help = String::from_utf8(help).unwrap();
|
||||
|
||||
assert!(help.contains("BROWNIE_POINTS"));
|
||||
assert!(!help.contains("MY_SPECIAL_ARG"));
|
||||
// Ensure the implicit `num_vals` is just 1
|
||||
assert_eq!(
|
||||
Opt { my_special_arg: 10 },
|
||||
Opt::try_parse_from(&["test", "10"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn option_type_is_optional() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
arg: Option<i32>,
|
||||
}
|
||||
assert_eq!(
|
||||
Opt { arg: Some(42) },
|
||||
Opt::try_parse_from(&["test", "42"]).unwrap()
|
||||
);
|
||||
assert_eq!(Opt { arg: None }, Opt::try_parse_from(&["test"]).unwrap());
|
||||
assert!(Opt::try_parse_from(&["test", "42", "24"]).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vec_type_is_multiple_values() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
arg: Vec<i32>,
|
||||
}
|
||||
assert_eq!(
|
||||
Opt { arg: vec![24] },
|
||||
Opt::try_parse_from(&["test", "24"]).unwrap()
|
||||
);
|
||||
assert_eq!(Opt { arg: vec![] }, Opt::try_parse_from(&["test"]).unwrap());
|
||||
assert_eq!(
|
||||
Opt { arg: vec![24, 42] },
|
||||
Opt::try_parse_from(&["test", "24", "42"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
clap::ErrorKind::ValueValidation,
|
||||
Opt::try_parse_from(&["test", "NOPE"]).err().unwrap().kind()
|
||||
);
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
|
||||
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
|
||||
// Ana Hobden (@hoverbear) <operator@hoverbear.org>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
//
|
||||
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
|
||||
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
|
||||
// MIT/Apache 2.0 license.
|
||||
|
||||
use crate::utils;
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
#[test]
|
||||
fn no_author_version_about() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
#[clap(name = "foo")]
|
||||
struct Opt {}
|
||||
|
||||
let output = utils::get_long_help::<Opt>();
|
||||
assert!(output.starts_with("foo \n\nUSAGE:"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn use_env() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
#[clap(author, about, version)]
|
||||
struct Opt {}
|
||||
|
||||
let output = utils::get_long_help::<Opt>();
|
||||
assert!(output.starts_with("clap"));
|
||||
assert!(output
|
||||
.contains("A simple to use, efficient, and full-featured Command Line Argument Parser"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn explicit_version_not_str_lit() {
|
||||
const VERSION: &str = "custom version";
|
||||
|
||||
#[derive(Parser)]
|
||||
#[clap(version = VERSION)]
|
||||
pub struct Opt {}
|
||||
|
||||
let output = utils::get_long_help::<Opt>();
|
||||
assert!(output.contains("custom version"));
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
|
||||
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
|
||||
// Ana Hobden (@hoverbear) <operator@hoverbear.org>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
//
|
||||
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
|
||||
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
|
||||
// MIT/Apache 2.0 license.
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
#[test]
|
||||
fn basic() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short = 'a', long = "arg")]
|
||||
arg: i32,
|
||||
}
|
||||
assert_eq!(
|
||||
Opt { arg: 24 },
|
||||
Opt::try_parse_from(&["test", "-a24"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_basic() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short = 'a', long = "arg")]
|
||||
single_value: i32,
|
||||
}
|
||||
|
||||
let mut opt = Opt::try_parse_from(&["test", "-a0"]).unwrap();
|
||||
|
||||
opt.update_from(&["test", "-a42"]);
|
||||
|
||||
assert_eq!(Opt { single_value: 42 }, opt);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unit_struct() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt;
|
||||
|
||||
assert_eq!(Opt {}, Opt::try_parse_from(&["test"]).unwrap());
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
use clap::{Args, Parser, Subcommand};
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(subcommand)]
|
||||
sub: Box<Sub>,
|
||||
}
|
||||
|
||||
#[derive(Subcommand, PartialEq, Debug)]
|
||||
enum Sub {
|
||||
Flame {
|
||||
#[clap(flatten)]
|
||||
arg: Box<Ext>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Ext {
|
||||
arg: u32,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boxed_flatten_subcommand() {
|
||||
assert_eq!(
|
||||
Opt {
|
||||
sub: Box::new(Sub::Flame {
|
||||
arg: Box::new(Ext { arg: 1 })
|
||||
})
|
||||
},
|
||||
Opt::try_parse_from(&["test", "flame", "1"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_boxed_flatten_subcommand() {
|
||||
let mut opt = Opt::try_parse_from(&["test", "flame", "1"]).unwrap();
|
||||
|
||||
opt.update_from(&["test", "flame", "42"]);
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
sub: Box::new(Sub::Flame {
|
||||
arg: Box::new(Ext { arg: 42 })
|
||||
})
|
||||
},
|
||||
opt
|
||||
);
|
||||
}
|
|
@ -1,205 +0,0 @@
|
|||
// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
|
||||
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
|
||||
// Ana Hobden (@hoverbear) <operator@hoverbear.org>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
//
|
||||
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
|
||||
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
|
||||
// MIT/Apache 2.0 license.
|
||||
|
||||
#![allow(deprecated)]
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
use std::num::ParseIntError;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct PathOpt {
|
||||
#[clap(short, long)]
|
||||
path: PathBuf,
|
||||
|
||||
#[clap(short, default_value = "../")]
|
||||
default_path: PathBuf,
|
||||
|
||||
#[clap(short, multiple_occurrences(true))]
|
||||
vector_path: Vec<PathBuf>,
|
||||
|
||||
#[clap(short)]
|
||||
option_path_1: Option<PathBuf>,
|
||||
|
||||
#[clap(short = 'q')]
|
||||
option_path_2: Option<PathBuf>,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_path_opt_simple() {
|
||||
assert_eq!(
|
||||
PathOpt {
|
||||
path: PathBuf::from("/usr/bin"),
|
||||
default_path: PathBuf::from("../"),
|
||||
vector_path: vec![
|
||||
PathBuf::from("/a/b/c"),
|
||||
PathBuf::from("/d/e/f"),
|
||||
PathBuf::from("/g/h/i"),
|
||||
],
|
||||
option_path_1: None,
|
||||
option_path_2: Some(PathBuf::from("j.zip")),
|
||||
},
|
||||
PathOpt::try_parse_from(&[
|
||||
"test", "-p", "/usr/bin", "-v", "/a/b/c", "-v", "/d/e/f", "-v", "/g/h/i", "-q",
|
||||
"j.zip",
|
||||
])
|
||||
.unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
fn parse_hex(input: &str) -> Result<u64, ParseIntError> {
|
||||
u64::from_str_radix(input, 16)
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct HexOpt {
|
||||
#[clap(short, value_parser = parse_hex)]
|
||||
number: u64,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_hex() {
|
||||
assert_eq!(
|
||||
HexOpt { number: 5 },
|
||||
HexOpt::try_parse_from(&["test", "-n", "5"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
HexOpt {
|
||||
number: 0x00ab_cdef
|
||||
},
|
||||
HexOpt::try_parse_from(&["test", "-n", "abcdef"]).unwrap()
|
||||
);
|
||||
|
||||
let err = HexOpt::try_parse_from(&["test", "-n", "gg"]).unwrap_err();
|
||||
assert!(
|
||||
err.to_string().contains("invalid digit found in string"),
|
||||
"{}",
|
||||
err
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ErrCode(u32);
|
||||
impl std::error::Error for ErrCode {}
|
||||
impl std::fmt::Display for ErrCode {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
std::fmt::Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
fn custom_parser_2(_: &str) -> Result<&'static str, ErrCode> {
|
||||
Ok("B")
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct NoOpOpt {
|
||||
#[clap(short, value_parser = custom_parser_2)]
|
||||
b: &'static str,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_every_custom_parser() {
|
||||
assert_eq!(
|
||||
NoOpOpt { b: "B" },
|
||||
NoOpOpt::try_parse_from(&["test", "-b=?"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_every_custom_parser() {
|
||||
let mut opt = NoOpOpt { b: "0" };
|
||||
|
||||
opt.try_update_from(&["test", "-b=?"]).unwrap();
|
||||
|
||||
assert_eq!(NoOpOpt { b: "B" }, opt);
|
||||
}
|
||||
|
||||
// Note: can't use `Vec<u8>` directly, as clap would instead look for
|
||||
// conversion function from `&str` to `u8`.
|
||||
type Bytes = Vec<u8>;
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct DefaultedOpt {
|
||||
#[clap(short, parse(from_str))]
|
||||
bytes: Bytes,
|
||||
|
||||
#[clap(short)]
|
||||
integer: u64,
|
||||
|
||||
#[clap(short)]
|
||||
path: PathBuf,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parser_with_default_value() {
|
||||
assert_eq!(
|
||||
DefaultedOpt {
|
||||
bytes: b"E\xc2\xb2=p\xc2\xb2c\xc2\xb2+m\xc2\xb2c\xe2\x81\xb4".to_vec(),
|
||||
integer: 9000,
|
||||
path: PathBuf::from("src/lib.rs"),
|
||||
},
|
||||
DefaultedOpt::try_parse_from(&[
|
||||
"test",
|
||||
"-b",
|
||||
"E²=p²c²+m²c⁴",
|
||||
"-i",
|
||||
"9000",
|
||||
"-p",
|
||||
"src/lib.rs",
|
||||
])
|
||||
.unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
struct Foo(u8);
|
||||
|
||||
fn foo(value: u64) -> Foo {
|
||||
Foo(value as u8)
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Occurrences {
|
||||
#[clap(short, long, parse(from_occurrences))]
|
||||
signed: i32,
|
||||
|
||||
#[clap(short, parse(from_occurrences))]
|
||||
little_signed: i8,
|
||||
|
||||
#[clap(short, parse(from_occurrences))]
|
||||
unsigned: usize,
|
||||
|
||||
#[clap(short = 'r', parse(from_occurrences))]
|
||||
little_unsigned: u8,
|
||||
|
||||
#[clap(short, long, parse(from_occurrences = foo))]
|
||||
custom: Foo,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parser_occurrences() {
|
||||
assert_eq!(
|
||||
Occurrences {
|
||||
signed: 3,
|
||||
little_signed: 1,
|
||||
unsigned: 0,
|
||||
little_unsigned: 4,
|
||||
custom: Foo(5),
|
||||
},
|
||||
Occurrences::try_parse_from(&[
|
||||
"test", "-s", "--signed", "--signed", "-l", "-rrrr", "-cccc", "--custom",
|
||||
])
|
||||
.unwrap()
|
||||
);
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
use clap::{CommandFactory, Parser};
|
||||
|
||||
use crate::utils;
|
||||
|
||||
#[test]
|
||||
fn default_value() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(default_value = "3")]
|
||||
arg: i32,
|
||||
}
|
||||
assert_eq!(Opt { arg: 3 }, Opt::try_parse_from(&["test"]).unwrap());
|
||||
assert_eq!(Opt { arg: 1 }, Opt::try_parse_from(&["test", "1"]).unwrap());
|
||||
|
||||
let help = utils::get_long_help::<Opt>();
|
||||
assert!(help.contains("[default: 3]"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_value_t() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(default_value_t = 3)]
|
||||
arg: i32,
|
||||
}
|
||||
assert_eq!(Opt { arg: 3 }, Opt::try_parse_from(&["test"]).unwrap());
|
||||
assert_eq!(Opt { arg: 1 }, Opt::try_parse_from(&["test", "1"]).unwrap());
|
||||
|
||||
let help = utils::get_long_help::<Opt>();
|
||||
assert!(help.contains("[default: 3]"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn auto_default_value_t() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(default_value_t)]
|
||||
arg: i32,
|
||||
}
|
||||
assert_eq!(Opt { arg: 0 }, Opt::try_parse_from(&["test"]).unwrap());
|
||||
assert_eq!(Opt { arg: 1 }, Opt::try_parse_from(&["test", "1"]).unwrap());
|
||||
|
||||
let help = utils::get_long_help::<Opt>();
|
||||
assert!(help.contains("[default: 0]"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn detect_os_variant() {
|
||||
#![allow(unused_parens)] // needed for `as_ref` call
|
||||
|
||||
#[derive(clap::Parser)]
|
||||
pub struct Options {
|
||||
#[clap(default_value_os = ("123".as_ref()))]
|
||||
x: String,
|
||||
}
|
||||
Options::command().debug_assert();
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
|
||||
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
|
||||
// Ana Hobden (@hoverbear) <operator@hoverbear.org>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
//
|
||||
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
|
||||
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
|
||||
// MIT/Apache 2.0 license.
|
||||
|
||||
#![deny(warnings)]
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
fn try_str(s: &str) -> Result<String, std::convert::Infallible> {
|
||||
Ok(s.into())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn warning_never_struct() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(value_parser = try_str, default_value_t)]
|
||||
s: String,
|
||||
}
|
||||
assert_eq!(
|
||||
Opt {
|
||||
s: "foo".to_string()
|
||||
},
|
||||
Opt::try_parse_from(&["test", "foo"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn warning_never_enum() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
enum Opt {
|
||||
Foo {
|
||||
#[clap(value_parser = try_str, default_value_t)]
|
||||
s: String,
|
||||
},
|
||||
}
|
||||
assert_eq!(
|
||||
Opt::Foo {
|
||||
s: "foo".to_string()
|
||||
},
|
||||
Opt::try_parse_from(&["test", "foo", "foo"]).unwrap()
|
||||
);
|
||||
}
|
|
@ -1,240 +0,0 @@
|
|||
// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
|
||||
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
|
||||
// Ana Hobden (@hoverbear) <operator@hoverbear.org>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
//
|
||||
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
|
||||
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
|
||||
// MIT/Apache 2.0 license.
|
||||
|
||||
use crate::utils;
|
||||
|
||||
use clap::{CommandFactory, Parser, ValueEnum};
|
||||
|
||||
#[test]
|
||||
fn doc_comments() {
|
||||
/// Lorem ipsum
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct LoremIpsum {
|
||||
/// Fooify a bar
|
||||
/// and a baz
|
||||
#[clap(short, long)]
|
||||
foo: bool,
|
||||
}
|
||||
|
||||
let help = utils::get_long_help::<LoremIpsum>();
|
||||
assert!(help.contains("Lorem ipsum"));
|
||||
assert!(help.contains("Fooify a bar and a baz"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn help_is_better_than_comments() {
|
||||
/// Lorem ipsum
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
#[clap(name = "lorem-ipsum", about = "Dolor sit amet")]
|
||||
struct LoremIpsum {
|
||||
/// Fooify a bar
|
||||
#[clap(short, long, help = "DO NOT PASS A BAR UNDER ANY CIRCUMSTANCES")]
|
||||
foo: bool,
|
||||
}
|
||||
|
||||
let help = utils::get_long_help::<LoremIpsum>();
|
||||
assert!(help.contains("Dolor sit amet"));
|
||||
assert!(!help.contains("Lorem ipsum"));
|
||||
assert!(help.contains("DO NOT PASS A BAR"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_line_in_doc_comment_is_double_linefeed() {
|
||||
/// Foo.
|
||||
///
|
||||
/// Bar
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
#[clap(name = "lorem-ipsum")]
|
||||
struct LoremIpsum {}
|
||||
|
||||
let help = utils::get_long_help::<LoremIpsum>();
|
||||
assert!(help.starts_with("lorem-ipsum \nFoo.\n\nBar\n\nUSAGE:"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn field_long_doc_comment_both_help_long_help() {
|
||||
/// Lorem ipsumclap
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
#[clap(name = "lorem-ipsum", about = "Dolor sit amet")]
|
||||
struct LoremIpsum {
|
||||
/// Dot is removed from multiline comments.
|
||||
///
|
||||
/// Long help
|
||||
#[clap(long)]
|
||||
foo: bool,
|
||||
|
||||
/// Dot is removed from one short comment.
|
||||
#[clap(long)]
|
||||
bar: bool,
|
||||
}
|
||||
|
||||
let short_help = utils::get_help::<LoremIpsum>();
|
||||
let long_help = utils::get_long_help::<LoremIpsum>();
|
||||
|
||||
assert!(short_help.contains("Dot is removed from one short comment"));
|
||||
assert!(!short_help.contains("Dot is removed from one short comment."));
|
||||
assert!(short_help.contains("Dot is removed from multiline comments"));
|
||||
assert!(!short_help.contains("Dot is removed from multiline comments."));
|
||||
assert!(long_help.contains("Long help"));
|
||||
assert!(!short_help.contains("Long help"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn top_long_doc_comment_both_help_long_help() {
|
||||
/// Lorem ipsumclap
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(name = "lorem-ipsum", about = "Dolor sit amet")]
|
||||
struct LoremIpsum {
|
||||
#[clap(subcommand)]
|
||||
foo: SubCommand,
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
pub enum SubCommand {
|
||||
/// DO NOT PASS A BAR UNDER ANY CIRCUMSTANCES
|
||||
///
|
||||
/// Or something else
|
||||
Foo {
|
||||
#[clap(help = "foo")]
|
||||
bars: String,
|
||||
},
|
||||
}
|
||||
|
||||
let short_help = utils::get_help::<LoremIpsum>();
|
||||
let long_help = utils::get_subcommand_long_help::<LoremIpsum>("foo");
|
||||
|
||||
assert!(!short_help.contains("Or something else"));
|
||||
assert!(long_help.contains("DO NOT PASS A BAR UNDER ANY CIRCUMSTANCES"));
|
||||
assert!(long_help.contains("Or something else"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verbatim_doc_comment() {
|
||||
/// DANCE!
|
||||
///
|
||||
/// ()
|
||||
/// |
|
||||
/// ( () )
|
||||
/// ) ________ // )
|
||||
/// () |\ \ //
|
||||
/// ( \\__ \ ______\//
|
||||
/// \__) | |
|
||||
/// | | |
|
||||
/// \ | |
|
||||
/// \|_______|
|
||||
/// // \\
|
||||
/// (( ||
|
||||
/// \\ ||
|
||||
/// ( () ||
|
||||
/// ( () ) )
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(verbatim_doc_comment)]
|
||||
struct SeeFigure1 {
|
||||
#[clap(long)]
|
||||
foo: bool,
|
||||
}
|
||||
|
||||
let help = utils::get_long_help::<SeeFigure1>();
|
||||
let sample = r#"
|
||||
()
|
||||
|
|
||||
( () )
|
||||
) ________ // )
|
||||
() |\ \ //
|
||||
( \\__ \ ______\//
|
||||
\__) | |
|
||||
| | |
|
||||
\ | |
|
||||
\|_______|
|
||||
// \\
|
||||
(( ||
|
||||
\\ ||
|
||||
( () ||
|
||||
( () ) )"#;
|
||||
|
||||
assert!(help.contains(sample))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verbatim_doc_comment_field() {
|
||||
#[derive(Parser, Debug)]
|
||||
struct Command {
|
||||
/// This help ends in a period.
|
||||
#[clap(long, verbatim_doc_comment)]
|
||||
foo: bool,
|
||||
/// This help does not end in a period.
|
||||
#[clap(long)]
|
||||
bar: bool,
|
||||
}
|
||||
|
||||
let help = utils::get_long_help::<Command>();
|
||||
|
||||
assert!(help.contains("This help ends in a period."));
|
||||
assert!(help.contains("This help does not end in a period"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiline_separates_default() {
|
||||
#[derive(Parser, Debug)]
|
||||
struct Command {
|
||||
/// Multiline
|
||||
///
|
||||
/// Doc comment
|
||||
#[clap(long, default_value = "x")]
|
||||
x: String,
|
||||
}
|
||||
|
||||
let help = utils::get_long_help::<Command>();
|
||||
assert!(!help.contains("Doc comment [default"));
|
||||
assert!(help.lines().any(|s| s.trim().starts_with("[default")));
|
||||
|
||||
// The short help should still have the default on the same line
|
||||
let help = utils::get_help::<Command>();
|
||||
assert!(help.contains("Multiline [default"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn argenum_multiline_doc_comment() {
|
||||
#[derive(ValueEnum, Clone)]
|
||||
enum LoremIpsum {
|
||||
/// Multiline
|
||||
///
|
||||
/// Doc comment
|
||||
Bar,
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn doc_comment_about_handles_both_abouts() {
|
||||
/// Opts doc comment summary
|
||||
#[derive(Parser, Debug)]
|
||||
pub struct Opts {
|
||||
#[clap(subcommand)]
|
||||
pub cmd: Sub,
|
||||
}
|
||||
|
||||
/// Sub doc comment summary
|
||||
///
|
||||
/// Sub doc comment body
|
||||
#[derive(Parser, PartialEq, Eq, Debug)]
|
||||
pub enum Sub {
|
||||
Compress { output: String },
|
||||
}
|
||||
|
||||
let cmd = Opts::command();
|
||||
assert_eq!(cmd.get_about(), Some("Opts doc comment summary"));
|
||||
// clap will fallback to `about` on `None`. The main care about is not providing a `Sub` doc
|
||||
// comment.
|
||||
assert_eq!(cmd.get_long_about(), None);
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
use crate::utils;
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
#[test]
|
||||
fn explicit_short_long_no_rename() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short = '.', long = ".foo")]
|
||||
foo: String,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt { foo: "long".into() },
|
||||
Opt::try_parse_from(&["test", "--.foo", "long"]).unwrap()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
foo: "short".into(),
|
||||
},
|
||||
Opt::try_parse_from(&["test", "-.", "short"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn explicit_name_no_rename() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(name = ".options")]
|
||||
foo: String,
|
||||
}
|
||||
|
||||
let help = utils::get_long_help::<Opt>();
|
||||
assert!(help.contains("<.options>"))
|
||||
}
|
|
@ -1,231 +0,0 @@
|
|||
// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
|
||||
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
|
||||
// Ana Hobden (@hoverbear) <operator@hoverbear.org>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
//
|
||||
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
|
||||
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
|
||||
// MIT/Apache 2.0 license.
|
||||
|
||||
#![allow(deprecated)]
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
#[test]
|
||||
fn bool_type_is_flag() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short, long)]
|
||||
alice: bool,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt { alice: false },
|
||||
Opt::try_parse_from(&["test"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt { alice: true },
|
||||
Opt::try_parse_from(&["test", "-a"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt { alice: true },
|
||||
Opt::try_parse_from(&["test", "-a", "-a"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt { alice: true },
|
||||
Opt::try_parse_from(&["test", "--alice"]).unwrap()
|
||||
);
|
||||
assert!(Opt::try_parse_from(&["test", "-i"]).is_err());
|
||||
assert!(Opt::try_parse_from(&["test", "-a", "foo"]).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn count() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short, long, action = clap::ArgAction::Count)]
|
||||
alice: u8,
|
||||
#[clap(short, long, action = clap::ArgAction::Count)]
|
||||
bob: u8,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt { alice: 0, bob: 0 },
|
||||
Opt::try_parse_from(&["test"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt { alice: 1, bob: 0 },
|
||||
Opt::try_parse_from(&["test", "-a"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt { alice: 2, bob: 0 },
|
||||
Opt::try_parse_from(&["test", "-a", "-a"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt { alice: 2, bob: 2 },
|
||||
Opt::try_parse_from(&["test", "-a", "--alice", "-bb"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt { alice: 3, bob: 1 },
|
||||
Opt::try_parse_from(&["test", "-aaa", "--bob"]).unwrap()
|
||||
);
|
||||
assert!(Opt::try_parse_from(&["test", "-i"]).is_err());
|
||||
assert!(Opt::try_parse_from(&["test", "-a", "foo"]).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn non_bool_type_flag() {
|
||||
fn parse_from_flag(b: bool) -> std::sync::atomic::AtomicBool {
|
||||
std::sync::atomic::AtomicBool::new(b)
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short, long, parse(from_flag = parse_from_flag))]
|
||||
alice: std::sync::atomic::AtomicBool,
|
||||
#[clap(short, long, parse(from_flag))]
|
||||
bob: std::sync::atomic::AtomicBool,
|
||||
}
|
||||
|
||||
let falsey = Opt::try_parse_from(&["test"]).unwrap();
|
||||
assert!(!falsey.alice.load(std::sync::atomic::Ordering::Relaxed));
|
||||
assert!(!falsey.bob.load(std::sync::atomic::Ordering::Relaxed));
|
||||
|
||||
let alice = Opt::try_parse_from(&["test", "-a"]).unwrap();
|
||||
assert!(alice.alice.load(std::sync::atomic::Ordering::Relaxed));
|
||||
assert!(!alice.bob.load(std::sync::atomic::Ordering::Relaxed));
|
||||
|
||||
let bob = Opt::try_parse_from(&["test", "-b"]).unwrap();
|
||||
assert!(!bob.alice.load(std::sync::atomic::Ordering::Relaxed));
|
||||
assert!(bob.bob.load(std::sync::atomic::Ordering::Relaxed));
|
||||
|
||||
let both = Opt::try_parse_from(&["test", "-b", "-a"]).unwrap();
|
||||
assert!(both.alice.load(std::sync::atomic::Ordering::Relaxed));
|
||||
assert!(both.bob.load(std::sync::atomic::Ordering::Relaxed));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mixed_type_flags() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short, long)]
|
||||
alice: bool,
|
||||
#[clap(short, long, action = clap::ArgAction::Count)]
|
||||
bob: u8,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
alice: false,
|
||||
bob: 0
|
||||
},
|
||||
Opt::try_parse_from(&["test"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
alice: true,
|
||||
bob: 0
|
||||
},
|
||||
Opt::try_parse_from(&["test", "-a"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
alice: true,
|
||||
bob: 0
|
||||
},
|
||||
Opt::try_parse_from(&["test", "-a"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
alice: false,
|
||||
bob: 1
|
||||
},
|
||||
Opt::try_parse_from(&["test", "-b"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
alice: true,
|
||||
bob: 1
|
||||
},
|
||||
Opt::try_parse_from(&["test", "--alice", "--bob"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
alice: true,
|
||||
bob: 4
|
||||
},
|
||||
Opt::try_parse_from(&["test", "-bb", "-a", "-bb"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ignore_qualified_bool_type() {
|
||||
mod inner {
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
pub struct bool(pub String);
|
||||
|
||||
impl std::str::FromStr for self::bool {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Ok(self::bool(s.into()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
arg: inner::bool,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: inner::bool("success".into())
|
||||
},
|
||||
Opt::try_parse_from(&["test", "success"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn override_implicit_action() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(long, action = clap::ArgAction::Set)]
|
||||
arg: bool,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt { arg: false },
|
||||
Opt::try_parse_from(&["test", "--arg", "false"]).unwrap()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Opt { arg: true },
|
||||
Opt::try_parse_from(&["test", "--arg", "true"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn override_implicit_from_flag_positional() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(action = clap::ArgAction::Set)]
|
||||
arg: bool,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt { arg: false },
|
||||
Opt::try_parse_from(&["test", "false"]).unwrap()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Opt { arg: true },
|
||||
Opt::try_parse_from(&["test", "true"]).unwrap()
|
||||
);
|
||||
}
|
|
@ -1,257 +0,0 @@
|
|||
// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
|
||||
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
|
||||
// Ana Hobden (@hoverbear) <operator@hoverbear.org>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
//
|
||||
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
|
||||
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
|
||||
// MIT/Apache 2.0 license.
|
||||
|
||||
use crate::utils;
|
||||
|
||||
use clap::{Args, Parser, Subcommand};
|
||||
|
||||
#[test]
|
||||
fn flatten() {
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Common {
|
||||
arg: i32,
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(flatten)]
|
||||
common: Common,
|
||||
}
|
||||
assert_eq!(
|
||||
Opt {
|
||||
common: Common { arg: 42 }
|
||||
},
|
||||
Opt::try_parse_from(&["test", "42"]).unwrap()
|
||||
);
|
||||
assert!(Opt::try_parse_from(&["test"]).is_err());
|
||||
assert!(Opt::try_parse_from(&["test", "42", "24"]).is_err());
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn flatten_twice() {
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Common {
|
||||
arg: i32,
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(flatten)]
|
||||
c1: Common,
|
||||
// Defines "arg" twice, so this should not work.
|
||||
#[clap(flatten)]
|
||||
c2: Common,
|
||||
}
|
||||
Opt::try_parse_from(&["test", "42", "43"]).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn flatten_in_subcommand() {
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Common {
|
||||
arg: i32,
|
||||
}
|
||||
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Add {
|
||||
#[clap(short)]
|
||||
interactive: bool,
|
||||
#[clap(flatten)]
|
||||
common: Common,
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
enum Opt {
|
||||
Fetch {
|
||||
#[clap(short)]
|
||||
all: bool,
|
||||
#[clap(flatten)]
|
||||
common: Common,
|
||||
},
|
||||
|
||||
Add(Add),
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt::Fetch {
|
||||
all: false,
|
||||
common: Common { arg: 42 }
|
||||
},
|
||||
Opt::try_parse_from(&["test", "fetch", "42"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt::Add(Add {
|
||||
interactive: true,
|
||||
common: Common { arg: 43 }
|
||||
}),
|
||||
Opt::try_parse_from(&["test", "add", "-i", "43"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_args_with_flatten() {
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Common {
|
||||
arg: i32,
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(flatten)]
|
||||
common: Common,
|
||||
}
|
||||
|
||||
let mut opt = Opt {
|
||||
common: Common { arg: 42 },
|
||||
};
|
||||
opt.try_update_from(&["test"]).unwrap();
|
||||
assert_eq!(Opt::try_parse_from(&["test", "42"]).unwrap(), opt);
|
||||
|
||||
let mut opt = Opt {
|
||||
common: Common { arg: 42 },
|
||||
};
|
||||
opt.try_update_from(&["test", "52"]).unwrap();
|
||||
assert_eq!(Opt::try_parse_from(&["test", "52"]).unwrap(), opt);
|
||||
}
|
||||
|
||||
#[derive(Subcommand, PartialEq, Debug)]
|
||||
enum BaseCli {
|
||||
Command1(Command1),
|
||||
}
|
||||
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Command1 {
|
||||
arg1: i32,
|
||||
|
||||
arg2: i32,
|
||||
}
|
||||
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Command2 {
|
||||
arg2: i32,
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
enum Opt {
|
||||
#[clap(flatten)]
|
||||
BaseCli(BaseCli),
|
||||
Command2(Command2),
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn merge_subcommands_with_flatten() {
|
||||
assert_eq!(
|
||||
Opt::BaseCli(BaseCli::Command1(Command1 { arg1: 42, arg2: 44 })),
|
||||
Opt::try_parse_from(&["test", "command1", "42", "44"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt::Command2(Command2 { arg2: 43 }),
|
||||
Opt::try_parse_from(&["test", "command2", "43"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_subcommands_with_flatten() {
|
||||
let mut opt = Opt::BaseCli(BaseCli::Command1(Command1 { arg1: 12, arg2: 14 }));
|
||||
opt.try_update_from(&["test", "command1", "42", "44"])
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
Opt::try_parse_from(&["test", "command1", "42", "44"]).unwrap(),
|
||||
opt
|
||||
);
|
||||
|
||||
let mut opt = Opt::BaseCli(BaseCli::Command1(Command1 { arg1: 12, arg2: 14 }));
|
||||
opt.try_update_from(&["test", "command1", "42"]).unwrap();
|
||||
assert_eq!(
|
||||
Opt::try_parse_from(&["test", "command1", "42", "14"]).unwrap(),
|
||||
opt
|
||||
);
|
||||
|
||||
let mut opt = Opt::BaseCli(BaseCli::Command1(Command1 { arg1: 12, arg2: 14 }));
|
||||
opt.try_update_from(&["test", "command2", "43"]).unwrap();
|
||||
assert_eq!(
|
||||
Opt::try_parse_from(&["test", "command2", "43"]).unwrap(),
|
||||
opt
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn flatten_with_doc_comment() {
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Common {
|
||||
/// This is an arg. Arg means "argument". Command line argument.
|
||||
arg: i32,
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
/// The very important comment that clippy had me put here.
|
||||
/// It knows better.
|
||||
#[clap(flatten)]
|
||||
common: Common,
|
||||
}
|
||||
assert_eq!(
|
||||
Opt {
|
||||
common: Common { arg: 42 }
|
||||
},
|
||||
Opt::try_parse_from(&["test", "42"]).unwrap()
|
||||
);
|
||||
|
||||
let help = utils::get_help::<Opt>();
|
||||
assert!(help.contains("This is an arg."));
|
||||
assert!(!help.contains("The very important"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn docstrings_ordering_with_multiple_clap() {
|
||||
/// This is the docstring for Flattened
|
||||
#[derive(Args)]
|
||||
struct Flattened {
|
||||
#[clap(long)]
|
||||
foo: bool,
|
||||
}
|
||||
|
||||
/// This is the docstring for Command
|
||||
#[derive(Parser)]
|
||||
struct Command {
|
||||
#[clap(flatten)]
|
||||
flattened: Flattened,
|
||||
}
|
||||
|
||||
let short_help = utils::get_help::<Command>();
|
||||
|
||||
assert!(short_help.contains("This is the docstring for Command"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn docstrings_ordering_with_multiple_clap_partial() {
|
||||
/// This is the docstring for Flattened
|
||||
#[derive(Args)]
|
||||
struct Flattened {
|
||||
#[clap(long)]
|
||||
foo: bool,
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
struct Command {
|
||||
#[clap(flatten)]
|
||||
flattened: Flattened,
|
||||
}
|
||||
|
||||
let short_help = utils::get_help::<Command>();
|
||||
|
||||
assert!(short_help.contains("This is the docstring for Flattened"));
|
||||
}
|
|
@ -1,145 +0,0 @@
|
|||
use clap::{Args, Parser};
|
||||
|
||||
#[test]
|
||||
fn generic_struct_flatten() {
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Inner {
|
||||
pub answer: isize,
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Outer<T: Args> {
|
||||
#[clap(flatten)]
|
||||
pub inner: T,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Outer {
|
||||
inner: Inner { answer: 42 }
|
||||
},
|
||||
Outer::parse_from(&["--answer", "42"])
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generic_struct_flatten_w_where_clause() {
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Inner {
|
||||
pub answer: isize,
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Outer<T>
|
||||
where
|
||||
T: Args,
|
||||
{
|
||||
#[clap(flatten)]
|
||||
pub inner: T,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Outer {
|
||||
inner: Inner { answer: 42 }
|
||||
},
|
||||
Outer::parse_from(&["--answer", "42"])
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generic_enum() {
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Inner {
|
||||
pub answer: isize,
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
enum GenericEnum<T: Args> {
|
||||
Start(T),
|
||||
Stop,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
GenericEnum::Start(Inner { answer: 42 }),
|
||||
GenericEnum::parse_from(&["test", "start", "42"])
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generic_enum_w_where_clause() {
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Inner {
|
||||
pub answer: isize,
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
enum GenericEnum<T>
|
||||
where
|
||||
T: Args,
|
||||
{
|
||||
Start(T),
|
||||
Stop,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
GenericEnum::Start(Inner { answer: 42 }),
|
||||
GenericEnum::parse_from(&["test", "start", "42"])
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generic_w_fromstr_trait_bound() {
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt<T>
|
||||
where
|
||||
T: FromStr + Send + Sync + Clone + 'static,
|
||||
<T as FromStr>::Err: std::error::Error + Sync + Send + 'static,
|
||||
{
|
||||
answer: T,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt::<isize> { answer: 42 },
|
||||
Opt::<isize>::parse_from(&["--answer", "42"])
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generic_wo_trait_bound() {
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt<T> {
|
||||
answer: isize,
|
||||
#[clap(skip)]
|
||||
took: Option<T>,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt::<Duration> {
|
||||
answer: 42,
|
||||
took: None
|
||||
},
|
||||
Opt::<Duration>::parse_from(&["--answer", "42"])
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generic_where_clause_w_trailing_comma() {
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt<T>
|
||||
where
|
||||
T: FromStr + Send + Sync + Clone + 'static,
|
||||
<T as FromStr>::Err: std::error::Error + Sync + Send + 'static,
|
||||
{
|
||||
pub answer: T,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt::<isize> { answer: 42 },
|
||||
Opt::<isize>::parse_from(&["--answer", "42"])
|
||||
)
|
||||
}
|
|
@ -1,520 +0,0 @@
|
|||
use clap::{AppSettings, Args, CommandFactory, Parser, Subcommand};
|
||||
|
||||
#[test]
|
||||
fn arg_help_heading_applied() {
|
||||
#[derive(Debug, Clone, Parser)]
|
||||
struct CliOptions {
|
||||
#[clap(long)]
|
||||
#[clap(help_heading = Some("HEADING A"))]
|
||||
should_be_in_section_a: u32,
|
||||
|
||||
#[clap(long)]
|
||||
no_section: u32,
|
||||
}
|
||||
|
||||
let cmd = CliOptions::command();
|
||||
|
||||
let should_be_in_section_a = if cfg!(feature = "unstable-v4") {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_section_a")
|
||||
.unwrap()
|
||||
} else {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should-be-in-section-a")
|
||||
.unwrap()
|
||||
};
|
||||
assert_eq!(should_be_in_section_a.get_help_heading(), Some("HEADING A"));
|
||||
|
||||
let should_be_in_section_b = if cfg!(feature = "unstable-v4") {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "no_section")
|
||||
.unwrap()
|
||||
} else {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "no-section")
|
||||
.unwrap()
|
||||
};
|
||||
assert_eq!(should_be_in_section_b.get_help_heading(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn app_help_heading_applied() {
|
||||
#[derive(Debug, Clone, Parser)]
|
||||
#[clap(next_help_heading = "DEFAULT")]
|
||||
struct CliOptions {
|
||||
#[clap(long)]
|
||||
#[clap(help_heading = Some("HEADING A"))]
|
||||
should_be_in_section_a: u32,
|
||||
|
||||
#[clap(long)]
|
||||
should_be_in_default_section: u32,
|
||||
}
|
||||
|
||||
let cmd = CliOptions::command();
|
||||
|
||||
let should_be_in_section_a = if cfg!(feature = "unstable-v4") {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_section_a")
|
||||
.unwrap()
|
||||
} else {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should-be-in-section-a")
|
||||
.unwrap()
|
||||
};
|
||||
assert_eq!(should_be_in_section_a.get_help_heading(), Some("HEADING A"));
|
||||
|
||||
let should_be_in_default_section = if cfg!(feature = "unstable-v4") {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_default_section")
|
||||
.unwrap()
|
||||
} else {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should-be-in-default-section")
|
||||
.unwrap()
|
||||
};
|
||||
assert_eq!(
|
||||
should_be_in_default_section.get_help_heading(),
|
||||
Some("DEFAULT")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn app_help_heading_flattened() {
|
||||
// Used to help track the cause in tests
|
||||
#![allow(clippy::enum_variant_names)]
|
||||
|
||||
#[derive(Debug, Clone, Parser)]
|
||||
struct CliOptions {
|
||||
#[clap(flatten)]
|
||||
options_a: OptionsA,
|
||||
|
||||
#[clap(flatten)]
|
||||
options_b: OptionsB,
|
||||
|
||||
#[clap(subcommand)]
|
||||
sub_a: SubA,
|
||||
|
||||
#[clap(long)]
|
||||
should_be_in_default_section: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Args)]
|
||||
#[clap(next_help_heading = "HEADING A")]
|
||||
struct OptionsA {
|
||||
#[clap(long)]
|
||||
should_be_in_section_a: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Args)]
|
||||
#[clap(next_help_heading = "HEADING B")]
|
||||
struct OptionsB {
|
||||
#[clap(long)]
|
||||
should_be_in_section_b: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Subcommand)]
|
||||
enum SubA {
|
||||
#[clap(flatten)]
|
||||
SubB(SubB),
|
||||
#[clap(subcommand)]
|
||||
SubC(SubC),
|
||||
SubAOne,
|
||||
#[clap(next_help_heading = "SUB A")]
|
||||
SubATwo {
|
||||
should_be_in_sub_a: u32,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Subcommand)]
|
||||
enum SubB {
|
||||
#[clap(next_help_heading = "SUB B")]
|
||||
SubBOne { should_be_in_sub_b: u32 },
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Subcommand)]
|
||||
enum SubC {
|
||||
#[clap(next_help_heading = "SUB C")]
|
||||
SubCOne { should_be_in_sub_c: u32 },
|
||||
}
|
||||
|
||||
let cmd = CliOptions::command();
|
||||
|
||||
let should_be_in_section_a = if cfg!(feature = "unstable-v4") {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_section_a")
|
||||
.unwrap()
|
||||
} else {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should-be-in-section-a")
|
||||
.unwrap()
|
||||
};
|
||||
assert_eq!(should_be_in_section_a.get_help_heading(), Some("HEADING A"));
|
||||
|
||||
let should_be_in_section_b = if cfg!(feature = "unstable-v4") {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_section_b")
|
||||
.unwrap()
|
||||
} else {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should-be-in-section-b")
|
||||
.unwrap()
|
||||
};
|
||||
assert_eq!(should_be_in_section_b.get_help_heading(), Some("HEADING B"));
|
||||
|
||||
let should_be_in_default_section = if cfg!(feature = "unstable-v4") {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_default_section")
|
||||
.unwrap()
|
||||
} else {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should-be-in-default-section")
|
||||
.unwrap()
|
||||
};
|
||||
assert_eq!(should_be_in_default_section.get_help_heading(), None);
|
||||
|
||||
let sub_a_two = cmd.find_subcommand("sub-a-two").unwrap();
|
||||
|
||||
let should_be_in_sub_a = if cfg!(feature = "unstable-v4") {
|
||||
sub_a_two
|
||||
.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_sub_a")
|
||||
.unwrap()
|
||||
} else {
|
||||
sub_a_two
|
||||
.get_arguments()
|
||||
.find(|a| a.get_id() == "should-be-in-sub-a")
|
||||
.unwrap()
|
||||
};
|
||||
assert_eq!(should_be_in_sub_a.get_help_heading(), Some("SUB A"));
|
||||
|
||||
let sub_b_one = cmd.find_subcommand("sub-b-one").unwrap();
|
||||
|
||||
let should_be_in_sub_b = if cfg!(feature = "unstable-v4") {
|
||||
sub_b_one
|
||||
.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_sub_b")
|
||||
.unwrap()
|
||||
} else {
|
||||
sub_b_one
|
||||
.get_arguments()
|
||||
.find(|a| a.get_id() == "should-be-in-sub-b")
|
||||
.unwrap()
|
||||
};
|
||||
assert_eq!(should_be_in_sub_b.get_help_heading(), Some("SUB B"));
|
||||
|
||||
let sub_c = cmd.find_subcommand("sub-c").unwrap();
|
||||
let sub_c_one = sub_c.find_subcommand("sub-c-one").unwrap();
|
||||
|
||||
let should_be_in_sub_c = if cfg!(feature = "unstable-v4") {
|
||||
sub_c_one
|
||||
.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_sub_c")
|
||||
.unwrap()
|
||||
} else {
|
||||
sub_c_one
|
||||
.get_arguments()
|
||||
.find(|a| a.get_id() == "should-be-in-sub-c")
|
||||
.unwrap()
|
||||
};
|
||||
assert_eq!(should_be_in_sub_c.get_help_heading(), Some("SUB C"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn flatten_field_with_help_heading() {
|
||||
#[derive(Debug, Clone, Parser)]
|
||||
struct CliOptions {
|
||||
#[clap(flatten)]
|
||||
#[clap(next_help_heading = "HEADING A")]
|
||||
options_a: OptionsA,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Args)]
|
||||
struct OptionsA {
|
||||
#[clap(long)]
|
||||
should_be_in_section_a: u32,
|
||||
}
|
||||
|
||||
let cmd = CliOptions::command();
|
||||
|
||||
let should_be_in_section_a = if cfg!(feature = "unstable-v4") {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should_be_in_section_a")
|
||||
.unwrap()
|
||||
} else {
|
||||
cmd.get_arguments()
|
||||
.find(|a| a.get_id() == "should-be-in-section-a")
|
||||
.unwrap()
|
||||
};
|
||||
assert_eq!(should_be_in_section_a.get_help_heading(), Some("HEADING A"));
|
||||
}
|
||||
|
||||
// The challenge with this test is creating an error situation not caught by `clap`'s error checking
|
||||
// but by the code that `clap_derive` generates.
|
||||
//
|
||||
// Ultimately, the easiest way to confirm is to put a debug statement in the desired error path.
|
||||
#[test]
|
||||
fn derive_generated_error_has_full_context() {
|
||||
#[derive(Debug, Parser)]
|
||||
#[clap(subcommand_negates_reqs = true)]
|
||||
struct Opts {
|
||||
#[clap(long)]
|
||||
req_str: String,
|
||||
|
||||
#[clap(subcommand)]
|
||||
cmd: Option<SubCommands>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
enum SubCommands {
|
||||
Sub {
|
||||
#[clap(short, long, action = clap::ArgAction::Count)]
|
||||
verbose: u8,
|
||||
},
|
||||
}
|
||||
|
||||
let result = Opts::try_parse_from(&["test", "sub"]);
|
||||
assert!(
|
||||
result.is_err(),
|
||||
"`SubcommandsNegateReqs` with non-optional `req_str` should fail: {:?}",
|
||||
result.unwrap()
|
||||
);
|
||||
|
||||
if cfg!(feature = "unstable-v4") {
|
||||
let expected = r#"error: The following required argument was not provided: req_str
|
||||
|
||||
USAGE:
|
||||
clap --req-str <REQ_STR>
|
||||
clap <SUBCOMMAND>
|
||||
|
||||
For more information try --help
|
||||
"#;
|
||||
assert_eq!(result.unwrap_err().to_string(), expected);
|
||||
} else {
|
||||
let expected = r#"error: The following required argument was not provided: req-str
|
||||
|
||||
USAGE:
|
||||
clap --req-str <REQ_STR>
|
||||
clap <SUBCOMMAND>
|
||||
|
||||
For more information try --help
|
||||
"#;
|
||||
assert_eq!(result.unwrap_err().to_string(), expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derive_order_next_order() {
|
||||
static HELP: &str = "test 1.2
|
||||
|
||||
USAGE:
|
||||
test [OPTIONS]
|
||||
|
||||
OPTIONS:
|
||||
--flag-b first flag
|
||||
--option-b <OPTION_B> first option
|
||||
-h, --help Print help information
|
||||
-V, --version Print version information
|
||||
--flag-a second flag
|
||||
--option-a <OPTION_A> second option
|
||||
";
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(name = "test", version = "1.2")]
|
||||
#[clap(setting = AppSettings::DeriveDisplayOrder)]
|
||||
struct Args {
|
||||
#[clap(flatten)]
|
||||
a: A,
|
||||
#[clap(flatten)]
|
||||
b: B,
|
||||
}
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
#[clap(next_display_order = 10000)]
|
||||
struct A {
|
||||
/// second flag
|
||||
#[clap(long)]
|
||||
flag_a: bool,
|
||||
/// second option
|
||||
#[clap(long)]
|
||||
option_a: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
#[clap(next_display_order = 10)]
|
||||
struct B {
|
||||
/// first flag
|
||||
#[clap(long)]
|
||||
flag_b: bool,
|
||||
/// first option
|
||||
#[clap(long)]
|
||||
option_b: Option<String>,
|
||||
}
|
||||
|
||||
use clap::CommandFactory;
|
||||
let mut cmd = Args::command();
|
||||
|
||||
let mut buffer: Vec<u8> = Default::default();
|
||||
cmd.write_help(&mut buffer).unwrap();
|
||||
let help = String::from_utf8(buffer).unwrap();
|
||||
snapbox::assert_eq(HELP, help);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derive_order_next_order_flatten() {
|
||||
static HELP: &str = "test 1.2
|
||||
|
||||
USAGE:
|
||||
test [OPTIONS]
|
||||
|
||||
OPTIONS:
|
||||
--flag-b first flag
|
||||
--option-b <OPTION_B> first option
|
||||
-h, --help Print help information
|
||||
-V, --version Print version information
|
||||
--flag-a second flag
|
||||
--option-a <OPTION_A> second option
|
||||
";
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(setting = AppSettings::DeriveDisplayOrder)]
|
||||
#[clap(name = "test", version = "1.2")]
|
||||
struct Args {
|
||||
#[clap(flatten)]
|
||||
#[clap(next_display_order = 10000)]
|
||||
a: A,
|
||||
#[clap(flatten)]
|
||||
#[clap(next_display_order = 10)]
|
||||
b: B,
|
||||
}
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
struct A {
|
||||
/// second flag
|
||||
#[clap(long)]
|
||||
flag_a: bool,
|
||||
/// second option
|
||||
#[clap(long)]
|
||||
option_a: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
struct B {
|
||||
/// first flag
|
||||
#[clap(long)]
|
||||
flag_b: bool,
|
||||
/// first option
|
||||
#[clap(long)]
|
||||
option_b: Option<String>,
|
||||
}
|
||||
|
||||
use clap::CommandFactory;
|
||||
let mut cmd = Args::command();
|
||||
|
||||
let mut buffer: Vec<u8> = Default::default();
|
||||
cmd.write_help(&mut buffer).unwrap();
|
||||
let help = String::from_utf8(buffer).unwrap();
|
||||
snapbox::assert_eq(HELP, help);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derive_order_no_next_order() {
|
||||
static HELP: &str = "test 1.2
|
||||
|
||||
USAGE:
|
||||
test [OPTIONS]
|
||||
|
||||
OPTIONS:
|
||||
--flag-a first flag
|
||||
--flag-b second flag
|
||||
-h, --help Print help information
|
||||
--option-a <OPTION_A> first option
|
||||
--option-b <OPTION_B> second option
|
||||
-V, --version Print version information
|
||||
";
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(name = "test", version = "1.2")]
|
||||
#[clap(setting = AppSettings::DeriveDisplayOrder)]
|
||||
#[clap(next_display_order = None)]
|
||||
struct Args {
|
||||
#[clap(flatten)]
|
||||
a: A,
|
||||
#[clap(flatten)]
|
||||
b: B,
|
||||
}
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
struct A {
|
||||
/// first flag
|
||||
#[clap(long)]
|
||||
flag_a: bool,
|
||||
/// first option
|
||||
#[clap(long)]
|
||||
option_a: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
struct B {
|
||||
/// second flag
|
||||
#[clap(long)]
|
||||
flag_b: bool,
|
||||
/// second option
|
||||
#[clap(long)]
|
||||
option_b: Option<String>,
|
||||
}
|
||||
|
||||
use clap::CommandFactory;
|
||||
let mut cmd = Args::command();
|
||||
|
||||
let mut buffer: Vec<u8> = Default::default();
|
||||
cmd.write_help(&mut buffer).unwrap();
|
||||
let help = String::from_utf8(buffer).unwrap();
|
||||
snapbox::assert_eq(HELP, help);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
fn derive_possible_value_help() {
|
||||
static HELP: &str = "clap
|
||||
Application help
|
||||
|
||||
USAGE:
|
||||
clap <ARG>
|
||||
|
||||
ARGS:
|
||||
<ARG>
|
||||
Argument help
|
||||
|
||||
Possible values:
|
||||
- foo: Foo help
|
||||
- bar: Bar help
|
||||
|
||||
OPTIONS:
|
||||
-h, --help
|
||||
Print help information
|
||||
";
|
||||
|
||||
/// Application help
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Args {
|
||||
/// Argument help
|
||||
#[clap(value_enum)]
|
||||
arg: ArgChoice,
|
||||
}
|
||||
|
||||
#[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
|
||||
enum ArgChoice {
|
||||
/// Foo help
|
||||
Foo,
|
||||
/// Bar help
|
||||
Bar,
|
||||
}
|
||||
|
||||
use clap::CommandFactory;
|
||||
let mut cmd = Args::command();
|
||||
|
||||
let mut buffer: Vec<u8> = Default::default();
|
||||
cmd.write_long_help(&mut buffer).unwrap();
|
||||
let help = String::from_utf8(buffer).unwrap();
|
||||
snapbox::assert_eq(HELP, help);
|
||||
}
|
|
@ -1,130 +0,0 @@
|
|||
// https://github.com/TeXitoi/structopt/issues/{NUMBER}
|
||||
|
||||
use crate::utils;
|
||||
|
||||
use clap::{ArgGroup, Args, Parser, Subcommand};
|
||||
|
||||
#[test]
|
||||
fn issue_151_groups_within_subcommands() {
|
||||
#[derive(Args, Debug)]
|
||||
#[clap(group = ArgGroup::new("verb").required(true).multiple(true))]
|
||||
struct Opt {
|
||||
#[clap(long, group = "verb")]
|
||||
foo: Option<String>,
|
||||
#[clap(long, group = "verb")]
|
||||
bar: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
struct Cli {
|
||||
#[clap(flatten)]
|
||||
a: Opt,
|
||||
}
|
||||
|
||||
assert!(Cli::try_parse_from(&["test"]).is_err());
|
||||
assert!(Cli::try_parse_from(&["test", "--foo=v1"]).is_ok());
|
||||
assert!(Cli::try_parse_from(&["test", "--bar=v2"]).is_ok());
|
||||
assert!(Cli::try_parse_from(&["test", "--zebra=v3"]).is_err());
|
||||
assert!(Cli::try_parse_from(&["test", "--foo=v1", "--bar=v2"]).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_289() {
|
||||
#[derive(Parser)]
|
||||
#[clap(infer_subcommands = true)]
|
||||
enum Args {
|
||||
SomeCommand {
|
||||
#[clap(subcommand)]
|
||||
sub: SubSubCommand,
|
||||
},
|
||||
AnotherCommand,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
#[clap(infer_subcommands = true)]
|
||||
enum SubSubCommand {
|
||||
TestCommand,
|
||||
}
|
||||
|
||||
assert!(Args::try_parse_from(&["test", "some-command", "test-command"]).is_ok());
|
||||
assert!(Args::try_parse_from(&["test", "some", "test-command"]).is_ok());
|
||||
assert!(Args::try_parse_from(&["test", "some-command", "test"]).is_ok());
|
||||
assert!(Args::try_parse_from(&["test", "some", "test"]).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_324() {
|
||||
fn my_version() -> &'static str {
|
||||
"MY_VERSION"
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
#[clap(version = my_version())]
|
||||
struct Opt {
|
||||
#[clap(subcommand)]
|
||||
_cmd: SubCommand,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum SubCommand {
|
||||
Start,
|
||||
}
|
||||
|
||||
let help = utils::get_long_help::<Opt>();
|
||||
assert!(help.contains("MY_VERSION"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_418() {
|
||||
#[derive(Debug, Parser)]
|
||||
struct Opts {
|
||||
#[clap(subcommand)]
|
||||
/// The command to run
|
||||
command: Command,
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
enum Command {
|
||||
/// Reticulate the splines
|
||||
#[clap(visible_alias = "ret")]
|
||||
Reticulate {
|
||||
/// How many splines
|
||||
num_splines: u8,
|
||||
},
|
||||
/// Frobnicate the rest
|
||||
#[clap(visible_alias = "frob")]
|
||||
Frobnicate,
|
||||
}
|
||||
|
||||
let help = utils::get_long_help::<Opts>();
|
||||
assert!(help.contains("Reticulate the splines [aliases: ret]"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_490() {
|
||||
use clap::Parser;
|
||||
use std::iter::FromIterator;
|
||||
use std::str::FromStr;
|
||||
|
||||
struct U16ish;
|
||||
impl FromStr for U16ish {
|
||||
type Err = ();
|
||||
fn from_str(_: &str) -> Result<Self, Self::Err> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
impl<'a> FromIterator<&'a U16ish> for Vec<u16> {
|
||||
fn from_iter<T: IntoIterator<Item = &'a U16ish>>(_: T) -> Self {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
struct Opt {
|
||||
opt_vec: Vec<u16>,
|
||||
#[clap(long)]
|
||||
opt_opt_vec: Option<Vec<u16>>,
|
||||
}
|
||||
|
||||
// Assert that it compiles
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
|
||||
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
|
||||
// Ana Hobden (@hoverbear) <operator@hoverbear.org>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
//
|
||||
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
|
||||
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
|
||||
// MIT/Apache 2.0 license.
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
// Tests that clap_derive properly detects an `Option` field
|
||||
// that results from a macro expansion
|
||||
#[test]
|
||||
fn use_option() {
|
||||
macro_rules! expand_ty {
|
||||
($name:ident: $ty:ty) => {
|
||||
#[derive(Parser)]
|
||||
struct Outer {
|
||||
#[clap(short, long)]
|
||||
#[allow(dead_code)]
|
||||
$name: $ty,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
expand_ty!(my_field: Option<String>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_447() {
|
||||
macro_rules! Command {
|
||||
( $name:ident, [
|
||||
#[$meta:meta] $var:ident($inner:ty)
|
||||
] ) => {
|
||||
#[derive(Debug, PartialEq, clap::Parser)]
|
||||
enum $name {
|
||||
#[$meta]
|
||||
$var($inner),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Command! {GitCmd, [
|
||||
#[clap(external_subcommand)]
|
||||
Ext(Vec<String>)
|
||||
]}
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
#![cfg(feature = "derive")]
|
||||
#![cfg(feature = "unstable-v4")]
|
||||
|
||||
mod app_name;
|
||||
mod arguments;
|
||||
mod author_version_about;
|
||||
mod basic;
|
||||
mod boxed;
|
||||
mod custom_string_parsers;
|
||||
mod default_value;
|
||||
mod deny_warnings;
|
||||
mod doc_comments_help;
|
||||
mod explicit_name_no_renaming;
|
||||
mod flags;
|
||||
mod flatten;
|
||||
mod generic;
|
||||
mod help;
|
||||
mod issues;
|
||||
mod macros;
|
||||
mod naming;
|
||||
mod nested_subcommands;
|
||||
mod non_literal_attributes;
|
||||
mod options;
|
||||
mod privacy;
|
||||
mod raw_bool_literal;
|
||||
mod raw_idents;
|
||||
mod rename_all_env;
|
||||
mod skip;
|
||||
mod subcommands;
|
||||
mod type_alias_regressions;
|
||||
mod utf8;
|
||||
mod utils;
|
||||
mod value_enum;
|
|
@ -1,354 +0,0 @@
|
|||
use clap::Parser;
|
||||
|
||||
#[test]
|
||||
fn test_standalone_long_generates_kebab_case() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
#[allow(non_snake_case)]
|
||||
struct Opt {
|
||||
#[clap(long)]
|
||||
FOO_OPTION: bool,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt { FOO_OPTION: true },
|
||||
Opt::try_parse_from(&["test", "--foo-option"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_custom_long_overwrites_default_name() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(long = "foo")]
|
||||
foo_option: bool,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt { foo_option: true },
|
||||
Opt::try_parse_from(&["test", "--foo"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_standalone_long_uses_previous_defined_custom_name() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(name = "foo", long)]
|
||||
foo_option: bool,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt { foo_option: true },
|
||||
Opt::try_parse_from(&["test", "--foo"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_standalone_long_ignores_afterwards_defined_custom_name() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(long, name = "foo")]
|
||||
foo_option: bool,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt { foo_option: true },
|
||||
Opt::try_parse_from(&["test", "--foo-option"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_standalone_short_generates_kebab_case() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
#[allow(non_snake_case)]
|
||||
struct Opt {
|
||||
#[clap(short)]
|
||||
FOO_OPTION: bool,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt { FOO_OPTION: true },
|
||||
Opt::try_parse_from(&["test", "-f"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_custom_short_overwrites_default_name() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(short = 'o')]
|
||||
foo_option: bool,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt { foo_option: true },
|
||||
Opt::try_parse_from(&["test", "-o"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_standalone_short_uses_previous_defined_custom_name() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(name = "option", short)]
|
||||
foo_option: bool,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt { foo_option: true },
|
||||
Opt::try_parse_from(&["test", "-o"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_standalone_short_ignores_afterwards_defined_custom_name() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(short, name = "option")]
|
||||
foo_option: bool,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt { foo_option: true },
|
||||
Opt::try_parse_from(&["test", "-f"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_standalone_long_uses_previous_defined_casing() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(rename_all = "screaming_snake", long)]
|
||||
foo_option: bool,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt { foo_option: true },
|
||||
Opt::try_parse_from(&["test", "--FOO_OPTION"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_standalone_short_uses_previous_defined_casing() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(rename_all = "screaming_snake", short)]
|
||||
foo_option: bool,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt { foo_option: true },
|
||||
Opt::try_parse_from(&["test", "-F"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_standalone_long_works_with_verbatim_casing() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
#[allow(non_snake_case)]
|
||||
struct Opt {
|
||||
#[clap(rename_all = "verbatim", long)]
|
||||
_fOO_oPtiON: bool,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt { _fOO_oPtiON: true },
|
||||
Opt::try_parse_from(&["test", "--_fOO_oPtiON"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_standalone_short_works_with_verbatim_casing() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(rename_all = "verbatim", short)]
|
||||
_foo: bool,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt { _foo: true },
|
||||
Opt::try_parse_from(&["test", "-_"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rename_all_is_propagated_from_struct_to_fields() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
#[clap(rename_all = "screaming_snake")]
|
||||
struct Opt {
|
||||
#[clap(long)]
|
||||
foo: bool,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt { foo: true },
|
||||
Opt::try_parse_from(&["test", "--FOO"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rename_all_is_not_propagated_from_struct_into_flattened() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
#[clap(rename_all = "screaming_snake")]
|
||||
struct Opt {
|
||||
#[clap(flatten)]
|
||||
foo: Foo,
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Foo {
|
||||
#[clap(long)]
|
||||
foo: bool,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
foo: Foo { foo: true }
|
||||
},
|
||||
Opt::try_parse_from(&["test", "--foo"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lower_is_renamed() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(rename_all = "lower", long)]
|
||||
foo_option: bool,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt { foo_option: true },
|
||||
Opt::try_parse_from(&["test", "--foooption"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_upper_is_renamed() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(rename_all = "upper", long)]
|
||||
foo_option: bool,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt { foo_option: true },
|
||||
Opt::try_parse_from(&["test", "--FOOOPTION"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_single_word_enum_variant_is_default_renamed_into_kebab_case() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
enum Opt {
|
||||
Command { foo: u32 },
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt::Command { foo: 0 },
|
||||
Opt::try_parse_from(&["test", "command", "0"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multi_word_enum_variant_is_renamed() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
enum Opt {
|
||||
FirstCommand { foo: u32 },
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt::FirstCommand { foo: 0 },
|
||||
Opt::try_parse_from(&["test", "first-command", "0"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rename_all_is_not_propagated_from_struct_into_subcommand() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
#[clap(rename_all = "screaming_snake")]
|
||||
struct Opt {
|
||||
#[clap(subcommand)]
|
||||
foo: Foo,
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
enum Foo {
|
||||
Command {
|
||||
#[clap(long)]
|
||||
foo: bool,
|
||||
},
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
foo: Foo::Command { foo: true }
|
||||
},
|
||||
Opt::try_parse_from(&["test", "command", "--foo"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rename_all_is_propagated_from_enum_to_variants() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
#[clap(rename_all = "screaming_snake")]
|
||||
enum Opt {
|
||||
FirstVariant,
|
||||
SecondVariant {
|
||||
#[clap(long)]
|
||||
foo: String,
|
||||
},
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt::FirstVariant,
|
||||
Opt::try_parse_from(&["test", "FIRST_VARIANT"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rename_all_is_propagated_from_enum_to_variant_fields() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
#[clap(rename_all = "screaming_snake")]
|
||||
enum Opt {
|
||||
FirstVariant,
|
||||
SecondVariant {
|
||||
#[clap(long)]
|
||||
foo: String,
|
||||
},
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt::SecondVariant {
|
||||
foo: "value".into()
|
||||
},
|
||||
Opt::try_parse_from(&["test", "SECOND_VARIANT", "--FOO", "value"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rename_all_is_propagation_can_be_overridden() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
#[clap(rename_all = "screaming_snake")]
|
||||
enum Opt {
|
||||
#[clap(rename_all = "kebab_case")]
|
||||
FirstVariant {
|
||||
#[clap(long)]
|
||||
foo_option: bool,
|
||||
},
|
||||
SecondVariant {
|
||||
#[clap(rename_all = "kebab_case", long)]
|
||||
foo_option: bool,
|
||||
},
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt::FirstVariant { foo_option: true },
|
||||
Opt::try_parse_from(&["test", "first-variant", "--foo-option"]).unwrap()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Opt::SecondVariant { foo_option: true },
|
||||
Opt::try_parse_from(&["test", "SECOND_VARIANT", "--foo-option"]).unwrap()
|
||||
);
|
||||
}
|
|
@ -1,194 +0,0 @@
|
|||
// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
|
||||
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
|
||||
// Ana Hobden (@hoverbear) <operator@hoverbear.org>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
//
|
||||
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
|
||||
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
|
||||
// MIT/Apache 2.0 license.
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short, long)]
|
||||
force: bool,
|
||||
#[clap(short, long, action = clap::ArgAction::Count)]
|
||||
verbose: u8,
|
||||
#[clap(subcommand)]
|
||||
cmd: Sub,
|
||||
}
|
||||
|
||||
#[derive(Subcommand, PartialEq, Debug)]
|
||||
enum Sub {
|
||||
Fetch {},
|
||||
Add {},
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt2 {
|
||||
#[clap(short, long)]
|
||||
force: bool,
|
||||
#[clap(short, long, action = clap::ArgAction::Count)]
|
||||
verbose: u8,
|
||||
#[clap(subcommand)]
|
||||
cmd: Option<Sub>,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_cmd() {
|
||||
let result = Opt::try_parse_from(&["test"]);
|
||||
assert!(result.is_err());
|
||||
|
||||
assert_eq!(
|
||||
Opt2 {
|
||||
force: false,
|
||||
verbose: 0,
|
||||
cmd: None
|
||||
},
|
||||
Opt2::try_parse_from(&["test"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fetch() {
|
||||
assert_eq!(
|
||||
Opt {
|
||||
force: false,
|
||||
verbose: 3,
|
||||
cmd: Sub::Fetch {}
|
||||
},
|
||||
Opt::try_parse_from(&["test", "-vvv", "fetch"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
force: true,
|
||||
verbose: 0,
|
||||
cmd: Sub::Fetch {}
|
||||
},
|
||||
Opt::try_parse_from(&["test", "--force", "fetch"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add() {
|
||||
assert_eq!(
|
||||
Opt {
|
||||
force: false,
|
||||
verbose: 0,
|
||||
cmd: Sub::Add {}
|
||||
},
|
||||
Opt::try_parse_from(&["test", "add"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
force: false,
|
||||
verbose: 2,
|
||||
cmd: Sub::Add {}
|
||||
},
|
||||
Opt::try_parse_from(&["test", "-vv", "add"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_badinput() {
|
||||
let result = Opt::try_parse_from(&["test", "badcmd"]);
|
||||
assert!(result.is_err());
|
||||
let result = Opt::try_parse_from(&["test", "add", "--verbose"]);
|
||||
assert!(result.is_err());
|
||||
let result = Opt::try_parse_from(&["test", "--badopt", "add"]);
|
||||
assert!(result.is_err());
|
||||
let result = Opt::try_parse_from(&["test", "add", "--badopt"]);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt3 {
|
||||
#[clap(short, long)]
|
||||
all: bool,
|
||||
#[clap(subcommand)]
|
||||
cmd: Sub2,
|
||||
}
|
||||
|
||||
#[derive(Subcommand, PartialEq, Debug)]
|
||||
enum Sub2 {
|
||||
Foo {
|
||||
file: String,
|
||||
#[clap(subcommand)]
|
||||
cmd: Sub3,
|
||||
},
|
||||
Bar {},
|
||||
}
|
||||
|
||||
#[derive(Subcommand, PartialEq, Debug)]
|
||||
enum Sub3 {
|
||||
Baz {},
|
||||
Quux {},
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_subsubcommand() {
|
||||
assert_eq!(
|
||||
Opt3 {
|
||||
all: true,
|
||||
cmd: Sub2::Foo {
|
||||
file: "lib.rs".to_string(),
|
||||
cmd: Sub3::Quux {}
|
||||
}
|
||||
},
|
||||
Opt3::try_parse_from(&["test", "--all", "foo", "lib.rs", "quux"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
enum SubSubCmdWithOption {
|
||||
Remote {
|
||||
#[clap(subcommand)]
|
||||
cmd: Option<Remote>,
|
||||
},
|
||||
Stash {
|
||||
#[clap(subcommand)]
|
||||
cmd: Stash,
|
||||
},
|
||||
}
|
||||
#[derive(Subcommand, PartialEq, Debug)]
|
||||
enum Remote {
|
||||
Add { name: String, url: String },
|
||||
Remove { name: String },
|
||||
}
|
||||
|
||||
#[derive(Subcommand, PartialEq, Debug)]
|
||||
enum Stash {
|
||||
Save,
|
||||
Pop,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sub_sub_cmd_with_option() {
|
||||
fn make(args: &[&str]) -> Option<SubSubCmdWithOption> {
|
||||
SubSubCmdWithOption::try_parse_from(args).ok()
|
||||
}
|
||||
assert_eq!(
|
||||
Some(SubSubCmdWithOption::Remote { cmd: None }),
|
||||
make(&["", "remote"])
|
||||
);
|
||||
assert_eq!(
|
||||
Some(SubSubCmdWithOption::Remote {
|
||||
cmd: Some(Remote::Add {
|
||||
name: "origin".into(),
|
||||
url: "http".into()
|
||||
})
|
||||
}),
|
||||
make(&["", "remote", "add", "origin", "http"])
|
||||
);
|
||||
assert_eq!(
|
||||
Some(SubSubCmdWithOption::Stash { cmd: Stash::Save }),
|
||||
make(&["", "stash", "save"])
|
||||
);
|
||||
assert_eq!(None, make(&["", "stash"]));
|
||||
}
|
|
@ -1,156 +0,0 @@
|
|||
// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
|
||||
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
|
||||
// Ana Hobden (@hoverbear) <operator@hoverbear.org>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
//
|
||||
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
|
||||
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
|
||||
// MIT/Apache 2.0 license.
|
||||
|
||||
use clap::{ErrorKind, Parser};
|
||||
use std::num::ParseIntError;
|
||||
|
||||
pub const DISPLAY_ORDER: usize = 2;
|
||||
|
||||
// Check if the global settings compile
|
||||
#[derive(Parser, Debug, PartialEq, Eq)]
|
||||
#[clap(allow_hyphen_values = true)]
|
||||
struct Opt {
|
||||
#[clap(
|
||||
long = "x",
|
||||
display_order = DISPLAY_ORDER,
|
||||
next_line_help = true,
|
||||
default_value = "0",
|
||||
require_equals = true,
|
||||
)]
|
||||
x: i32,
|
||||
|
||||
#[clap(short = 'l', long = "level", aliases = &["set-level", "lvl"])]
|
||||
level: String,
|
||||
|
||||
#[clap(long("values"))]
|
||||
values: Vec<i32>,
|
||||
|
||||
#[clap(name = "FILE", requires_if("FILE", "values"))]
|
||||
files: Vec<String>,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_slice() {
|
||||
assert_eq!(
|
||||
Opt {
|
||||
x: 0,
|
||||
level: "1".to_string(),
|
||||
files: Vec::new(),
|
||||
values: vec![],
|
||||
},
|
||||
Opt::try_parse_from(&["test", "-l", "1"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
x: 0,
|
||||
level: "1".to_string(),
|
||||
files: Vec::new(),
|
||||
values: vec![],
|
||||
},
|
||||
Opt::try_parse_from(&["test", "--level", "1"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
x: 0,
|
||||
level: "1".to_string(),
|
||||
files: Vec::new(),
|
||||
values: vec![],
|
||||
},
|
||||
Opt::try_parse_from(&["test", "--set-level", "1"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
x: 0,
|
||||
level: "1".to_string(),
|
||||
files: Vec::new(),
|
||||
values: vec![],
|
||||
},
|
||||
Opt::try_parse_from(&["test", "--lvl", "1"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multi_args() {
|
||||
assert_eq!(
|
||||
Opt {
|
||||
x: 0,
|
||||
level: "1".to_string(),
|
||||
files: vec!["file".to_string()],
|
||||
values: vec![],
|
||||
},
|
||||
Opt::try_parse_from(&["test", "-l", "1", "file"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
x: 0,
|
||||
level: "1".to_string(),
|
||||
files: vec!["FILE".to_string()],
|
||||
values: vec![1],
|
||||
},
|
||||
Opt::try_parse_from(&["test", "-l", "1", "--values", "1", "--", "FILE"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multi_args_fail() {
|
||||
let result = Opt::try_parse_from(&["test", "-l", "1", "--", "FILE"]);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bool() {
|
||||
assert_eq!(
|
||||
Opt {
|
||||
x: 1,
|
||||
level: "1".to_string(),
|
||||
files: vec![],
|
||||
values: vec![],
|
||||
},
|
||||
Opt::try_parse_from(&["test", "-l", "1", "--x=1"]).unwrap()
|
||||
);
|
||||
let result = Opt::try_parse_from(&["test", "-l", "1", "--x", "1"]);
|
||||
assert!(result.is_err());
|
||||
assert_eq!(result.unwrap_err().kind(), ErrorKind::NoEquals);
|
||||
}
|
||||
|
||||
fn parse_hex(input: &str) -> Result<u64, ParseIntError> {
|
||||
u64::from_str_radix(input, 16)
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct HexOpt {
|
||||
#[clap(short, value_parser = parse_hex)]
|
||||
number: u64,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_hex_function_path() {
|
||||
assert_eq!(
|
||||
HexOpt { number: 5 },
|
||||
HexOpt::try_parse_from(&["test", "-n", "5"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
HexOpt {
|
||||
number: 0x00ab_cdef
|
||||
},
|
||||
HexOpt::try_parse_from(&["test", "-n", "abcdef"]).unwrap()
|
||||
);
|
||||
|
||||
let err = HexOpt::try_parse_from(&["test", "-n", "gg"]).unwrap_err();
|
||||
assert!(
|
||||
err.to_string().contains("invalid digit found in string"),
|
||||
"{}",
|
||||
err
|
||||
);
|
||||
}
|
|
@ -1,520 +0,0 @@
|
|||
// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
|
||||
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
|
||||
// Ana Hobden (@hoverbear) <operator@hoverbear.org>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
//
|
||||
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
|
||||
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
|
||||
// MIT/Apache 2.0 license.
|
||||
|
||||
#![allow(clippy::option_option)]
|
||||
|
||||
use crate::utils;
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
|
||||
#[test]
|
||||
fn required_option() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short, long)]
|
||||
arg: i32,
|
||||
}
|
||||
assert_eq!(
|
||||
Opt { arg: 42 },
|
||||
Opt::try_parse_from(&["test", "-a42"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt { arg: 42 },
|
||||
Opt::try_parse_from(&["test", "-a", "42"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt { arg: 42 },
|
||||
Opt::try_parse_from(&["test", "--arg", "42"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt { arg: 42 },
|
||||
Opt::try_parse_from(&["test", "--arg", "24", "--arg", "42"]).unwrap()
|
||||
);
|
||||
assert!(Opt::try_parse_from(&["test"]).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn option_with_default() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short, default_value = "42")]
|
||||
arg: i32,
|
||||
}
|
||||
assert_eq!(
|
||||
Opt { arg: 24 },
|
||||
Opt::try_parse_from(&["test", "-a24"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt { arg: 42 },
|
||||
Opt::try_parse_from(&["test", "-a", "24", "-a", "42"]).unwrap()
|
||||
);
|
||||
assert_eq!(Opt { arg: 42 }, Opt::try_parse_from(&["test"]).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn option_with_raw_default() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short, default_value = "42")]
|
||||
arg: i32,
|
||||
}
|
||||
assert_eq!(
|
||||
Opt { arg: 24 },
|
||||
Opt::try_parse_from(&["test", "-a24"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt { arg: 42 },
|
||||
Opt::try_parse_from(&["test", "-a", "24", "-a", "42"]).unwrap()
|
||||
);
|
||||
assert_eq!(Opt { arg: 42 }, Opt::try_parse_from(&["test"]).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn option_from_str() {
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
struct A;
|
||||
|
||||
impl std::str::FromStr for A {
|
||||
type Err = std::convert::Infallible;
|
||||
|
||||
fn from_str(_: &str) -> Result<A, Self::Err> {
|
||||
Ok(A)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Parser, PartialEq)]
|
||||
struct Opt {
|
||||
a: Option<A>,
|
||||
}
|
||||
|
||||
assert_eq!(Opt { a: None }, Opt::try_parse_from(&["test"]).unwrap());
|
||||
assert_eq!(
|
||||
Opt { a: Some(A) },
|
||||
Opt::try_parse_from(&["test", "foo"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vec_from_str() {
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
struct A;
|
||||
|
||||
impl std::str::FromStr for A {
|
||||
type Err = std::convert::Infallible;
|
||||
|
||||
fn from_str(_: &str) -> Result<A, Self::Err> {
|
||||
Ok(A)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Parser, PartialEq)]
|
||||
struct Opt {
|
||||
a: Vec<A>,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt { a: Vec::new() },
|
||||
Opt::try_parse_from(&["test"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt { a: vec![A] },
|
||||
Opt::try_parse_from(&["test", "foo"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn option_vec_from_str() {
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
struct A;
|
||||
|
||||
impl std::str::FromStr for A {
|
||||
type Err = std::convert::Infallible;
|
||||
|
||||
fn from_str(_: &str) -> Result<A, Self::Err> {
|
||||
Ok(A)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Parser, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(short)]
|
||||
a: Option<Vec<A>>,
|
||||
}
|
||||
|
||||
assert_eq!(Opt { a: None }, Opt::try_parse_from(&["test"]).unwrap());
|
||||
assert_eq!(
|
||||
Opt { a: Some(vec![A]) },
|
||||
Opt::try_parse_from(&["test", "-a", "foo"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn option_type_is_optional() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short)]
|
||||
arg: Option<i32>,
|
||||
}
|
||||
assert_eq!(
|
||||
Opt { arg: Some(42) },
|
||||
Opt::try_parse_from(&["test", "-a42"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt { arg: Some(42) },
|
||||
Opt::try_parse_from(&["test", "-a", "24", "-a", "42"]).unwrap()
|
||||
);
|
||||
assert_eq!(Opt { arg: None }, Opt::try_parse_from(&["test"]).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn required_with_option_type() {
|
||||
#[derive(Debug, PartialEq, Eq, Parser)]
|
||||
#[clap(subcommand_negates_reqs = true)]
|
||||
struct Opt {
|
||||
#[clap(required = true)]
|
||||
req_str: Option<String>,
|
||||
|
||||
#[clap(subcommand)]
|
||||
cmd: Option<SubCommands>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Subcommand)]
|
||||
enum SubCommands {
|
||||
ExSub {
|
||||
#[clap(short, long, action = clap::ArgAction::Count)]
|
||||
verbose: u8,
|
||||
},
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
req_str: Some(("arg").into()),
|
||||
cmd: None,
|
||||
},
|
||||
Opt::try_parse_from(&["test", "arg"]).unwrap()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
req_str: None,
|
||||
cmd: Some(SubCommands::ExSub { verbose: 1 }),
|
||||
},
|
||||
Opt::try_parse_from(&["test", "ex-sub", "-v"]).unwrap()
|
||||
);
|
||||
|
||||
assert!(Opt::try_parse_from(&["test"]).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ignore_qualified_option_type() {
|
||||
fn parser(s: &str) -> Result<Option<String>, std::convert::Infallible> {
|
||||
Ok(Some(s.to_string()))
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_parser = parser)]
|
||||
arg: ::std::option::Option<String>,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: Some("success".into())
|
||||
},
|
||||
Opt::try_parse_from(&["test", "success"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn option_option_type_is_optional_value() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short)]
|
||||
#[allow(clippy::option_option)]
|
||||
arg: Option<Option<i32>>,
|
||||
}
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: Some(Some(42))
|
||||
},
|
||||
Opt::try_parse_from(&["test", "-a42"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt { arg: Some(None) },
|
||||
Opt::try_parse_from(&["test", "-a"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: Some(Some(42))
|
||||
},
|
||||
Opt::try_parse_from(&["test", "-a", "24", "-a", "42"]).unwrap()
|
||||
);
|
||||
assert_eq!(Opt { arg: None }, Opt::try_parse_from(&["test"]).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn option_option_type_help() {
|
||||
#[derive(Parser, Debug)]
|
||||
struct Opt {
|
||||
#[clap(long, value_name = "val")]
|
||||
arg: Option<Option<i32>>,
|
||||
}
|
||||
let help = utils::get_help::<Opt>();
|
||||
assert!(help.contains("--arg [<val>]"));
|
||||
assert!(!help.contains("--arg [<val>]..."));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn two_option_option_types() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short)]
|
||||
arg: Option<Option<i32>>,
|
||||
|
||||
#[clap(long)]
|
||||
field: Option<Option<String>>,
|
||||
}
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: Some(Some(42)),
|
||||
field: Some(Some("f".into()))
|
||||
},
|
||||
Opt::try_parse_from(&["test", "-a42", "--field", "f"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: Some(Some(42)),
|
||||
field: Some(None)
|
||||
},
|
||||
Opt::try_parse_from(&["test", "-a42", "--field"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: Some(None),
|
||||
field: Some(None)
|
||||
},
|
||||
Opt::try_parse_from(&["test", "-a", "--field"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: Some(None),
|
||||
field: Some(Some("f".into()))
|
||||
},
|
||||
Opt::try_parse_from(&["test", "-a", "--field", "f"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: None,
|
||||
field: Some(None)
|
||||
},
|
||||
Opt::try_parse_from(&["test", "--field"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: None,
|
||||
field: None
|
||||
},
|
||||
Opt::try_parse_from(&["test"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vec_type_is_multiple_occurrences() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short, long)]
|
||||
arg: Vec<i32>,
|
||||
}
|
||||
assert_eq!(
|
||||
Opt { arg: vec![24] },
|
||||
Opt::try_parse_from(&["test", "-a24"]).unwrap()
|
||||
);
|
||||
assert_eq!(Opt { arg: vec![] }, Opt::try_parse_from(&["test"]).unwrap());
|
||||
assert_eq!(
|
||||
Opt { arg: vec![24, 42] },
|
||||
Opt::try_parse_from(&["test", "-a", "24", "-a", "42"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vec_type_with_required() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short, long, required = true)]
|
||||
arg: Vec<i32>,
|
||||
}
|
||||
assert_eq!(
|
||||
Opt { arg: vec![24] },
|
||||
Opt::try_parse_from(&["test", "-a24"]).unwrap()
|
||||
);
|
||||
assert!(Opt::try_parse_from(&["test"]).is_err());
|
||||
assert_eq!(
|
||||
Opt { arg: vec![24, 42] },
|
||||
Opt::try_parse_from(&["test", "-a", "24", "-a", "42"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vec_type_with_multiple_values_only() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short, long, multiple_values(true))]
|
||||
arg: Vec<i32>,
|
||||
}
|
||||
assert_eq!(
|
||||
Opt { arg: vec![24] },
|
||||
Opt::try_parse_from(&["test", "-a24"]).unwrap()
|
||||
);
|
||||
assert_eq!(Opt { arg: vec![] }, Opt::try_parse_from(&["test"]).unwrap());
|
||||
assert_eq!(
|
||||
Opt { arg: vec![24, 42] },
|
||||
Opt::try_parse_from(&["test", "-a", "24", "42"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ignore_qualified_vec_type() {
|
||||
fn parser(s: &str) -> Result<Vec<String>, std::convert::Infallible> {
|
||||
Ok(vec![s.to_string()])
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_parser = parser)]
|
||||
arg: ::std::vec::Vec<String>,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: vec!["success".into()]
|
||||
},
|
||||
Opt::try_parse_from(&["test", "success"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn option_vec_type() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short)]
|
||||
arg: Option<Vec<i32>>,
|
||||
}
|
||||
assert_eq!(
|
||||
Opt { arg: Some(vec![1]) },
|
||||
Opt::try_parse_from(&["test", "-a", "1"]).unwrap()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: Some(vec![1, 2])
|
||||
},
|
||||
Opt::try_parse_from(&["test", "-a", "1", "-a", "2"]).unwrap()
|
||||
);
|
||||
|
||||
assert_eq!(Opt { arg: None }, Opt::try_parse_from(&["test"]).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn option_vec_type_structopt_behavior() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short, long, multiple_values(true), min_values(0))]
|
||||
arg: Option<Vec<i32>>,
|
||||
}
|
||||
assert_eq!(
|
||||
Opt { arg: Some(vec![1]) },
|
||||
Opt::try_parse_from(&["test", "-a", "1"]).unwrap()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: Some(vec![1, 2])
|
||||
},
|
||||
Opt::try_parse_from(&["test", "-a", "1", "2"]).unwrap()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Opt { arg: Some(vec![]) },
|
||||
Opt::try_parse_from(&["test", "-a"]).unwrap()
|
||||
);
|
||||
|
||||
assert_eq!(Opt { arg: None }, Opt::try_parse_from(&["test"]).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn two_option_vec_types() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short)]
|
||||
arg: Option<Vec<i32>>,
|
||||
|
||||
#[clap(short)]
|
||||
b: Option<Vec<i32>>,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: Some(vec![1]),
|
||||
b: None,
|
||||
},
|
||||
Opt::try_parse_from(&["test", "-a", "1"]).unwrap()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: Some(vec![1]),
|
||||
b: Some(vec![1])
|
||||
},
|
||||
Opt::try_parse_from(&["test", "-a", "1", "-b", "1"]).unwrap()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: Some(vec![1, 2]),
|
||||
b: Some(vec![1, 2])
|
||||
},
|
||||
Opt::try_parse_from(&["test", "-a", "1", "-a", "2", "-b", "1", "-b", "2"]).unwrap()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Opt { arg: None, b: None },
|
||||
Opt::try_parse_from(&["test"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn explicit_value_parser() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(long, value_parser = clap::value_parser!(i32))]
|
||||
arg: i32,
|
||||
}
|
||||
assert_eq!(
|
||||
Opt { arg: 42 },
|
||||
Opt::try_parse_from(&["test", "--arg", "42"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn implicit_value_parser() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(long)]
|
||||
arg: i32,
|
||||
}
|
||||
assert_eq!(
|
||||
Opt { arg: 42 },
|
||||
Opt::try_parse_from(&["test", "--arg", "42"]).unwrap()
|
||||
);
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
|
||||
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
|
||||
// Ana Hobden (@hoverbear) <operator@hoverbear.org>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
//
|
||||
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
|
||||
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
|
||||
// MIT/Apache 2.0 license.
|
||||
|
||||
mod options {
|
||||
use clap::Parser;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct Options {
|
||||
#[clap(subcommand)]
|
||||
pub subcommand: super::subcommands::SubCommand,
|
||||
}
|
||||
}
|
||||
|
||||
mod subcommands {
|
||||
use clap::Subcommand;
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum SubCommand {
|
||||
/// foo
|
||||
Foo {
|
||||
/// foo
|
||||
bars: String,
|
||||
},
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
#[test]
|
||||
fn raw_bool_literal() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
#[clap(name = "raw_bool")]
|
||||
struct Opt {
|
||||
#[clap(raw(false))]
|
||||
a: String,
|
||||
#[clap(raw(true))]
|
||||
b: String,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
a: "one".into(),
|
||||
b: "--help".into()
|
||||
},
|
||||
Opt::try_parse_from(&["test", "one", "--", "--help"]).unwrap()
|
||||
);
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
use clap::Parser;
|
||||
|
||||
#[test]
|
||||
fn raw_idents() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(short, long)]
|
||||
r#type: String,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
r#type: "long".into()
|
||||
},
|
||||
Opt::try_parse_from(&["test", "--type", "long"]).unwrap()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
r#type: "short".into()
|
||||
},
|
||||
Opt::try_parse_from(&["test", "-t", "short"]).unwrap()
|
||||
);
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
#![cfg(feature = "env")]
|
||||
|
||||
use crate::utils;
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
#[derive(Debug, PartialEq, Parser)]
|
||||
#[clap(rename_all_env = "kebab")]
|
||||
struct BehaviorModel {
|
||||
#[clap(env)]
|
||||
be_nice: String,
|
||||
}
|
||||
|
||||
let help = utils::get_help::<BehaviorModel>();
|
||||
assert!(help.contains("[env: be-nice=]"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_is_screaming() {
|
||||
#[derive(Debug, PartialEq, Parser)]
|
||||
struct BehaviorModel {
|
||||
#[clap(env)]
|
||||
be_nice: String,
|
||||
}
|
||||
|
||||
let help = utils::get_help::<BehaviorModel>();
|
||||
assert!(help.contains("[env: BE_NICE=]"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn overridable() {
|
||||
#[derive(Debug, PartialEq, Parser)]
|
||||
#[clap(rename_all_env = "kebab")]
|
||||
struct BehaviorModel {
|
||||
#[clap(env)]
|
||||
be_nice: String,
|
||||
|
||||
#[clap(rename_all_env = "pascal", env)]
|
||||
be_aggressive: String,
|
||||
}
|
||||
|
||||
let help = utils::get_help::<BehaviorModel>();
|
||||
assert!(help.contains("[env: be-nice=]"));
|
||||
assert!(help.contains("[env: BeAggressive=]"));
|
||||
}
|
|
@ -1,157 +0,0 @@
|
|||
// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
#[test]
|
||||
fn skip_1() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(short)]
|
||||
x: u32,
|
||||
#[clap(skip)]
|
||||
s: u32,
|
||||
}
|
||||
|
||||
assert!(Opt::try_parse_from(&["test", "-x", "10", "20"]).is_err());
|
||||
|
||||
let mut opt = Opt::try_parse_from(&["test", "-x", "10"]).unwrap();
|
||||
assert_eq!(
|
||||
opt,
|
||||
Opt {
|
||||
x: 10,
|
||||
s: 0, // default
|
||||
}
|
||||
);
|
||||
opt.s = 42;
|
||||
|
||||
opt.update_from(&["test", "-x", "22"]);
|
||||
|
||||
assert_eq!(opt, Opt { x: 22, s: 42 });
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn skip_2() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(short)]
|
||||
x: u32,
|
||||
#[clap(skip)]
|
||||
ss: String,
|
||||
#[clap(skip)]
|
||||
sn: u8,
|
||||
|
||||
y: u32,
|
||||
#[clap(skip)]
|
||||
sz: u16,
|
||||
|
||||
t: u32,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt::try_parse_from(&["test", "-x", "10", "20", "30"]).unwrap(),
|
||||
Opt {
|
||||
x: 10,
|
||||
ss: String::from(""),
|
||||
sn: 0,
|
||||
y: 20,
|
||||
sz: 0,
|
||||
t: 30,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn skip_enum() {
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[allow(unused)]
|
||||
enum Kind {
|
||||
A,
|
||||
B,
|
||||
}
|
||||
|
||||
impl Default for Kind {
|
||||
fn default() -> Self {
|
||||
Kind::B
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
pub struct Opt {
|
||||
#[clap(long, short)]
|
||||
number: u32,
|
||||
#[clap(skip)]
|
||||
k: Kind,
|
||||
#[clap(skip)]
|
||||
v: Vec<u32>,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt::try_parse_from(&["test", "-n", "10"]).unwrap(),
|
||||
Opt {
|
||||
number: 10,
|
||||
k: Kind::B,
|
||||
v: vec![],
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn skip_help_doc_comments() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
pub struct Opt {
|
||||
#[clap(skip, help = "internal_stuff")]
|
||||
a: u32,
|
||||
|
||||
#[clap(skip, long_help = "internal_stuff\ndo not touch")]
|
||||
b: u32,
|
||||
|
||||
/// Not meant to be used by clap.
|
||||
///
|
||||
/// I want a default here.
|
||||
#[clap(skip)]
|
||||
c: u32,
|
||||
|
||||
#[clap(short)]
|
||||
n: u32,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt::try_parse_from(&["test", "-n", "10"]).unwrap(),
|
||||
Opt {
|
||||
n: 10,
|
||||
a: 0,
|
||||
b: 0,
|
||||
c: 0,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn skip_val() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
pub struct Opt {
|
||||
#[clap(long, short)]
|
||||
number: u32,
|
||||
|
||||
#[clap(skip = "key")]
|
||||
k: String,
|
||||
|
||||
#[clap(skip = vec![1, 2, 3])]
|
||||
v: Vec<u32>,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt::try_parse_from(&["test", "-n", "10"]).unwrap(),
|
||||
Opt {
|
||||
number: 10,
|
||||
k: "key".to_string(),
|
||||
v: vec![1, 2, 3]
|
||||
}
|
||||
);
|
||||
}
|
|
@ -1,609 +0,0 @@
|
|||
// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
|
||||
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
|
||||
// Ana Hobden (@hoverbear) <operator@hoverbear.org>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
//
|
||||
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
|
||||
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
|
||||
// MIT/Apache 2.0 license.
|
||||
|
||||
use crate::utils;
|
||||
|
||||
use clap::{Args, Parser, Subcommand};
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
enum Opt {
|
||||
/// Fetch stuff from GitHub
|
||||
Fetch {
|
||||
#[clap(long)]
|
||||
all: bool,
|
||||
/// Overwrite local branches.
|
||||
#[clap(short, long)]
|
||||
force: bool,
|
||||
|
||||
repo: String,
|
||||
},
|
||||
|
||||
Add {
|
||||
#[clap(short, long)]
|
||||
interactive: bool,
|
||||
#[clap(short, long)]
|
||||
verbose: bool,
|
||||
},
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fetch() {
|
||||
assert_eq!(
|
||||
Opt::Fetch {
|
||||
all: true,
|
||||
force: false,
|
||||
repo: "origin".to_string()
|
||||
},
|
||||
Opt::try_parse_from(&["test", "fetch", "--all", "origin"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt::Fetch {
|
||||
all: false,
|
||||
force: true,
|
||||
repo: "origin".to_string()
|
||||
},
|
||||
Opt::try_parse_from(&["test", "fetch", "-f", "origin"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add() {
|
||||
assert_eq!(
|
||||
Opt::Add {
|
||||
interactive: false,
|
||||
verbose: false
|
||||
},
|
||||
Opt::try_parse_from(&["test", "add"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt::Add {
|
||||
interactive: true,
|
||||
verbose: true
|
||||
},
|
||||
Opt::try_parse_from(&["test", "add", "-i", "-v"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_parse() {
|
||||
let result = Opt::try_parse_from(&["test", "badcmd", "-i", "-v"]);
|
||||
assert!(result.is_err());
|
||||
|
||||
let result = Opt::try_parse_from(&["test", "add", "--badoption"]);
|
||||
assert!(result.is_err());
|
||||
|
||||
let result = Opt::try_parse_from(&["test"]);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
enum Opt2 {
|
||||
DoSomething { arg: String },
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// This test is specifically to make sure that hyphenated subcommands get
|
||||
/// processed correctly.
|
||||
fn test_hyphenated_subcommands() {
|
||||
assert_eq!(
|
||||
Opt2::DoSomething {
|
||||
arg: "blah".to_string()
|
||||
},
|
||||
Opt2::try_parse_from(&["test", "do-something", "blah"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
enum Opt3 {
|
||||
Add,
|
||||
Init,
|
||||
Fetch,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_null_commands() {
|
||||
assert_eq!(Opt3::Add, Opt3::try_parse_from(&["test", "add"]).unwrap());
|
||||
assert_eq!(Opt3::Init, Opt3::try_parse_from(&["test", "init"]).unwrap());
|
||||
assert_eq!(
|
||||
Opt3::Fetch,
|
||||
Opt3::try_parse_from(&["test", "fetch"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
#[clap(about = "Not shown")]
|
||||
struct Add {
|
||||
file: String,
|
||||
}
|
||||
/// Not shown
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Fetch {
|
||||
remote: String,
|
||||
}
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
enum Opt4 {
|
||||
// Not shown
|
||||
/// Add a file
|
||||
Add(Add),
|
||||
Init,
|
||||
/// download history from remote
|
||||
Fetch(Fetch),
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tuple_commands() {
|
||||
assert_eq!(
|
||||
Opt4::Add(Add {
|
||||
file: "f".to_string()
|
||||
}),
|
||||
Opt4::try_parse_from(&["test", "add", "f"]).unwrap()
|
||||
);
|
||||
assert_eq!(Opt4::Init, Opt4::try_parse_from(&["test", "init"]).unwrap());
|
||||
assert_eq!(
|
||||
Opt4::Fetch(Fetch {
|
||||
remote: "origin".to_string()
|
||||
}),
|
||||
Opt4::try_parse_from(&["test", "fetch", "origin"]).unwrap()
|
||||
);
|
||||
|
||||
let output = utils::get_long_help::<Opt4>();
|
||||
|
||||
assert!(output.contains("download history from remote"));
|
||||
assert!(output.contains("Add a file"));
|
||||
assert!(!output.contains("Not shown"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn global_passed_down() {
|
||||
#[derive(Debug, PartialEq, Parser)]
|
||||
struct Opt {
|
||||
#[clap(global = true, long)]
|
||||
other: bool,
|
||||
#[clap(subcommand)]
|
||||
sub: Subcommands,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Subcommand)]
|
||||
enum Subcommands {
|
||||
Add,
|
||||
Global(GlobalCmd),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Args)]
|
||||
struct GlobalCmd {
|
||||
#[clap(from_global)]
|
||||
other: bool,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt::try_parse_from(&["test", "global"]).unwrap(),
|
||||
Opt {
|
||||
other: false,
|
||||
sub: Subcommands::Global(GlobalCmd { other: false })
|
||||
}
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Opt::try_parse_from(&["test", "global", "--other"]).unwrap(),
|
||||
Opt {
|
||||
other: true,
|
||||
sub: Subcommands::Global(GlobalCmd { other: true })
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn external_subcommand() {
|
||||
#[derive(Debug, PartialEq, Parser)]
|
||||
struct Opt {
|
||||
#[clap(subcommand)]
|
||||
sub: Subcommands,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Subcommand)]
|
||||
enum Subcommands {
|
||||
Add,
|
||||
Remove,
|
||||
#[clap(external_subcommand)]
|
||||
Other(Vec<String>),
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt::try_parse_from(&["test", "add"]).unwrap(),
|
||||
Opt {
|
||||
sub: Subcommands::Add
|
||||
}
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Opt::try_parse_from(&["test", "remove"]).unwrap(),
|
||||
Opt {
|
||||
sub: Subcommands::Remove
|
||||
}
|
||||
);
|
||||
|
||||
assert!(Opt::try_parse_from(&["test"]).is_err());
|
||||
|
||||
assert_eq!(
|
||||
Opt::try_parse_from(&["test", "git", "status"]).unwrap(),
|
||||
Opt {
|
||||
sub: Subcommands::Other(vec!["git".into(), "status".into()])
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn external_subcommand_os_string() {
|
||||
use std::ffi::OsString;
|
||||
|
||||
#[derive(Debug, PartialEq, Parser)]
|
||||
struct Opt {
|
||||
#[clap(subcommand)]
|
||||
sub: Subcommands,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Subcommand)]
|
||||
enum Subcommands {
|
||||
#[clap(external_subcommand)]
|
||||
Other(Vec<OsString>),
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt::try_parse_from(&["test", "git", "status"]).unwrap(),
|
||||
Opt {
|
||||
sub: Subcommands::Other(vec!["git".into(), "status".into()])
|
||||
}
|
||||
);
|
||||
|
||||
assert!(Opt::try_parse_from(&["test"]).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn external_subcommand_optional() {
|
||||
#[derive(Debug, PartialEq, Parser)]
|
||||
struct Opt {
|
||||
#[clap(subcommand)]
|
||||
sub: Option<Subcommands>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Subcommand)]
|
||||
enum Subcommands {
|
||||
#[clap(external_subcommand)]
|
||||
Other(Vec<String>),
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt::try_parse_from(&["test", "git", "status"]).unwrap(),
|
||||
Opt {
|
||||
sub: Some(Subcommands::Other(vec!["git".into(), "status".into()]))
|
||||
}
|
||||
);
|
||||
|
||||
assert_eq!(Opt::try_parse_from(&["test"]).unwrap(), Opt { sub: None });
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn enum_in_enum_subsubcommand() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
pub enum Opt {
|
||||
#[clap(alias = "l")]
|
||||
List,
|
||||
#[clap(subcommand, alias = "d")]
|
||||
Daemon(DaemonCommand),
|
||||
}
|
||||
|
||||
#[derive(Subcommand, Debug, PartialEq)]
|
||||
pub enum DaemonCommand {
|
||||
Start,
|
||||
Stop,
|
||||
}
|
||||
|
||||
let result = Opt::try_parse_from(&["test"]);
|
||||
assert!(result.is_err());
|
||||
|
||||
let result = Opt::try_parse_from(&["test", "list"]).unwrap();
|
||||
assert_eq!(Opt::List, result);
|
||||
|
||||
let result = Opt::try_parse_from(&["test", "l"]).unwrap();
|
||||
assert_eq!(Opt::List, result);
|
||||
|
||||
let result = Opt::try_parse_from(&["test", "daemon"]);
|
||||
assert!(result.is_err());
|
||||
|
||||
let result = Opt::try_parse_from(&["test", "daemon", "start"]).unwrap();
|
||||
assert_eq!(Opt::Daemon(DaemonCommand::Start), result);
|
||||
|
||||
let result = Opt::try_parse_from(&["test", "d", "start"]).unwrap();
|
||||
assert_eq!(Opt::Daemon(DaemonCommand::Start), result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_subcommands() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
enum Opt {
|
||||
Command1(Command1),
|
||||
Command2(Command2),
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Command1 {
|
||||
arg1: i32,
|
||||
|
||||
arg2: i32,
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Command2 {
|
||||
arg2: i32,
|
||||
}
|
||||
|
||||
// Full subcommand update
|
||||
let mut opt = Opt::Command1(Command1 { arg1: 12, arg2: 14 });
|
||||
opt.try_update_from(&["test", "command1", "42", "44"])
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
Opt::try_parse_from(&["test", "command1", "42", "44"]).unwrap(),
|
||||
opt
|
||||
);
|
||||
|
||||
// Partial subcommand update
|
||||
let mut opt = Opt::Command1(Command1 { arg1: 12, arg2: 14 });
|
||||
opt.try_update_from(&["test", "command1", "42"]).unwrap();
|
||||
assert_eq!(
|
||||
Opt::try_parse_from(&["test", "command1", "42", "14"]).unwrap(),
|
||||
opt
|
||||
);
|
||||
|
||||
// Change subcommand
|
||||
let mut opt = Opt::Command1(Command1 { arg1: 12, arg2: 14 });
|
||||
opt.try_update_from(&["test", "command2", "43"]).unwrap();
|
||||
assert_eq!(
|
||||
Opt::try_parse_from(&["test", "command2", "43"]).unwrap(),
|
||||
opt
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_sub_subcommands() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
enum Opt {
|
||||
#[clap(subcommand)]
|
||||
Child1(Child1),
|
||||
#[clap(subcommand)]
|
||||
Child2(Child2),
|
||||
}
|
||||
|
||||
#[derive(Subcommand, PartialEq, Debug)]
|
||||
enum Child1 {
|
||||
Command1(Command1),
|
||||
Command2(Command2),
|
||||
}
|
||||
|
||||
#[derive(Subcommand, PartialEq, Debug)]
|
||||
enum Child2 {
|
||||
Command1(Command1),
|
||||
Command2(Command2),
|
||||
}
|
||||
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Command1 {
|
||||
arg1: i32,
|
||||
|
||||
arg2: i32,
|
||||
}
|
||||
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Command2 {
|
||||
arg2: i32,
|
||||
}
|
||||
|
||||
// Full subcommand update
|
||||
let mut opt = Opt::Child1(Child1::Command1(Command1 { arg1: 12, arg2: 14 }));
|
||||
opt.try_update_from(&["test", "child1", "command1", "42", "44"])
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
Opt::try_parse_from(&["test", "child1", "command1", "42", "44"]).unwrap(),
|
||||
opt
|
||||
);
|
||||
|
||||
// Partial subcommand update
|
||||
let mut opt = Opt::Child1(Child1::Command1(Command1 { arg1: 12, arg2: 14 }));
|
||||
opt.try_update_from(&["test", "child1", "command1", "42"])
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
Opt::try_parse_from(&["test", "child1", "command1", "42", "14"]).unwrap(),
|
||||
opt
|
||||
);
|
||||
|
||||
// Partial subcommand update
|
||||
let mut opt = Opt::Child1(Child1::Command1(Command1 { arg1: 12, arg2: 14 }));
|
||||
opt.try_update_from(&["test", "child1", "command2", "43"])
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
Opt::try_parse_from(&["test", "child1", "command2", "43"]).unwrap(),
|
||||
opt
|
||||
);
|
||||
|
||||
// Change subcommand
|
||||
let mut opt = Opt::Child1(Child1::Command1(Command1 { arg1: 12, arg2: 14 }));
|
||||
opt.try_update_from(&["test", "child2", "command2", "43"])
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
Opt::try_parse_from(&["test", "child2", "command2", "43"]).unwrap(),
|
||||
opt
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_ext_subcommand() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
enum Opt {
|
||||
Command1(Command1),
|
||||
Command2(Command2),
|
||||
#[clap(external_subcommand)]
|
||||
Ext(Vec<String>),
|
||||
}
|
||||
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Command1 {
|
||||
arg1: i32,
|
||||
|
||||
arg2: i32,
|
||||
}
|
||||
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Command2 {
|
||||
arg2: i32,
|
||||
}
|
||||
|
||||
// Full subcommand update
|
||||
let mut opt = Opt::Ext(vec!["12".into(), "14".into()]);
|
||||
opt.try_update_from(&["test", "ext", "42", "44"]).unwrap();
|
||||
assert_eq!(
|
||||
Opt::try_parse_from(&["test", "ext", "42", "44"]).unwrap(),
|
||||
opt
|
||||
);
|
||||
|
||||
// No partial subcommand update
|
||||
let mut opt = Opt::Ext(vec!["12".into(), "14".into()]);
|
||||
opt.try_update_from(&["test", "ext", "42"]).unwrap();
|
||||
assert_eq!(Opt::try_parse_from(&["test", "ext", "42"]).unwrap(), opt);
|
||||
|
||||
// Change subcommand
|
||||
let mut opt = Opt::Ext(vec!["12".into(), "14".into()]);
|
||||
opt.try_update_from(&["test", "command2", "43"]).unwrap();
|
||||
assert_eq!(
|
||||
Opt::try_parse_from(&["test", "command2", "43"]).unwrap(),
|
||||
opt
|
||||
);
|
||||
|
||||
let mut opt = Opt::Command1(Command1 { arg1: 12, arg2: 14 });
|
||||
opt.try_update_from(&["test", "ext", "42", "44"]).unwrap();
|
||||
assert_eq!(
|
||||
Opt::try_parse_from(&["test", "ext", "42", "44"]).unwrap(),
|
||||
opt
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn subcommand_name_not_literal() {
|
||||
fn get_name() -> &'static str {
|
||||
"renamed"
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(subcommand)]
|
||||
subcmd: SubCmd,
|
||||
}
|
||||
|
||||
#[derive(Subcommand, PartialEq, Debug)]
|
||||
enum SubCmd {
|
||||
#[clap(name = get_name())]
|
||||
SubCmd1,
|
||||
}
|
||||
|
||||
assert!(Opt::try_parse_from(&["test", "renamed"]).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn skip_subcommand() {
|
||||
#[derive(Debug, PartialEq, Parser)]
|
||||
struct Opt {
|
||||
#[clap(subcommand)]
|
||||
sub: Subcommands,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Subcommand)]
|
||||
enum Subcommands {
|
||||
Add,
|
||||
Remove,
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[clap(skip)]
|
||||
Skip,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt::try_parse_from(&["test", "add"]).unwrap(),
|
||||
Opt {
|
||||
sub: Subcommands::Add
|
||||
}
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Opt::try_parse_from(&["test", "remove"]).unwrap(),
|
||||
Opt {
|
||||
sub: Subcommands::Remove
|
||||
}
|
||||
);
|
||||
|
||||
let res = Opt::try_parse_from(&["test", "skip"]);
|
||||
assert_eq!(res.unwrap_err().kind(), clap::ErrorKind::UnknownArgument,);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
fn built_in_subcommand_escaped() {
|
||||
#[derive(Debug, PartialEq, Parser)]
|
||||
enum Command {
|
||||
Install {
|
||||
arg: Option<String>,
|
||||
},
|
||||
#[clap(external_subcommand)]
|
||||
Custom(Vec<String>),
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Command::try_parse_from(&["test", "install", "arg"]).unwrap(),
|
||||
Command::Install {
|
||||
arg: Some(String::from("arg"))
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
Command::try_parse_from(&["test", "--", "install"]).unwrap(),
|
||||
Command::Custom(vec![String::from("install")])
|
||||
);
|
||||
assert_eq!(
|
||||
Command::try_parse_from(&["test", "--", "install", "arg"]).unwrap(),
|
||||
Command::Custom(vec![String::from("install"), String::from("arg")])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(feature = "unstable-v4"))]
|
||||
fn built_in_subcommand_escaped() {
|
||||
#[derive(Debug, PartialEq, Parser)]
|
||||
enum Command {
|
||||
Install {
|
||||
arg: Option<String>,
|
||||
},
|
||||
#[clap(external_subcommand)]
|
||||
Custom(Vec<String>),
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Command::try_parse_from(&["test", "install", "arg"]).unwrap(),
|
||||
Command::Install {
|
||||
arg: Some(String::from("arg"))
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
Command::try_parse_from(&["test", "--", "install"]).unwrap(),
|
||||
Command::Install { arg: None }
|
||||
);
|
||||
assert_eq!(
|
||||
Command::try_parse_from(&["test", "--", "install", "arg"]).unwrap(),
|
||||
Command::Install { arg: None }
|
||||
);
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
//! Regression test to ensure that type aliases do not cause compilation failures.
|
||||
#![allow(deprecated)]
|
||||
|
||||
use clap::{Parser, Subcommand, ValueEnum};
|
||||
|
||||
// Result type alias
|
||||
#[allow(dead_code)]
|
||||
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
||||
|
||||
type Option<T> = std::option::Option<T>;
|
||||
|
||||
#[derive(Parser)]
|
||||
pub struct Opts {
|
||||
another_string: String,
|
||||
#[clap(subcommand)]
|
||||
command: Command,
|
||||
#[clap(short, long, value_enum)]
|
||||
choice: ArgChoice,
|
||||
}
|
||||
|
||||
#[derive(Subcommand, PartialEq, Debug)]
|
||||
enum Command {
|
||||
DoSomething { arg: Option<String> },
|
||||
}
|
||||
|
||||
#[derive(ValueEnum, PartialEq, Debug, Clone)]
|
||||
enum ArgChoice {
|
||||
Foo,
|
||||
Bar,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn type_alias_regressions() {
|
||||
Opts::try_parse_from(["test", "value", "--choice=foo", "do-something"]).unwrap();
|
||||
}
|
|
@ -1,225 +0,0 @@
|
|||
#![cfg(not(windows))]
|
||||
|
||||
use clap::{ErrorKind, Parser};
|
||||
use std::ffi::OsString;
|
||||
use std::os::unix::ffi::OsStringExt;
|
||||
|
||||
#[derive(Parser, Debug, PartialEq, Eq)]
|
||||
struct Positional {
|
||||
arg: String,
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug, PartialEq, Eq)]
|
||||
struct Named {
|
||||
#[clap(short, long)]
|
||||
arg: String,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_utf8_strict_positional() {
|
||||
let m = Positional::try_parse_from(vec![OsString::from(""), OsString::from_vec(vec![0xe9])]);
|
||||
assert!(m.is_err());
|
||||
assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_utf8_strict_option_short_space() {
|
||||
let m = Named::try_parse_from(vec![
|
||||
OsString::from(""),
|
||||
OsString::from("-a"),
|
||||
OsString::from_vec(vec![0xe9]),
|
||||
]);
|
||||
assert!(m.is_err());
|
||||
assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_utf8_strict_option_short_equals() {
|
||||
let m = Named::try_parse_from(vec![
|
||||
OsString::from(""),
|
||||
OsString::from_vec(vec![0x2d, 0x61, 0x3d, 0xe9]),
|
||||
]);
|
||||
assert!(m.is_err());
|
||||
assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_utf8_strict_option_short_no_space() {
|
||||
let m = Named::try_parse_from(vec![
|
||||
OsString::from(""),
|
||||
OsString::from_vec(vec![0x2d, 0x61, 0xe9]),
|
||||
]);
|
||||
assert!(m.is_err());
|
||||
assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_utf8_strict_option_long_space() {
|
||||
let m = Named::try_parse_from(vec![
|
||||
OsString::from(""),
|
||||
OsString::from("--arg"),
|
||||
OsString::from_vec(vec![0xe9]),
|
||||
]);
|
||||
assert!(m.is_err());
|
||||
assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_utf8_strict_option_long_equals() {
|
||||
let m = Named::try_parse_from(vec![
|
||||
OsString::from(""),
|
||||
OsString::from_vec(vec![0x2d, 0x2d, 0x61, 0x72, 0x67, 0x3d, 0xe9]),
|
||||
]);
|
||||
assert!(m.is_err());
|
||||
assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8);
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug, PartialEq, Eq)]
|
||||
struct PositionalOs {
|
||||
arg: OsString,
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug, PartialEq, Eq)]
|
||||
struct NamedOs {
|
||||
#[clap(short, long)]
|
||||
arg: OsString,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_utf8_positional() {
|
||||
let r = PositionalOs::try_parse_from(vec![OsString::from(""), OsString::from_vec(vec![0xe9])]);
|
||||
assert_eq!(
|
||||
r.unwrap(),
|
||||
PositionalOs {
|
||||
arg: OsString::from_vec(vec![0xe9])
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_utf8_option_short_space() {
|
||||
let r = NamedOs::try_parse_from(vec![
|
||||
OsString::from(""),
|
||||
OsString::from("-a"),
|
||||
OsString::from_vec(vec![0xe9]),
|
||||
]);
|
||||
assert_eq!(
|
||||
r.unwrap(),
|
||||
NamedOs {
|
||||
arg: OsString::from_vec(vec![0xe9])
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_utf8_option_short_equals() {
|
||||
let r = NamedOs::try_parse_from(vec![
|
||||
OsString::from(""),
|
||||
OsString::from_vec(vec![0x2d, 0x61, 0x3d, 0xe9]),
|
||||
]);
|
||||
assert_eq!(
|
||||
r.unwrap(),
|
||||
NamedOs {
|
||||
arg: OsString::from_vec(vec![0xe9])
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_utf8_option_short_no_space() {
|
||||
let r = NamedOs::try_parse_from(vec![
|
||||
OsString::from(""),
|
||||
OsString::from_vec(vec![0x2d, 0x61, 0xe9]),
|
||||
]);
|
||||
assert_eq!(
|
||||
r.unwrap(),
|
||||
NamedOs {
|
||||
arg: OsString::from_vec(vec![0xe9])
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_utf8_option_long_space() {
|
||||
let r = NamedOs::try_parse_from(vec![
|
||||
OsString::from(""),
|
||||
OsString::from("--arg"),
|
||||
OsString::from_vec(vec![0xe9]),
|
||||
]);
|
||||
assert_eq!(
|
||||
r.unwrap(),
|
||||
NamedOs {
|
||||
arg: OsString::from_vec(vec![0xe9])
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_utf8_option_long_equals() {
|
||||
let r = NamedOs::try_parse_from(vec![
|
||||
OsString::from(""),
|
||||
OsString::from_vec(vec![0x2d, 0x2d, 0x61, 0x72, 0x67, 0x3d, 0xe9]),
|
||||
]);
|
||||
assert_eq!(
|
||||
r.unwrap(),
|
||||
NamedOs {
|
||||
arg: OsString::from_vec(vec![0xe9])
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Parser)]
|
||||
enum External {
|
||||
#[clap(external_subcommand)]
|
||||
Other(Vec<String>),
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn refuse_invalid_utf8_subcommand_with_allow_external_subcommands() {
|
||||
let m = External::try_parse_from(vec![
|
||||
OsString::from(""),
|
||||
OsString::from_vec(vec![0xe9]),
|
||||
OsString::from("normal"),
|
||||
]);
|
||||
assert!(m.is_err());
|
||||
assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn refuse_invalid_utf8_subcommand_args_with_allow_external_subcommands() {
|
||||
let m = External::try_parse_from(vec![
|
||||
OsString::from(""),
|
||||
OsString::from("subcommand"),
|
||||
OsString::from("normal"),
|
||||
OsString::from_vec(vec![0xe9]),
|
||||
OsString::from("--another_normal"),
|
||||
]);
|
||||
assert!(m.is_err());
|
||||
assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidUtf8);
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Parser)]
|
||||
enum ExternalOs {
|
||||
#[clap(external_subcommand)]
|
||||
Other(Vec<OsString>),
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn allow_invalid_utf8_subcommand_args_with_allow_external_subcommands() {
|
||||
let m = ExternalOs::try_parse_from(vec![
|
||||
OsString::from(""),
|
||||
OsString::from("subcommand"),
|
||||
OsString::from("normal"),
|
||||
OsString::from_vec(vec![0xe9]),
|
||||
OsString::from("--another_normal"),
|
||||
]);
|
||||
assert_eq!(
|
||||
m.unwrap(),
|
||||
ExternalOs::Other(vec![
|
||||
OsString::from("subcommand"),
|
||||
OsString::from("normal"),
|
||||
OsString::from_vec(vec![0xe9]),
|
||||
OsString::from("--another_normal"),
|
||||
])
|
||||
);
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
// Hi, future me (or whoever you are)!
|
||||
//
|
||||
// Yes, we do need this attr.
|
||||
// No, the warnings cannot be fixed otherwise.
|
||||
// Accept and endure. Do not touch.
|
||||
#![allow(unused)]
|
||||
|
||||
use clap::CommandFactory;
|
||||
|
||||
pub fn get_help<T: CommandFactory>() -> String {
|
||||
let mut output = Vec::new();
|
||||
<T as CommandFactory>::command()
|
||||
.write_help(&mut output)
|
||||
.unwrap();
|
||||
let output = String::from_utf8(output).unwrap();
|
||||
|
||||
eprintln!("\n%%% HELP %%%:=====\n{}\n=====\n", output);
|
||||
eprintln!("\n%%% HELP (DEBUG) %%%:=====\n{:?}\n=====\n", output);
|
||||
|
||||
output
|
||||
}
|
||||
|
||||
pub fn get_long_help<T: CommandFactory>() -> String {
|
||||
let mut output = Vec::new();
|
||||
<T as CommandFactory>::command()
|
||||
.write_long_help(&mut output)
|
||||
.unwrap();
|
||||
let output = String::from_utf8(output).unwrap();
|
||||
|
||||
eprintln!("\n%%% LONG_HELP %%%:=====\n{}\n=====\n", output);
|
||||
eprintln!("\n%%% LONG_HELP (DEBUG) %%%:=====\n{:?}\n=====\n", output);
|
||||
|
||||
output
|
||||
}
|
||||
|
||||
pub fn get_subcommand_long_help<T: CommandFactory>(subcmd: &str) -> String {
|
||||
let mut output = Vec::new();
|
||||
<T as CommandFactory>::command()
|
||||
.get_subcommands_mut()
|
||||
.find(|s| s.get_name() == subcmd)
|
||||
.unwrap()
|
||||
.write_long_help(&mut output)
|
||||
.unwrap();
|
||||
let output = String::from_utf8(output).unwrap();
|
||||
|
||||
eprintln!(
|
||||
"\n%%% SUBCOMMAND `{}` HELP %%%:=====\n{}\n=====\n",
|
||||
subcmd, output
|
||||
);
|
||||
eprintln!(
|
||||
"\n%%% SUBCOMMAND `{}` HELP (DEBUG) %%%:=====\n{:?}\n=====\n",
|
||||
subcmd, output
|
||||
);
|
||||
|
||||
output
|
||||
}
|
|
@ -1,526 +0,0 @@
|
|||
// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
|
||||
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
|
||||
// Ana Hobden (@hoverbear) <operator@hoverbear.org>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
use clap::Parser;
|
||||
|
||||
#[test]
|
||||
fn basic() {
|
||||
#[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
|
||||
enum ArgChoice {
|
||||
Foo,
|
||||
Bar,
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum)]
|
||||
arg: ArgChoice,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: ArgChoice::Foo
|
||||
},
|
||||
Opt::try_parse_from(&["", "foo"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: ArgChoice::Bar
|
||||
},
|
||||
Opt::try_parse_from(&["", "bar"]).unwrap()
|
||||
);
|
||||
assert!(Opt::try_parse_from(&["", "fOo"]).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_value() {
|
||||
#[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
|
||||
enum ArgChoice {
|
||||
Foo,
|
||||
Bar,
|
||||
}
|
||||
|
||||
impl Default for ArgChoice {
|
||||
fn default() -> Self {
|
||||
Self::Bar
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum, default_value_t)]
|
||||
arg: ArgChoice,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: ArgChoice::Foo
|
||||
},
|
||||
Opt::try_parse_from(&["", "foo"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: ArgChoice::Bar
|
||||
},
|
||||
Opt::try_parse_from(&["", "bar"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: ArgChoice::Bar
|
||||
},
|
||||
Opt::try_parse_from(&[""]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multi_word_is_renamed_kebab() {
|
||||
#[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
|
||||
#[allow(non_camel_case_types)]
|
||||
enum ArgChoice {
|
||||
FooBar,
|
||||
BAR_BAZ,
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum)]
|
||||
arg: ArgChoice,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: ArgChoice::FooBar
|
||||
},
|
||||
Opt::try_parse_from(&["", "foo-bar"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: ArgChoice::BAR_BAZ
|
||||
},
|
||||
Opt::try_parse_from(&["", "bar-baz"]).unwrap()
|
||||
);
|
||||
assert!(Opt::try_parse_from(&["", "FooBar"]).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn variant_with_defined_casing() {
|
||||
#[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
|
||||
enum ArgChoice {
|
||||
#[clap(rename_all = "screaming_snake")]
|
||||
FooBar,
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum)]
|
||||
arg: ArgChoice,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: ArgChoice::FooBar
|
||||
},
|
||||
Opt::try_parse_from(&["", "FOO_BAR"]).unwrap()
|
||||
);
|
||||
assert!(Opt::try_parse_from(&["", "FooBar"]).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn casing_is_propagated_from_parent() {
|
||||
#[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
|
||||
#[clap(rename_all = "screaming_snake")]
|
||||
enum ArgChoice {
|
||||
FooBar,
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum)]
|
||||
arg: ArgChoice,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: ArgChoice::FooBar
|
||||
},
|
||||
Opt::try_parse_from(&["", "FOO_BAR"]).unwrap()
|
||||
);
|
||||
assert!(Opt::try_parse_from(&["", "FooBar"]).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn casing_propagation_is_overridden() {
|
||||
#[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
|
||||
#[clap(rename_all = "screaming_snake")]
|
||||
enum ArgChoice {
|
||||
#[clap(rename_all = "camel")]
|
||||
FooBar,
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum)]
|
||||
arg: ArgChoice,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: ArgChoice::FooBar
|
||||
},
|
||||
Opt::try_parse_from(&["", "fooBar"]).unwrap()
|
||||
);
|
||||
assert!(Opt::try_parse_from(&["", "FooBar"]).is_err());
|
||||
assert!(Opt::try_parse_from(&["", "FOO_BAR"]).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ignore_case() {
|
||||
#[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
|
||||
enum ArgChoice {
|
||||
Foo,
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum, ignore_case(true))]
|
||||
arg: ArgChoice,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: ArgChoice::Foo
|
||||
},
|
||||
Opt::try_parse_from(&["", "foo"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: ArgChoice::Foo
|
||||
},
|
||||
Opt::try_parse_from(&["", "fOo"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ignore_case_set_to_false() {
|
||||
#[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
|
||||
enum ArgChoice {
|
||||
Foo,
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum, ignore_case(false))]
|
||||
arg: ArgChoice,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: ArgChoice::Foo
|
||||
},
|
||||
Opt::try_parse_from(&["", "foo"]).unwrap()
|
||||
);
|
||||
assert!(Opt::try_parse_from(&["", "fOo"]).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn alias() {
|
||||
#[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
|
||||
enum ArgChoice {
|
||||
#[clap(alias = "TOTP")]
|
||||
Totp,
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum, ignore_case(false))]
|
||||
arg: ArgChoice,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: ArgChoice::Totp
|
||||
},
|
||||
Opt::try_parse_from(&["", "totp"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: ArgChoice::Totp
|
||||
},
|
||||
Opt::try_parse_from(&["", "TOTP"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_alias() {
|
||||
#[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
|
||||
enum ArgChoice {
|
||||
#[clap(alias = "TOTP", alias = "t")]
|
||||
Totp,
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum, ignore_case(false))]
|
||||
arg: ArgChoice,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: ArgChoice::Totp
|
||||
},
|
||||
Opt::try_parse_from(&["", "totp"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: ArgChoice::Totp
|
||||
},
|
||||
Opt::try_parse_from(&["", "TOTP"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: ArgChoice::Totp
|
||||
},
|
||||
Opt::try_parse_from(&["", "t"]).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn skip_variant() {
|
||||
#[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
|
||||
#[allow(dead_code)] // silence warning about `Baz` being unused
|
||||
enum ArgChoice {
|
||||
Foo,
|
||||
Bar,
|
||||
#[clap(skip)]
|
||||
Baz,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
<ArgChoice as clap::ValueEnum>::value_variants()
|
||||
.iter()
|
||||
.map(clap::ValueEnum::to_possible_value)
|
||||
.map(Option::unwrap)
|
||||
.collect::<Vec<_>>(),
|
||||
vec![
|
||||
clap::PossibleValue::new("foo"),
|
||||
clap::PossibleValue::new("bar")
|
||||
]
|
||||
);
|
||||
|
||||
{
|
||||
use clap::ValueEnum;
|
||||
assert!(ArgChoice::from_str("foo", true).is_ok());
|
||||
assert!(ArgChoice::from_str("bar", true).is_ok());
|
||||
assert!(ArgChoice::from_str("baz", true).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn skip_non_unit_variant() {
|
||||
#[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
|
||||
#[allow(dead_code)] // silence warning about `Baz` being unused
|
||||
enum ArgChoice {
|
||||
Foo,
|
||||
Bar,
|
||||
#[clap(skip)]
|
||||
Baz(usize),
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
<ArgChoice as clap::ValueEnum>::value_variants()
|
||||
.iter()
|
||||
.map(clap::ValueEnum::to_possible_value)
|
||||
.map(Option::unwrap)
|
||||
.collect::<Vec<_>>(),
|
||||
vec![
|
||||
clap::PossibleValue::new("foo"),
|
||||
clap::PossibleValue::new("bar")
|
||||
]
|
||||
);
|
||||
|
||||
{
|
||||
use clap::ValueEnum;
|
||||
assert!(ArgChoice::from_str("foo", true).is_ok());
|
||||
assert!(ArgChoice::from_str("bar", true).is_ok());
|
||||
assert!(ArgChoice::from_str("baz", true).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str_invalid() {
|
||||
#[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
|
||||
enum ArgChoice {
|
||||
Foo,
|
||||
}
|
||||
|
||||
{
|
||||
use clap::ValueEnum;
|
||||
assert!(ArgChoice::from_str("bar", true).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn option_type() {
|
||||
#[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
|
||||
enum ArgChoice {
|
||||
Foo,
|
||||
Bar,
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum)]
|
||||
arg: Option<ArgChoice>,
|
||||
}
|
||||
|
||||
assert_eq!(Opt { arg: None }, Opt::try_parse_from(&[""]).unwrap());
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: Some(ArgChoice::Foo)
|
||||
},
|
||||
Opt::try_parse_from(&["", "foo"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: Some(ArgChoice::Bar)
|
||||
},
|
||||
Opt::try_parse_from(&["", "bar"]).unwrap()
|
||||
);
|
||||
assert!(Opt::try_parse_from(&["", "fOo"]).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn option_option_type() {
|
||||
#[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
|
||||
enum ArgChoice {
|
||||
Foo,
|
||||
Bar,
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum, long)]
|
||||
arg: Option<Option<ArgChoice>>,
|
||||
}
|
||||
|
||||
assert_eq!(Opt { arg: None }, Opt::try_parse_from(&[""]).unwrap());
|
||||
assert_eq!(
|
||||
Opt { arg: Some(None) },
|
||||
Opt::try_parse_from(&["", "--arg"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: Some(Some(ArgChoice::Foo))
|
||||
},
|
||||
Opt::try_parse_from(&["", "--arg", "foo"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: Some(Some(ArgChoice::Bar))
|
||||
},
|
||||
Opt::try_parse_from(&["", "--arg", "bar"]).unwrap()
|
||||
);
|
||||
assert!(Opt::try_parse_from(&["", "--arg", "fOo"]).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vec_type() {
|
||||
#[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
|
||||
enum ArgChoice {
|
||||
Foo,
|
||||
Bar,
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum, short, long)]
|
||||
arg: Vec<ArgChoice>,
|
||||
}
|
||||
|
||||
assert_eq!(Opt { arg: vec![] }, Opt::try_parse_from(&[""]).unwrap());
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: vec![ArgChoice::Foo]
|
||||
},
|
||||
Opt::try_parse_from(&["", "-a", "foo"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: vec![ArgChoice::Foo, ArgChoice::Bar]
|
||||
},
|
||||
Opt::try_parse_from(&["", "-a", "foo", "-a", "bar"]).unwrap()
|
||||
);
|
||||
assert!(Opt::try_parse_from(&["", "-a", "fOo"]).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn option_vec_type() {
|
||||
#[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
|
||||
enum ArgChoice {
|
||||
Foo,
|
||||
Bar,
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum, short, long)]
|
||||
arg: Option<Vec<ArgChoice>>,
|
||||
}
|
||||
|
||||
assert_eq!(Opt { arg: None }, Opt::try_parse_from(&[""]).unwrap());
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: Some(vec![ArgChoice::Foo])
|
||||
},
|
||||
Opt::try_parse_from(&["", "-a", "foo"]).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: Some(vec![ArgChoice::Foo, ArgChoice::Bar])
|
||||
},
|
||||
Opt::try_parse_from(&["", "-a", "foo", "-a", "bar"]).unwrap()
|
||||
);
|
||||
assert!(Opt::try_parse_from(&["", "-a", "fOo"]).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vec_type_default_value() {
|
||||
#[derive(clap::ValueEnum, PartialEq, Debug, Clone)]
|
||||
enum ArgChoice {
|
||||
Foo,
|
||||
Bar,
|
||||
Baz,
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(
|
||||
value_enum,
|
||||
short,
|
||||
long,
|
||||
default_value = "foo,bar",
|
||||
value_delimiter = ','
|
||||
)]
|
||||
arg: Vec<ArgChoice>,
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: vec![ArgChoice::Foo, ArgChoice::Bar]
|
||||
},
|
||||
Opt::try_parse_from(&[""]).unwrap()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: vec![ArgChoice::Foo, ArgChoice::Baz]
|
||||
},
|
||||
Opt::try_parse_from(&["", "-a", "foo,baz"]).unwrap()
|
||||
);
|
||||
}
|
|
@ -27,17 +27,16 @@ struct Opt {
|
|||
next_line_help = true,
|
||||
default_value = "0",
|
||||
require_equals = true,
|
||||
value_parser
|
||||
)]
|
||||
x: i32,
|
||||
|
||||
#[clap(short = 'l', long = "level", value_parser, aliases = &["set-level", "lvl"])]
|
||||
#[clap(short = 'l', long = "level", aliases = &["set-level", "lvl"])]
|
||||
level: String,
|
||||
|
||||
#[clap(long("values"), value_parser)]
|
||||
#[clap(long("values"))]
|
||||
values: Vec<i32>,
|
||||
|
||||
#[clap(name = "FILE", value_parser, requires_if("FILE", "values"))]
|
||||
#[clap(name = "FILE", requires_if("FILE", "values"))]
|
||||
files: Vec<String>,
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ use clap::{Parser, Subcommand};
|
|||
fn required_option() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short, long, value_parser)]
|
||||
#[clap(short, long)]
|
||||
arg: i32,
|
||||
}
|
||||
assert_eq!(
|
||||
|
@ -48,7 +48,7 @@ fn required_option() {
|
|||
fn option_with_default() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short, value_parser, default_value = "42")]
|
||||
#[clap(short, default_value = "42")]
|
||||
arg: i32,
|
||||
}
|
||||
assert_eq!(
|
||||
|
@ -66,7 +66,7 @@ fn option_with_default() {
|
|||
fn option_with_raw_default() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short, value_parser, default_value = "42")]
|
||||
#[clap(short, default_value = "42")]
|
||||
arg: i32,
|
||||
}
|
||||
assert_eq!(
|
||||
|
@ -95,7 +95,6 @@ fn option_from_str() {
|
|||
|
||||
#[derive(Debug, Parser, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(value_parser)]
|
||||
a: Option<A>,
|
||||
}
|
||||
|
||||
|
@ -121,7 +120,6 @@ fn vec_from_str() {
|
|||
|
||||
#[derive(Debug, Parser, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(value_parser)]
|
||||
a: Vec<A>,
|
||||
}
|
||||
|
||||
|
@ -150,7 +148,7 @@ fn option_vec_from_str() {
|
|||
|
||||
#[derive(Debug, Parser, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(short, value_parser)]
|
||||
#[clap(short)]
|
||||
a: Option<Vec<A>>,
|
||||
}
|
||||
|
||||
|
@ -165,7 +163,7 @@ fn option_vec_from_str() {
|
|||
fn option_type_is_optional() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short, value_parser)]
|
||||
#[clap(short)]
|
||||
arg: Option<i32>,
|
||||
}
|
||||
assert_eq!(
|
||||
|
@ -184,7 +182,7 @@ fn required_with_option_type() {
|
|||
#[derive(Debug, PartialEq, Eq, Parser)]
|
||||
#[clap(subcommand_negates_reqs = true)]
|
||||
struct Opt {
|
||||
#[clap(value_parser, required = true)]
|
||||
#[clap(required = true)]
|
||||
req_str: Option<String>,
|
||||
|
||||
#[clap(subcommand)]
|
||||
|
@ -242,7 +240,7 @@ fn ignore_qualified_option_type() {
|
|||
fn option_option_type_is_optional_value() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short, value_parser)]
|
||||
#[clap(short)]
|
||||
#[allow(clippy::option_option)]
|
||||
arg: Option<Option<i32>>,
|
||||
}
|
||||
|
@ -269,7 +267,7 @@ fn option_option_type_is_optional_value() {
|
|||
fn option_option_type_help() {
|
||||
#[derive(Parser, Debug)]
|
||||
struct Opt {
|
||||
#[clap(long, value_name = "val", value_parser)]
|
||||
#[clap(long, value_name = "val")]
|
||||
arg: Option<Option<i32>>,
|
||||
}
|
||||
let help = utils::get_help::<Opt>();
|
||||
|
@ -281,10 +279,10 @@ fn option_option_type_help() {
|
|||
fn two_option_option_types() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short, value_parser)]
|
||||
#[clap(short)]
|
||||
arg: Option<Option<i32>>,
|
||||
|
||||
#[clap(long, value_parser)]
|
||||
#[clap(long)]
|
||||
field: Option<Option<String>>,
|
||||
}
|
||||
assert_eq!(
|
||||
|
@ -335,7 +333,7 @@ fn two_option_option_types() {
|
|||
fn vec_type_is_multiple_occurrences() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short, long, value_parser)]
|
||||
#[clap(short, long)]
|
||||
arg: Vec<i32>,
|
||||
}
|
||||
assert_eq!(
|
||||
|
@ -353,7 +351,7 @@ fn vec_type_is_multiple_occurrences() {
|
|||
fn vec_type_with_required() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short, long, required = true, value_parser)]
|
||||
#[clap(short, long, required = true)]
|
||||
arg: Vec<i32>,
|
||||
}
|
||||
assert_eq!(
|
||||
|
@ -371,7 +369,7 @@ fn vec_type_with_required() {
|
|||
fn vec_type_with_multiple_values_only() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short, long, multiple_values(true), value_parser)]
|
||||
#[clap(short, long, multiple_values(true))]
|
||||
arg: Vec<i32>,
|
||||
}
|
||||
assert_eq!(
|
||||
|
@ -409,7 +407,7 @@ fn ignore_qualified_vec_type() {
|
|||
fn option_vec_type() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short, value_parser)]
|
||||
#[clap(short)]
|
||||
arg: Option<Vec<i32>>,
|
||||
}
|
||||
assert_eq!(
|
||||
|
@ -431,7 +429,7 @@ fn option_vec_type() {
|
|||
fn option_vec_type_structopt_behavior() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short, long, multiple_values(true), min_values(0), value_parser)]
|
||||
#[clap(short, long, multiple_values(true), min_values(0))]
|
||||
arg: Option<Vec<i32>>,
|
||||
}
|
||||
assert_eq!(
|
||||
|
@ -458,10 +456,10 @@ fn option_vec_type_structopt_behavior() {
|
|||
fn two_option_vec_types() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(short, value_parser)]
|
||||
#[clap(short)]
|
||||
arg: Option<Vec<i32>>,
|
||||
|
||||
#[clap(short, value_parser)]
|
||||
#[clap(short)]
|
||||
b: Option<Vec<i32>>,
|
||||
}
|
||||
|
||||
|
@ -512,7 +510,7 @@ fn explicit_value_parser() {
|
|||
fn implicit_value_parser() {
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(long, value_parser)]
|
||||
#[clap(long)]
|
||||
arg: i32,
|
||||
}
|
||||
assert_eq!(
|
||||
|
|
|
@ -30,7 +30,6 @@ mod subcommands {
|
|||
/// foo
|
||||
Foo {
|
||||
/// foo
|
||||
#[clap(value_parser)]
|
||||
bars: String,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -13,9 +13,9 @@ fn raw_bool_literal() {
|
|||
#[derive(Parser, Debug, PartialEq)]
|
||||
#[clap(name = "raw_bool")]
|
||||
struct Opt {
|
||||
#[clap(raw(false), value_parser)]
|
||||
#[clap(raw(false))]
|
||||
a: String,
|
||||
#[clap(raw(true), value_parser)]
|
||||
#[clap(raw(true))]
|
||||
b: String,
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ use clap::Parser;
|
|||
fn raw_idents() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(short, long, value_parser)]
|
||||
#[clap(short, long)]
|
||||
r#type: String,
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ fn it_works() {
|
|||
#[derive(Debug, PartialEq, Parser)]
|
||||
#[clap(rename_all_env = "kebab")]
|
||||
struct BehaviorModel {
|
||||
#[clap(env, value_parser)]
|
||||
#[clap(env)]
|
||||
be_nice: String,
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ fn it_works() {
|
|||
fn default_is_screaming() {
|
||||
#[derive(Debug, PartialEq, Parser)]
|
||||
struct BehaviorModel {
|
||||
#[clap(env, value_parser)]
|
||||
#[clap(env)]
|
||||
be_nice: String,
|
||||
}
|
||||
|
||||
|
@ -34,10 +34,10 @@ fn overridable() {
|
|||
#[derive(Debug, PartialEq, Parser)]
|
||||
#[clap(rename_all_env = "kebab")]
|
||||
struct BehaviorModel {
|
||||
#[clap(env, value_parser)]
|
||||
#[clap(env)]
|
||||
be_nice: String,
|
||||
|
||||
#[clap(rename_all_env = "pascal", env, value_parser)]
|
||||
#[clap(rename_all_env = "pascal", env)]
|
||||
be_aggressive: String,
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ use clap::Parser;
|
|||
fn skip_1() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(short, value_parser)]
|
||||
#[clap(short)]
|
||||
x: u32,
|
||||
#[clap(skip)]
|
||||
s: u32,
|
||||
|
@ -39,17 +39,17 @@ fn skip_1() {
|
|||
fn skip_2() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
struct Opt {
|
||||
#[clap(short, value_parser)]
|
||||
#[clap(short)]
|
||||
x: u32,
|
||||
#[clap(skip)]
|
||||
ss: String,
|
||||
#[clap(skip)]
|
||||
sn: u8,
|
||||
#[clap(value_parser)]
|
||||
|
||||
y: u32,
|
||||
#[clap(skip)]
|
||||
sz: u16,
|
||||
#[clap(value_parser)]
|
||||
|
||||
t: u32,
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ fn skip_enum() {
|
|||
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
pub struct Opt {
|
||||
#[clap(long, short, value_parser)]
|
||||
#[clap(long, short)]
|
||||
number: u32,
|
||||
#[clap(skip)]
|
||||
k: Kind,
|
||||
|
@ -117,7 +117,7 @@ fn skip_help_doc_comments() {
|
|||
#[clap(skip)]
|
||||
c: u32,
|
||||
|
||||
#[clap(short, value_parser)]
|
||||
#[clap(short)]
|
||||
n: u32,
|
||||
}
|
||||
|
||||
|
@ -136,7 +136,7 @@ fn skip_help_doc_comments() {
|
|||
fn skip_val() {
|
||||
#[derive(Parser, Debug, PartialEq)]
|
||||
pub struct Opt {
|
||||
#[clap(long, short, value_parser)]
|
||||
#[clap(long, short)]
|
||||
number: u32,
|
||||
|
||||
#[clap(skip = "key")]
|
||||
|
|
|
@ -20,19 +20,19 @@ use clap::{Args, Parser, Subcommand};
|
|||
enum Opt {
|
||||
/// Fetch stuff from GitHub
|
||||
Fetch {
|
||||
#[clap(long, action)]
|
||||
#[clap(long)]
|
||||
all: bool,
|
||||
/// Overwrite local branches.
|
||||
#[clap(short, long, action)]
|
||||
#[clap(short, long)]
|
||||
force: bool,
|
||||
#[clap(value_parser)]
|
||||
|
||||
repo: String,
|
||||
},
|
||||
|
||||
Add {
|
||||
#[clap(short, long, action)]
|
||||
#[clap(short, long)]
|
||||
interactive: bool,
|
||||
#[clap(short, long, action)]
|
||||
#[clap(short, long)]
|
||||
verbose: bool,
|
||||
},
|
||||
}
|
||||
|
@ -89,10 +89,7 @@ fn test_no_parse() {
|
|||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
enum Opt2 {
|
||||
DoSomething {
|
||||
#[clap(value_parser)]
|
||||
arg: String,
|
||||
},
|
||||
DoSomething { arg: String },
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -127,13 +124,11 @@ fn test_null_commands() {
|
|||
#[derive(Parser, PartialEq, Debug)]
|
||||
#[clap(about = "Not shown")]
|
||||
struct Add {
|
||||
#[clap(value_parser)]
|
||||
file: String,
|
||||
}
|
||||
/// Not shown
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Fetch {
|
||||
#[clap(value_parser)]
|
||||
remote: String,
|
||||
}
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
|
@ -173,7 +168,7 @@ fn test_tuple_commands() {
|
|||
fn global_passed_down() {
|
||||
#[derive(Debug, PartialEq, Parser)]
|
||||
struct Opt {
|
||||
#[clap(global = true, long, action)]
|
||||
#[clap(global = true, long)]
|
||||
other: bool,
|
||||
#[clap(subcommand)]
|
||||
sub: Subcommands,
|
||||
|
@ -187,7 +182,7 @@ fn global_passed_down() {
|
|||
|
||||
#[derive(Debug, PartialEq, Args)]
|
||||
struct GlobalCmd {
|
||||
#[clap(from_global, action)]
|
||||
#[clap(from_global)]
|
||||
other: bool,
|
||||
}
|
||||
|
||||
|
@ -343,15 +338,13 @@ fn update_subcommands() {
|
|||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Command1 {
|
||||
#[clap(value_parser)]
|
||||
arg1: i32,
|
||||
#[clap(value_parser)]
|
||||
|
||||
arg2: i32,
|
||||
}
|
||||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Command2 {
|
||||
#[clap(value_parser)]
|
||||
arg2: i32,
|
||||
}
|
||||
|
||||
|
@ -405,15 +398,13 @@ fn update_sub_subcommands() {
|
|||
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Command1 {
|
||||
#[clap(value_parser)]
|
||||
arg1: i32,
|
||||
#[clap(value_parser)]
|
||||
|
||||
arg2: i32,
|
||||
}
|
||||
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Command2 {
|
||||
#[clap(value_parser)]
|
||||
arg2: i32,
|
||||
}
|
||||
|
||||
|
@ -466,15 +457,13 @@ fn update_ext_subcommand() {
|
|||
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Command1 {
|
||||
#[clap(value_parser)]
|
||||
arg1: i32,
|
||||
#[clap(value_parser)]
|
||||
|
||||
arg2: i32,
|
||||
}
|
||||
|
||||
#[derive(Args, PartialEq, Debug)]
|
||||
struct Command2 {
|
||||
#[clap(value_parser)]
|
||||
arg2: i32,
|
||||
}
|
||||
|
||||
|
@ -564,12 +553,10 @@ fn skip_subcommand() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
fn built_in_subcommand_escaped() {
|
||||
#[derive(Debug, PartialEq, Parser)]
|
||||
enum Command {
|
||||
Install {
|
||||
#[clap(value_parser)]
|
||||
arg: Option<String>,
|
||||
},
|
||||
#[clap(external_subcommand)]
|
||||
|
@ -591,32 +578,3 @@ fn built_in_subcommand_escaped() {
|
|||
Command::Custom(vec![String::from("install"), String::from("arg")])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(feature = "unstable-v4"))]
|
||||
fn built_in_subcommand_escaped() {
|
||||
#[derive(Debug, PartialEq, Parser)]
|
||||
enum Command {
|
||||
Install {
|
||||
#[clap(value_parser)]
|
||||
arg: Option<String>,
|
||||
},
|
||||
#[clap(external_subcommand)]
|
||||
Custom(Vec<String>),
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
Command::try_parse_from(&["test", "install", "arg"]).unwrap(),
|
||||
Command::Install {
|
||||
arg: Some(String::from("arg"))
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
Command::try_parse_from(&["test", "--", "install"]).unwrap(),
|
||||
Command::Install { arg: None }
|
||||
);
|
||||
assert_eq!(
|
||||
Command::try_parse_from(&["test", "--", "install", "arg"]).unwrap(),
|
||||
Command::Install { arg: None }
|
||||
);
|
||||
}
|
||||
|
|
|
@ -11,20 +11,16 @@ type Option<T> = std::option::Option<T>;
|
|||
|
||||
#[derive(Parser)]
|
||||
pub struct Opts {
|
||||
#[clap(value_parser)]
|
||||
another_string: String,
|
||||
#[clap(subcommand)]
|
||||
command: Command,
|
||||
#[clap(short, long, value_enum, value_parser)]
|
||||
#[clap(short, long, value_enum)]
|
||||
choice: ArgChoice,
|
||||
}
|
||||
|
||||
#[derive(Subcommand, PartialEq, Debug)]
|
||||
enum Command {
|
||||
DoSomething {
|
||||
#[clap(value_parser)]
|
||||
arg: Option<String>,
|
||||
},
|
||||
DoSomething { arg: Option<String> },
|
||||
}
|
||||
|
||||
#[derive(ValueEnum, PartialEq, Debug, Clone)]
|
||||
|
|
|
@ -6,13 +6,12 @@ use std::os::unix::ffi::OsStringExt;
|
|||
|
||||
#[derive(Parser, Debug, PartialEq, Eq)]
|
||||
struct Positional {
|
||||
#[clap(value_parser)]
|
||||
arg: String,
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug, PartialEq, Eq)]
|
||||
struct Named {
|
||||
#[clap(short, long, value_parser)]
|
||||
#[clap(short, long)]
|
||||
arg: String,
|
||||
}
|
||||
|
||||
|
@ -77,13 +76,12 @@ fn invalid_utf8_strict_option_long_equals() {
|
|||
|
||||
#[derive(Parser, Debug, PartialEq, Eq)]
|
||||
struct PositionalOs {
|
||||
#[clap(value_parser)]
|
||||
arg: OsString,
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug, PartialEq, Eq)]
|
||||
struct NamedOs {
|
||||
#[clap(short, long, value_parser)]
|
||||
#[clap(short, long)]
|
||||
arg: OsString,
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ fn basic() {
|
|||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum, value_parser)]
|
||||
#[clap(value_enum)]
|
||||
arg: ArgChoice,
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ fn default_value() {
|
|||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum, value_parser, default_value_t)]
|
||||
#[clap(value_enum, default_value_t)]
|
||||
arg: ArgChoice,
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,7 @@ fn multi_word_is_renamed_kebab() {
|
|||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum, value_parser)]
|
||||
#[clap(value_enum)]
|
||||
arg: ArgChoice,
|
||||
}
|
||||
|
||||
|
@ -118,7 +118,7 @@ fn variant_with_defined_casing() {
|
|||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum, value_parser)]
|
||||
#[clap(value_enum)]
|
||||
arg: ArgChoice,
|
||||
}
|
||||
|
||||
|
@ -141,7 +141,7 @@ fn casing_is_propagated_from_parent() {
|
|||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum, value_parser)]
|
||||
#[clap(value_enum)]
|
||||
arg: ArgChoice,
|
||||
}
|
||||
|
||||
|
@ -165,7 +165,7 @@ fn casing_propagation_is_overridden() {
|
|||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum, value_parser)]
|
||||
#[clap(value_enum)]
|
||||
arg: ArgChoice,
|
||||
}
|
||||
|
||||
|
@ -188,7 +188,7 @@ fn ignore_case() {
|
|||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum, value_parser, ignore_case(true))]
|
||||
#[clap(value_enum, ignore_case(true))]
|
||||
arg: ArgChoice,
|
||||
}
|
||||
|
||||
|
@ -215,7 +215,7 @@ fn ignore_case_set_to_false() {
|
|||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum, ignore_case(false), value_parser)]
|
||||
#[clap(value_enum, ignore_case(false))]
|
||||
arg: ArgChoice,
|
||||
}
|
||||
|
||||
|
@ -238,7 +238,7 @@ fn alias() {
|
|||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum, ignore_case(false), value_parser)]
|
||||
#[clap(value_enum, ignore_case(false))]
|
||||
arg: ArgChoice,
|
||||
}
|
||||
|
||||
|
@ -266,7 +266,7 @@ fn multiple_alias() {
|
|||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum, ignore_case(false), value_parser)]
|
||||
#[clap(value_enum, ignore_case(false))]
|
||||
arg: ArgChoice,
|
||||
}
|
||||
|
||||
|
@ -375,7 +375,7 @@ fn option_type() {
|
|||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum, value_parser)]
|
||||
#[clap(value_enum)]
|
||||
arg: Option<ArgChoice>,
|
||||
}
|
||||
|
||||
|
@ -405,7 +405,7 @@ fn option_option_type() {
|
|||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum, long, value_parser)]
|
||||
#[clap(value_enum, long)]
|
||||
arg: Option<Option<ArgChoice>>,
|
||||
}
|
||||
|
||||
|
@ -439,7 +439,7 @@ fn vec_type() {
|
|||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum, short, long, value_parser)]
|
||||
#[clap(value_enum, short, long)]
|
||||
arg: Vec<ArgChoice>,
|
||||
}
|
||||
|
||||
|
@ -469,7 +469,7 @@ fn option_vec_type() {
|
|||
|
||||
#[derive(Parser, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(value_enum, short, long, value_parser)]
|
||||
#[clap(value_enum, short, long)]
|
||||
arg: Option<Vec<ArgChoice>>,
|
||||
}
|
||||
|
||||
|
@ -505,8 +505,7 @@ fn vec_type_default_value() {
|
|||
short,
|
||||
long,
|
||||
default_value = "foo,bar",
|
||||
value_delimiter = ',',
|
||||
value_parser
|
||||
value_delimiter = ','
|
||||
)]
|
||||
arg: Vec<ArgChoice>,
|
||||
}
|
||||
|
|
|
@ -11,8 +11,4 @@
|
|||
fn ui() {
|
||||
let t = trybuild::TestCases::new();
|
||||
t.compile_fail("tests/derive_ui/*.rs");
|
||||
#[cfg(feature = "unstable-v4")]
|
||||
t.compile_fail("tests/derive_ui/next/*.rs");
|
||||
#[cfg(not(feature = "unstable-v4"))]
|
||||
t.compile_fail("tests/derive_ui/stable/*.rs");
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0277]: the trait bound `bool: ValueEnum` is not satisfied
|
||||
--> tests/derive_ui/next/bool_value_enum.rs:6:31
|
||||
--> tests/derive_ui/bool_value_enum.rs:6:31
|
||||
|
|
||||
6 | #[clap(short, value_enum, default_value_t)]
|
||||
| ^^^^^^^^^^^^^^^ the trait `ValueEnum` is not implemented for `bool`
|
|
@ -1,5 +1,5 @@
|
|||
error[E0599]: no method named `non_existing_attribute` found for struct `Arg` in the current scope
|
||||
--> tests/derive_ui/next/non_existent_attr.rs:14:19
|
||||
--> tests/derive_ui/non_existent_attr.rs:14:19
|
||||
|
|
||||
14 | #[clap(short, non_existing_attribute = 1)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ method not found in `Arg<'_>`
|
|
@ -1,13 +0,0 @@
|
|||
use clap::Parser;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(name = "basic")]
|
||||
struct Opt {
|
||||
#[clap(short, value_enum)]
|
||||
opts: bool,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let opt = Opt::parse();
|
||||
println!("{:?}", opt);
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
error[E0277]: the trait bound `bool: ValueEnum` is not satisfied
|
||||
--> tests/derive_ui/stable/bool_value_enum.rs:7:11
|
||||
|
|
||||
7 | opts: bool,
|
||||
| ^^^^ the trait `ValueEnum` is not implemented for `bool`
|
||||
|
|
||||
note: required by `clap::ValueEnum::from_str`
|
||||
--> src/derive.rs
|
||||
|
|
||||
| fn from_str(input: &str, ignore_case: bool) -> Result<Self, String> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0618]: expected function, found enum variant `bool`
|
||||
--> tests/derive_ui/stable/bool_value_enum.rs:7:11
|
||||
|
|
||||
7 | opts: bool,
|
||||
| ^^^^ call expression requires function
|
||||
|
|
||||
help: `bool` is a unit variant, you need to write it without the parenthesis
|
||||
|
|
||||
7 | opts: bool,
|
||||
| ~~~~
|
||||
|
||||
error[E0599]: no method named `possible_values` found for struct `Arg` in the current scope
|
||||
--> tests/derive_ui/stable/bool_value_enum.rs:7:11
|
||||
|
|
||||
7 | opts: bool,
|
||||
| ^^^^ help: there is an associated function with a similar name: `hide_possible_values`
|
||||
|
||||
error[E0277]: the trait bound `bool: ValueEnum` is not satisfied
|
||||
--> tests/derive_ui/stable/bool_value_enum.rs:7:11
|
||||
|
|
||||
7 | opts: bool,
|
||||
| ^^^^ the trait `ValueEnum` is not implemented for `bool`
|
||||
|
|
||||
note: required by `value_variants`
|
||||
--> src/derive.rs
|
||||
|
|
||||
| fn value_variants<'a>() -> &'a [Self];
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
@ -1,21 +0,0 @@
|
|||
// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(name = "basic")]
|
||||
struct Opt {
|
||||
#[clap(short, non_existing_attribute = 1)]
|
||||
debug: bool,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let opt = Opt::parse();
|
||||
println!("{:?}", opt);
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
error[E0599]: no method named `non_existing_attribute` found for struct `Arg` in the current scope
|
||||
--> tests/derive_ui/stable/non_existent_attr.rs:14:19
|
||||
|
|
||||
14 | #[clap(short, non_existing_attribute = 1)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ method not found in `Arg<'_>`
|
|
@ -1,18 +0,0 @@
|
|||
// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(name = "basic")]
|
||||
struct Opt(u32);
|
||||
|
||||
fn main() {
|
||||
let opt = Opt::parse();
|
||||
println!("{:?}", opt);
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
error: `#[derive(Parser)]` only supports non-tuple structs and enums
|
||||
--> tests/derive_ui/stable/tuple_struct.rs:11:10
|
||||
|
|
||||
11 | #[derive(Parser, Debug)]
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: this error originates in the derive macro `Parser` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0599]: no function or associated item named `parse` found for struct `Opt` in the current scope
|
||||
--> tests/derive_ui/stable/tuple_struct.rs:16:20
|
||||
|
|
||||
13 | struct Opt(u32);
|
||||
| ---------------- function or associated item `parse` not found for this
|
||||
...
|
||||
16 | let opt = Opt::parse();
|
||||
| ^^^^^ function or associated item not found in `Opt`
|
||||
|
|
||||
= help: items from traits can only be used if the trait is implemented and in scope
|
||||
= note: the following traits define an item `parse`, perhaps you need to implement one of them:
|
||||
candidate #1: `Parser`
|
||||
candidate #2: `TypedValueParser`
|
|
@ -1,5 +1,5 @@
|
|||
error: `#[derive(Parser)]` only supports non-tuple structs and enums
|
||||
--> tests/derive_ui/next/tuple_struct.rs:11:10
|
||||
--> tests/derive_ui/tuple_struct.rs:11:10
|
||||
|
|
||||
11 | #[derive(Parser, Debug)]
|
||||
| ^^^^^^
|
||||
|
@ -7,7 +7,7 @@ error: `#[derive(Parser)]` only supports non-tuple structs and enums
|
|||
= note: this error originates in the derive macro `Parser` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0599]: no function or associated item named `parse` found for struct `Opt` in the current scope
|
||||
--> tests/derive_ui/next/tuple_struct.rs:16:20
|
||||
--> tests/derive_ui/tuple_struct.rs:16:20
|
||||
|
|
||||
13 | struct Opt(u32);
|
||||
| ---------------- function or associated item `parse` not found for this
|
Loading…
Reference in a new issue