Repository: clap-rs/clap (Rust)

Issue:
Arguments with takes_value(false) still accept "compact"-style arguments
# Rust Version

* 1.37.0

### Affected Version of clap

* 2.33.0

### Bug or Feature Request Summary

Arguments configured to not take a value still successfully parse from the `--key=value` form.

### Expected Behavior Summary

The command line should fail to validate (or only accept `--key=true` or `--key=false`.

### Actual Behavior Summary

The command line successfully validates as if it just contained `--key`.

### Sample Code or Link to Sample Code

```rust
use clap::*;

fn main() {
    let matches = App::new("foo")
        .arg(Arg::with_name("foobar").long("foobar").takes_value(false).multiple(false))
        .get_matches_from(["foo", "--foobar=false"].iter());
    println!("{:?}", matches)
}
```
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=d08679674fa982b892dcc26d8ed8bb25


Discussion:
Can we reopen this issue? I tested this from the tip of the git tree and the problem is still happening, also I faced the same issue on my own code using `3.1.6`.

Modify `tests/builder/multiple_occurrences.rs` (just for the sake of quick dirty test)

```rust
#[cfg(feature = "env")]
#[test]
fn multiple_occurrences_of_before_env() {
    let cmd = Command::new("mo_before_env").arg(
        Arg::new("verbose")
            .env("VERBOSE")
            .short('v')
            .long("verbose")
            .takes_value(false)
            .multiple_occurrences(true),
    );

    let m = cmd.clone().try_get_matches_from(vec![""]);
    assert!(m.is_ok(), "{}", m.unwrap_err());
    assert_eq!(m.unwrap().occurrences_of("verbose"), 0);

    let m = cmd.clone().try_get_matches_from(vec!["", "-v"]);
    assert!(m.is_ok(), "{}", m.unwrap_err());
    assert_eq!(m.unwrap().occurrences_of("verbose"), 1);

    let m = cmd.clone().try_get_matches_from(vec!["", "-vv"]);
    assert!(m.is_ok(), "{}", m.unwrap_err());
    assert_eq!(m.unwrap().occurrences_of("verbose"), 2);
    let m = cmd.clone().try_get_matches_from(vec!["", "-vvv"]);
    assert!(m.is_ok(), "{}", m.unwrap_err());
    assert_eq!(m.unwrap().occurrences_of("verbose"), 3);

    // this chunk of code is added to test
    // notice `-vvv=false`, test result is fine, no error out
    let m = cmd.clone().try_get_matches_from(vec!["", "-vvv=false"]);
    assert!(m.is_ok(), "{}", m.unwrap_err());
    assert_eq!(m.unwrap().occurrences_of("verbose"), 3);
}
```

as well I didn't see relevant changes that fix this issue in #2619.
My apology if I'm wrong nor missing something.

I just tried reproducing with the code sample you gave and it failed
```
thread 'multiple_occurrences::multiple_occurrences_of_before_env' panicked at 'error: Found argument '-=' which wasn't expected, or isn't valid in this context

        If you tried to supply `-=` as a value rather than a flag, use `-- -=`

USAGE:
    mo_before_env [OPTIONS]

For more information try --help
', tests/builder/multiple_occurrences.rs:128:5
```



Patch:
diff --git a/src/parse/parser.rs b/src/parse/parser.rs
index 04dc6c96137..6d5fa9b4655 100644
--- a/src/parse/parser.rs
+++ b/src/parse/parser.rs
@@ -1075,11 +1075,38 @@ impl<'help, 'app> Parser<'help, 'app> {
             self.app.settings.set(AS::ValidArgFound);
             self.seen.push(opt.id.clone());
             if opt.is_set(ArgSettings::TakesValue) {
+                debug!(
+                    "Parser::parse_long_arg: Found an opt with value '{:?}'",
+                    &val
+                );
                 return self.parse_opt(&val, opt, matcher);
-            } else {
-                self.check_for_help_and_version_str(&arg)?;
-                return Ok(self.parse_flag(opt, matcher));
             }
+            debug!("Parser::parse_long_arg: Found a flag");
+            if let Some(rest) = val {
+                debug!(
+                    "Parser::parse_long_arg: Got invalid literal `{:?}`",
+                    rest.to_os_string()
+                );
+                let used: Vec<Id> = matcher
+                    .arg_names()
+                    .filter(|&n| {
+                        self.app.find(n).map_or(true, |a| {
+                            !(a.is_set(ArgSettings::Hidden) || self.required.contains(&a.id))
+                        })
+                    })
+                    .cloned()
+                    .collect();
+
+                return Err(ClapError::too_many_values(
+                    rest.to_string_lossy().into(),
+                    opt,
+                    Usage::new(self).create_usage_no_title(&used),
+                    self.app.color(),
+                ));
+            }
+            self.check_for_help_and_version_str(&arg)?;
+            debug!("Parser::parse_long_arg: Presence validated");
+            return Ok(self.parse_flag(opt, matcher));
         }
 
         if let Some(sc_name) = self.possible_long_flag_subcommand(&arg) {


Test patch:
diff --git a/tests/flags.rs b/tests/flags.rs
index 8502676ba01..a3e561de9f9 100644
--- a/tests/flags.rs
+++ b/tests/flags.rs
@@ -87,6 +87,17 @@ fn flag_using_long() {
     assert!(m.is_present("color"));
 }
 
+#[test]
+fn flag_using_long_with_literals() {
+    use clap::ErrorKind;
+
+    let m = App::new("flag")
+        .arg(Arg::new("rainbow").long("rainbow"))
+        .try_get_matches_from(vec!["", "--rainbow=false"]);
+    assert!(m.is_err(), "{:#?}", m.unwrap());
+    assert_eq!(m.unwrap_err().kind, ErrorKind::TooManyValues);
+}
+
 #[test]
 fn flag_using_mixed() {
     let m = App::new("flag")