Repository: clap-rs/clap
Pull request #4288 (2022-09-29 14:54:34)

fix(error): Specialize the self-conflicts error
Inspired by rust-lang/cargo#11159


Patch:
diff --git a/examples/tutorial_builder/03_01_flag_bool.md b/examples/tutorial_builder/03_01_flag_bool.md
index 0842935f..71f6f906 100644
--- a/examples/tutorial_builder/03_01_flag_bool.md
+++ b/examples/tutorial_builder/03_01_flag_bool.md
@@ -17,7 +17,7 @@ verbose: true
 
 $ 03_01_flag_bool --verbose --verbose
 ? failed
-error: The argument '--verbose' cannot be used with '--verbose'
+error: The argument '--verbose' was provided more than once, but cannot be used multiple times
 
 Usage: 03_01_flag_bool[EXE] [OPTIONS]
 
diff --git a/examples/tutorial_derive/03_01_flag_bool.md b/examples/tutorial_derive/03_01_flag_bool.md
index 77975698..83f57fa6 100644
--- a/examples/tutorial_derive/03_01_flag_bool.md
+++ b/examples/tutorial_derive/03_01_flag_bool.md
@@ -17,7 +17,7 @@ verbose: true
 
 $ 03_01_flag_bool_derive --verbose --verbose
 ? failed
-error: The argument '--verbose' cannot be used with '--verbose'
+error: The argument '--verbose' was provided more than once, but cannot be used multiple times
 
 Usage: 03_01_flag_bool_derive[EXE] [OPTIONS]
 
diff --git a/src/error/format.rs b/src/error/format.rs
index eec7867c..15208b32 100644
--- a/src/error/format.rs
+++ b/src/error/format.rs
@@ -90,26 +90,32 @@ fn write_dynamic_context(error: &crate::error::Error, styled: &mut StyledStr) ->
             if let (Some(ContextValue::String(invalid_arg)), Some(prior_arg)) =
                 (invalid_arg, prior_arg)
             {
-                styled.none("The argument '");
-                styled.warning(invalid_arg);
-                styled.none("' cannot be used with");
+                if ContextValue::String(invalid_arg.clone()) == *prior_arg {
+                    styled.none("The argument '");
+                    styled.warning(invalid_arg);
+                    styled.none("' was provided more than once, but cannot be used multiple times");
+                } else {
+                    styled.none("The argument '");
+                    styled.warning(invalid_arg);
+                    styled.none("' cannot be used with");
 
-                match prior_arg {
-                    ContextValue::Strings(values) => {
-                        styled.none(":");
-                        for v in values {
-                            styled.none("\n");
-                            styled.none(TAB);
-                            styled.warning(&**v);
+                    match prior_arg {
+                        ContextValue::Strings(values) => {
+                            styled.none(":");
+                            for v in values {
+                                styled.none("\n");
+                                styled.none(TAB);
+                                styled.warning(&**v);
+                            }
+                        }
+                        ContextValue::String(value) => {
+                            styled.none(" '");
+                            styled.warning(value);
+                            styled.none("'");
+                        }
+                        _ => {
+                            styled.none(" one or more of the other specified arguments");
                         }
-                    }
-                    ContextValue::String(value) => {
-                        styled.none(" '");
-                        styled.warning(value);
-                        styled.none("'");
-                    }
-                    _ => {
-                        styled.none(" one or more of the other specified arguments");
                     }
                 }
                 true


Test patch:
diff --git a/tests/builder/conflicts.rs b/tests/builder/conflicts.rs
index 44393ef4..dbee06b1 100644
--- a/tests/builder/conflicts.rs
+++ b/tests/builder/conflicts.rs
@@ -309,6 +309,20 @@ For more information try '--help'
     );
 }
 
+#[test]
+#[cfg(feature = "error-context")]
+fn conflict_output_repeat() {
+    static ERR: &str = "\
+error: The argument '-F' was provided more than once, but cannot be used multiple times
+
+Usage: clap-test [OPTIONS] [positional] [positional2] [positional3]... [COMMAND]
+
+For more information try '--help'
+";
+
+    utils::assert_output(utils::complex_app(), "clap-test -F -F", ERR, true);
+}
+
 #[test]
 #[cfg(feature = "error-context")]
 fn conflict_output_with_required() {