mirror of
https://github.com/clap-rs/clap
synced 2025-01-18 23:53:54 +00:00
fix(lex): Make long args more convinient
This commit is contained in:
parent
1247a955cf
commit
6291289c0f
4 changed files with 53 additions and 25 deletions
|
@ -10,7 +10,6 @@ use std::ops::Index;
|
|||
use std::path::Path;
|
||||
|
||||
// Third Party
|
||||
use os_str_bytes::RawOsStr;
|
||||
#[cfg(feature = "yaml")]
|
||||
use yaml_rust::Yaml;
|
||||
|
||||
|
@ -4655,7 +4654,7 @@ impl<'help> App<'help> {
|
|||
}
|
||||
|
||||
/// Find a flag subcommand name by long flag or an alias
|
||||
pub(crate) fn find_long_subcmd(&self, long: &RawOsStr) -> Option<&str> {
|
||||
pub(crate) fn find_long_subcmd(&self, long: &str) -> Option<&str> {
|
||||
self.get_subcommands()
|
||||
.find(|sc| sc.long_flag_aliases_to(long))
|
||||
.map(|sc| sc.get_name())
|
||||
|
|
|
@ -49,6 +49,15 @@ impl PartialEq<&str> for KeyType {
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialEq<str> for KeyType {
|
||||
fn eq(&self, rhs: &str) -> bool {
|
||||
match self {
|
||||
KeyType::Long(l) => l == rhs,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<OsStr> for KeyType {
|
||||
fn eq(&self, rhs: &OsStr) -> bool {
|
||||
match self {
|
||||
|
|
|
@ -124,14 +124,28 @@ impl<'s> ParsedArg<'s> {
|
|||
/// Treat as a long-flag
|
||||
///
|
||||
/// **NOTE:** May return an empty flag. Check [`ParsedArg::is_escape`] to separately detect `--`.
|
||||
pub fn to_long(&self) -> Option<(&RawOsStr, Option<&RawOsStr>)> {
|
||||
let remainder = self.inner.as_ref().strip_prefix("--")?;
|
||||
let parts = if let Some((p0, p1)) = remainder.split_once("=") {
|
||||
(p0, Some(p1))
|
||||
pub fn to_long(&self) -> Option<(Result<&str, &RawOsStr>, Option<&RawOsStr>)> {
|
||||
if let Some(raw) = self.utf8 {
|
||||
let remainder = raw.strip_prefix("--")?;
|
||||
let (flag, value) = if let Some((p0, p1)) = remainder.split_once("=") {
|
||||
(p0, Some(p1))
|
||||
} else {
|
||||
(remainder, None)
|
||||
};
|
||||
let flag = Ok(flag);
|
||||
let value = value.map(RawOsStr::from_str);
|
||||
Some((flag, value))
|
||||
} else {
|
||||
(remainder, None)
|
||||
};
|
||||
Some(parts)
|
||||
let raw = self.inner.as_ref();
|
||||
let remainder = raw.strip_prefix("--")?;
|
||||
let (flag, value) = if let Some((p0, p1)) = remainder.split_once("=") {
|
||||
(p0, Some(p1))
|
||||
} else {
|
||||
(remainder, None)
|
||||
};
|
||||
let flag = flag.to_str().ok_or_else(|| flag);
|
||||
Some((flag, value))
|
||||
}
|
||||
}
|
||||
|
||||
/// Can treat as a long-flag
|
||||
|
|
|
@ -568,21 +568,18 @@ impl<'help, 'cmd> Parser<'help, 'cmd> {
|
|||
}
|
||||
|
||||
// Checks if the arg matches a long flag subcommand name, or any of its aliases (if defined)
|
||||
fn possible_long_flag_subcommand(&self, arg_os: &RawOsStr) -> Option<&str> {
|
||||
debug!("Parser::possible_long_flag_subcommand: arg={:?}", arg_os);
|
||||
fn possible_long_flag_subcommand(&self, arg: &str) -> Option<&str> {
|
||||
debug!("Parser::possible_long_flag_subcommand: arg={:?}", arg);
|
||||
if self.cmd.is_infer_subcommands_set() {
|
||||
let options = self
|
||||
.cmd
|
||||
.get_subcommands()
|
||||
.fold(Vec::new(), |mut options, sc| {
|
||||
if let Some(long) = sc.get_long_flag() {
|
||||
if RawOsStr::from_str(long).starts_with_os(arg_os) {
|
||||
if long.starts_with(arg) {
|
||||
options.push(long);
|
||||
}
|
||||
options.extend(
|
||||
sc.get_all_aliases()
|
||||
.filter(|alias| RawOsStr::from_str(alias).starts_with_os(arg_os)),
|
||||
)
|
||||
options.extend(sc.get_all_aliases().filter(|alias| alias.starts_with(arg)))
|
||||
}
|
||||
options
|
||||
});
|
||||
|
@ -591,11 +588,11 @@ impl<'help, 'cmd> Parser<'help, 'cmd> {
|
|||
}
|
||||
|
||||
for sc in options {
|
||||
if sc == arg_os {
|
||||
if sc == arg {
|
||||
return Some(sc);
|
||||
}
|
||||
}
|
||||
} else if let Some(sc_name) = self.cmd.find_long_subcmd(arg_os) {
|
||||
} else if let Some(sc_name) = self.cmd.find_long_subcmd(arg) {
|
||||
return Some(sc_name);
|
||||
}
|
||||
None
|
||||
|
@ -827,7 +824,7 @@ impl<'help, 'cmd> Parser<'help, 'cmd> {
|
|||
fn parse_long_arg(
|
||||
&mut self,
|
||||
matcher: &mut ArgMatcher,
|
||||
long_arg: &RawOsStr,
|
||||
long_arg: Result<&str, &RawOsStr>,
|
||||
long_value: Option<&RawOsStr>,
|
||||
parse_state: &ParseState,
|
||||
valid_arg_found: &mut bool,
|
||||
|
@ -847,24 +844,31 @@ impl<'help, 'cmd> Parser<'help, 'cmd> {
|
|||
debug!("Parser::parse_long_arg: cur_idx:={}", self.cur_idx.get());
|
||||
|
||||
debug!("Parser::parse_long_arg: Does it contain '='...");
|
||||
let long_arg = match long_arg {
|
||||
Ok(long_arg) => long_arg,
|
||||
Err(long_arg) => {
|
||||
return ParseResult::NoMatchingArg {
|
||||
arg: long_arg.to_str_lossy().into_owned(),
|
||||
};
|
||||
}
|
||||
};
|
||||
if long_arg.is_empty() {
|
||||
debug_assert!(long_value.is_none(), "{:?}", long_value);
|
||||
return ParseResult::NoArg;
|
||||
}
|
||||
|
||||
let opt = if let Some(opt) = self.cmd.get_keymap().get(&*long_arg.to_os_str()) {
|
||||
let opt = if let Some(opt) = self.cmd.get_keymap().get(long_arg) {
|
||||
debug!(
|
||||
"Parser::parse_long_arg: Found valid opt or flag '{}'",
|
||||
opt.to_string()
|
||||
);
|
||||
Some(opt)
|
||||
} else if self.cmd.is_infer_long_args_set() {
|
||||
let arg_str = long_arg.to_str_lossy();
|
||||
self.cmd.get_arguments().find(|a| {
|
||||
a.long.map_or(false, |long| long.starts_with(&*arg_str))
|
||||
a.long.map_or(false, |long| long.starts_with(long_arg))
|
||||
|| a.aliases
|
||||
.iter()
|
||||
.any(|(alias, _)| alias.starts_with(&*arg_str))
|
||||
.any(|(alias, _)| alias.starts_with(long_arg))
|
||||
})
|
||||
} else {
|
||||
None
|
||||
|
@ -898,7 +902,9 @@ impl<'help, 'cmd> Parser<'help, 'cmd> {
|
|||
used,
|
||||
arg: opt.to_string(),
|
||||
}
|
||||
} else if let Some(parse_result) = self.check_for_help_and_version_str(long_arg) {
|
||||
} else if let Some(parse_result) =
|
||||
self.check_for_help_and_version_str(RawOsStr::from_str(long_arg))
|
||||
{
|
||||
parse_result
|
||||
} else {
|
||||
debug!("Parser::parse_long_arg: Presence validated");
|
||||
|
@ -910,7 +916,7 @@ impl<'help, 'cmd> Parser<'help, 'cmd> {
|
|||
ParseResult::MaybeHyphenValue
|
||||
} else {
|
||||
ParseResult::NoMatchingArg {
|
||||
arg: long_arg.to_str_lossy().into_owned(),
|
||||
arg: long_arg.to_owned(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue