mirror of
https://github.com/clap-rs/clap
synced 2025-03-04 23:37:32 +00:00
commit
1de71c0058
4 changed files with 101 additions and 2 deletions
|
@ -8,6 +8,7 @@ pub struct AppMeta<'b> {
|
|||
pub about: Option<&'b str>,
|
||||
pub more_help: Option<&'b str>,
|
||||
pub pre_help: Option<&'b str>,
|
||||
pub aliases: Option<Vec<&'b str>>,
|
||||
pub usage_str: Option<&'b str>,
|
||||
pub usage: Option<String>,
|
||||
pub help_str: Option<&'b str>,
|
||||
|
@ -30,6 +31,7 @@ impl<'b> Default for AppMeta<'b> {
|
|||
help_str: None,
|
||||
disp_ord: 999,
|
||||
template: None,
|
||||
aliases: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -58,6 +60,7 @@ impl<'b> Clone for AppMeta<'b> {
|
|||
help_str: self.help_str,
|
||||
disp_ord: self.disp_ord,
|
||||
template: self.template,
|
||||
aliases: self.aliases.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -504,6 +504,56 @@ impl<'a, 'b> App<'a, 'b> {
|
|||
self
|
||||
}
|
||||
|
||||
/// Allows adding a subcommand alias, which function as "hidden" subcommands that automatically
|
||||
/// dispatch as if this subcommand was used. This is more efficient, and easier than creating
|
||||
/// multiple hidden subcommands as one only needs to check for the existing of this command,
|
||||
/// and not all vairants.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg, SubCommand};
|
||||
/// let m = App::new("myprog")
|
||||
/// .subcommand(SubCommand::with_name("test")
|
||||
/// .alias("do-stuff"))
|
||||
/// .get_matches_from(vec!["myprog", "do-stuff"]);
|
||||
/// assert_eq!(m.subcommand_name(), Some("test"));
|
||||
/// ```
|
||||
pub fn alias<S: Into<&'b str>>(mut self, name: S) -> Self {
|
||||
if let Some(ref mut als) = self.p.meta.aliases {
|
||||
als.push(name.into());
|
||||
} else {
|
||||
self.p.meta.aliases = Some(vec![name.into()]);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Allows adding subcommand aliases, which function as "hidden" subcommands that automatically
|
||||
/// dispatch as if this subcommand was used. This is more efficient, and easier than creating
|
||||
/// multiple hidden subcommands as one only needs to check for the existing of this command,
|
||||
/// and not all vairants.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use clap::{App, Arg, SubCommand};
|
||||
/// let m = App::new("myprog")
|
||||
/// .subcommand(SubCommand::with_name("test")
|
||||
/// .aliases(&["do-stuff", "do-tests", "tests"]))
|
||||
/// .get_matches_from(vec!["myprog", "do-tests"]);
|
||||
/// assert_eq!(m.subcommand_name(), Some("test"));
|
||||
/// ```
|
||||
pub fn aliases<S: AsRef<str> + 'b>(mut self, names: &'b [S]) -> Self {
|
||||
if let Some(ref mut als) = self.p.meta.aliases {
|
||||
for n in names {
|
||||
als.push(n.as_ref());
|
||||
}
|
||||
} else {
|
||||
self.p.meta.aliases = Some(names.iter().map(|n| n.as_ref()).collect());
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds an `ArgGroup` to the application. `ArgGroup`s are a family of related arguments. By
|
||||
/// placing them in a logical group, you can build easier requirement and exclusion rules. For
|
||||
/// instance, you can make an entire `ArgGroup` required, meaning that one (and *only* one)
|
||||
|
|
|
@ -466,7 +466,16 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
|
||||
// Has the user already passed '--'?
|
||||
if !pos_only {
|
||||
let pos_sc = self.subcommands.iter().any(|s| &s.p.meta.name[..] == &*arg_os);
|
||||
// Does the arg match a subcommand name, or any of it's aliases (if defined)
|
||||
let pos_sc = self.subcommands
|
||||
.iter()
|
||||
.any(|s| &s.p.meta.name[..] == &*arg_os ||
|
||||
(s.p.meta.aliases.is_some() &&
|
||||
s.p.meta.aliases
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.any(|&a| a == &*arg_os)));
|
||||
if (!starts_new_arg || self.is_set(AppSettings::AllowLeadingHyphen)) && !pos_sc {
|
||||
// Check to see if parsing a value from an option
|
||||
if let Some(nvo) = needs_val_of {
|
||||
|
@ -603,7 +612,26 @@ impl<'a, 'b> Parser<'a, 'b>
|
|||
!reqs_validated {
|
||||
try!(self.validate_required(matcher));
|
||||
}
|
||||
if let Some(sc_name) = subcmd_name {
|
||||
if let Some(pos_sc_name) = subcmd_name {
|
||||
// is this is a real subcommand, or an alias
|
||||
let sc_name = if self.subcommands.iter().any(|sc| sc.p.meta.name == pos_sc_name) {
|
||||
pos_sc_name
|
||||
} else {
|
||||
self.subcommands
|
||||
.iter()
|
||||
.filter(|sc| sc.p.meta.aliases.is_some())
|
||||
.filter_map(|sc| if sc.p.meta.aliases
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.any(|&a| a == &*pos_sc_name) {
|
||||
Some(sc.p.meta.name.clone())
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.next()
|
||||
.expect(INTERNAL_ERROR_MSG)
|
||||
};
|
||||
try!(self.parse_subcommand(sc_name, matcher, it));
|
||||
} else if self.is_set(AppSettings::SubcommandRequired) {
|
||||
let bn = self.meta.bin_name.as_ref().unwrap_or(&self.meta.name);
|
||||
|
|
|
@ -62,6 +62,24 @@ fn subcommand_multiple() {
|
|||
assert_eq!(sub_m.value_of("test").unwrap(), "testing");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn single_alias() {
|
||||
let m = App::new("myprog")
|
||||
.subcommand(SubCommand::with_name("test")
|
||||
.alias("do-stuff"))
|
||||
.get_matches_from(vec!["myprog", "do-stuff"]);
|
||||
assert_eq!(m.subcommand_name(), Some("test"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_aliases() {
|
||||
let m = App::new("myprog")
|
||||
.subcommand(SubCommand::with_name("test")
|
||||
.aliases(&["do-stuff", "test-stuff"]))
|
||||
.get_matches_from(vec!["myprog", "test-stuff"]);
|
||||
assert_eq!(m.subcommand_name(), Some("test"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn subcmd_did_you_mean_output() {
|
||||
test::check_err_output(test::complex_app(), "clap-test subcm",
|
||||
|
|
Loading…
Add table
Reference in a new issue