Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions src/builder/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T, F>(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.
Expand Down
19 changes: 19 additions & 0 deletions tests/builder/tests.rs
Original file line number Diff line number Diff line change
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