Skip to content

Commit d509c11

Browse files
committed
feat: Add mut_subcommand method to Command
this allows us modify existing subcommands on an existing/already built Command struct
1 parent b4a1362 commit d509c11

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

src/builder/command.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,51 @@ impl<'help> App<'help> {
274274
self
275275
}
276276

277+
/// Allows one to mutate a [`Command`] after it's been added as a subcommand.
278+
///
279+
/// This can be useful for modifying auto-generated arguments of nested subcommands with
280+
/// [`Command::mut_arg`].
281+
///
282+
/// # Examples
283+
///
284+
/// ```rust
285+
/// # use clap::Command;
286+
///
287+
/// let mut cmd = Command::new("foo")
288+
/// .subcommand(Command::new("bar"))
289+
/// .mut_subcommand("bar", |subcmd| subcmd.disable_help_flag(true));
290+
///
291+
/// let res = cmd.try_get_matches_from_mut(vec!["foo", "bar", "--help"]);
292+
///
293+
/// // Since we disabled the help flag on the "bar" subcommand, this should err.
294+
///
295+
/// assert!(res.is_err());
296+
///
297+
/// let res = cmd.try_get_matches_from_mut(vec!["foo", "bar"]);
298+
/// assert!(res.is_ok());
299+
/// ```
300+
#[must_use]
301+
pub fn mut_subcommand<T, F>(mut self, name: T, f: F) -> Self
302+
where
303+
F: FnOnce(App<'help>) -> App<'help>,
304+
T: Into<&'help str>,
305+
{
306+
let subcmd_name: &str = name.into();
307+
let pos = self
308+
.subcommands
309+
.iter()
310+
.position(|s| s.aliases_to(subcmd_name));
311+
312+
let subcmd = if let Some(idx) = pos {
313+
self.subcommands.remove(idx)
314+
} else {
315+
App::new(subcmd_name)
316+
};
317+
318+
self.subcommands.push(f(subcmd));
319+
self
320+
}
321+
277322
/// Adds an [`ArgGroup`] to the application.
278323
///
279324
/// [`ArgGroup`]s are a family of related arguments.

tests/builder/tests.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,25 @@ fn mut_arg_all() {
426426
}
427427
}
428428

429+
#[test]
430+
fn mut_subcommand_all() {
431+
let cmd = utils::complex_app();
432+
433+
assert_eq!(
434+
cmd.find_subcommand("subcmd")
435+
.unwrap()
436+
.is_disable_version_flag_set(),
437+
false
438+
);
439+
let cmd = cmd.mut_subcommand("subcmd", |subcmd| subcmd.disable_version_flag(true));
440+
assert_eq!(
441+
cmd.find_subcommand("subcmd")
442+
.unwrap()
443+
.is_disable_version_flag_set(),
444+
true
445+
);
446+
}
447+
429448
#[test]
430449
fn issue_3669_command_build_recurses() {
431450
let mut cmd = Command::new("ctest").subcommand(

0 commit comments

Comments
 (0)