Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
feat: Add mut_subcommand method to Command
this allows us modify existing subcommands on an existing/already built
Command struct
  • Loading branch information
emersonford committed Jun 29, 2022
1 parent b4a1362 commit d509c11
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 0 deletions.
45 changes: 45 additions & 0 deletions src/builder/command.rs
Expand Up @@ -274,6 +274,51 @@ 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<T, F>(mut self, name: T, f: F) -> Self
where
F: FnOnce(App<'help>) -> App<'help>,
T: Into<&'help str>,
{
let subcmd_name: &str = name.into();
let pos = self
.subcommands
.iter()
.position(|s| s.aliases_to(subcmd_name));

let subcmd = if let Some(idx) = pos {
self.subcommands.remove(idx)
} else {
App::new(subcmd_name)
};

self.subcommands.push(f(subcmd));
self
}

/// Adds an [`ArgGroup`] to the application.
///
/// [`ArgGroup`]s are a family of related arguments.
Expand Down
19 changes: 19 additions & 0 deletions tests/builder/tests.rs
Expand Up @@ -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(
Expand Down

0 comments on commit d509c11

Please sign in to comment.