From 397e8443f93111cbe90394fcf22af5a2b4f0211e Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 29 Apr 2022 09:16:20 -0500 Subject: [PATCH 01/11] refactor(builder): Consistently use internal function --- src/build/command.rs | 18 +++++++++--------- src/error/mod.rs | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/build/command.rs b/src/build/command.rs index 5e273a0cbe8..98eb12333e1 100644 --- a/src/build/command.rs +++ b/src/build/command.rs @@ -695,7 +695,7 @@ impl<'help> App<'help> { /// ``` /// [`io::stdout()`]: std::io::stdout() pub fn print_help(&mut self) -> io::Result<()> { - self._build(); + self._build_self(); let color = self.get_color(); let mut c = Colorizer::new(Stream::Stdout, color); @@ -720,7 +720,7 @@ impl<'help> App<'help> { /// [`-h` (short)]: Arg::help() /// [`--help` (long)]: Arg::long_help() pub fn print_long_help(&mut self) -> io::Result<()> { - self._build(); + self._build_self(); let color = self.get_color(); let mut c = Colorizer::new(Stream::Stdout, color); @@ -746,7 +746,7 @@ impl<'help> App<'help> { /// [`-h` (short)]: Arg::help() /// [`--help` (long)]: Arg::long_help() pub fn write_help(&mut self, w: &mut W) -> io::Result<()> { - self._build(); + self._build_self(); let usage = Usage::new(self); Help::new(HelpWriter::Normal(w), self, &usage, false).write_help()?; @@ -770,7 +770,7 @@ impl<'help> App<'help> { /// [`-h` (short)]: Arg::help() /// [`--help` (long)]: Arg::long_help() pub fn write_long_help(&mut self, w: &mut W) -> io::Result<()> { - self._build(); + self._build_self(); let usage = Usage::new(self); Help::new(HelpWriter::Normal(w), self, &usage, true).write_help()?; @@ -838,7 +838,7 @@ impl<'help> App<'help> { pub fn render_usage(&mut self) -> String { // If there are global arguments, or settings we need to propagate them down to subcommands // before parsing incase we run into a subcommand - self._build(); + self._build_self(); Usage::new(self).create_usage_with_title(&[]) } @@ -3963,7 +3963,7 @@ impl<'help> App<'help> { // If there are global arguments, or settings we need to propagate them down to subcommands // before parsing in case we run into a subcommand - self._build(); + self._build_self(); let mut matcher = ArgMatcher::new(self); @@ -3996,9 +3996,9 @@ impl<'help> App<'help> { /// Call this on the top-level [`Command`] when done building and before reading state for /// cases like completions, custom help output, etc. pub fn build(&mut self) { - self._build(); + self._build_self(); for subcmd in self.get_subcommands_mut() { - subcmd._build(); + subcmd._build_self(); } self._build_bin_names(); } @@ -4051,7 +4051,7 @@ impl<'help> App<'help> { )); // Ensure all args are built and ready to parse - sc._build(); + sc._build_self(); Some(sc) } diff --git a/src/error/mod.rs b/src/error/mod.rs index d4fe8a32de3..3e48610152d 100644 --- a/src/error/mod.rs +++ b/src/error/mod.rs @@ -77,7 +77,7 @@ impl Error { /// Format the existing message with the Command's context #[must_use] pub fn format(mut self, cmd: &mut Command) -> Self { - cmd._build(); + cmd._build_self(); let usage = cmd.render_usage(); if let Some(message) = self.inner.message.as_mut() { message.format(cmd, usage); From 7113e463886459b00c30f58ae3aa986154498d08 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 29 Apr 2022 09:21:39 -0500 Subject: [PATCH 02/11] fix(builder): Deprecate public `Command::_build_bin_names` --- src/build/command.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/build/command.rs b/src/build/command.rs index 98eb12333e1..14ce872bd72 100644 --- a/src/build/command.rs +++ b/src/build/command.rs @@ -4000,7 +4000,7 @@ impl<'help> App<'help> { for subcmd in self.get_subcommands_mut() { subcmd._build_self(); } - self._build_bin_names(); + self._build_bin_names_internal(); } pub(crate) fn _build_subcommand(&mut self, name: &str) -> Option<&mut Self> { @@ -4385,9 +4385,13 @@ To change `help`s short, call `cmd.arg(Arg::new(\"help\")...)`.", } } - // used in clap_complete (https://github.com/clap-rs/clap_complete) #[doc(hidden)] + #[deprecated(since = "3.1.13", note = "Replaced with `Command::build`")] pub fn _build_bin_names(&mut self) { + self._build_bin_names_internal(); + } + + fn _build_bin_names_internal(&mut self) { debug!("App::_build_bin_names"); if !self.is_set(AppSettings::BinNameBuilt) { From ba0301d9b420b838640c0d7d1b9e631ed0966b4d Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 29 Apr 2022 09:31:46 -0500 Subject: [PATCH 03/11] refactor(builder): Group related build functions --- src/build/command.rs | 190 +++++++++++++++++++++---------------------- 1 file changed, 95 insertions(+), 95 deletions(-) diff --git a/src/build/command.rs b/src/build/command.rs index 14ce872bd72..f1c0ea99a1d 100644 --- a/src/build/command.rs +++ b/src/build/command.rs @@ -3991,6 +3991,18 @@ impl<'help> App<'help> { self.build(); } + #[doc(hidden)] + #[deprecated(since = "3.1.10", note = "Replaced with `Command::build`")] + pub fn _build(&mut self) { + self._build_self() + } + + #[doc(hidden)] + #[deprecated(since = "3.1.13", note = "Replaced with `Command::build`")] + pub fn _build_bin_names(&mut self) { + self._build_bin_names_internal(); + } + /// Prepare for introspecting on all included [`Command`]s /// /// Call this on the top-level [`Command`] when done building and before reading state for @@ -4003,6 +4015,62 @@ impl<'help> App<'help> { self._build_bin_names_internal(); } + pub(crate) fn _build_self(&mut self) { + debug!("App::_build"); + if !self.settings.is_set(AppSettings::Built) { + // Make sure all the globally set flags apply to us as well + self.settings = self.settings | self.g_settings; + + self._propagate(); + self._check_help_and_version(); + self._propagate_global_args(); + self._derive_display_order(); + + let mut pos_counter = 1; + let self_override = self.is_set(AppSettings::AllArgsOverrideSelf); + let hide_pv = self.is_set(AppSettings::HidePossibleValues); + for a in self.args.args_mut() { + // Fill in the groups + for g in &a.groups { + if let Some(ag) = self.groups.iter_mut().find(|grp| grp.id == *g) { + ag.args.push(a.id.clone()); + } else { + let mut ag = ArgGroup::with_id(g.clone()); + ag.args.push(a.id.clone()); + self.groups.push(ag); + } + } + + // Figure out implied settings + if a.is_last_set() { + // if an arg has `Last` set, we need to imply DontCollapseArgsInUsage so that args + // in the usage string don't get confused or left out. + self.settings.set(AppSettings::DontCollapseArgsInUsage); + } + if hide_pv && a.is_takes_value_set() { + a.settings.set(ArgSettings::HidePossibleValues); + } + if self_override { + let self_id = a.id.clone(); + a.overrides.push(self_id); + } + a._build(); + if a.is_positional() && a.index.is_none() { + a.index = Some(pos_counter); + pos_counter += 1; + } + } + + self.args._build(); + + #[cfg(debug_assertions)] + assert_app(self); + self.settings.set(AppSettings::Built); + } else { + debug!("App::_build: already built"); + } + } + pub(crate) fn _build_subcommand(&mut self, name: &str) -> Option<&mut Self> { use std::fmt::Write; @@ -4056,65 +4124,38 @@ impl<'help> App<'help> { Some(sc) } - #[doc(hidden)] - #[deprecated(since = "3.1.10", note = "Replaced with `Command::build`")] - pub fn _build(&mut self) { - self._build_self() - } - - pub(crate) fn _build_self(&mut self) { - debug!("App::_build"); - if !self.settings.is_set(AppSettings::Built) { - // Make sure all the globally set flags apply to us as well - self.settings = self.settings | self.g_settings; - - self._propagate(); - self._check_help_and_version(); - self._propagate_global_args(); - self._derive_display_order(); + fn _build_bin_names_internal(&mut self) { + debug!("App::_build_bin_names"); - let mut pos_counter = 1; - let self_override = self.is_set(AppSettings::AllArgsOverrideSelf); - let hide_pv = self.is_set(AppSettings::HidePossibleValues); - for a in self.args.args_mut() { - // Fill in the groups - for g in &a.groups { - if let Some(ag) = self.groups.iter_mut().find(|grp| grp.id == *g) { - ag.args.push(a.id.clone()); - } else { - let mut ag = ArgGroup::with_id(g.clone()); - ag.args.push(a.id.clone()); - self.groups.push(ag); - } - } + if !self.is_set(AppSettings::BinNameBuilt) { + for mut sc in &mut self.subcommands { + debug!("App::_build_bin_names:iter: bin_name set..."); - // Figure out implied settings - if a.is_last_set() { - // if an arg has `Last` set, we need to imply DontCollapseArgsInUsage so that args - // in the usage string don't get confused or left out. - self.settings.set(AppSettings::DontCollapseArgsInUsage); - } - if hide_pv && a.is_takes_value_set() { - a.settings.set(ArgSettings::HidePossibleValues); - } - if self_override { - let self_id = a.id.clone(); - a.overrides.push(self_id); - } - a._build(); - if a.is_positional() && a.index.is_none() { - a.index = Some(pos_counter); - pos_counter += 1; + if sc.bin_name.is_none() { + debug!("No"); + let bin_name = format!( + "{}{}{}", + self.bin_name.as_ref().unwrap_or(&self.name), + if self.bin_name.is_some() { " " } else { "" }, + &*sc.name + ); + debug!( + "App::_build_bin_names:iter: Setting bin_name of {} to {}", + self.name, bin_name + ); + sc.bin_name = Some(bin_name); + } else { + debug!("yes ({:?})", sc.bin_name); } + debug!( + "App::_build_bin_names:iter: Calling build_bin_names from...{}", + sc.name + ); + sc._build_bin_names_internal(); } - - self.args._build(); - - #[cfg(debug_assertions)] - assert_app(self); - self.settings.set(AppSettings::Built); + self.set(AppSettings::BinNameBuilt); } else { - debug!("App::_build: already built"); + debug!("App::_build_bin_names: already built"); } } @@ -4385,47 +4426,6 @@ To change `help`s short, call `cmd.arg(Arg::new(\"help\")...)`.", } } - #[doc(hidden)] - #[deprecated(since = "3.1.13", note = "Replaced with `Command::build`")] - pub fn _build_bin_names(&mut self) { - self._build_bin_names_internal(); - } - - fn _build_bin_names_internal(&mut self) { - debug!("App::_build_bin_names"); - - if !self.is_set(AppSettings::BinNameBuilt) { - for mut sc in &mut self.subcommands { - debug!("App::_build_bin_names:iter: bin_name set..."); - - if sc.bin_name.is_none() { - debug!("No"); - let bin_name = format!( - "{}{}{}", - self.bin_name.as_ref().unwrap_or(&self.name), - if self.bin_name.is_some() { " " } else { "" }, - &*sc.name - ); - debug!( - "App::_build_bin_names:iter: Setting bin_name of {} to {}", - self.name, bin_name - ); - sc.bin_name = Some(bin_name); - } else { - debug!("yes ({:?})", sc.bin_name); - } - debug!( - "App::_build_bin_names:iter: Calling build_bin_names from...{}", - sc.name - ); - sc._build_bin_names(); - } - self.set(AppSettings::BinNameBuilt); - } else { - debug!("App::_build_bin_names: already built"); - } - } - pub(crate) fn _render_version(&self, use_long: bool) -> String { debug!("App::_render_version"); From 7cdce9cabe739a53f14152855d219a5356f9a62c Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 29 Apr 2022 15:32:25 -0500 Subject: [PATCH 04/11] refactor(test): Use snapbox's diffs --- Cargo.toml | 1 + tests/builder/app_settings.rs | 40 +-- tests/builder/arg_aliases.rs | 14 +- tests/builder/arg_aliases_short.rs | 14 +- tests/builder/conflicts.rs | 20 +- tests/builder/default_vals.rs | 4 +- tests/builder/derive_order.rs | 44 +-- tests/builder/display_order.rs | 6 +- tests/builder/empty_values.rs | 7 +- tests/builder/error.rs | 11 +- tests/builder/flag_subcommands.rs | 19 +- tests/builder/flags.rs | 14 +- tests/builder/groups.rs | 26 +- tests/builder/help.rs | 536 +++++++---------------------- tests/builder/help_env.rs | 46 +-- tests/builder/hidden_args.rs | 70 +--- tests/builder/opts.rs | 20 +- tests/builder/possible_values.rs | 40 +-- tests/builder/require.rs | 69 +--- tests/builder/subcommands.rs | 58 +--- tests/builder/template_help.rs | 36 +- tests/builder/utils.rs | 52 +-- tests/builder/version.rs | 7 +- 23 files changed, 274 insertions(+), 880 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4fe3edbd598..8f3dd23f677 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -142,6 +142,7 @@ rustversion = "1" # Cutting out `filesystem` feature trycmd = { version = "0.13", default-features = false, features = ["color-auto", "diff", "examples"] } humantime = "2" +snapbox = "0.2.9" [[example]] name = "demo" diff --git a/tests/builder/app_settings.rs b/tests/builder/app_settings.rs index cdcdd804047..3013406b816 100644 --- a/tests/builder/app_settings.rs +++ b/tests/builder/app_settings.rs @@ -250,12 +250,12 @@ fn arg_required_else_help_error_message() { .short('i') .long("info"), ); - assert!(utils::compare_output( + utils::assert_output( cmd, "test", ARG_REQUIRED_ELSE_HELP, - true // Unlike normal displaying of help, we should provide a fatal exit code - )); + true, // Unlike normal displaying of help, we should provide a fatal exit code + ); } #[test] @@ -281,12 +281,12 @@ fn subcommand_required_else_help_error_message() { .setting(AppSettings::SubcommandRequiredElseHelp) .version("1.0") .subcommand(Command::new("info").arg(Arg::new("filename"))); - assert!(utils::compare_output( + utils::assert_output( cmd, "test", SUBCOMMAND_REQUIRED_ELSE_HELP, - true // Unlike normal displaying of help, we should provide a fatal exit code - )); + true, // Unlike normal displaying of help, we should provide a fatal exit code + ); } #[cfg(not(feature = "suggestions"))] @@ -419,12 +419,7 @@ fn skip_possible_values() { arg!([arg1] "some pos arg").possible_values(["three", "four"]), ]); - assert!(utils::compare_output( - cmd, - "test --help", - SKIP_POS_VALS, - false - )); + utils::assert_output(cmd, "test --help", SKIP_POS_VALS, false); } #[test] @@ -624,12 +619,7 @@ fn dont_collapse_args() { Arg::new("arg2").help("some"), Arg::new("arg3").help("some"), ]); - assert!(utils::compare_output( - cmd, - "clap-test --help", - DONT_COLLAPSE_ARGS, - false - )); + utils::assert_output(cmd, "clap-test --help", DONT_COLLAPSE_ARGS, false); } #[test] @@ -643,12 +633,7 @@ fn require_eq() { .value_name("FILE") .help("some"), ); - assert!(utils::compare_output( - cmd, - "clap-test --help", - REQUIRE_EQUALS, - false - )); + utils::assert_output(cmd, "clap-test --help", REQUIRE_EQUALS, false); } #[test] @@ -863,12 +848,7 @@ fn issue_1093_allow_ext_sc() { let cmd = Command::new("clap-test") .version("v1.4.8") .allow_external_subcommands(true); - assert!(utils::compare_output( - cmd, - "clap-test --help", - ALLOW_EXT_SC, - false - )); + utils::assert_output(cmd, "clap-test --help", ALLOW_EXT_SC, false); } #[test] diff --git a/tests/builder/arg_aliases.rs b/tests/builder/arg_aliases.rs index f8401674ff6..e0df5825df4 100644 --- a/tests/builder/arg_aliases.rs +++ b/tests/builder/arg_aliases.rs @@ -168,12 +168,7 @@ fn invisible_arg_aliases_help_output() { ) .arg(arg!(-f - -flag).aliases(&["unseeable", "flg1", "anyway"])), ); - assert!(utils::compare_output( - cmd, - "ct test --help", - SC_INVISIBLE_ALIAS_HELP, - false - )); + utils::assert_output(cmd, "ct test --help", SC_INVISIBLE_ALIAS_HELP, false); } #[test] @@ -197,10 +192,5 @@ fn visible_arg_aliases_help_output() { .visible_aliases(&["v_flg", "flag2", "flg3"]), ), ); - assert!(utils::compare_output( - cmd, - "ct test --help", - SC_VISIBLE_ALIAS_HELP, - false - )); + utils::assert_output(cmd, "ct test --help", SC_VISIBLE_ALIAS_HELP, false); } diff --git a/tests/builder/arg_aliases_short.rs b/tests/builder/arg_aliases_short.rs index 5069bcb799d..d939c49db73 100644 --- a/tests/builder/arg_aliases_short.rs +++ b/tests/builder/arg_aliases_short.rs @@ -164,12 +164,7 @@ fn invisible_short_arg_aliases_help_output() { ) .arg(arg!(-f - -flag).short_aliases(&['x', 'y', 'z'])), ); - assert!(utils::compare_output( - cmd, - "ct test --help", - SC_INVISIBLE_ALIAS_HELP, - false - )); + utils::assert_output(cmd, "ct test --help", SC_INVISIBLE_ALIAS_HELP, false); } #[test] @@ -194,10 +189,5 @@ fn visible_short_arg_aliases_help_output() { .visible_short_aliases(&['a', 'b', '🦆']), ), ); - assert!(utils::compare_output( - cmd, - "ct test --help", - SC_VISIBLE_ALIAS_HELP, - false - )); + utils::assert_output(cmd, "ct test --help", SC_VISIBLE_ALIAS_HELP, false); } diff --git a/tests/builder/conflicts.rs b/tests/builder/conflicts.rs index 8126c93b5f7..f1fb64f1693 100644 --- a/tests/builder/conflicts.rs +++ b/tests/builder/conflicts.rs @@ -248,42 +248,42 @@ fn required_group_conflicts_with_arg() { #[test] fn conflict_output() { - assert!(utils::compare_output( + utils::assert_output( utils::complex_app(), "clap-test val1 fa --flag --long-option-2 val2 -F", CONFLICT_ERR, true, - )); + ); } #[test] fn conflict_output_rev() { - assert!(utils::compare_output( + utils::assert_output( utils::complex_app(), "clap-test val1 fa -F --long-option-2 val2 --flag", CONFLICT_ERR_REV, true, - )); + ); } #[test] fn conflict_output_with_required() { - assert!(utils::compare_output( + utils::assert_output( utils::complex_app(), "clap-test val1 --flag --long-option-2 val2 -F", CONFLICT_ERR, true, - )); + ); } #[test] fn conflict_output_rev_with_required() { - assert!(utils::compare_output( + utils::assert_output( utils::complex_app(), "clap-test val1 -F --long-option-2 val2 --flag", CONFLICT_ERR_REV, true, - )); + ); } #[test] @@ -304,12 +304,12 @@ fn conflict_output_three_conflicting() { .long("three") .conflicts_with_all(&["one", "two"]), ); - assert!(utils::compare_output( + utils::assert_output( cmd, "three_conflicting_arguments --one --two --three", CONFLICT_ERR_THREE, true, - )); + ); } #[test] diff --git a/tests/builder/default_vals.rs b/tests/builder/default_vals.rs index 640a525eb84..c86ea38cf17 100644 --- a/tests/builder/default_vals.rs +++ b/tests/builder/default_vals.rs @@ -577,7 +577,7 @@ fn default_vals_donnot_show_in_smart_usage() { ) .arg(Arg::new("input").required(true)); - assert!(utils::compare_output( + utils::assert_output( cmd, "bug", "error: The following required arguments were not provided: @@ -589,7 +589,7 @@ USAGE: For more information try --help ", true, - )); + ); } #[test] diff --git a/tests/builder/derive_order.rs b/tests/builder/derive_order.rs index 9e5608e8a8f..a257b77cc76 100644 --- a/tests/builder/derive_order.rs +++ b/tests/builder/derive_order.rs @@ -99,12 +99,7 @@ fn no_derive_order() { .help("second option"), ]); - assert!(utils::compare_output( - cmd, - "test --help", - NO_DERIVE_ORDER, - false - )); + utils::assert_output(cmd, "test --help", NO_DERIVE_ORDER, false); } #[test] @@ -125,12 +120,7 @@ fn derive_order() { .help("second option"), ]); - assert!(utils::compare_output( - cmd, - "test --help", - UNIFIED_HELP_AND_DERIVE, - false - )); + utils::assert_output(cmd, "test --help", UNIFIED_HELP_AND_DERIVE, false); } #[test] @@ -169,7 +159,7 @@ OPTIONS: .help("first option"), ); - assert!(utils::compare_output(cmd, "test --help", HELP, false)); + utils::assert_output(cmd, "test --help", HELP, false); } #[test] @@ -207,7 +197,7 @@ OPTIONS: .help("second option"), ); - assert!(utils::compare_output(cmd, "test --help", HELP, false)); + utils::assert_output(cmd, "test --help", HELP, false); } #[test] @@ -229,12 +219,7 @@ fn derive_order_subcommand_propagate() { ]), ); - assert!(utils::compare_output( - cmd, - "test sub --help", - UNIFIED_DERIVE_SC_PROP, - false - )); + utils::assert_output(cmd, "test sub --help", UNIFIED_DERIVE_SC_PROP, false); } #[test] @@ -259,12 +244,12 @@ fn derive_order_subcommand_propagate_with_explicit_display_order() { ]), ); - assert!(utils::compare_output( + utils::assert_output( cmd, "test sub --help", UNIFIED_DERIVE_SC_PROP_EXPLICIT_ORDER, - false - )); + false, + ); } #[test] @@ -281,12 +266,7 @@ fn prefer_user_help_with_derive_order() { Arg::new("flag_a").long("flag_a").help("second flag"), ]); - assert!(utils::compare_output( - cmd, - "test --help", - PREFER_USER_HELP_DERIVE_ORDER, - false - )); + utils::assert_output(cmd, "test --help", PREFER_USER_HELP_DERIVE_ORDER, false); } #[test] @@ -304,10 +284,10 @@ fn prefer_user_help_in_subcommand_with_derive_order() { ]), ); - assert!(utils::compare_output( + utils::assert_output( cmd, "test sub --help", PREFER_USER_HELP_SUBCMD_DERIVE_ORDER, - false - )); + false, + ); } diff --git a/tests/builder/display_order.rs b/tests/builder/display_order.rs index 1c97ba2eb0d..68b4c3d3634 100644 --- a/tests/builder/display_order.rs +++ b/tests/builder/display_order.rs @@ -6,7 +6,7 @@ use clap::Command; fn very_large_display_order() { let cmd = Command::new("test").subcommand(Command::new("sub").display_order(usize::MAX)); - assert!(utils::compare_output( + utils::assert_output( cmd, "test --help", "test @@ -21,6 +21,6 @@ SUBCOMMANDS: help Print this message or the help of the given subcommand(s) sub ", - false - )); + false, + ); } diff --git a/tests/builder/empty_values.rs b/tests/builder/empty_values.rs index 5d57f160be4..c537f0c310a 100644 --- a/tests/builder/empty_values.rs +++ b/tests/builder/empty_values.rs @@ -124,10 +124,5 @@ USAGE: For more information try --help "; - assert!(utils::compare_output( - cmd, - "config --config", - NO_EUQALS_ERROR, - true - )); + utils::assert_output(cmd, "config --config", NO_EUQALS_ERROR, true); } diff --git a/tests/builder/error.rs b/tests/builder/error.rs index 3e4f923fec4..15cdefd1e3b 100644 --- a/tests/builder/error.rs +++ b/tests/builder/error.rs @@ -2,12 +2,7 @@ use crate::utils; use clap::{arg, error::ErrorKind, Arg, Command, Error}; -fn compare_error( - err: Error, - expected_kind: ErrorKind, - expected_output: &str, - stderr: bool, -) -> bool { +fn assert_error(err: Error, expected_kind: ErrorKind, expected_output: &str, stderr: bool) { let actual_output = err.to_string(); assert_eq!( stderr, @@ -17,7 +12,7 @@ fn compare_error( err.use_stderr() ); assert_eq!(expected_kind, err.kind()); - utils::compare(expected_output, actual_output) + utils::assert_eq(expected_output, actual_output) } #[test] @@ -55,7 +50,7 @@ For more information try --help let mut cmd = cmd; let expected_kind = ErrorKind::InvalidValue; let err = cmd.error(expected_kind, "Failed for mysterious reasons"); - assert!(compare_error(err, expected_kind, MESSAGE, true)); + assert_error(err, expected_kind, MESSAGE, true); } #[test] diff --git a/tests/builder/flag_subcommands.rs b/tests/builder/flag_subcommands.rs index c5c24983dea..6c43414846b 100644 --- a/tests/builder/flag_subcommands.rs +++ b/tests/builder/flag_subcommands.rs @@ -503,12 +503,7 @@ fn flag_subcommand_long_short_normal_usage_string() { .multiple_values(true), ), ); - assert!(utils::compare_output( - cmd, - "pacman -Qh", - FLAG_SUBCOMMAND_HELP, - false - )); + utils::assert_output(cmd, "pacman -Qh", FLAG_SUBCOMMAND_HELP, false); } static FLAG_SUBCOMMAND_NO_SHORT_HELP: &str = "pacman-query @@ -556,12 +551,12 @@ fn flag_subcommand_long_normal_usage_string() { .multiple_values(true), ), ); - assert!(utils::compare_output( + utils::assert_output( cmd, "pacman query --help", FLAG_SUBCOMMAND_NO_SHORT_HELP, - false - )); + false, + ); } static FLAG_SUBCOMMAND_NO_LONG_HELP: &str = "pacman-query @@ -609,10 +604,10 @@ fn flag_subcommand_short_normal_usage_string() { .multiple_values(true), ), ); - assert!(utils::compare_output( + utils::assert_output( cmd, "pacman query --help", FLAG_SUBCOMMAND_NO_LONG_HELP, - false - )); + false, + ); } diff --git a/tests/builder/flags.rs b/tests/builder/flags.rs index 3d782ff37d0..343cc3a979b 100644 --- a/tests/builder/flags.rs +++ b/tests/builder/flags.rs @@ -160,12 +160,7 @@ fn issue_1284_argument_in_flag_style() { .unwrap(); assert_eq!(m.value_of("filename"), Some("--a-flag")); - assert!(utils::compare_output( - cmd, - "mycat --another-flag", - USE_FLAG_AS_ARGUMENT, - true - )); + utils::assert_output(cmd, "mycat --another-flag", USE_FLAG_AS_ARGUMENT, true); } #[test] @@ -182,10 +177,5 @@ For more information try --help "; let cmd = Command::new("test").arg(Arg::new("arg").takes_value(true).required(true)); - assert!(utils::compare_output( - cmd, - "test -----", - MULTIPLE_DASHES, - true - )); + utils::assert_output(cmd, "test -----", MULTIPLE_DASHES, true); } diff --git a/tests/builder/groups.rs b/tests/builder/groups.rs index 76d5761a51d..e9f0c561cd6 100644 --- a/tests/builder/groups.rs +++ b/tests/builder/groups.rs @@ -178,12 +178,7 @@ fn req_group_usage_string() { .required(true), ); - assert!(utils::compare_output( - cmd, - "clap-test", - REQ_GROUP_USAGE, - true - )); + utils::assert_output(cmd, "clap-test", REQ_GROUP_USAGE, true); } #[test] @@ -199,12 +194,12 @@ fn req_group_with_conflict_usage_string() { .required(true), ); - assert!(utils::compare_output( + utils::assert_output( cmd, "clap-test --delete base", REQ_GROUP_CONFLICT_USAGE, - true - )); + true, + ); } #[test] @@ -219,12 +214,12 @@ fn req_group_with_conflict_usage_string_only_options() { .args(&["all", "delete"]) .required(true), ); - assert!(utils::compare_output( + utils::assert_output( cmd, "clap-test --delete --all", REQ_GROUP_CONFLICT_ONLY_OPTIONS, - true - )); + true, + ); } #[test] @@ -286,12 +281,7 @@ OPTIONS: let cmd = Command::new("prog") .arg(Arg::new("a").value_name("A")) .group(ArgGroup::new("group").arg("a").required(true)); - assert!(utils::compare_output( - cmd, - "prog --help", - GROUP_USAGE_USE_VAL_NAME, - false, - )); + utils::assert_output(cmd, "prog --help", GROUP_USAGE_USE_VAL_NAME, false); } #[test] diff --git a/tests/builder/help.rs b/tests/builder/help.rs index 48eb1cf2533..93048689c9e 100644 --- a/tests/builder/help.rs +++ b/tests/builder/help.rs @@ -672,12 +672,7 @@ fn req_last_arg_usage() { .required(true) .last(true), ); - assert!(utils::compare_output( - cmd, - "example --help", - LAST_ARG_REQ_MULT, - false - )); + utils::assert_output(cmd, "example --help", LAST_ARG_REQ_MULT, false); } #[test] @@ -719,12 +714,7 @@ fn args_with_last_usage() { .last(true) .value_name("ARGS"), ); - assert!(utils::compare_output( - cmd, - "flamegraph --help", - LAST_ARG_USAGE, - false - )); + utils::assert_output(cmd, "flamegraph --help", LAST_ARG_USAGE, false); } #[test] @@ -753,12 +743,7 @@ fn subcommand_help_rev() { #[test] fn complex_help_output() { - assert!(utils::compare_output( - utils::complex_app(), - "clap-test --help", - HELP, - false - )); + utils::assert_output(utils::complex_app(), "clap-test --help", HELP, false); } #[test] @@ -768,18 +753,8 @@ fn after_and_before_help_output() { .about("tests clap library") .before_help("some text that comes before the help") .after_help("some text that comes after the help"); - assert!(utils::compare_output( - cmd.clone(), - "clap-test -h", - AFTER_HELP, - false - )); - assert!(utils::compare_output( - cmd, - "clap-test --help", - AFTER_HELP, - false - )); + utils::assert_output(cmd.clone(), "clap-test -h", AFTER_HELP, false); + utils::assert_output(cmd, "clap-test --help", AFTER_HELP, false); } #[test] @@ -791,18 +766,8 @@ fn after_and_before_long_help_output() { .after_help("some text that comes after the help") .before_long_help("some longer text that comes before the help") .after_long_help("some longer text that comes after the help"); - assert!(utils::compare_output( - cmd.clone(), - "clap-test --help", - AFTER_LONG_HELP, - false - )); - assert!(utils::compare_output( - cmd, - "clap-test -h", - AFTER_HELP, - false - )); + utils::assert_output(cmd.clone(), "clap-test --help", AFTER_LONG_HELP, false); + utils::assert_output(cmd, "clap-test -h", AFTER_HELP, false); } #[test] @@ -826,12 +791,7 @@ fn multi_level_sc_help() { ), ), ); - assert!(utils::compare_output( - cmd, - "ctest help subcmd multi", - MULTI_SC_HELP, - false - )); + utils::assert_output(cmd, "ctest help subcmd multi", MULTI_SC_HELP, false); } #[test] @@ -839,23 +799,13 @@ fn no_wrap_help() { let cmd = Command::new("ctest") .term_width(0) .override_help(MULTI_SC_HELP); - assert!(utils::compare_output( - cmd, - "ctest --help", - &format!("{}\n", MULTI_SC_HELP), - false - )); + utils::assert_output(cmd, "ctest --help", &format!("{}\n", MULTI_SC_HELP), false); } #[test] fn no_wrap_default_help() { let cmd = Command::new("ctest").version("1.0").term_width(0); - assert!(utils::compare_output( - cmd, - "ctest --help", - DEFAULT_HELP, - false - )); + utils::assert_output(cmd, "ctest --help", DEFAULT_HELP, false); } #[test] @@ -907,12 +857,7 @@ OPTIONS: .long("no-git-push") .help("Do not push generated commit and tags to git remote"), ); - assert!(utils::compare_output( - cmd, - "test --help", - WRAPPED_HELP, - false - )); + utils::assert_output(cmd, "test --help", WRAPPED_HELP, false); } #[test] @@ -956,12 +901,7 @@ OPTIONS: .long("no-git-push") .help("Do not push generated commit and tags to git remote"), ); - assert!(utils::compare_output( - cmd, - "test --help", - UNWRAPPED_HELP, - false - )); + utils::assert_output(cmd, "test --help", UNWRAPPED_HELP, false); } #[test] @@ -1039,23 +979,13 @@ OPTIONS: ) .possible_value(PossibleValue::new("second").help("short help")), ); - assert!(utils::compare_output( - cmd, - "test --help", - WRAPPED_HELP, - false - )); + utils::assert_output(cmd, "test --help", WRAPPED_HELP, false); } #[test] fn complex_subcommand_help_output() { let a = utils::complex_app(); - assert!(utils::compare_output( - a, - "clap-test subcmd --help", - SC_HELP, - false - )); + utils::assert_output(a, "clap-test subcmd --help", SC_HELP, false); } #[test] @@ -1075,12 +1005,7 @@ fn issue_626_unicode_cutoff() { ) .takes_value(true), ); - assert!(utils::compare_output( - cmd, - "ctest --help", - ISSUE_626_CUTOFF, - false - )); + utils::assert_output(cmd, "ctest --help", ISSUE_626_CUTOFF, false); } #[test] @@ -1106,12 +1031,7 @@ fn hide_possible_vals() { .help("A coffeehouse, coffee shop, or café.") .takes_value(true), ); - assert!(utils::compare_output( - cmd, - "ctest --help", - HIDE_POS_VALS, - false - )); + utils::assert_output(cmd, "ctest --help", HIDE_POS_VALS, false); } #[test] @@ -1136,12 +1056,7 @@ fn hide_single_possible_val() { .help("A coffeehouse, coffee shop, or café.") .takes_value(true), ); - assert!(utils::compare_output( - cmd, - "ctest --help", - HIDE_POS_VALS, - false - )); + utils::assert_output(cmd, "ctest --help", HIDE_POS_VALS, false); } #[test] @@ -1202,12 +1117,7 @@ OPTIONS: .help("A coffeehouse, coffee shop, or café.") .takes_value(true), ); - assert!(utils::compare_output( - app, - "ctest --help", - POS_VALS_HELP, - false - )); + utils::assert_output(app, "ctest --help", POS_VALS_HELP, false); } #[test] @@ -1223,12 +1133,7 @@ fn issue_626_panic() { d'Afrique et d'Asie, dans des plantations qui sont cultivées pour les marchés d'exportation. \ Le café est souvent une contribution majeure aux exportations des régions productrices.") .takes_value(true)); - assert!(utils::compare_output( - cmd, - "ctest --help", - ISSUE_626_PANIC, - false - )); + utils::assert_output(cmd, "ctest --help", ISSUE_626_PANIC, false); } #[test] @@ -1252,12 +1157,7 @@ fn issue_626_variable_panic() { #[test] fn final_word_wrapping() { let cmd = Command::new("ctest").version("0.1").term_width(24); - assert!(utils::compare_output( - cmd, - "ctest --help", - FINAL_WORD_WRAPPING, - false - )); + utils::assert_output(cmd, "ctest --help", FINAL_WORD_WRAPPING, false); } #[test] @@ -1270,12 +1170,7 @@ fn wrapping_newline_chars() { l, long Copy-friendly, 14 characters, contains symbols.\n\ m, med, medium Copy-friendly, 8 characters, contains symbols.\n", )); - assert!(utils::compare_output( - cmd, - "ctest --help", - WRAPPING_NEWLINE_CHARS, - false - )); + utils::assert_output(cmd, "ctest --help", WRAPPING_NEWLINE_CHARS, false); } #[test] @@ -1288,12 +1183,7 @@ fn wrapping_newline_variables() { l, long Copy-friendly, 14 characters, contains symbols.{n}\ m, med, medium Copy-friendly, 8 characters, contains symbols.{n}", )); - assert!(utils::compare_output( - cmd, - "ctest --help", - WRAPPING_NEWLINE_CHARS, - false - )); + utils::assert_output(cmd, "ctest --help", WRAPPING_NEWLINE_CHARS, false); } #[test] @@ -1303,12 +1193,7 @@ fn old_newline_chars() { .short('m') .help("Some help with some wrapping\n(Defaults to something)"), ); - assert!(utils::compare_output( - cmd, - "ctest --help", - OLD_NEWLINE_CHARS, - false - )); + utils::assert_output(cmd, "ctest --help", OLD_NEWLINE_CHARS, false); } #[test] @@ -1318,12 +1203,7 @@ fn old_newline_variables() { .short('m') .help("Some help with some wrapping{n}(Defaults to something)"), ); - assert!(utils::compare_output( - cmd, - "ctest --help", - OLD_NEWLINE_CHARS, - false - )); + utils::assert_output(cmd, "ctest --help", OLD_NEWLINE_CHARS, false); } #[test] @@ -1340,12 +1220,7 @@ fn issue_688_hide_pos_vals() { .long("filter") .possible_values(filter_values) .takes_value(true)); - assert!(utils::compare_output( - app1, - "ctest --help", - ISSUE_688, - false - )); + utils::assert_output(app1, "ctest --help", ISSUE_688, false); let app2 = Command::new("ctest") .version("0.1") @@ -1356,12 +1231,7 @@ fn issue_688_hide_pos_vals() { .long("filter") .possible_values(filter_values) .takes_value(true)); - assert!(utils::compare_output( - app2, - "ctest --help", - ISSUE_688, - false - )); + utils::assert_output(app2, "ctest --help", ISSUE_688, false); let app3 = Command::new("ctest") .version("0.1") @@ -1371,12 +1241,7 @@ fn issue_688_hide_pos_vals() { images. The default is Linear (Bilinear). [possible values: Nearest, Linear, Cubic, Gaussian, Lanczos3]") .long("filter") .takes_value(true)); - assert!(utils::compare_output( - app3, - "ctest --help", - ISSUE_688, - false - )); + utils::assert_output(app3, "ctest --help", ISSUE_688, false); } #[test] @@ -1414,7 +1279,7 @@ fn issue_702_multiple_values() { .multiple_values(true) .takes_value(true), ); - assert!(utils::compare_output(cmd, "myapp --help", ISSUE_702, false)); + utils::assert_output(cmd, "myapp --help", ISSUE_702, false); } #[test] @@ -1427,12 +1292,7 @@ fn long_about() { "something really really long, with\nmultiple lines of text\nthat should be displayed", ) .arg(Arg::new("arg1").help("some option")); - assert!(utils::compare_output( - cmd, - "myapp --help", - LONG_ABOUT, - false - )); + utils::assert_output(cmd, "myapp --help", LONG_ABOUT, false); } #[test] @@ -1455,7 +1315,7 @@ fn issue_760() { .long("opt") .takes_value(true), ); - assert!(utils::compare_output(cmd, "ctest --help", ISSUE_760, false)); + utils::assert_output(cmd, "ctest --help", ISSUE_760, false); } #[test] @@ -1468,7 +1328,7 @@ fn issue_1571() { .takes_value(true) .multiple_values(true), ); - assert!(utils::compare_output( + utils::assert_output( cmd, "hello --help", "hello @@ -1480,8 +1340,8 @@ OPTIONS: -h, --help Print help information -p, --package ", - false - )); + false, + ); } #[test] @@ -1493,12 +1353,7 @@ fn ripgrep_usage() { rg [OPTIONS] --type-list", ); - assert!(utils::compare_output( - cmd, - "rg --help", - RIPGREP_USAGE, - false - )); + utils::assert_output(cmd, "rg --help", RIPGREP_USAGE, false); } #[test] @@ -1522,12 +1377,7 @@ OPTIONS: {options}", ); - assert!(utils::compare_output( - cmd, - "rg --help", - RIPGREP_USAGE, - false - )); + utils::assert_output(cmd, "rg --help", RIPGREP_USAGE, false); } #[test] @@ -1538,12 +1388,7 @@ fn sc_negates_reqs() { .arg(arg!(-o --opt "tests options")) .arg(Arg::new("PATH").help("help")) .subcommand(Command::new("test")); - assert!(utils::compare_output( - cmd, - "prog --help", - SC_NEGATES_REQS, - false - )); + utils::assert_output(cmd, "prog --help", SC_NEGATES_REQS, false); } #[test] @@ -1553,12 +1398,7 @@ fn hide_args() { .arg(arg!(-f --flag "testing flags")) .arg(arg!(-o --opt "tests options").required(false)) .arg(Arg::new("pos").hide(true)); - assert!(utils::compare_output( - cmd, - "prog --help", - HIDDEN_ARGS, - false - )); + utils::assert_output(cmd, "prog --help", HIDDEN_ARGS, false); } #[test] @@ -1570,12 +1410,7 @@ fn args_negate_sc() { .arg(arg!(-o --opt "tests options").required(false)) .arg(Arg::new("PATH").help("help")) .subcommand(Command::new("test")); - assert!(utils::compare_output( - cmd, - "prog --help", - ARGS_NEGATE_SC, - false - )); + utils::assert_output(cmd, "prog --help", ARGS_NEGATE_SC, false); } #[test] @@ -1586,12 +1421,7 @@ fn issue_1046_hide_scs() { .arg(arg!(-o --opt "tests options").required(false)) .arg(Arg::new("PATH").help("some")) .subcommand(Command::new("test").hide(true)); - assert!(utils::compare_output( - cmd, - "prog --help", - ISSUE_1046_HIDDEN_SCS, - false - )); + utils::assert_output(cmd, "prog --help", ISSUE_1046_HIDDEN_SCS, false); } #[test] @@ -1601,7 +1431,7 @@ fn issue_777_wrap_all_things() { .author("Some Very Long Name and crazy long email ") .about("Show how the about text is not wrapped") .term_width(35); - assert!(utils::compare_output(cmd, "ctest --help", ISSUE_777, false)); + utils::assert_output(cmd, "ctest --help", ISSUE_777, false); } static OVERRIDE_HELP_SHORT: &str = "test 0.1 @@ -1620,18 +1450,8 @@ fn override_help_short() { .version("0.1") .mut_arg("help", |h| h.short('H')); - assert!(utils::compare_output( - cmd.clone(), - "test --help", - OVERRIDE_HELP_SHORT, - false - )); - assert!(utils::compare_output( - cmd, - "test -H", - OVERRIDE_HELP_SHORT, - false - )); + utils::assert_output(cmd.clone(), "test --help", OVERRIDE_HELP_SHORT, false); + utils::assert_output(cmd, "test -H", OVERRIDE_HELP_SHORT, false); } static OVERRIDE_HELP_LONG: &str = "test 0.1 @@ -1650,18 +1470,8 @@ fn override_help_long() { .version("0.1") .mut_arg("help", |h| h.long("hell")); - assert!(utils::compare_output( - cmd.clone(), - "test --hell", - OVERRIDE_HELP_LONG, - false - )); - assert!(utils::compare_output( - cmd, - "test -h", - OVERRIDE_HELP_LONG, - false - )); + utils::assert_output(cmd.clone(), "test --hell", OVERRIDE_HELP_LONG, false); + utils::assert_output(cmd, "test -h", OVERRIDE_HELP_LONG, false); } static OVERRIDE_HELP_ABOUT: &str = "test 0.1 @@ -1680,30 +1490,15 @@ fn override_help_about() { .version("0.1") .mut_arg("help", |h| h.help("Print help information")); - assert!(utils::compare_output( - cmd.clone(), - "test --help", - OVERRIDE_HELP_ABOUT, - false - )); - assert!(utils::compare_output( - cmd, - "test -h", - OVERRIDE_HELP_ABOUT, - false - )); + utils::assert_output(cmd.clone(), "test --help", OVERRIDE_HELP_ABOUT, false); + utils::assert_output(cmd, "test -h", OVERRIDE_HELP_ABOUT, false); } #[test] fn arg_short_conflict_with_help() { let cmd = Command::new("conflict").arg(Arg::new("home").short('h')); - assert!(utils::compare_output( - cmd, - "conflict --help", - HELP_CONFLICT, - false - )); + utils::assert_output(cmd, "conflict --help", HELP_CONFLICT, false); } #[cfg(debug_assertions)] @@ -1729,7 +1524,7 @@ fn last_arg_mult_usage() { .last(true) .help("some"), ); - assert!(utils::compare_output(cmd, "last --help", LAST_ARG, false)); + utils::assert_output(cmd, "last --help", LAST_ARG, false); } #[test] @@ -1746,12 +1541,7 @@ fn last_arg_mult_usage_req() { .required(true) .help("some"), ); - assert!(utils::compare_output( - cmd, - "last --help", - LAST_ARG_REQ, - false - )); + utils::assert_output(cmd, "last --help", LAST_ARG_REQ, false); } #[test] @@ -1770,12 +1560,7 @@ fn last_arg_mult_usage_req_with_sc() { .help("some"), ) .subcommand(Command::new("test").about("some")); - assert!(utils::compare_output( - cmd, - "last --help", - LAST_ARG_REQ_SC, - false - )); + utils::assert_output(cmd, "last --help", LAST_ARG_REQ_SC, false); } #[test] @@ -1793,12 +1578,7 @@ fn last_arg_mult_usage_with_sc() { .help("some"), ) .subcommand(Command::new("test").about("some")); - assert!(utils::compare_output( - cmd, - "last --help", - LAST_ARG_SC, - false - )); + utils::assert_output(cmd, "last --help", LAST_ARG_SC, false); } #[test] @@ -1810,12 +1590,7 @@ fn hide_default_val() { .default_value("default-argument") .hide_default_value(true), ); - assert!(utils::compare_output( - app1, - "default --help", - HIDE_DEFAULT_VAL, - false - )); + utils::assert_output(app1, "default --help", HIDE_DEFAULT_VAL, false); let app2 = Command::new("default").version("0.1").term_width(120).arg( Arg::new("argument") @@ -1823,12 +1598,7 @@ fn hide_default_val() { .long("arg") .default_value("default-argument"), ); - assert!(utils::compare_output( - app2, - "default --help", - HIDE_DEFAULT_VAL, - false - )); + utils::assert_output(app2, "default --help", HIDE_DEFAULT_VAL, false); } #[test] @@ -1840,12 +1610,7 @@ fn escaped_whitespace_values() { .default_value("\n") .possible_values(["normal", " ", "\n", "\t", "other"]), ); - assert!(utils::compare_output( - app1, - "default --help", - ESCAPED_DEFAULT_VAL, - false - )); + utils::assert_output(app1, "default --help", ESCAPED_DEFAULT_VAL, false); } fn issue_1112_setup() -> Command<'static> { @@ -1913,12 +1678,7 @@ fn issue_1052_require_delim_help() { .value_delimiter(':'), ); - assert!(utils::compare_output( - cmd, - "test --help", - REQUIRE_DELIM_HELP, - false - )); + utils::assert_output(cmd, "test --help", REQUIRE_DELIM_HELP, false); } #[test] @@ -1945,12 +1705,7 @@ fn custom_headers_headers() { ) .args(&[Arg::new("port").long("port")]); - assert!(utils::compare_output( - cmd, - "test --help", - CUSTOM_HELP_SECTION, - false - )); + utils::assert_output(cmd, "test --help", CUSTOM_HELP_SECTION, false); } static MULTIPLE_CUSTOM_HELP_SECTIONS: &str = "blorp 1.4 @@ -2031,12 +1786,7 @@ fn multiple_custom_help_headers() { .takes_value(true), ); - assert!(utils::compare_output( - cmd, - "test --help", - MULTIPLE_CUSTOM_HELP_SECTIONS, - false - )); + utils::assert_output(cmd, "test --help", MULTIPLE_CUSTOM_HELP_SECTIONS, false); } static CUSTOM_HELP_SECTION_HIDDEN_ARGS: &str = "blorp 1.4 @@ -2089,12 +1839,7 @@ fn custom_help_headers_hide_args() { .hide_short_help(true), ); - assert!(utils::compare_output( - cmd, - "test -h", - CUSTOM_HELP_SECTION_HIDDEN_ARGS, - false - )); + utils::assert_output(cmd, "test -h", CUSTOM_HELP_SECTION_HIDDEN_ARGS, false); } static ISSUE_897: &str = "ctest-foo 0.1 @@ -2119,12 +1864,7 @@ fn show_long_about_issue_897() { .about("About foo") .long_about("Long about foo"), ); - assert!(utils::compare_output( - cmd, - "ctest foo --help", - ISSUE_897, - false - )); + utils::assert_output(cmd, "ctest foo --help", ISSUE_897, false); } static ISSUE_897_SHORT: &str = "ctest-foo 0.1 @@ -2146,12 +1886,7 @@ fn show_short_about_issue_897() { .about("About foo") .long_about("Long about foo"), ); - assert!(utils::compare_output( - cmd, - "ctest foo -h", - ISSUE_897_SHORT, - false - )); + utils::assert_output(cmd, "ctest foo -h", ISSUE_897_SHORT, false); } #[test] @@ -2171,7 +1906,7 @@ fn issue_1364_no_short_options() { .multiple_values(true), ); - assert!(utils::compare_output(cmd, "demo -h", ISSUE_1364, false)); + utils::assert_output(cmd, "demo -h", ISSUE_1364, false); } #[rustfmt::skip] @@ -2185,7 +1920,7 @@ fn issue_1487() { .group(ArgGroup::new("group1") .args(&["arg1", "arg2"]) .required(true)); - assert!(utils::compare_output(cmd, "ctest -h", ISSUE_1487, false)); + utils::assert_output(cmd, "ctest -h", ISSUE_1487, false); } #[cfg(debug_assertions)] @@ -2292,7 +2027,7 @@ with only valid keys and may not contain other nonsense that cannot be read by this program. Obviously I'm going on and on, so I'll stop now.", )); - assert!(utils::compare_output(cmd, "prog --help", ISSUE_1642, false)); + utils::assert_output(cmd, "prog --help", ISSUE_1642, false); } const AFTER_HELP_NO_ARGS: &str = "myapp 1.0 @@ -2339,12 +2074,7 @@ fn help_subcmd_help() { .mut_arg("help", |h| h.help("Print custom help text")) .subcommand(Command::new("subcmd").subcommand(Command::new("multi").version("1.0"))); - assert!(utils::compare_output( - cmd.clone(), - "myapp help help", - HELP_SUBCMD_HELP, - false - )); + utils::assert_output(cmd.clone(), "myapp help help", HELP_SUBCMD_HELP, false); } static SUBCMD_HELP_SUBCMD_HELP: &str = "myapp-subcmd-help @@ -2366,12 +2096,12 @@ fn subcmd_help_subcmd_help() { .mut_arg("help", |h| h.help("Print custom help text")) .subcommand(Command::new("subcmd").subcommand(Command::new("multi").version("1.0"))); - assert!(utils::compare_output( + utils::assert_output( cmd.clone(), "myapp subcmd help help", SUBCMD_HELP_SUBCMD_HELP, - false - )); + false, + ); } static HELP_ABOUT_MULTI_SC: &str = "myapp-subcmd-multi 1.0 @@ -2400,24 +2130,19 @@ fn help_about_multi_subcmd() { .mut_arg("help", |h| h.help("Print custom help text")) .subcommand(Command::new("subcmd").subcommand(Command::new("multi").version("1.0"))); - assert!(utils::compare_output( + utils::assert_output( cmd.clone(), "myapp help subcmd multi", HELP_ABOUT_MULTI_SC, - false - )); - assert!(utils::compare_output( + false, + ); + utils::assert_output( cmd.clone(), "myapp subcmd multi -h", HELP_ABOUT_MULTI_SC, - false - )); - assert!(utils::compare_output( - cmd, - "myapp subcmd multi --help", - HELP_ABOUT_MULTI_SC, - false - )); + false, + ); + utils::assert_output(cmd, "myapp subcmd multi --help", HELP_ABOUT_MULTI_SC, false); } #[test] @@ -2432,24 +2157,24 @@ fn help_about_multi_subcmd_override() { ), ); - assert!(utils::compare_output( + utils::assert_output( cmd.clone(), "myapp help subcmd multi", HELP_ABOUT_MULTI_SC_OVERRIDE, - false - )); - assert!(utils::compare_output( + false, + ); + utils::assert_output( cmd.clone(), "myapp subcmd multi -h", HELP_ABOUT_MULTI_SC_OVERRIDE, - false - )); - assert!(utils::compare_output( + false, + ); + utils::assert_output( cmd, "myapp subcmd multi --help", HELP_ABOUT_MULTI_SC_OVERRIDE, - false - )); + false, + ); } #[test] @@ -2464,12 +2189,7 @@ fn option_usage_order() { Arg::new("x").short('x'), ]); - assert!(utils::compare_output( - cmd, - "order --help", - OPTION_USAGE_ORDER, - false - )); + utils::assert_output(cmd, "order --help", OPTION_USAGE_ORDER, false); } #[test] @@ -2480,12 +2200,12 @@ fn prefer_about_over_long_about_in_subcommands_list() { .about("short about sub"), ); - assert!(utils::compare_output( + utils::assert_output( cmd, "about-in-subcommands-list --help", ABOUT_IN_SUBCOMMANDS_LIST, - false - )); + false, + ); } #[test] @@ -2515,12 +2235,7 @@ OPTIONS: ) .arg(Arg::new("pos2").takes_value(true)); - assert!(utils::compare_output( - cmd, - "deno --help", - USAGE_WITH_GROUP, - false - )); + utils::assert_output(cmd, "deno --help", USAGE_WITH_GROUP, false); } static CUSTOM_HEADING_POS: &str = "test 1.4 @@ -2547,12 +2262,7 @@ fn custom_heading_pos() { .next_help_heading(Some("NETWORKING")) .arg(Arg::new("speed").help("How fast")); - assert!(utils::compare_output( - cmd, - "test --help", - CUSTOM_HEADING_POS, - false - )); + utils::assert_output(cmd, "test --help", CUSTOM_HEADING_POS, false); } static ONLY_CUSTOM_HEADING_OPTS_NO_ARGS: &str = "test 1.4 @@ -2573,12 +2283,7 @@ fn only_custom_heading_opts_no_args() { .next_help_heading(Some("NETWORKING")) .arg(arg!(-s --speed "How fast").required(false)); - assert!(utils::compare_output( - cmd, - "test --help", - ONLY_CUSTOM_HEADING_OPTS_NO_ARGS, - false - )); + utils::assert_output(cmd, "test --help", ONLY_CUSTOM_HEADING_OPTS_NO_ARGS, false); } static ONLY_CUSTOM_HEADING_POS_NO_ARGS: &str = "test 1.4 @@ -2599,12 +2304,7 @@ fn only_custom_heading_pos_no_args() { .next_help_heading(Some("NETWORKING")) .arg(Arg::new("speed").help("How fast")); - assert!(utils::compare_output( - cmd, - "test --help", - ONLY_CUSTOM_HEADING_POS_NO_ARGS, - false - )); + utils::assert_output(cmd, "test --help", ONLY_CUSTOM_HEADING_POS_NO_ARGS, false); } #[test] @@ -2617,7 +2317,7 @@ fn issue_2508_number_of_values_with_single_value_name() { .number_of_values(2) .value_name("ARG"), ); - assert!(utils::compare_output( + utils::assert_output( cmd, "my_app --help", "my_app @@ -2630,8 +2330,8 @@ OPTIONS: --some_arg --some_arg_issue ", - false - )); + false, + ); } #[test] @@ -2640,7 +2340,7 @@ fn missing_positional_final_required() { .allow_missing_positional(true) .arg(Arg::new("arg1")) .arg(Arg::new("arg2").required(true)); - assert!(utils::compare_output( + utils::assert_output( cmd, "test --help", "test @@ -2655,8 +2355,8 @@ ARGS: OPTIONS: -h, --help Print help information ", - false - )); + false, + ); } #[test] @@ -2666,7 +2366,7 @@ fn missing_positional_final_multiple() { .arg(Arg::new("foo")) .arg(Arg::new("bar")) .arg(Arg::new("baz").takes_value(true).multiple_values(true)); - assert!(utils::compare_output( + utils::assert_output( cmd, "test --help", "test @@ -2682,8 +2382,8 @@ ARGS: OPTIONS: -h, --help Print help information ", - false - )); + false, + ); } #[test] @@ -2694,7 +2394,7 @@ fn positional_multiple_values_is_dotted() { .takes_value(true) .multiple_values(true), ); - assert!(utils::compare_output( + utils::assert_output( cmd, "test --help", "test @@ -2708,8 +2408,8 @@ ARGS: OPTIONS: -h, --help Print help information ", - false - )); + false, + ); let cmd = Command::new("test").arg( Arg::new("foo") @@ -2718,7 +2418,7 @@ OPTIONS: .value_name("BAR") .multiple_values(true), ); - assert!(utils::compare_output( + utils::assert_output( cmd, "test --help", "test @@ -2732,8 +2432,8 @@ ARGS: OPTIONS: -h, --help Print help information ", - false - )); + false, + ); } #[test] @@ -2744,7 +2444,7 @@ fn positional_multiple_occurrences_is_dotted() { .takes_value(true) .multiple_occurrences(true), ); - assert!(utils::compare_output( + utils::assert_output( cmd, "test --help", "test @@ -2758,8 +2458,8 @@ ARGS: OPTIONS: -h, --help Print help information ", - false - )); + false, + ); let cmd = Command::new("test").arg( Arg::new("foo") @@ -2768,7 +2468,7 @@ OPTIONS: .value_name("BAR") .multiple_occurrences(true), ); - assert!(utils::compare_output( + utils::assert_output( cmd, "test --help", "test @@ -2782,8 +2482,8 @@ ARGS: OPTIONS: -h, --help Print help information ", - false - )); + false, + ); } #[test] @@ -2851,7 +2551,7 @@ fn subcommand_help_doesnt_have_useless_help_flag() { // currently ignores the `--help` flag, the output shouldn't have it. let cmd = Command::new("test_app").subcommand(Command::new("test").about("Subcommand")); - assert!(utils::compare_output( + utils::assert_output( cmd, "example help help", "example-help @@ -2863,8 +2563,8 @@ USAGE: ARGS: ... The subcommand whose help message to display ", - false - )); + false, + ); } #[test] @@ -2894,7 +2594,7 @@ fn dont_propagate_version_to_help_subcommand() { .propagate_version(true) .subcommand(clap::Command::new("subcommand")); - assert!(utils::compare_output( + utils::assert_output( cmd.clone(), "example help help", "example-help @@ -2906,8 +2606,8 @@ USAGE: ARGS: ... The subcommand whose help message to display ", - false - )); + false, + ); cmd.debug_assert(); } diff --git a/tests/builder/help_env.rs b/tests/builder/help_env.rs index c18e3994392..7aa5d8154b7 100644 --- a/tests/builder/help_env.rs +++ b/tests/builder/help_env.rs @@ -109,7 +109,7 @@ fn hide_env() { .takes_value(true), ); - assert!(utils::compare_output(cmd, "ctest --help", HIDE_ENV, false)); + utils::assert_output(cmd, "ctest --help", HIDE_ENV, false); } #[test] @@ -126,7 +126,7 @@ fn show_env() { .takes_value(true), ); - assert!(utils::compare_output(cmd, "ctest --help", SHOW_ENV, false)); + utils::assert_output(cmd, "ctest --help", SHOW_ENV, false); } #[test] @@ -144,12 +144,7 @@ fn hide_env_vals() { .takes_value(true), ); - assert!(utils::compare_output( - cmd, - "ctest --help", - HIDE_ENV_VALS, - false - )); + utils::assert_output(cmd, "ctest --help", HIDE_ENV_VALS, false); } #[test] @@ -166,12 +161,7 @@ fn show_env_vals() { .takes_value(true), ); - assert!(utils::compare_output( - cmd, - "ctest --help", - SHOW_ENV_VALS, - false - )); + utils::assert_output(cmd, "ctest --help", SHOW_ENV_VALS, false); } #[test] @@ -187,12 +177,7 @@ fn hide_env_flag() { .help("A coffeehouse, coffee shop, or café."), ); - assert!(utils::compare_output( - cmd, - "ctest --help", - HIDE_ENV_FLAG, - false - )); + utils::assert_output(cmd, "ctest --help", HIDE_ENV_FLAG, false); } #[test] @@ -207,12 +192,7 @@ fn show_env_flag() { .help("A coffeehouse, coffee shop, or café."), ); - assert!(utils::compare_output( - cmd, - "ctest --help", - SHOW_ENV_FLAG, - false - )); + utils::assert_output(cmd, "ctest --help", SHOW_ENV_FLAG, false); } #[test] @@ -228,12 +208,7 @@ fn hide_env_vals_flag() { .help("A coffeehouse, coffee shop, or café."), ); - assert!(utils::compare_output( - cmd, - "ctest --help", - HIDE_ENV_VALS_FLAG, - false - )); + utils::assert_output(cmd, "ctest --help", HIDE_ENV_VALS_FLAG, false); } #[test] @@ -248,10 +223,5 @@ fn show_env_vals_flag() { .help("A coffeehouse, coffee shop, or café."), ); - assert!(utils::compare_output( - cmd, - "ctest --help", - SHOW_ENV_VALS_FLAG, - false - )); + utils::assert_output(cmd, "ctest --help", SHOW_ENV_VALS_FLAG, false); } diff --git a/tests/builder/hidden_args.rs b/tests/builder/hidden_args.rs index 3827fe80d07..d2421d7ca47 100644 --- a/tests/builder/hidden_args.rs +++ b/tests/builder/hidden_args.rs @@ -28,12 +28,7 @@ fn hide_args() { arg!(--option "some option").required(false), Arg::new("DUMMY").hide(true), ]); - assert!(utils::compare_output( - cmd, - "test --help", - HIDDEN_ARGS, - false - )); + utils::assert_output(cmd, "test --help", HIDDEN_ARGS, false); } static HIDDEN_SHORT_ARGS: &str = "test 2.31.2 @@ -89,12 +84,7 @@ fn hide_short_args() { .help("This text should be visible"), ]); - assert!(utils::compare_output( - cmd, - "test -h", - HIDDEN_SHORT_ARGS, - false - )); + utils::assert_output(cmd, "test -h", HIDDEN_SHORT_ARGS, false); } /// Ensure visible with opposite option @@ -116,12 +106,7 @@ fn hide_short_args_long_help() { .help("This text should be visible"), ]); - assert!(utils::compare_output( - cmd, - "test --help", - HIDDEN_SHORT_ARGS_LONG_HELP, - false - )); + utils::assert_output(cmd, "test --help", HIDDEN_SHORT_ARGS_LONG_HELP, false); } static HIDDEN_LONG_ARGS: &str = "test 2.31.2 @@ -160,12 +145,7 @@ fn hide_long_args() { .help("This text should be visible"), ]); - assert!(utils::compare_output( - cmd, - "test --help", - HIDDEN_LONG_ARGS, - false - )); + utils::assert_output(cmd, "test --help", HIDDEN_LONG_ARGS, false); } static HIDDEN_LONG_ARGS_SHORT_HELP: &str = "test 2.31.2 @@ -200,12 +180,7 @@ fn hide_long_args_short_help() { .help("This text should be visible"), ]); - assert!(utils::compare_output( - cmd, - "test -h", - HIDDEN_LONG_ARGS_SHORT_HELP, - false - )); + utils::assert_output(cmd, "test -h", HIDDEN_LONG_ARGS_SHORT_HELP, false); } static HIDDEN_POS_ARGS: &str = "test 1.4 @@ -228,12 +203,7 @@ fn hide_pos_args() { Arg::new("another").help("another pos"), ]); - assert!(utils::compare_output( - cmd, - "test --help", - HIDDEN_POS_ARGS, - false - )); + utils::assert_output(cmd, "test --help", HIDDEN_POS_ARGS, false); } static HIDDEN_SUBCMDS: &str = "test 1.4 @@ -252,12 +222,7 @@ fn hide_subcmds() { .version("1.4") .subcommand(Command::new("sub").hide(true)); - assert!(utils::compare_output( - cmd, - "test --help", - HIDDEN_SUBCMDS, - false - )); + utils::assert_output(cmd, "test --help", HIDDEN_SUBCMDS, false); } static HIDDEN_OPT_ARGS_ONLY: &str = "test 1.4 @@ -281,12 +246,7 @@ fn hide_opt_args_only() { .hide(true), ); - assert!(utils::compare_output( - cmd, - "test --help", - HIDDEN_OPT_ARGS_ONLY, - false - )); + utils::assert_output(cmd, "test --help", HIDDEN_OPT_ARGS_ONLY, false); } static HIDDEN_POS_ARGS_ONLY: &str = "test 1.4 @@ -306,12 +266,7 @@ fn hide_pos_args_only() { .mut_arg("version", |a| a.hide(true)) .args(&[Arg::new("pos").help("some pos").hide(true)]); - assert!(utils::compare_output( - cmd, - "test --help", - HIDDEN_POS_ARGS_ONLY, - false - )); + utils::assert_output(cmd, "test --help", HIDDEN_POS_ARGS_ONLY, false); } static HIDDEN_SUBCMDS_ONLY: &str = "test 1.4 @@ -331,10 +286,5 @@ fn hide_subcmds_only() { .mut_arg("version", |a| a.hide(true)) .subcommand(Command::new("sub").hide(true)); - assert!(utils::compare_output( - cmd, - "test --help", - HIDDEN_SUBCMDS_ONLY, - false - )); + utils::assert_output(cmd, "test --help", HIDDEN_SUBCMDS_ONLY, false); } diff --git a/tests/builder/opts.rs b/tests/builder/opts.rs index 5f8a63a2e11..f0b927ba6c8 100644 --- a/tests/builder/opts.rs +++ b/tests/builder/opts.rs @@ -61,12 +61,7 @@ For more information try --help .takes_value(true) .long("config"), ); - assert!(utils::compare_output( - cmd, - "prog --config file.conf", - NO_EQUALS, - true - )); + utils::assert_output(cmd, "prog --config file.conf", NO_EQUALS, true); } #[test] @@ -427,12 +422,7 @@ fn leading_hyphen_with_only_pos_follows() { #[test] #[cfg(feature = "suggestions")] fn did_you_mean() { - assert!(utils::compare_output( - utils::complex_app(), - "clap-test --optio=foo", - DYM, - true - )); + utils::assert_output(utils::complex_app(), "clap-test --optio=foo", DYM, true); } #[test] @@ -520,12 +510,12 @@ fn issue_1073_suboptimal_flag_suggestion() { let cmd = Command::new("ripgrep-616") .arg(Arg::new("files-with-matches").long("files-with-matches")) .arg(Arg::new("files-without-match").long("files-without-match")); - assert!(utils::compare_output( + utils::assert_output( cmd, "ripgrep-616 --files-without-matches", DYM_ISSUE_1073, - true - )); + true, + ); } #[test] diff --git a/tests/builder/possible_values.rs b/tests/builder/possible_values.rs index 61f87ebd39d..58e6bd55fc8 100644 --- a/tests/builder/possible_values.rs +++ b/tests/builder/possible_values.rs @@ -207,79 +207,79 @@ fn possible_values_of_option_multiple_fail() { #[test] fn possible_values_output() { - assert!(utils::compare_output( + utils::assert_output( Command::new("test").arg(Arg::new("option").short('O').possible_values([ "slow", "fast", - "ludicrous speed" + "ludicrous speed", ])), "clap-test -O slo", PV_ERROR, - true - )); + true, + ); } #[test] fn possible_values_alias_output() { - assert!(utils::compare_output( + utils::assert_output( Command::new("test").arg( Arg::new("option") .short('O') .possible_value("slow") .possible_value(PossibleValue::new("fast").alias("fost")) - .possible_value(PossibleValue::new("ludicrous speed").aliases(["ls", "lcs"])) + .possible_value(PossibleValue::new("ludicrous speed").aliases(["ls", "lcs"])), ), "clap-test -O slo", PV_ERROR, - true - )); + true, + ); } #[test] fn possible_values_hidden_output() { - assert!(utils::compare_output( + utils::assert_output( Command::new("test").arg( Arg::new("option") .short('O') .possible_values(["slow", "fast"]) .possible_value(PossibleValue::new("ludicrous speed")) - .possible_value(PossibleValue::new("forbidden speed").hide(true)) + .possible_value(PossibleValue::new("forbidden speed").hide(true)), ), "clap-test -O slo", PV_ERROR, - true - )); + true, + ); } #[test] fn escaped_possible_values_output() { - assert!(utils::compare_output( + utils::assert_output( Command::new("test").arg(Arg::new("option").short('O').possible_values([ "slow", "fast", - "ludicrous speed" + "ludicrous speed", ])), "clap-test -O ludicrous", PV_ERROR_ESCAPED, - true - )); + true, + ); } #[test] fn missing_possible_value_error() { - assert!(utils::compare_output( + utils::assert_output( Command::new("test").arg( Arg::new("option") .short('O') .possible_value("slow") .possible_value(PossibleValue::new("fast").alias("fost")) .possible_value(PossibleValue::new("ludicrous speed")) - .possible_value(PossibleValue::new("forbidden speed").hide(true)) + .possible_value(PossibleValue::new("forbidden speed").hide(true)), ), "clap-test -O", MISSING_PV_ERROR, - true - )); + true, + ); } static MISSING_PV_ERROR: &str = diff --git a/tests/builder/require.rs b/tests/builder/require.rs index e1cc956a194..7caa4795135 100644 --- a/tests/builder/require.rs +++ b/tests/builder/require.rs @@ -122,12 +122,7 @@ fn positional_required_with_requires() { .arg(Arg::new("opt")) .arg(Arg::new("bar")); - assert!(utils::compare_output( - cmd, - "clap-test", - POSITIONAL_REQ, - true - )); + utils::assert_output(cmd, "clap-test", POSITIONAL_REQ, true); } static POSITIONAL_REQ: &str = "error: The following required arguments were not provided: @@ -147,12 +142,7 @@ fn positional_required_with_requires_if_no_value() { .arg(Arg::new("opt")) .arg(Arg::new("bar")); - assert!(utils::compare_output( - cmd, - "clap-test", - POSITIONAL_REQ_IF_NO_VAL, - true - )); + utils::assert_output(cmd, "clap-test", POSITIONAL_REQ_IF_NO_VAL, true); } static POSITIONAL_REQ_IF_NO_VAL: &str = "error: The following required arguments were not provided: @@ -172,12 +162,7 @@ fn positional_required_with_requires_if_value() { .arg(Arg::new("opt")) .arg(Arg::new("bar")); - assert!(utils::compare_output( - cmd, - "clap-test val", - POSITIONAL_REQ_IF_VAL, - true - )); + utils::assert_output(cmd, "clap-test val", POSITIONAL_REQ_IF_VAL, true); } static POSITIONAL_REQ_IF_VAL: &str = "error: The following required arguments were not provided: @@ -532,12 +517,7 @@ fn required_unless_any_err() { #[test] fn missing_required_output() { - assert!(utils::compare_output( - utils::complex_app(), - "clap-test -F", - MISSING_REQ, - true - )); + utils::assert_output(utils::complex_app(), "clap-test -F", MISSING_REQ, true); } // Conditional external requirements @@ -794,12 +774,12 @@ fn list_correct_required_args() { .long("output"), ); - assert!(utils::compare_output( + utils::assert_output( cmd, "test --input somepath --target file", COND_REQ_IN_USAGE, - true - )); + true, + ); } #[test] @@ -828,12 +808,12 @@ fn required_if_val_present_fail_error_output() { .long("output"), ); - assert!(utils::compare_output( + utils::assert_output( cmd, "test --input somepath --target file", COND_REQ_IN_USAGE, - true - )); + true, + ); } #[test] @@ -928,12 +908,7 @@ fn require_eq() { .value_name("FILE") .help("some"), ); - assert!(utils::compare_output( - cmd, - "clap-test", - REQUIRE_EQUALS, - true - )); + utils::assert_output(cmd, "clap-test", REQUIRE_EQUALS, true); } #[test] @@ -958,12 +933,7 @@ fn require_eq_filtered() { .value_name("FILE") .help("some other arg"), ); - assert!(utils::compare_output( - cmd, - "clap-test -f=blah", - REQUIRE_EQUALS_FILTERED, - true - )); + utils::assert_output(cmd, "clap-test -f=blah", REQUIRE_EQUALS_FILTERED, true); } #[test] @@ -1005,12 +975,12 @@ fn require_eq_filtered_group() { .args(&["g1", "g2"]) .required(true), ); - assert!(utils::compare_output( + utils::assert_output( cmd, "clap-test -f=blah --g1=blah", REQUIRE_EQUALS_FILTERED_GROUP, - true - )); + true, + ); } static ISSUE_1158: &str = "error: The following required arguments were not provided: @@ -1084,19 +1054,14 @@ For more information try --help .required_unless_present("c") .conflicts_with("c"), ); - assert!(utils::compare_output( - cmd, - "test --c asd", - MULTIPLE_REQUIRED_UNLESS_USAGE, - true - )); + utils::assert_output(cmd, "test --c asd", MULTIPLE_REQUIRED_UNLESS_USAGE, true); } #[test] fn issue_1158_conflicting_requirements() { let cmd = issue_1158_app(); - assert!(utils::compare_output(cmd, "example id", ISSUE_1158, true)); + utils::assert_output(cmd, "example id", ISSUE_1158, true); } #[test] diff --git a/tests/builder/subcommands.rs b/tests/builder/subcommands.rs index a4152858d83..90f815ea171 100644 --- a/tests/builder/subcommands.rs +++ b/tests/builder/subcommands.rs @@ -174,12 +174,12 @@ fn subcommand_display_order() { .arg(Arg::new("roster").short('r')), ]); - assert!(utils::compare_output( + utils::assert_output( app_subcmd_alpha_order, "test --help", SUBCMD_ALPHA_ORDER, false, - )); + ); let app_subcmd_decl_order = Command::new("test") .version("1") @@ -193,12 +193,12 @@ fn subcommand_display_order() { .arg(Arg::new("roster").short('r')), ]); - assert!(utils::compare_output( + utils::assert_output( app_subcmd_decl_order, "test --help", SUBCMD_DECL_ORDER, false, - )); + ); } #[test] @@ -223,7 +223,7 @@ fn multiple_aliases() { #[cfg(feature = "suggestions")] fn subcmd_did_you_mean_output() { let cmd = Command::new("dym").subcommand(Command::new("subcmd")); - assert!(utils::compare_output(cmd, "dym subcm", DYM_SUBCMD, true)); + utils::assert_output(cmd, "dym subcm", DYM_SUBCMD, true); } #[test] @@ -232,12 +232,7 @@ fn subcmd_did_you_mean_output_ambiguous() { let cmd = Command::new("dym") .subcommand(Command::new("test")) .subcommand(Command::new("temp")); - assert!(utils::compare_output( - cmd, - "dym te", - DYM_SUBCMD_AMBIGUOUS, - true - )); + utils::assert_output(cmd, "dym te", DYM_SUBCMD_AMBIGUOUS, true); } #[test] @@ -260,12 +255,7 @@ For more information try --help Command::new("subcmd").arg(arg!(-s --subcmdarg "tests").required(false)), ); - assert!(utils::compare_output( - cmd, - "dym --subcmarg subcmd", - EXPECTED, - true - )); + utils::assert_output(cmd, "dym --subcmarg subcmd", EXPECTED, true); } #[test] @@ -286,12 +276,7 @@ For more information try --help Command::new("subcmd").arg(arg!(-s --subcmdarg "tests").required(false)), ); - assert!(utils::compare_output( - cmd, - "dym --subcmarg foo", - EXPECTED, - true - )); + utils::assert_output(cmd, "dym --subcmarg foo", EXPECTED, true); } #[test] @@ -312,12 +297,7 @@ fn visible_aliases_help_output() { .visible_alias("dongle") .visible_alias("done"), ); - assert!(utils::compare_output( - cmd, - "clap-test --help", - VISIBLE_ALIAS_HELP, - false - )); + utils::assert_output(cmd, "clap-test --help", VISIBLE_ALIAS_HELP, false); } #[test] @@ -325,12 +305,7 @@ fn invisible_aliases_help_output() { let cmd = Command::new("clap-test") .version("2.6") .subcommand(Command::new("test").about("Some help").alias("invisible")); - assert!(utils::compare_output( - cmd, - "clap-test --help", - INVISIBLE_ALIAS_HELP, - false - )); + utils::assert_output(cmd, "clap-test --help", INVISIBLE_ALIAS_HELP, false); } #[test] @@ -449,12 +424,7 @@ fn subcommand_placeholder_test() { fn subcommand_used_after_double_dash() { let cmd = Command::new("cmd").subcommand(Command::new("subcmd")); - assert!(utils::compare_output( - cmd, - "cmd -- subcmd", - SUBCMD_AFTER_DOUBLE_DASH, - true - )); + utils::assert_output(cmd, "cmd -- subcmd", SUBCMD_AFTER_DOUBLE_DASH, true); } #[test] @@ -510,7 +480,7 @@ fn subcommand_not_recognized() { .subcommand(Command::new("sub")) .disable_help_subcommand(true) .infer_subcommands(true); - assert!(utils::compare_output( + utils::assert_output( cmd, "fake help", "error: The subcommand 'help' wasn't recognized @@ -520,8 +490,8 @@ USAGE: For more information try --help ", - true - )); + true, + ); } #[cfg(feature = "unstable-multicall")] diff --git a/tests/builder/template_help.rs b/tests/builder/template_help.rs index ed5387e665f..08940567535 100644 --- a/tests/builder/template_help.rs +++ b/tests/builder/template_help.rs @@ -68,23 +68,13 @@ SUBCOMMANDS: #[test] fn with_template() { let cmd = get_app().help_template(EXAMPLE1_TMPL_S); - assert!(utils::compare_output( - cmd, - "MyApp --help", - SIMPLE_TEMPLATE, - false - )); + utils::assert_output(cmd, "MyApp --help", SIMPLE_TEMPLATE, false); } #[test] fn custom_template() { let cmd = get_app().help_template(EXAMPLE1_TMPS_F); - assert!(utils::compare_output( - cmd, - "MyApp --help", - CUSTOM_TEMPL_HELP, - false - )); + utils::assert_output(cmd, "MyApp --help", CUSTOM_TEMPL_HELP, false); } #[test] @@ -94,7 +84,7 @@ fn template_empty() { .author("Kevin K. ") .about("Does awesome things") .help_template(""); - assert!(utils::compare_output(cmd, "MyApp --help", "\n", false)); + utils::assert_output(cmd, "MyApp --help", "\n", false); } #[test] @@ -104,12 +94,7 @@ fn template_notag() { .author("Kevin K. ") .about("Does awesome things") .help_template("test no tag test"); - assert!(utils::compare_output( - cmd, - "MyApp --help", - "test no tag test\n", - false - )); + utils::assert_output(cmd, "MyApp --help", "test no tag test\n", false); } #[test] @@ -119,12 +104,7 @@ fn template_unknowntag() { .author("Kevin K. ") .about("Does awesome things") .help_template("test {unknown_tag} test"); - assert!(utils::compare_output( - cmd, - "MyApp --help", - "test {unknown_tag} test\n", - false - )); + utils::assert_output(cmd, "MyApp --help", "test {unknown_tag} test\n", false); } #[test] @@ -134,12 +114,12 @@ fn template_author_version() { .author("Kevin K. ") .about("Does awesome things") .help_template("{author}\n{version}\n{about}\n{bin}"); - assert!(utils::compare_output( + utils::assert_output( cmd, "MyApp --help", "Kevin K. \n1.0\nDoes awesome things\nMyApp\n", - false - )); + false, + ); } // ---------- diff --git a/tests/builder/utils.rs b/tests/builder/utils.rs index 1e146ea4056..432fef443f6 100644 --- a/tests/builder/utils.rs +++ b/tests/builder/utils.rs @@ -7,57 +7,25 @@ use regex::Regex; use clap::{arg, Arg, ArgGroup, Command}; -pub fn compare(l: S, r: S2) -> bool +#[track_caller] +pub fn assert_eq(expected: S, actual: S2) where S: AsRef, S2: AsRef, { - let re = Regex::new("\x1b[^m]*m").unwrap(); - // Strip out any mismatching \r character on windows that might sneak in on either side - let ls = l.as_ref().replace('\r', ""); - let rs = r.as_ref().replace('\r', ""); - let left_ = re.replace_all(&*ls, ""); - let right = re.replace_all(&*rs, ""); - let b = left_ == right; - let line_diff = left_ - .lines() - .zip(right.lines()) - .enumerate() - .filter_map(|(line, (left, right))| { - if left != right { - Some(format!("Line {}:\n{}\n{}", line, left, right)) - } else { - None - } - }) - .collect::>() - .join("\n"); - let line_count_diff = (left_.lines().count() as isize) - right.lines().count() as isize; - if !b { - dbg!(&left_); - dbg!(&right); - println!(); - println!("--> left"); - println!("{}", left_); - println!("--> right"); - println!("{}", right); - println!("--> diff"); - println!("{}", line_diff); - println!("--"); - if line_count_diff != 0 { - println!("left line count - right line count = {}", line_count_diff); - } - } - b + let expected = expected.as_ref(); + let actual = actual.as_ref(); + snapbox::assert_eq(expected, actual); } -pub fn compare_output(l: Command, args: &str, right: &str, stderr: bool) -> bool { +#[track_caller] +pub fn assert_output(l: Command, args: &str, expected: &str, stderr: bool) { let mut buf = Cursor::new(Vec::with_capacity(50)); let res = l.try_get_matches_from(args.split(' ').collect::>()); let err = res.unwrap_err(); write!(&mut buf, "{}", err).unwrap(); - let content = buf.into_inner(); - let left = String::from_utf8(content).unwrap(); + let actual = buf.into_inner(); + let actual = String::from_utf8(actual).unwrap(); assert_eq!( stderr, err.use_stderr(), @@ -65,7 +33,7 @@ pub fn compare_output(l: Command, args: &str, right: &str, stderr: bool) -> bool stderr, err.use_stderr() ); - compare(left, right) + assert_eq(actual, expected) } // Legacy tests from the python script days diff --git a/tests/builder/version.rs b/tests/builder/version.rs index b534ae2021d..1170380785d 100644 --- a/tests/builder/version.rs +++ b/tests/builder/version.rs @@ -160,12 +160,7 @@ fn version_about_multi_subcmd() { .mut_arg("version", |a| a.help("Print custom version about text")) .propagate_version(true); - assert!(utils::compare_output( - cmd, - "foo bar baz -h", - VERSION_ABOUT_MULTI_SC, - false - )); + utils::assert_output(cmd, "foo bar baz -h", VERSION_ABOUT_MULTI_SC, false); } #[test] From 2edc1a2bdfc8ff55012b523fe21ceefd958f7274 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 29 Apr 2022 15:39:17 -0500 Subject: [PATCH 05/11] test(help): Verify showing of required attributes --- tests/builder/help.rs | 48 ++++++++++++++++++++++++++++++++++++++++++ tests/builder/utils.rs | 2 +- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/tests/builder/help.rs b/tests/builder/help.rs index 93048689c9e..0e255e9aff0 100644 --- a/tests/builder/help.rs +++ b/tests/builder/help.rs @@ -2625,3 +2625,51 @@ fn help_without_short() { let m = cmd.try_get_matches_from(["test", "-h", "0x100"]).unwrap(); assert_eq!(m.value_of("hex"), Some("0x100")); } + +#[test] +fn parent_cmd_req_in_usage_with_help_flag() { + static EXPECTED: &str = "parent-test +some + +USAGE: + parent test + +OPTIONS: + -h, --help Print help information +"; + let cmd = Command::new("parent") + .version("0.1") + .arg(Arg::new("TARGET").required(true).help("some")) + .arg( + Arg::new("ARGS") + .takes_value(true) + .required(true) + .help("some"), + ) + .subcommand(Command::new("test").about("some")); + utils::assert_output(cmd, "parent test --help", EXPECTED, false); +} + +#[test] +fn parent_cmd_req_in_usage_with_help_subcommand() { + static EXPECTED: &str = "parent-test +some + +USAGE: + parent test + +OPTIONS: + -h, --help Print help information +"; + let cmd = Command::new("parent") + .version("0.1") + .arg(Arg::new("TARGET").required(true).help("some")) + .arg( + Arg::new("ARGS") + .takes_value(true) + .required(true) + .help("some"), + ) + .subcommand(Command::new("test").about("some")); + utils::assert_output(cmd, "parent help test", EXPECTED, false); +} diff --git a/tests/builder/utils.rs b/tests/builder/utils.rs index 432fef443f6..4385f796cd6 100644 --- a/tests/builder/utils.rs +++ b/tests/builder/utils.rs @@ -33,7 +33,7 @@ pub fn assert_output(l: Command, args: &str, expected: &str, stderr: bool) { stderr, err.use_stderr() ); - assert_eq(actual, expected) + assert_eq(expected, actual) } // Legacy tests from the python script days From bcde91b101421ec2de1d91901d6ac93d3d60edd2 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 29 Apr 2022 16:07:47 -0500 Subject: [PATCH 06/11] fix(debug): Update Command's debug statements --- src/build/command.rs | 58 ++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/build/command.rs b/src/build/command.rs index f1c0ea99a1d..34a174907d8 100644 --- a/src/build/command.rs +++ b/src/build/command.rs @@ -644,13 +644,13 @@ impl<'help> App<'help> { // Stop borrowing command so we can get another mut ref to it. let command = command.to_owned(); debug!( - "App::try_get_matches_from_mut: Parsed command {} from argv", + "Command::try_get_matches_from_mut: Parsed command {} from argv", command ); - debug!("App::try_get_matches_from_mut: Reinserting command into arguments so subcommand parser matches it"); + debug!("Command::try_get_matches_from_mut: Reinserting command into arguments so subcommand parser matches it"); raw_args.insert(&cursor, &[&command]); - debug!("App::try_get_matches_from_mut: Clearing name and bin_name so that displayed command name starts with applet name"); + debug!("Command::try_get_matches_from_mut: Clearing name and bin_name so that displayed command name starts with applet name"); self.name.clear(); self.bin_name = None; return self._do_parse(&mut raw_args, cursor); @@ -3299,7 +3299,7 @@ impl<'help> App<'help> { /// Should we color the output? #[inline(never)] pub fn get_color(&self) -> ColorChoice { - debug!("App::color: Color setting..."); + debug!("Command::color: Color setting..."); if cfg!(feature = "color") { #[allow(deprecated)] @@ -3447,7 +3447,7 @@ impl<'help> App<'help> { .iter() .map(|id| { self.args.args().find(|arg| arg.id == *id).expect( - "App::get_arg_conflicts_with: \ + "Command::get_arg_conflicts_with: \ The passed arg conflicts with an arg unknown to the cmd", ) }) @@ -3478,7 +3478,7 @@ impl<'help> App<'help> { ) .find(|arg| arg.id == *id) .expect( - "App::get_arg_conflicts_with: \ + "Command::get_arg_conflicts_with: \ The passed arg conflicts with an arg unknown to the cmd", ) }) @@ -3959,7 +3959,7 @@ impl<'help> App<'help> { raw_args: &mut clap_lex::RawArgs, args_cursor: clap_lex::ArgCursor, ) -> ClapResult { - debug!("App::_do_parse"); + debug!("Command::_do_parse"); // If there are global arguments, or settings we need to propagate them down to subcommands // before parsing in case we run into a subcommand @@ -3971,7 +3971,7 @@ impl<'help> App<'help> { let mut parser = Parser::new(self); if let Err(error) = parser.get_matches_with(&mut matcher, raw_args, args_cursor) { if self.is_set(AppSettings::IgnoreErrors) { - debug!("App::_do_parse: ignoring error: {}", error); + debug!("Command::_do_parse: ignoring error: {}", error); } else { return Err(error); } @@ -4016,7 +4016,7 @@ impl<'help> App<'help> { } pub(crate) fn _build_self(&mut self) { - debug!("App::_build"); + debug!("Command::_build"); if !self.settings.is_set(AppSettings::Built) { // Make sure all the globally set flags apply to us as well self.settings = self.settings | self.g_settings; @@ -4067,7 +4067,7 @@ impl<'help> App<'help> { assert_app(self); self.settings.set(AppSettings::Built); } else { - debug!("App::_build: already built"); + debug!("Command::_build: already built"); } } @@ -4125,11 +4125,11 @@ impl<'help> App<'help> { } fn _build_bin_names_internal(&mut self) { - debug!("App::_build_bin_names"); + debug!("Command::_build_bin_names"); if !self.is_set(AppSettings::BinNameBuilt) { for mut sc in &mut self.subcommands { - debug!("App::_build_bin_names:iter: bin_name set..."); + debug!("Command::_build_bin_names:iter: bin_name set..."); if sc.bin_name.is_none() { debug!("No"); @@ -4140,7 +4140,7 @@ impl<'help> App<'help> { &*sc.name ); debug!( - "App::_build_bin_names:iter: Setting bin_name of {} to {}", + "Command::_build_bin_names:iter: Setting bin_name of {} to {}", self.name, bin_name ); sc.bin_name = Some(bin_name); @@ -4148,14 +4148,14 @@ impl<'help> App<'help> { debug!("yes ({:?})", sc.bin_name); } debug!( - "App::_build_bin_names:iter: Calling build_bin_names from...{}", + "Command::_build_bin_names:iter: Calling build_bin_names from...{}", sc.name ); sc._build_bin_names_internal(); } self.set(AppSettings::BinNameBuilt); } else { - debug!("App::_build_bin_names: already built"); + debug!("Command::_build_bin_names: already built"); } } @@ -4199,7 +4199,7 @@ impl<'help> App<'help> { /// Propagate global args pub(crate) fn _propagate_global_args(&mut self) { - debug!("App::_propagate_global_args:{}", self.name); + debug!("Command::_propagate_global_args:{}", self.name); for sc in &mut self.subcommands { for a in self.args.args().filter(|a| a.is_global_set()) { @@ -4233,7 +4233,7 @@ impl<'help> App<'help> { /// Propagate settings pub(crate) fn _propagate(&mut self) { - debug!("App::_propagate:{}", self.name); + debug!("Command::_propagate:{}", self.name); let mut subcommands = std::mem::take(&mut self.subcommands); for sc in &mut subcommands { self._propagate_subcommand(sc); @@ -4263,7 +4263,7 @@ impl<'help> App<'help> { #[allow(clippy::blocks_in_if_conditions)] pub(crate) fn _check_help_and_version(&mut self) { - debug!("App::_check_help_and_version: {}", self.name); + debug!("Command::_check_help_and_version: {}", self.name); if self.is_set(AppSettings::DisableHelpFlag) || self.args.args().any(|x| { @@ -4275,7 +4275,7 @@ impl<'help> App<'help> { .iter() .any(|sc| sc.long_flag == Some("help")) { - debug!("App::_check_help_and_version: Removing generated help"); + debug!("Command::_check_help_and_version: Removing generated help"); let generated_help_pos = self .args @@ -4318,7 +4318,7 @@ To change `help`s short, call `cmd.arg(Arg::new(\"help\")...)`.", .expect(INTERNAL_ERROR_MSG); help.short = Some('h'); } else { - debug!("App::_check_help_and_version: Removing `-h` from help"); + debug!("Command::_check_help_and_version: Removing `-h` from help"); } } @@ -4339,7 +4339,7 @@ To change `help`s short, call `cmd.arg(Arg::new(\"help\")...)`.", .iter() .any(|sc| sc.long_flag == Some("version")) { - debug!("App::_check_help_and_version: Removing generated version"); + debug!("Command::_check_help_and_version: Removing generated version"); // This is the check mentioned above that only checks for Generated, not // GeneratedMutated args by design. @@ -4380,7 +4380,7 @@ To change `help`s short, call `cmd.arg(Arg::new(\"help\")...)`.", && self.has_subcommands() && !self.subcommands.iter().any(|s| s.id == Id::help_hash()) { - debug!("App::_check_help_and_version: Building help subcommand"); + debug!("Command::_check_help_and_version: Building help subcommand"); let mut help_subcmd = App::new("help") .about("Print this message or the help of the given subcommand(s)") .arg( @@ -4406,7 +4406,7 @@ To change `help`s short, call `cmd.arg(Arg::new(\"help\")...)`.", } pub(crate) fn _derive_display_order(&mut self) { - debug!("App::_derive_display_order:{}", self.name); + debug!("Command::_derive_display_order:{}", self.name); if self.settings.is_set(AppSettings::DeriveDisplayOrder) { for a in self @@ -4427,7 +4427,7 @@ To change `help`s short, call `cmd.arg(Arg::new(\"help\")...)`.", } pub(crate) fn _render_version(&self, use_long: bool) -> String { - debug!("App::_render_version"); + debug!("Command::_render_version"); let ver = if use_long { self.long_version.or(self.version).unwrap_or("") @@ -4564,7 +4564,7 @@ impl<'help> App<'help> { /// Iterate through the groups this arg is member of. pub(crate) fn groups_for_arg<'a>(&'a self, arg: &Id) -> impl Iterator + 'a { - debug!("App::groups_for_arg: id={:?}", arg); + debug!("Command::groups_for_arg: id={:?}", arg); let arg = arg.clone(); self.groups .iter() @@ -4604,7 +4604,7 @@ impl<'help> App<'help> { } pub(crate) fn unroll_args_in_group(&self, group: &Id) -> Vec { - debug!("App::unroll_args_in_group: group={:?}", group); + debug!("Command::unroll_args_in_group: group={:?}", group); let mut g_vec = vec![group]; let mut args = vec![]; @@ -4617,13 +4617,13 @@ impl<'help> App<'help> { .args .iter() { - debug!("App::unroll_args_in_group:iter: entity={:?}", n); + debug!("Command::unroll_args_in_group:iter: entity={:?}", n); if !args.contains(n) { if self.find(n).is_some() { - debug!("App::unroll_args_in_group:iter: this is an arg"); + debug!("Command::unroll_args_in_group:iter: this is an arg"); args.push(n.clone()) } else { - debug!("App::unroll_args_in_group:iter: this is a group"); + debug!("Command::unroll_args_in_group:iter: this is a group"); g_vec.push(n); } } From 515a37dba18905cb2f9c0125466ac91c98268846 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 29 Apr 2022 16:18:30 -0500 Subject: [PATCH 07/11] fix(debug): Improve debug output of bin building --- src/build/command.rs | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/build/command.rs b/src/build/command.rs index 34a174907d8..02efb6d8f74 100644 --- a/src/build/command.rs +++ b/src/build/command.rs @@ -4102,12 +4102,12 @@ impl<'help> App<'help> { sc_names = format!("{{{}}}", sc_names); } - sc.usage_name = Some( - self.bin_name - .as_ref() - .map(|bin_name| format!("{}{}{}", bin_name, mid_string, sc_names)) - .unwrap_or(sc_names), - ); + let usage_name = self + .bin_name + .as_ref() + .map(|bin_name| format!("{}{}{}", bin_name, mid_string, sc_names)) + .unwrap_or(sc_names); + sc.usage_name = Some(usage_name); // bin_name should be parent's bin_name + [] + the sc's name separated by // a space @@ -4132,7 +4132,6 @@ impl<'help> App<'help> { debug!("Command::_build_bin_names:iter: bin_name set..."); if sc.bin_name.is_none() { - debug!("No"); let bin_name = format!( "{}{}{}", self.bin_name.as_ref().unwrap_or(&self.name), @@ -4140,17 +4139,16 @@ impl<'help> App<'help> { &*sc.name ); debug!( - "Command::_build_bin_names:iter: Setting bin_name of {} to {}", - self.name, bin_name + "Command::_build_bin_names:iter: Setting bin_name of {} to {:?}", + sc.name, bin_name ); sc.bin_name = Some(bin_name); } else { - debug!("yes ({:?})", sc.bin_name); + debug!( + "Command::_build_bin_names::iter: Using existing bin_name of {} ({:?})", + sc.name, sc.bin_name + ); } - debug!( - "Command::_build_bin_names:iter: Calling build_bin_names from...{}", - sc.name - ); sc._build_bin_names_internal(); } self.set(AppSettings::BinNameBuilt); From 37ebb71806f1746116c6b0c5492b23105c484fd9 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 29 Apr 2022 16:41:00 -0500 Subject: [PATCH 08/11] fix(help): `write_help` usage includes required arguments --- src/build/command.rs | 49 +++++++++++++++++++++++++++++++++++++++++-- tests/builder/help.rs | 29 +++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 2 deletions(-) diff --git a/src/build/command.rs b/src/build/command.rs index 02efb6d8f74..d9697af5f12 100644 --- a/src/build/command.rs +++ b/src/build/command.rs @@ -4128,14 +4128,59 @@ impl<'help> App<'help> { debug!("Command::_build_bin_names"); if !self.is_set(AppSettings::BinNameBuilt) { + let mut mid_string = String::from(" "); + if !self.is_subcommand_negates_reqs_set() { + let reqs = Usage::new(self).get_required_usage_from(&[], None, true); // maybe Some(m) + + for s in &reqs { + mid_string.push_str(s); + mid_string.push(' '); + } + } + for mut sc in &mut self.subcommands { debug!("Command::_build_bin_names:iter: bin_name set..."); + if sc.usage_name.is_none() { + use std::fmt::Write; + // Display subcommand name, short and long in usage + let mut sc_names = sc.name.clone(); + let mut flag_subcmd = false; + if let Some(l) = sc.long_flag { + write!(sc_names, "|--{}", l).unwrap(); + flag_subcmd = true; + } + if let Some(s) = sc.short_flag { + write!(sc_names, "|-{}", s).unwrap(); + flag_subcmd = true; + } + + if flag_subcmd { + sc_names = format!("{{{}}}", sc_names); + } + + let usage_name = format!( + "{}{}{}", + self.bin_name.as_ref().unwrap_or(&self.name), + mid_string, + sc_names + ); + debug!( + "Command::_build_bin_names:iter: Setting usage_name of {} to {:?}", + sc.name, usage_name + ); + sc.usage_name = Some(usage_name); + } else { + debug!( + "Command::_build_bin_names::iter: Using existing usage_name of {} ({:?})", + sc.name, sc.usage_name + ); + } + if sc.bin_name.is_none() { let bin_name = format!( - "{}{}{}", + "{} {}", self.bin_name.as_ref().unwrap_or(&self.name), - if self.bin_name.is_some() { " " } else { "" }, &*sc.name ); debug!( diff --git a/tests/builder/help.rs b/tests/builder/help.rs index 0e255e9aff0..bc2983875eb 100644 --- a/tests/builder/help.rs +++ b/tests/builder/help.rs @@ -2673,3 +2673,32 @@ OPTIONS: .subcommand(Command::new("test").about("some")); utils::assert_output(cmd, "parent help test", EXPECTED, false); } + +#[test] +fn parent_cmd_req_in_usage_with_render_help() { + static EXPECTED: &str = "parent-test +some + +USAGE: + parent test + +OPTIONS: + -h, --help Print help information +"; + let mut cmd = Command::new("parent") + .version("0.1") + .arg(Arg::new("TARGET").required(true).help("some")) + .arg( + Arg::new("ARGS") + .takes_value(true) + .required(true) + .help("some"), + ) + .subcommand(Command::new("test").about("some")); + cmd.build(); + let subcmd = cmd.find_subcommand_mut("test").unwrap(); + + let mut buf = Vec::new(); + subcmd.write_help(&mut buf).unwrap(); + utils::assert_eq(EXPECTED, String::from_utf8(buf).unwrap()); +} From 1452c1e42b71b8042bd8cb9ae0ed01dd472faea0 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 29 Apr 2022 20:15:44 -0500 Subject: [PATCH 09/11] fix(help): Help subcommands usage includes requires arguments --- src/parse/parser.rs | 26 +++++++------------------- tests/builder/help.rs | 2 +- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/src/parse/parser.rs b/src/parse/parser.rs index 7c62b2a3d43..39f53b171e4 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -613,20 +613,15 @@ impl<'help, 'cmd> Parser<'help, 'cmd> { ) -> ClapResult { debug!("Parser::parse_help_subcommand"); - let mut bin_name = self - .cmd - .get_bin_name() - .unwrap_or_else(|| self.cmd.get_name()) - .to_owned(); - + let mut cmd = self.cmd.clone(); let mut sc = { - let mut sc = self.cmd.clone(); + let mut sc = &mut cmd; for cmd in cmds { - sc = if let Some(c) = sc.find_subcommand(cmd) { - c - } else if let Some(c) = sc.find_subcommand(&cmd.to_string_lossy()) { - c + sc = if let Some(sc_name) = + sc.find_subcommand(cmd).map(|sc| sc.get_name().to_owned()) + { + sc._build_subcommand(&sc_name).unwrap() } else { return Err(ClapError::unrecognized_subcommand( self.cmd, @@ -636,18 +631,11 @@ impl<'help, 'cmd> Parser<'help, 'cmd> { .unwrap_or_else(|| self.cmd.get_name()) .to_owned(), )); - } - .clone(); - - sc._build_self(); - bin_name.push(' '); - bin_name.push_str(sc.get_name()); + }; } sc }; - sc = sc.bin_name(bin_name); - let parser = Parser::new(&mut sc); Err(parser.help_err(true, Stream::Stdout)) diff --git a/tests/builder/help.rs b/tests/builder/help.rs index bc2983875eb..1c1acd6c24c 100644 --- a/tests/builder/help.rs +++ b/tests/builder/help.rs @@ -2656,7 +2656,7 @@ fn parent_cmd_req_in_usage_with_help_subcommand() { some USAGE: - parent test + parent test OPTIONS: -h, --help Print help information From ccf8634c198e149f9abed195b7665fbf10855fda Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 29 Apr 2022 20:25:05 -0500 Subject: [PATCH 10/11] fix(help): Provide correct context for help subcmd errors --- src/parse/parser.rs | 7 +++---- tests/builder/help.rs | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/parse/parser.rs b/src/parse/parser.rs index 39f53b171e4..f26f8b593df 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -624,11 +624,10 @@ impl<'help, 'cmd> Parser<'help, 'cmd> { sc._build_subcommand(&sc_name).unwrap() } else { return Err(ClapError::unrecognized_subcommand( - self.cmd, + &sc, cmd.to_string_lossy().into_owned(), - self.cmd - .get_bin_name() - .unwrap_or_else(|| self.cmd.get_name()) + sc.get_bin_name() + .unwrap_or_else(|| sc.get_name()) .to_owned(), )); }; diff --git a/tests/builder/help.rs b/tests/builder/help.rs index 1c1acd6c24c..f2db0c0801a 100644 --- a/tests/builder/help.rs +++ b/tests/builder/help.rs @@ -655,6 +655,41 @@ fn help_subcommand() { assert_eq!(m.unwrap_err().kind(), ErrorKind::DisplayHelp); } +#[test] +fn help_multi_subcommand_error() { + let cmd = Command::new("ctest").subcommand( + Command::new("subcmd").subcommand( + Command::new("multi") + .about("tests subcommands") + .author("Kevin K. ") + .version("0.1") + .arg(arg!( + -f --flag "tests flags" + )) + .arg( + arg!( + -o --option "tests options" + ) + .required(false) + .multiple_values(true) + .multiple_occurrences(true), + ), + ), + ); + let err = cmd + .try_get_matches_from(["ctest", "help", "subcmd", "multi", "foo"]) + .unwrap_err(); + + static EXPECTED: &str = "error: The subcommand 'foo' wasn't recognized + +USAGE: + ctest subcmd multi + +For more information try --help +"; + utils::assert_eq(EXPECTED, err.to_string()); +} + #[test] fn req_last_arg_usage() { let cmd = Command::new("example") From 8df20478a4071e0ef34a26aa01bb40163731855e Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 29 Apr 2022 20:26:59 -0500 Subject: [PATCH 11/11] style: Make clippy happy --- src/parse/parser.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/parse/parser.rs b/src/parse/parser.rs index f26f8b593df..b5b696665d2 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -614,7 +614,7 @@ impl<'help, 'cmd> Parser<'help, 'cmd> { debug!("Parser::parse_help_subcommand"); let mut cmd = self.cmd.clone(); - let mut sc = { + let sc = { let mut sc = &mut cmd; for cmd in cmds { @@ -624,7 +624,7 @@ impl<'help, 'cmd> Parser<'help, 'cmd> { sc._build_subcommand(&sc_name).unwrap() } else { return Err(ClapError::unrecognized_subcommand( - &sc, + sc, cmd.to_string_lossy().into_owned(), sc.get_bin_name() .unwrap_or_else(|| sc.get_name()) @@ -635,7 +635,7 @@ impl<'help, 'cmd> Parser<'help, 'cmd> { sc }; - let parser = Parser::new(&mut sc); + let parser = Parser::new(sc); Err(parser.help_err(true, Stream::Stdout)) }