mirror of
https://github.com/clap-rs/clap
synced 2025-03-05 07:47:40 +00:00
feat: long flag subcommand infer
Added tests and feature to infer long flag subcommands similarly to normal subcommands.
This commit is contained in:
parent
1ea7178629
commit
ec35ab8813
2 changed files with 91 additions and 2 deletions
|
@ -865,6 +865,41 @@ where
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Checks if the arg matches a long flag subcommand name, or any of it's aliases (if defined)
|
||||||
|
fn possible_long_flag_subcommand(&self, arg_os: &ArgStr<'_>) -> Option<&str> {
|
||||||
|
debug!("Parser::possible_long_flag_subcommand: arg={:?}", arg_os);
|
||||||
|
if self.is_set(AS::InferSubcommands) {
|
||||||
|
let options = self
|
||||||
|
.app
|
||||||
|
.get_subcommands()
|
||||||
|
.iter()
|
||||||
|
.fold(Vec::new(), |mut options, sc| {
|
||||||
|
if let Some(long) = sc.long {
|
||||||
|
if arg_os.is_prefix_of(long) {
|
||||||
|
options.push(long);
|
||||||
|
}
|
||||||
|
options.extend(
|
||||||
|
sc.get_all_aliases()
|
||||||
|
.filter(|alias| arg_os.is_prefix_of(alias)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
options
|
||||||
|
});
|
||||||
|
if options.len() == 1 {
|
||||||
|
return Some(options[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for sc in &options {
|
||||||
|
if sc == arg_os {
|
||||||
|
return Some(sc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if let Some(sc_name) = self.app.find_long_subcmd(arg_os) {
|
||||||
|
return Some(sc_name);
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_help_subcommand(&self, cmds: &[OsString]) -> ClapResult<ParseResult> {
|
fn parse_help_subcommand(&self, cmds: &[OsString]) -> ClapResult<ParseResult> {
|
||||||
debug!("Parser::parse_help_subcommand");
|
debug!("Parser::parse_help_subcommand");
|
||||||
|
|
||||||
|
@ -1173,7 +1208,7 @@ where
|
||||||
self.parse_flag(opt, matcher)?;
|
self.parse_flag(opt, matcher)?;
|
||||||
|
|
||||||
return Ok(ParseResult::Flag(opt.id.clone()));
|
return Ok(ParseResult::Flag(opt.id.clone()));
|
||||||
} else if let Some(sc_name) = self.app.find_long_subcmd(&arg) {
|
} else if let Some(sc_name) = self.possible_long_flag_subcommand(&arg) {
|
||||||
return Ok(ParseResult::FlagSubCommand(sc_name.to_string()));
|
return Ok(ParseResult::FlagSubCommand(sc_name.to_string()));
|
||||||
} else if self.is_set(AS::AllowLeadingHyphen) {
|
} else if self.is_set(AS::AllowLeadingHyphen) {
|
||||||
return Ok(ParseResult::MaybeHyphenValue);
|
return Ok(ParseResult::MaybeHyphenValue);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use clap::{App, Arg};
|
use clap::{App, AppSettings, Arg, ErrorKind};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn flag_subcommand_normal() {
|
fn flag_subcommand_normal() {
|
||||||
|
@ -274,3 +274,57 @@ fn flag_subcommand_conflict_with_version() {
|
||||||
.subcommand(App::new("ver").short_flag('V').long_flag("version"))
|
.subcommand(App::new("ver").short_flag('V').long_flag("version"))
|
||||||
.get_matches_from(vec!["myprog", "--version"]);
|
.get_matches_from(vec!["myprog", "--version"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn flag_subcommand_long_infer_pass() {
|
||||||
|
let m = App::new("prog")
|
||||||
|
.setting(AppSettings::InferSubcommands)
|
||||||
|
.subcommand(App::new("test").long_flag("test"))
|
||||||
|
.get_matches_from(vec!["prog", "--te"]);
|
||||||
|
assert_eq!(m.subcommand_name(), Some("test"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "suggestions"))]
|
||||||
|
#[test]
|
||||||
|
fn flag_subcommand_long_infer_fail() {
|
||||||
|
let m = App::new("prog")
|
||||||
|
.setting(AppSettings::InferSubcommands)
|
||||||
|
.subcommand(App::new("test").long_flag("test"))
|
||||||
|
.subcommand(App::new("temp").long_flag("temp"))
|
||||||
|
.try_get_matches_from(vec!["prog", "--te"]);
|
||||||
|
assert!(m.is_err(), "{:#?}", m.unwrap());
|
||||||
|
assert_eq!(m.unwrap_err().kind, ErrorKind::UnknownArgument);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "suggestions")]
|
||||||
|
#[test]
|
||||||
|
fn flag_subcommand_long_infer_fail() {
|
||||||
|
let m = App::new("prog")
|
||||||
|
.setting(AppSettings::InferSubcommands)
|
||||||
|
.subcommand(App::new("test").long_flag("test"))
|
||||||
|
.subcommand(App::new("temp").long_flag("temp"))
|
||||||
|
.try_get_matches_from(vec!["prog", "--te"]);
|
||||||
|
assert!(m.is_err(), "{:#?}", m.unwrap());
|
||||||
|
assert_eq!(m.unwrap_err().kind, ErrorKind::UnknownArgument);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn flag_subcommands_long_infer_pass_close() {
|
||||||
|
let m = App::new("prog")
|
||||||
|
.setting(AppSettings::InferSubcommands)
|
||||||
|
.subcommand(App::new("test").long_flag("test"))
|
||||||
|
.subcommand(App::new("temp").long_flag("temp"))
|
||||||
|
.get_matches_from(vec!["prog", "--tes"]);
|
||||||
|
assert_eq!(m.subcommand_name(), Some("test"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn flag_subcommands_long_infer_exact_match() {
|
||||||
|
let m = App::new("prog")
|
||||||
|
.setting(AppSettings::InferSubcommands)
|
||||||
|
.subcommand(App::new("test").long_flag("test"))
|
||||||
|
.subcommand(App::new("testa").long_flag("testa"))
|
||||||
|
.subcommand(App::new("testb").long_flag("testb"))
|
||||||
|
.get_matches_from(vec!["prog", "--test"]);
|
||||||
|
assert_eq!(m.subcommand_name(), Some("test"));
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue