From 49cd3172c0c859e4fe0ea3f208b1306e5a91c3da Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 7 Jan 2025 10:32:03 -0600 Subject: [PATCH 1/2] test(parser): Verify ignore_errors with did-you-mean --- tests/builder/ignore_errors.rs | 35 +++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/tests/builder/ignore_errors.rs b/tests/builder/ignore_errors.rs index 702b7746e63..6070c17f383 100644 --- a/tests/builder/ignore_errors.rs +++ b/tests/builder/ignore_errors.rs @@ -1,4 +1,5 @@ -use clap::{arg, Arg, ArgAction, Command}; +use clap::{arg, error::ErrorKind, parser::ValueSource, Arg, ArgAction, Command}; +use snapbox::str; use super::utils; @@ -116,6 +117,38 @@ fn unexpected_argument() { assert_eq!(m.get_one::("unset-flag").copied(), Some(false)); } +#[test] +#[cfg(feature = "error-context")] +fn did_you_mean() { + let mut cmd = Command::new("cmd").arg(arg!(--"ignore-immutable")); + + // Verify we are in a "did you mean" error + let r = cmd.try_get_matches_from_mut(vec!["cmd", "--ig"]); + assert!(r.is_err()); + let err = r.unwrap_err(); + utils::assert_error(err, ErrorKind::UnknownArgument, str![[r#" +error: unexpected argument '--ig' found + + tip: a similar argument exists: '--ignore-immutable' + +Usage: cmd --ignore-immutable + +For more information, try '--help'. + +"#]], true); + + let r = cmd + .ignore_errors(true) + .try_get_matches_from(vec!["cmd", "--ig"]); + assert!(r.is_ok(), "unexpected error: {r:?}"); + let m = r.unwrap(); + assert!(m.contains_id("ignore-immutable"), "{m:#?}"); + assert_eq!( + m.value_source("ignore-immutable"), + Some(ValueSource::CommandLine) + ); +} + #[test] fn subcommand() { let cmd = Command::new("test") From c721b6cdc80ce43607d3a6666b7ea5ce5a40426f Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 7 Jan 2025 10:35:14 -0600 Subject: [PATCH 2/2] fix(parser): Set correct source on ignore-errors with did-you-mean Fixes #5867 --- clap_builder/src/parser/parser.rs | 8 +++++--- tests/builder/ignore_errors.rs | 11 ++++++++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/clap_builder/src/parser/parser.rs b/clap_builder/src/parser/parser.rs index 2949c3e1382..d787f89aa16 100644 --- a/clap_builder/src/parser/parser.rs +++ b/clap_builder/src/parser/parser.rs @@ -1571,9 +1571,11 @@ impl Parser<'_> { ); // Add the arg to the matches to build a proper usage string - if let Some((name, _)) = did_you_mean.as_ref() { - if let Some(arg) = self.cmd.get_keymap().get(&name.as_ref()) { - self.start_custom_arg(matcher, arg, ValueSource::CommandLine); + if !self.cmd.is_ignore_errors_set() { + if let Some((name, _)) = did_you_mean.as_ref() { + if let Some(arg) = self.cmd.get_keymap().get(&name.as_ref()) { + self.start_custom_arg(matcher, arg, ValueSource::CommandLine); + } } } let did_you_mean = did_you_mean.map(|(arg, cmd)| (format!("--{arg}"), cmd)); diff --git a/tests/builder/ignore_errors.rs b/tests/builder/ignore_errors.rs index 6070c17f383..8245b714b86 100644 --- a/tests/builder/ignore_errors.rs +++ b/tests/builder/ignore_errors.rs @@ -126,7 +126,10 @@ fn did_you_mean() { let r = cmd.try_get_matches_from_mut(vec!["cmd", "--ig"]); assert!(r.is_err()); let err = r.unwrap_err(); - utils::assert_error(err, ErrorKind::UnknownArgument, str![[r#" + utils::assert_error( + err, + ErrorKind::UnknownArgument, + str![[r#" error: unexpected argument '--ig' found tip: a similar argument exists: '--ignore-immutable' @@ -135,7 +138,9 @@ Usage: cmd --ignore-immutable For more information, try '--help'. -"#]], true); +"#]], + true, + ); let r = cmd .ignore_errors(true) @@ -145,7 +150,7 @@ For more information, try '--help'. assert!(m.contains_id("ignore-immutable"), "{m:#?}"); assert_eq!( m.value_source("ignore-immutable"), - Some(ValueSource::CommandLine) + Some(ValueSource::DefaultValue) ); }