Repository: clap-rs/clap
Pull request #4798 (2023-03-28 03:19:58)

fix(error): Give more idea why we are suggesting an arg
One challenge with this is finding something that generally works. Making this work perfectly for one setting will make it inconsistent with other settings and take up more binary size / compile time.

So in the end, I felt like just mirroring rustc (with a bit more brevity) seemed like a decent experiment.  This will be evaluated by the feedback on release.

This is a small part of #4638

<!--
Thanks for helping out!

Please link the appropriate issue from your PR.

If you don't have an issue, we'd recommend starting with one first so the PR can focus on the
implementation (unless its an obvious bug or documentation fix that will have
little conversation).
-->



Patch:
diff --git a/clap_builder/src/error/format.rs b/clap_builder/src/error/format.rs
index 6023b5c5..9f11846b 100644
--- a/clap_builder/src/error/format.rs
+++ b/clap_builder/src/error/format.rs
@@ -429,19 +429,22 @@ fn try_help(styled: &mut StyledStr, help: Option<&str>) {
 fn did_you_mean(styled: &mut StyledStr, context: &str, valid: &ContextValue) {
     if let ContextValue::String(valid) = valid {
         styled.none(TAB);
-        styled.good("tip: ");
+        styled.good("tip: a similar ");
         styled.none(context);
-        styled.none(" '");
+        styled.none(" exists: '");
         styled.good(valid);
-        styled.none("' exists");
+        styled.none("'");
     } else if let ContextValue::Strings(valid) = valid {
         styled.none(TAB);
-        styled.good("tip: ");
-        styled.none(context);
-        if valid.len() > 1 {
-            styled.none("s");
+        if valid.len() == 1 {
+            styled.good("tip: a similar ");
+            styled.none(context);
+            styled.none(" exists: ");
+        } else {
+            styled.good("tip: some similar ");
+            styled.none(context);
+            styled.none("s exist: ");
         }
-        styled.none(" ");
         for (i, valid) in valid.iter().enumerate() {
             if i != 0 {
                 styled.none(", ");
@@ -450,11 +453,6 @@ fn did_you_mean(styled: &mut StyledStr, context: &str, valid: &ContextValue) {
             styled.good(valid);
             styled.none("'");
         }
-        if valid.len() == 1 {
-            styled.none(" exists");
-        } else {
-            styled.none(" exist");
-        }
     }
 }
 


Test patch:
diff --git a/tests/builder/opts.rs b/tests/builder/opts.rs
index 8ca71966..7e61b763 100644
--- a/tests/builder/opts.rs
+++ b/tests/builder/opts.rs
@@ -448,7 +448,7 @@ fn did_you_mean() {
     static DYM: &str = "\
 error: unexpected argument '--optio' found
 
-  tip: argument '--option' exists
+  tip: a similar argument exists: '--option'
 
 Usage: clap-test --option <opt>... [positional] [positional2] [positional3]...
 
@@ -546,7 +546,7 @@ fn issue_1073_suboptimal_flag_suggestion() {
     static DYM_ISSUE_1073: &str = "\
 error: unexpected argument '--files-without-matches' found
 
-  tip: argument '--files-without-match' exists
+  tip: a similar argument exists: '--files-without-match'
 
 Usage: ripgrep-616 --files-without-match
 
diff --git a/tests/builder/possible_values.rs b/tests/builder/possible_values.rs
index eb3058d4..b3951727 100644
--- a/tests/builder/possible_values.rs
+++ b/tests/builder/possible_values.rs
@@ -181,7 +181,7 @@ fn possible_values_output() {
 error: invalid value 'slo' for '-O <option>'
   [possible values: slow, fast, \"ludicrous speed\"]
 
-  tip: value 'slow' exists
+  tip: a similar value exists: 'slow'
 
 For more information, try '--help'.
 ";
@@ -215,7 +215,7 @@ fn possible_values_alias_output() {
 error: invalid value 'slo' for '-O <option>'
   [possible values: slow, fast, \"ludicrous speed\"]
 
-  tip: value 'slow' exists
+  tip: a similar value exists: 'slow'
 
 For more information, try '--help'.
 ";
@@ -253,7 +253,7 @@ fn possible_values_hidden_output() {
 error: invalid value 'slo' for '-O <option>'
   [possible values: slow, fast, \"ludicrous speed\"]
 
-  tip: value 'slow' exists
+  tip: a similar value exists: 'slow'
 
 For more information, try '--help'.
 ";
@@ -292,7 +292,7 @@ fn escaped_possible_values_output() {
 error: invalid value 'ludicrous' for '-O <option>'
   [possible values: slow, fast, \"ludicrous speed\"]
 
-  tip: value 'ludicrous speed' exists
+  tip: a similar value exists: 'ludicrous speed'
 
 For more information, try '--help'.
 ";
diff --git a/tests/builder/subcommands.rs b/tests/builder/subcommands.rs
index f83e2ee1..c7be253d 100644
--- a/tests/builder/subcommands.rs
+++ b/tests/builder/subcommands.rs
@@ -100,7 +100,7 @@ fn subcmd_did_you_mean_output() {
     static DYM_SUBCMD: &str = "\
 error: unrecognized subcommand 'subcm'
 
-  tip: subcommand 'subcmd' exists
+  tip: a similar subcommand exists: 'subcmd'
   tip: to pass 'subcm' as a value, use 'dym -- subcm'
 
 Usage: dym [COMMAND]
@@ -120,7 +120,7 @@ fn subcmd_did_you_mean_output_ambiguous() {
     static DYM_SUBCMD_AMBIGUOUS: &str = "\
 error: unrecognized subcommand 'te'
 
-  tip: subcommands 'test', 'temp' exist
+  tip: some similar subcommands exist: 'test', 'temp'
   tip: to pass 'te' as a value, use 'dym -- te'
 
 Usage: dym [COMMAND]
@@ -517,7 +517,7 @@ For more information, try 'help'.
         static BAZ_EXPECTED: &str = "\
 error: unrecognized subcommand 'baz'
 
-  tip: subcommand 'bar' exists
+  tip: a similar subcommand exists: 'bar'
   tip: to pass 'baz' as a value, use ' -- baz'
 
 Usage: <COMMAND>