From 9bccded7ed879e8dbbcd0f31ed0add9fdb008c6c Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 23 Sep 2022 15:18:14 -0500 Subject: [PATCH] fix(parser): Conflict-with-self is back on by default See #4261 for more details --- CHANGELOG.md | 3 + examples/tutorial_builder/03_01_flag_bool.md | 7 ++- examples/tutorial_derive/03_01_flag_bool.md | 7 ++- src/builder/action.rs | 16 +++++- src/builder/app_settings.rs | 4 ++ src/builder/command.rs | 22 +++++++ src/builder/value_parser.rs | 2 +- src/parser/arg_matcher.rs | 4 +- src/parser/matches/arg_matches.rs | 2 +- src/parser/parser.rs | 27 ++++++++- tests/builder/action.rs | 15 +++++ tests/builder/app_settings.rs | 60 ++------------------ tests/builder/flags.rs | 2 + tests/builder/grouped_values.rs | 1 + tests/builder/indices.rs | 11 ++++ tests/builder/multiple_occurrences.rs | 2 + tests/builder/multiple_values.rs | 2 +- tests/derive/flags.rs | 1 + tests/derive/options.rs | 21 +++++++ 19 files changed, 142 insertions(+), 67 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4a810e28fc..1388fec61d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -183,6 +183,9 @@ Subtle changes (i.e. compiler won't catch): - `ArgAction::Count`, requiring `ArgMatches::get_count` instead of `ArgMatches::occurrences_of` - `ArgAction::Set`, requiring `ArgMatches::get_one` instead of `ArgMatches::value_of` - `ArgAction::Append`, requiring `ArgMatches::get_many` instead of `ArgMatches::values_of` +- `ArgAction::Set`, `ArgAction::SetTrue`, and `Arg::Action::SetFalse` now + conflict by default to be like `ArgAction::StoreValue` and + `ArgAction::IncOccurrences`, requiring `cmd.args_override_self(true)` to override instead (#4261) - By default, an `Arg`s default action is `ArgAction::Set`, rather than `ArgAction::IncOccurrence` to reduce confusing magic through consistency (#2687, #4032, see also #3977) - `mut_arg` can no longer be used to customize help and version arguments, instead disable them (`Command::disable_help_flag`, `Command::disable_version_flag`) and provide your own (#4056) - Removed lifetimes from `Command`, `Arg`, `ArgGroup`, and `PossibleValue`, assuming `'static`. `string` feature flag will enable support for `String`s (#1041, #2150, #4223) diff --git a/examples/tutorial_builder/03_01_flag_bool.md b/examples/tutorial_builder/03_01_flag_bool.md index c151af440a6..0842935f3f2 100644 --- a/examples/tutorial_builder/03_01_flag_bool.md +++ b/examples/tutorial_builder/03_01_flag_bool.md @@ -16,6 +16,11 @@ $ 03_01_flag_bool --verbose verbose: true $ 03_01_flag_bool --verbose --verbose -verbose: true +? failed +error: The argument '--verbose' cannot be used with '--verbose' + +Usage: 03_01_flag_bool[EXE] [OPTIONS] + +For more information try '--help' ``` diff --git a/examples/tutorial_derive/03_01_flag_bool.md b/examples/tutorial_derive/03_01_flag_bool.md index b5bfe58d811..77975698e35 100644 --- a/examples/tutorial_derive/03_01_flag_bool.md +++ b/examples/tutorial_derive/03_01_flag_bool.md @@ -16,6 +16,11 @@ $ 03_01_flag_bool_derive --verbose verbose: true $ 03_01_flag_bool_derive --verbose --verbose -verbose: true +? failed +error: The argument '--verbose' cannot be used with '--verbose' + +Usage: 03_01_flag_bool_derive[EXE] [OPTIONS] + +For more information try '--help' ``` diff --git a/src/builder/action.rs b/src/builder/action.rs index 7cd3e017908..dc7b79a7437 100644 --- a/src/builder/action.rs +++ b/src/builder/action.rs @@ -27,6 +27,10 @@ pub enum ArgAction { /// When encountered, store the associated value(s) in [`ArgMatches`][crate::ArgMatches] /// + /// **NOTE:** If the argument has previously been seen, it will result in a + /// [`ArgumentConflict`][crate::error::ErrorKind::ArgumentConflict] unless + /// [`Command::args_override_self(true)`][crate::Command::args_override_self] is set. + /// /// # Examples /// /// ```rust @@ -76,6 +80,10 @@ pub enum ArgAction { /// No value is allowed. To optionally accept a value, see /// [`Arg::default_missing_value`][super::Arg::default_missing_value] /// + /// **NOTE:** If the argument has previously been seen, it will result in a + /// [`ArgumentConflict`][crate::error::ErrorKind::ArgumentConflict] unless + /// [`Command::args_override_self(true)`][crate::Command::args_override_self] is set. + /// /// # Examples /// /// ```rust @@ -88,7 +96,7 @@ pub enum ArgAction { /// .action(clap::ArgAction::SetTrue) /// ); /// - /// let matches = cmd.clone().try_get_matches_from(["mycmd", "--flag", "--flag"]).unwrap(); + /// let matches = cmd.clone().try_get_matches_from(["mycmd", "--flag"]).unwrap(); /// assert!(matches.contains_id("flag")); /// assert_eq!( /// matches.get_one::("flag").copied(), @@ -123,7 +131,7 @@ pub enum ArgAction { /// ) /// ); /// - /// let matches = cmd.clone().try_get_matches_from(["mycmd", "--flag", "--flag"]).unwrap(); + /// let matches = cmd.clone().try_get_matches_from(["mycmd", "--flag"]).unwrap(); /// assert!(matches.contains_id("flag")); /// assert_eq!( /// matches.get_one::("flag").copied(), @@ -145,6 +153,10 @@ pub enum ArgAction { /// No value is allowed. To optionally accept a value, see /// [`Arg::default_missing_value`][super::Arg::default_missing_value] /// + /// **NOTE:** If the argument has previously been seen, it will result in a + /// [`ArgumentConflict`][crate::error::ErrorKind::ArgumentConflict] unless + /// [`Command::args_override_self(true)`][crate::Command::args_override_self] is set. + /// /// # Examples /// /// ```rust diff --git a/src/builder/app_settings.rs b/src/builder/app_settings.rs index 8fcad37e7e9..7a9ff8c69c5 100644 --- a/src/builder/app_settings.rs +++ b/src/builder/app_settings.rs @@ -31,6 +31,7 @@ pub(crate) enum AppSettings { IgnoreErrors, AllowHyphenValues, AllowNegativeNumbers, + AllArgsOverrideSelf, AllowMissingPositional, TrailingVarArg, DontDelimitTrailingValues, @@ -93,6 +94,7 @@ bitflags! { const VALID_ARG_FOUND = 1 << 35; const INFER_SUBCOMMANDS = 1 << 36; const CONTAINS_LAST = 1 << 37; + const ARGS_OVERRIDE_SELF = 1 << 38; const HELP_REQUIRED = 1 << 39; const SUBCOMMAND_PRECEDENCE_OVER_ARG = 1 << 40; const DISABLE_HELP_FLAG = 1 << 41; @@ -163,6 +165,8 @@ impl_settings! { AppSettings, AppFlags, => Flags::BIN_NAME_BUILT, InferSubcommands => Flags::INFER_SUBCOMMANDS, + AllArgsOverrideSelf + => Flags::ARGS_OVERRIDE_SELF, InferLongArgs => Flags::INFER_LONG_ARGS } diff --git a/src/builder/command.rs b/src/builder/command.rs index c0c115abec9..d685295fb5e 100644 --- a/src/builder/command.rs +++ b/src/builder/command.rs @@ -978,6 +978,23 @@ impl Command { } } + /// Specifies that all arguments override themselves. + /// + /// This is the equivalent to saying the `foo` arg using [`Arg::overrides_with("foo")`] for all + /// defined arguments. + /// + /// **NOTE:** This choice is propagated to all child subcommands. + /// + /// [`Arg::overrides_with("foo")`]: crate::Arg::overrides_with() + #[inline] + pub fn args_override_self(self, yes: bool) -> Self { + if yes { + self.global_setting(AppSettings::AllArgsOverrideSelf) + } else { + self.unset_global_setting(AppSettings::AllArgsOverrideSelf) + } + } + /// Disables the automatic delimiting of values after `--` or when [`Command::trailing_var_arg`] /// was used. /// @@ -3671,6 +3688,11 @@ impl Command { self.is_set(AppSettings::ArgsNegateSubcommands) } + #[doc(hidden)] + pub fn is_args_override_self(&self) -> bool { + self.is_set(AppSettings::AllArgsOverrideSelf) + } + /// Report whether [`Command::subcommand_precedence_over_arg`] is set pub fn is_subcommand_precedence_over_arg_set(&self) -> bool { self.is_set(AppSettings::SubcommandPrecedenceOverArg) diff --git a/src/builder/value_parser.rs b/src/builder/value_parser.rs index 8a5ae1beff6..7dcd07e132a 100644 --- a/src/builder/value_parser.rs +++ b/src/builder/value_parser.rs @@ -657,7 +657,7 @@ pub trait TypedValueParser: Clone + Send + Sync + 'static { /// ) /// ); /// - /// let matches = cmd.clone().try_get_matches_from(["mycmd", "--flag", "--flag"]).unwrap(); + /// let matches = cmd.clone().try_get_matches_from(["mycmd", "--flag"]).unwrap(); /// assert!(matches.contains_id("flag")); /// assert_eq!( /// matches.get_one::("flag").copied(), diff --git a/src/parser/arg_matcher.rs b/src/parser/arg_matcher.rs index 071e3b272db..3eac897fc0f 100644 --- a/src/parser/arg_matcher.rs +++ b/src/parser/arg_matcher.rs @@ -101,8 +101,8 @@ impl ArgMatcher { self.matches.args.get_mut(arg) } - pub(crate) fn remove(&mut self, arg: &Id) { - self.matches.args.remove(arg); + pub(crate) fn remove(&mut self, arg: &Id) -> bool { + self.matches.args.remove(arg).is_some() } pub(crate) fn contains(&self, arg: &Id) -> bool { diff --git a/src/parser/matches/arg_matches.rs b/src/parser/matches/arg_matches.rs index e743ca876cd..bcebb1fe003 100644 --- a/src/parser/matches/arg_matches.rs +++ b/src/parser/matches/arg_matches.rs @@ -162,7 +162,7 @@ impl ArgMatches { /// .action(clap::ArgAction::SetTrue) /// ); /// - /// let matches = cmd.clone().try_get_matches_from(["mycmd", "--flag", "--flag"]).unwrap(); + /// let matches = cmd.clone().try_get_matches_from(["mycmd", "--flag"]).unwrap(); /// assert!(matches.contains_id("flag")); /// assert_eq!( /// matches.get_flag("flag"), diff --git a/src/parser/parser.rs b/src/parser/parser.rs index 1db8495eff6..c493630f9f1 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -1179,7 +1179,14 @@ impl<'cmd> Parser<'cmd> { self.cur_idx.set(self.cur_idx.get() + 1); debug!("Parser::react: cur_idx:={}", self.cur_idx.get()); } - matcher.remove(&arg.id); + if matcher.remove(&arg.id) && !self.cmd.is_args_override_self() { + return Err(ClapError::argument_conflict( + self.cmd, + arg.to_string(), + vec![arg.to_string()], + Usage::new(self.cmd).create_usage_with_title(&[]), + )); + } self.start_custom_arg(matcher, arg, source); self.push_arg_values(arg, raw_vals, matcher)?; if cfg!(debug_assertions) && matcher.needs_more_vals(arg) { @@ -1213,7 +1220,14 @@ impl<'cmd> Parser<'cmd> { raw_vals }; - matcher.remove(&arg.id); + if matcher.remove(&arg.id) && !self.cmd.is_args_override_self() { + return Err(ClapError::argument_conflict( + self.cmd, + arg.to_string(), + vec![arg.to_string()], + Usage::new(self.cmd).create_usage_with_title(&[]), + )); + } self.start_custom_arg(matcher, arg, source); self.push_arg_values(arg, raw_vals, matcher)?; Ok(ParseResult::ValuesDone) @@ -1225,7 +1239,14 @@ impl<'cmd> Parser<'cmd> { raw_vals }; - matcher.remove(&arg.id); + if matcher.remove(&arg.id) && self.cmd.is_args_override_self() { + return Err(ClapError::argument_conflict( + self.cmd, + arg.to_string(), + vec![arg.to_string()], + Usage::new(self.cmd).create_usage_with_title(&[]), + )); + } self.start_custom_arg(matcher, arg, source); self.push_arg_values(arg, raw_vals, matcher)?; Ok(ParseResult::ValuesDone) diff --git a/tests/builder/action.rs b/tests/builder/action.rs index 6f4bcda2bf2..d9b24873b85 100644 --- a/tests/builder/action.rs +++ b/tests/builder/action.rs @@ -1,6 +1,7 @@ #![allow(clippy::bool_assert_comparison)] use clap::builder::ArgPredicate; +use clap::error::ErrorKind; use clap::Arg; use clap::ArgAction; use clap::Command; @@ -22,8 +23,15 @@ fn set() { assert_eq!(matches.contains_id("mammal"), true); assert_eq!(matches.index_of("mammal"), Some(2)); + let result = cmd + .clone() + .try_get_matches_from(["test", "--mammal", "dog", "--mammal", "cat"]); + let err = result.err().unwrap(); + assert_eq!(err.kind(), ErrorKind::ArgumentConflict); + let matches = cmd .clone() + .args_override_self(true) .try_get_matches_from(["test", "--mammal", "dog", "--mammal", "cat"]) .unwrap(); assert_eq!(matches.get_one::("mammal").unwrap(), "cat"); @@ -88,8 +96,15 @@ fn set_true() { assert_eq!(matches.contains_id("mammal"), true); assert_eq!(matches.index_of("mammal"), Some(1)); + let result = cmd + .clone() + .try_get_matches_from(["test", "--mammal", "--mammal"]); + let err = result.err().unwrap(); + assert_eq!(err.kind(), ErrorKind::ArgumentConflict); + let matches = cmd .clone() + .args_override_self(true) .try_get_matches_from(["test", "--mammal", "--mammal"]) .unwrap(); assert_eq!(*matches.get_one::("mammal").unwrap(), true); diff --git a/tests/builder/app_settings.rs b/tests/builder/app_settings.rs index 723e15d6b07..c9c8cf5a525 100644 --- a/tests/builder/app_settings.rs +++ b/tests/builder/app_settings.rs @@ -986,65 +986,11 @@ fn built_in_subcommand_escaped() { } } -#[test] -fn aaos_flags() { - // flags - let cmd = Command::new("posix").arg(arg!(--flag "some flag").action(ArgAction::SetTrue)); - - let res = cmd.clone().try_get_matches_from(vec!["", "--flag"]); - assert!(res.is_ok(), "{}", res.unwrap_err()); - let m = res.unwrap(); - assert!(m.contains_id("flag")); - assert!(*m.get_one::("flag").expect("defaulted by clap")); - - let res = cmd.try_get_matches_from(vec!["", "--flag", "--flag", "--flag", "--flag"]); - assert!(res.is_ok(), "{}", res.unwrap_err()); - let m = res.unwrap(); - assert!(m.contains_id("flag")); - assert!(*m.get_one::("flag").expect("defaulted by clap")); -} - -#[test] -fn aaos_flags_mult() { - // flags with multiple - let cmd = Command::new("posix").arg(arg!(--flag "some flag").action(ArgAction::Count)); - - let res = cmd.clone().try_get_matches_from(vec!["", "--flag"]); - assert!(res.is_ok(), "{}", res.unwrap_err()); - let m = res.unwrap(); - assert!(m.contains_id("flag")); - assert_eq!(*m.get_one::("flag").expect("defaulted by clap"), 1); - - let res = cmd.try_get_matches_from(vec!["", "--flag", "--flag", "--flag", "--flag"]); - assert!(res.is_ok(), "{}", res.unwrap_err()); - let m = res.unwrap(); - assert!(m.contains_id("flag")); - assert_eq!(*m.get_one::("flag").expect("defaulted by clap"), 4); -} - -#[test] -fn aaos_opts() { - // opts - let res = Command::new("posix") - .arg( - arg!(--opt "some option") - .required(true) - .action(ArgAction::Set), - ) - .try_get_matches_from(vec!["", "--opt=some", "--opt=other"]); - assert!(res.is_ok(), "{}", res.unwrap_err()); - let m = res.unwrap(); - assert!(m.contains_id("opt")); - assert_eq!( - m.get_one::("opt").map(|v| v.as_str()), - Some("other") - ); -} - #[test] fn aaos_opts_w_other_overrides() { // opts with other overrides let res = Command::new("posix") + .args_override_self(true) .arg(arg!(--opt "some option").action(ArgAction::Set)) .arg( arg!(--other "some other option") @@ -1066,6 +1012,7 @@ fn aaos_opts_w_other_overrides() { fn aaos_opts_w_other_overrides_rev() { // opts with other overrides, rev let res = Command::new("posix") + .args_override_self(true) .arg( arg!(--opt "some option") .required(true) @@ -1092,6 +1039,7 @@ fn aaos_opts_w_other_overrides_rev() { fn aaos_opts_w_other_overrides_2() { // opts with other overrides let res = Command::new("posix") + .args_override_self(true) .arg( arg!(--opt "some option") .overrides_with("other") @@ -1113,6 +1061,7 @@ fn aaos_opts_w_other_overrides_2() { fn aaos_opts_w_other_overrides_rev_2() { // opts with other overrides, rev let res = Command::new("posix") + .args_override_self(true) .arg( arg!(--opt "some option") .required(true) @@ -1259,6 +1208,7 @@ fn aaos_pos_mult() { #[test] fn aaos_option_use_delim_false() { let m = Command::new("posix") + .args_override_self(true) .arg( arg!(--opt "some option") .required(true) diff --git a/tests/builder/flags.rs b/tests/builder/flags.rs index 0f4d316f557..e86adcdfc7b 100644 --- a/tests/builder/flags.rs +++ b/tests/builder/flags.rs @@ -19,6 +19,7 @@ fn flag_using_short() { #[test] fn lots_o_flags_sep() { let r = Command::new("opts") + .args_override_self(true) .arg(arg!(o: -o ... "some flag").action(ArgAction::SetTrue)) .try_get_matches_from(vec![ "", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", "-o", @@ -53,6 +54,7 @@ fn lots_o_flags_sep() { #[test] fn lots_o_flags_combined() { let r = Command::new("opts") + .args_override_self(true) .arg(arg!(o: -o ... "some flag").action(ArgAction::SetTrue)) .try_get_matches_from(vec![ "", diff --git a/tests/builder/grouped_values.rs b/tests/builder/grouped_values.rs index a5336130be5..67df706ef54 100644 --- a/tests/builder/grouped_values.rs +++ b/tests/builder/grouped_values.rs @@ -223,6 +223,7 @@ fn grouped_interleaved_positional_occurrences() { #[test] fn issue_2171() { let schema = Command::new("ripgrep#1701 reproducer") + .args_override_self(true) .arg( Arg::new("pretty") .short('p') diff --git a/tests/builder/indices.rs b/tests/builder/indices.rs index 5f6d40deb79..dfe7d665184 100644 --- a/tests/builder/indices.rs +++ b/tests/builder/indices.rs @@ -3,6 +3,7 @@ use clap::{Arg, ArgAction, Command}; #[test] fn indices_mult_opts() { let m = Command::new("ind") + .args_override_self(true) .arg( Arg::new("exclude") .short('e') @@ -32,6 +33,7 @@ fn indices_mult_opts() { #[test] fn index_mult_opts() { let m = Command::new("ind") + .args_override_self(true) .arg( Arg::new("exclude") .short('e') @@ -55,6 +57,7 @@ fn index_mult_opts() { #[test] fn index_flag() { let m = Command::new("ind") + .args_override_self(true) .arg(Arg::new("exclude").short('e').action(ArgAction::SetTrue)) .arg(Arg::new("include").short('i').action(ArgAction::SetTrue)) .try_get_matches_from(vec!["ind", "-e", "-i"]) @@ -67,6 +70,7 @@ fn index_flag() { #[test] fn index_flags() { let m = Command::new("ind") + .args_override_self(true) .arg(Arg::new("exclude").short('e').action(ArgAction::SetTrue)) .arg(Arg::new("include").short('i').action(ArgAction::SetTrue)) .try_get_matches_from(vec!["ind", "-e", "-i", "-e", "-e", "-i"]) @@ -79,6 +83,7 @@ fn index_flags() { #[test] fn indices_mult_flags() { let m = Command::new("ind") + .args_override_self(true) .arg(Arg::new("exclude").short('e').action(ArgAction::SetTrue)) .arg(Arg::new("include").short('i').action(ArgAction::SetTrue)) .try_get_matches_from(vec!["ind", "-e", "-i", "-e", "-e", "-i"]) @@ -91,6 +96,7 @@ fn indices_mult_flags() { #[test] fn indices_mult_flags_combined() { let m = Command::new("ind") + .args_override_self(true) .arg(Arg::new("exclude").short('e').action(ArgAction::SetTrue)) .arg(Arg::new("include").short('i').action(ArgAction::SetTrue)) .try_get_matches_from(vec!["ind", "-eieei"]) @@ -103,6 +109,7 @@ fn indices_mult_flags_combined() { #[test] fn indices_mult_flags_opt_combined() { let m = Command::new("ind") + .args_override_self(true) .arg(Arg::new("exclude").short('e').action(ArgAction::SetTrue)) .arg(Arg::new("include").short('i').action(ArgAction::SetTrue)) .arg(Arg::new("option").short('o').action(ArgAction::Set)) @@ -117,6 +124,7 @@ fn indices_mult_flags_opt_combined() { #[test] fn indices_mult_flags_opt_combined_eq() { let m = Command::new("ind") + .args_override_self(true) .arg(Arg::new("exclude").short('e').action(ArgAction::SetTrue)) .arg(Arg::new("include").short('i').action(ArgAction::SetTrue)) .arg(Arg::new("option").short('o').action(ArgAction::Set)) @@ -131,6 +139,7 @@ fn indices_mult_flags_opt_combined_eq() { #[test] fn indices_mult_opt_value_delim_eq() { let m = Command::new("myapp") + .args_override_self(true) .arg( Arg::new("option") .short('o') @@ -149,6 +158,7 @@ fn indices_mult_opt_value_delim_eq() { #[test] fn indices_mult_opt_value_no_delim_eq() { let m = Command::new("myapp") + .args_override_self(true) .arg( Arg::new("option") .short('o') @@ -163,6 +173,7 @@ fn indices_mult_opt_value_no_delim_eq() { #[test] fn indices_mult_opt_mult_flag() { let m = Command::new("myapp") + .args_override_self(true) .arg(Arg::new("option").short('o').action(ArgAction::Append)) .arg(Arg::new("flag").short('f').action(ArgAction::SetTrue)) .try_get_matches_from(vec!["myapp", "-o", "val1", "-f", "-o", "val2", "-f"]) diff --git a/tests/builder/multiple_occurrences.rs b/tests/builder/multiple_occurrences.rs index 0b3d043a1d4..09e50e62b2a 100644 --- a/tests/builder/multiple_occurrences.rs +++ b/tests/builder/multiple_occurrences.rs @@ -3,6 +3,7 @@ use clap::{arg, Arg, ArgAction, Command}; #[test] fn multiple_occurrences_of_flags_long() { let m = Command::new("mo_flags_long") + .args_override_self(true) .arg(arg!(--multflag "allowed multiple flag").action(ArgAction::SetTrue)) .arg(arg!(--flag "disallowed multiple flag").action(ArgAction::SetTrue)) .try_get_matches_from(vec!["", "--multflag", "--flag", "--multflag"]) @@ -16,6 +17,7 @@ fn multiple_occurrences_of_flags_long() { #[test] fn multiple_occurrences_of_flags_short() { let m = Command::new("mo_flags_short") + .args_override_self(true) .arg(arg!(-m --multflag "allowed multiple flag").action(ArgAction::SetTrue)) .arg(arg!(-f --flag "disallowed multiple flag").action(ArgAction::SetTrue)) .try_get_matches_from(vec!["", "-m", "-f", "-m"]) diff --git a/tests/builder/multiple_values.rs b/tests/builder/multiple_values.rs index fffe8162cc8..83eec8b4770 100644 --- a/tests/builder/multiple_values.rs +++ b/tests/builder/multiple_values.rs @@ -401,7 +401,7 @@ fn option_max_more() { #[test] fn optional_value() { - let mut cmd = Command::new("test").arg( + let mut cmd = Command::new("test").args_override_self(true).arg( Arg::new("port") .short('p') .value_name("NUM") diff --git a/tests/derive/flags.rs b/tests/derive/flags.rs index 16ec2473dde..63fb216ae24 100644 --- a/tests/derive/flags.rs +++ b/tests/derive/flags.rs @@ -21,6 +21,7 @@ use clap::Parser; #[test] fn bool_type_is_flag() { #[derive(Parser, PartialEq, Eq, Debug)] + #[command(args_override_self = true)] struct Opt { #[arg(short, long)] alice: bool, diff --git a/tests/derive/options.rs b/tests/derive/options.rs index e9049376de9..d6420ab977b 100644 --- a/tests/derive/options.rs +++ b/tests/derive/options.rs @@ -21,6 +21,7 @@ use clap::{Parser, Subcommand}; #[test] fn required_option() { #[derive(Parser, PartialEq, Debug)] + #[command(args_override_self = true)] struct Opt { #[arg(short, long)] arg: i32, @@ -47,6 +48,7 @@ fn required_option() { #[test] fn option_with_default() { #[derive(Parser, PartialEq, Debug)] + #[command(args_override_self = true)] struct Opt { #[arg(short, default_value = "42")] arg: i32, @@ -65,6 +67,7 @@ fn option_with_default() { #[test] fn option_with_raw_default() { #[derive(Parser, PartialEq, Debug)] + #[command(args_override_self = true)] struct Opt { #[arg(short, default_value = "42")] arg: i32, @@ -94,6 +97,7 @@ fn option_from_str() { } #[derive(Debug, Parser, PartialEq)] + #[command(args_override_self = true)] struct Opt { a: Option, } @@ -119,6 +123,7 @@ fn vec_from_str() { } #[derive(Debug, Parser, PartialEq)] + #[command(args_override_self = true)] struct Opt { a: Vec, } @@ -147,6 +152,7 @@ fn option_vec_from_str() { } #[derive(Debug, Parser, PartialEq)] + #[command(args_override_self = true)] struct Opt { #[arg(short)] a: Option>, @@ -162,6 +168,7 @@ fn option_vec_from_str() { #[test] fn option_type_is_optional() { #[derive(Parser, PartialEq, Debug)] + #[command(args_override_self = true)] struct Opt { #[arg(short)] arg: Option, @@ -181,6 +188,7 @@ fn option_type_is_optional() { fn required_with_option_type() { #[derive(Debug, PartialEq, Eq, Parser)] #[command(subcommand_negates_reqs = true)] + #[command(args_override_self = true)] struct Opt { #[arg(required = true)] req_str: Option, @@ -223,6 +231,7 @@ fn ignore_qualified_option_type() { } #[derive(Parser, PartialEq, Debug)] + #[command(args_override_self = true)] struct Opt { #[arg(value_parser = parser)] arg: ::std::option::Option, @@ -239,6 +248,7 @@ fn ignore_qualified_option_type() { #[test] fn option_option_type_is_optional_value() { #[derive(Parser, PartialEq, Debug)] + #[command(args_override_self = true)] struct Opt { #[arg(short)] #[allow(clippy::option_option)] @@ -266,6 +276,7 @@ fn option_option_type_is_optional_value() { #[test] fn option_option_type_help() { #[derive(Parser, Debug)] + #[command(args_override_self = true)] struct Opt { #[arg(long, value_name = "val")] arg: Option>, @@ -278,6 +289,7 @@ fn option_option_type_help() { #[test] fn two_option_option_types() { #[derive(Parser, PartialEq, Debug)] + #[command(args_override_self = true)] struct Opt { #[arg(short)] arg: Option>, @@ -332,6 +344,7 @@ fn two_option_option_types() { #[test] fn vec_type_is_multiple_occurrences() { #[derive(Parser, PartialEq, Debug)] + #[command(args_override_self = true)] struct Opt { #[arg(short, long)] arg: Vec, @@ -350,6 +363,7 @@ fn vec_type_is_multiple_occurrences() { #[test] fn vec_type_with_required() { #[derive(Parser, PartialEq, Debug)] + #[command(args_override_self = true)] struct Opt { #[arg(short, long, required = true)] arg: Vec, @@ -368,6 +382,7 @@ fn vec_type_with_required() { #[test] fn vec_type_with_multiple_values_only() { #[derive(Parser, PartialEq, Debug)] + #[command(args_override_self = true)] struct Opt { #[arg(short, long, num_args(1..))] arg: Vec, @@ -390,6 +405,7 @@ fn ignore_qualified_vec_type() { } #[derive(Parser, PartialEq, Debug)] + #[command(args_override_self = true)] struct Opt { #[arg(value_parser = parser)] arg: ::std::vec::Vec, @@ -406,6 +422,7 @@ fn ignore_qualified_vec_type() { #[test] fn option_vec_type() { #[derive(Parser, PartialEq, Debug)] + #[command(args_override_self = true)] struct Opt { #[arg(short)] arg: Option>, @@ -428,6 +445,7 @@ fn option_vec_type() { #[test] fn option_vec_type_structopt_behavior() { #[derive(Parser, PartialEq, Debug)] + #[command(args_override_self = true)] struct Opt { #[arg(short, long, num_args(0..))] arg: Option>, @@ -455,6 +473,7 @@ fn option_vec_type_structopt_behavior() { #[test] fn two_option_vec_types() { #[derive(Parser, PartialEq, Debug)] + #[command(args_override_self = true)] struct Opt { #[arg(short)] arg: Option>, @@ -496,6 +515,7 @@ fn two_option_vec_types() { #[test] fn explicit_value_parser() { #[derive(Parser, PartialEq, Debug)] + #[command(args_override_self = true)] struct Opt { #[arg(long, value_parser = clap::value_parser!(i32))] arg: i32, @@ -509,6 +529,7 @@ fn explicit_value_parser() { #[test] fn implicit_value_parser() { #[derive(Parser, PartialEq, Debug)] + #[command(args_override_self = true)] struct Opt { #[arg(long)] arg: i32,