clap-rs / clap

A full featured, fast Command Line Argument Parser for Rust
docs.rs/clap
Apache License 2.0
13.65k stars 1.02k forks source link

Optional flag argument conflicts with required subcommand #5455

Closed domenkozar closed 2 months ago

domenkozar commented 2 months ago

Please complete the following tasks

Rust Version

1.76

Clap Version

4.5.4

Minimal reproducible code


use clap::{Parser, Subcommand};

#[derive(Parser, Debug)]
#[command(subcommand_required = true)]
struct Cli {
    #[arg(
        short,
        long,
        value_delimiter = ',',
    )]
    arg: Option<Vec<String>>,

    #[command(subcommand)]
    command: Subcommands,
}

#[derive(Subcommand, Clone, Debug)]
enum Subcommands {
    #[command()]
    Subcommand { },
}

fn main() {
    let cli = Cli::parse();
    println!("{:?}", cli);
}

Steps to reproduce the bug with the above code

❯ cargo run -- --arg subcommand
    Finished dev [unoptimized + debuginfo] target(s) in 0.03s
     Running `target/debug/clap-arg-subcommand --arg subcommand`
error: 'clap-arg-subcommand' requires a subcommand but one was not provided
  [subcommands: subcommand, help]

Usage: clap-arg-subcommand [OPTIONS] <COMMAND>

For more information, try '--help'.

Actual Behaviour

--arg consumed subcommand as an arg and then complains about missing subcommand

Expected Behaviour

❯ cargo run -- --arg subcommand
Cli { arg: Some([]), command: Subcommand }

❯ cargo run -- subcommand
Cli { arg: None, command: Subcommand }

❯ cargo run -- --arg arg1 subcommand
Cli { arg: Some(["arg1"]), command: Subcommand }

❯ cargo run -- --arg arg1,arg2 subcommand
Cli { arg: Some(["arg1", "arg2"]), command: Subcommand }

Additional Context

No response

Debug Output

No response

epage commented 2 months ago

Try enabling #[command(subcommand_precedence_over_arg = true)]

domenkozar commented 2 months ago

Thanks, I assume there's a good reason it's not on by default :)