mirror of
https://github.com/clap-rs/clap
synced 2024-12-14 14:52:33 +00:00
imp(Suggestions): suggests to use flag after subcommand when applicable
If an invalid flag is found and this flag is a valid flag for a sub-command, suggest using it after the subcommand fix https://github.com/kbknapp/clap-rs/issues/927
This commit is contained in:
parent
49f9dc166a
commit
2671ca7260
3 changed files with 37 additions and 31 deletions
|
@ -1662,11 +1662,10 @@ impl<'a, 'b> Parser<'a, 'b>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn did_you_mean_error(&self, arg: &str, matcher: &mut ArgMatcher<'a>) -> ClapResult<()> {
|
fn did_you_mean_error(&self, arg: &str, matcher: &mut ArgMatcher<'a>) -> ClapResult<()> {
|
||||||
// Didn't match a flag or option...maybe it was a typo and close to one
|
|
||||||
|
// Didn't match a flag or option
|
||||||
let suffix =
|
let suffix =
|
||||||
suggestions::did_you_mean_suffix(arg,
|
suggestions::did_you_mean_arg_suffix(arg, longs!(self), &self.subcommands);
|
||||||
longs!(self),
|
|
||||||
suggestions::DidYouMeanMessageStyle::LongFlag);
|
|
||||||
|
|
||||||
// Add the arg to the matches to build a proper usage string
|
// Add the arg to the matches to build a proper usage string
|
||||||
if let Some(name) = suffix.1 {
|
if let Some(name) = suffix.1 {
|
||||||
|
|
|
@ -483,9 +483,9 @@ impl Error {
|
||||||
when: color,
|
when: color,
|
||||||
});
|
});
|
||||||
let suffix =
|
let suffix =
|
||||||
suggestions::did_you_mean_suffix(bad_val.as_ref(),
|
suggestions::did_you_mean_value_suffix(
|
||||||
good_vals.iter(),
|
bad_val.as_ref(),
|
||||||
suggestions::DidYouMeanMessageStyle::EnumValue);
|
good_vals.iter());
|
||||||
|
|
||||||
let mut sorted = vec![];
|
let mut sorted = vec![];
|
||||||
for v in good_vals {
|
for v in good_vals {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use app::App;
|
||||||
// Third Party
|
// Third Party
|
||||||
#[cfg(feature = "suggestions")]
|
#[cfg(feature = "suggestions")]
|
||||||
use strsim;
|
use strsim;
|
||||||
|
@ -40,42 +41,48 @@ pub fn did_you_mean<'a, T: ?Sized, I>(_: &str, _: I) -> Option<&'a str>
|
||||||
|
|
||||||
/// Returns a suffix that can be empty, or is the standard 'did you mean' phrase
|
/// Returns a suffix that can be empty, or is the standard 'did you mean' phrase
|
||||||
#[cfg_attr(feature = "lints", allow(needless_lifetimes))]
|
#[cfg_attr(feature = "lints", allow(needless_lifetimes))]
|
||||||
pub fn did_you_mean_suffix<'z, T, I>(arg: &str,
|
pub fn did_you_mean_flag_suffix<'z, T, I>(arg: &str, longs: I, subcommands: &'z [App])
|
||||||
values: I,
|
|
||||||
style: DidYouMeanMessageStyle)
|
|
||||||
-> (String, Option<&'z str>)
|
-> (String, Option<&'z str>)
|
||||||
where T: AsRef<str> + 'z,
|
where T: AsRef<str> + 'z,
|
||||||
I: IntoIterator<Item = &'z T>
|
I: IntoIterator<Item = &'z T>
|
||||||
|
{
|
||||||
|
match did_you_mean(arg, longs) {
|
||||||
|
Some(candidate) => {
|
||||||
|
let suffix = format!("\n\tDid you mean {}{}?", Format::Good("--"), Format::Good(candidate));
|
||||||
|
return (suffix, Some(candidate))
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
for subcommand in subcommands {
|
||||||
|
let opts = subcommand.p.flags.iter().filter_map(|f| f.s.long).chain(
|
||||||
|
subcommand.p.opts.iter().filter_map(|o| o.s.long));
|
||||||
|
|
||||||
|
if let Some(candidate) = did_you_mean(arg, opts) {
|
||||||
|
let suffix = format!(
|
||||||
|
"\n\tDid you mean to put '--{}' after the subcommand '{}'?",
|
||||||
|
Format::Good(arg),
|
||||||
|
Format::Good(candidate));
|
||||||
|
return (suffix, Some(candidate));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (String::new(), None)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a suffix that can be empty, or is the standard 'did you mean' phrase
|
||||||
|
pub fn did_you_mean_value_suffix<'z, T, I>(arg: &str, values: I) -> (String, Option<&'z str>)
|
||||||
|
where T: AsRef<str> + 'z,
|
||||||
|
I: IntoIterator<Item = &'z T>
|
||||||
{
|
{
|
||||||
match did_you_mean(arg, values) {
|
match did_you_mean(arg, values) {
|
||||||
Some(candidate) => {
|
Some(candidate) => {
|
||||||
let mut suffix = "\n\tDid you mean ".to_owned();
|
let suffix = format!("\n\tDid you mean '{}'?", Format::Good(candidate));
|
||||||
match style {
|
|
||||||
DidYouMeanMessageStyle::LongFlag => {
|
|
||||||
suffix.push_str(&Format::Good("--").to_string())
|
|
||||||
}
|
|
||||||
DidYouMeanMessageStyle::EnumValue => suffix.push('\''),
|
|
||||||
}
|
|
||||||
suffix.push_str(&Format::Good(candidate).to_string()[..]);
|
|
||||||
if let DidYouMeanMessageStyle::EnumValue = style {
|
|
||||||
suffix.push('\'');
|
|
||||||
}
|
|
||||||
suffix.push_str("?");
|
|
||||||
(suffix, Some(candidate))
|
(suffix, Some(candidate))
|
||||||
}
|
}
|
||||||
None => (String::new(), None),
|
None => (String::new(), None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A helper to determine message formatting
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
|
||||||
pub enum DidYouMeanMessageStyle {
|
|
||||||
/// Suggested value is a long flag
|
|
||||||
LongFlag,
|
|
||||||
/// Suggested value is one of various possible values
|
|
||||||
EnumValue,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(all(test, features = "suggestions"))]
|
#[cfg(all(test, features = "suggestions"))]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
Loading…
Reference in a new issue