diff --git a/src/builder/command.rs b/src/builder/command.rs index bbd14dc6caf..d644cb7681f 100644 --- a/src/builder/command.rs +++ b/src/builder/command.rs @@ -274,6 +274,50 @@ impl<'help> App<'help> { self } + /// Allows one to mutate a [`Command`] after it's been added as a subcommand. + /// + /// This can be useful for modifying auto-generated arguments of nested subcommands with + /// [`Command::mut_arg`]. + /// + /// # Examples + /// + /// ```rust + /// # use clap::Command; + /// + /// let mut cmd = Command::new("foo") + /// .subcommand(Command::new("bar")) + /// .mut_subcommand("bar", |subcmd| subcmd.disable_help_flag(true)); + /// + /// let res = cmd.try_get_matches_from_mut(vec!["foo", "bar", "--help"]); + /// + /// // Since we disabled the help flag on the "bar" subcommand, this should err. + /// + /// assert!(res.is_err()); + /// + /// let res = cmd.try_get_matches_from_mut(vec!["foo", "bar"]); + /// assert!(res.is_ok()); + /// ``` + #[must_use] + pub fn mut_subcommand(mut self, subcmd_id: T, f: F) -> Self + where + F: FnOnce(App<'help>) -> App<'help>, + T: Into<&'help str>, + { + let subcmd_id: &str = subcmd_id.into(); + let id = Id::from(subcmd_id); + + let pos = self.subcommands.iter().position(|s| s.id == id); + + let subcmd = if let Some(idx) = pos { + self.subcommands.remove(idx) + } else { + App::new(subcmd_id) + }; + + self.subcommands.push(f(subcmd)); + self + } + /// Adds an [`ArgGroup`] to the application. /// /// [`ArgGroup`]s are a family of related arguments. diff --git a/tests/builder/tests.rs b/tests/builder/tests.rs index e40349ba112..196884e0e07 100644 --- a/tests/builder/tests.rs +++ b/tests/builder/tests.rs @@ -426,6 +426,25 @@ fn mut_arg_all() { } } +#[test] +fn mut_subcommand_all() { + let cmd = utils::complex_app(); + + assert_eq!( + cmd.find_subcommand("subcmd") + .unwrap() + .is_disable_version_flag_set(), + false + ); + let cmd = cmd.mut_subcommand("subcmd", |subcmd| subcmd.disable_version_flag(true)); + assert_eq!( + cmd.find_subcommand("subcmd") + .unwrap() + .is_disable_version_flag_set(), + true + ); +} + #[test] fn issue_3669_command_build_recurses() { let mut cmd = Command::new("ctest").subcommand(