clap-rs / clap

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

Error messages / `ContextKind::InvalidArg` should show the flag used instead of always using `long` #5748

Open mamekoro opened 3 weeks ago

mamekoro commented 3 weeks ago

Please complete the following tasks

Rust Version

rustc 1.81.0 (eeb90cda1 2024-09-04)

Clap Version

4.5.18

Minimal reproducible code

use clap::Parser;

#[derive(Debug, Parser)]
struct Cli {
    #[arg(short, long)]
    name: String,
}

fn main() {
    let error = Cli::try_parse_from(["program", "-n"]).unwrap_err();
    for context in error.context() {
        println!("{context:?}");
    }
}

Steps to reproduce the bug with the above code

cargo add clap --features derive
cargo run

Actual Behaviour

(InvalidArg, String("--name <NAME>"))
(InvalidValue, String(""))
(ValidValue, Strings([]))

Expected Behaviour

The value of InvalidArg should be "-n <NAME>" because the user passed -n, not --name.

(InvalidArg, String("-n <NAME>"))
(InvalidValue, String(""))
(ValidValue, Strings([]))

Additional Context

If I use parse_from like this:

fn main() {
    Cli::parse_from(["program", "-n"]);
}

I get the following error message:

error: a value is required for '--name <NAME>' but none was supplied

For more information, try '--help'.

Again, the long option --name is used.

This can be confusing to users because the actual arguments and the arguments displayed in the error message are different.

Debug Output

[clap_builder::builder::command]Command::_do_parse
[clap_builder::builder::command]Command::_build: name="opt"
[clap_builder::builder::command]Command::_propagate:opt
[clap_builder::builder::command]Command::_check_help_and_version:opt expand_help_tree=false
[clap_builder::builder::command]Command::long_help_exists
[clap_builder::builder::command]Command::_check_help_and_version: Building default --help
[clap_builder::builder::command]Command::_propagate_global_args:opt
[clap_builder::builder::debug_asserts]Command::_debug_asserts
[clap_builder::builder::debug_asserts]Arg::_debug_asserts:name
[clap_builder::builder::debug_asserts]Arg::_debug_asserts:help
[clap_builder::builder::debug_asserts]Command::_verify_positionals
[clap_builder::parser::parser]Parser::get_matches_with
[clap_builder::parser::parser]Parser::get_matches_with: Begin parsing '"-n"'
[clap_builder::parser::parser]Parser::possible_subcommand: arg=Ok("-n")
[clap_builder::parser::parser]Parser::get_matches_with: sc=None
[clap_builder::parser::parser]Parser::parse_short_arg: short_arg=ShortFlags { inner: "n", utf8_prefix: CharIndices { front_offset: 0, iter: Chars(['n']) }, invalid_suffix: None }
[clap_builder::parser::parser]Parser::parse_short_arg:iter:n
[clap_builder::parser::parser]Parser::parse_short_arg:iter:n: Found valid opt or flag
[clap_builder::parser::parser]Parser::parse_short_arg:iter:n: val="", short_arg=ShortFlags { inner: "n", utf8_prefix: CharIndices { front_offset: 1, iter: Chars([]) }, invalid_suffix: None }
[clap_builder::parser::parser]Parser::parse_opt_value; arg=name, val=None, has_eq=false
[clap_builder::parser::parser]Parser::parse_opt_value; arg.settings=ArgFlags(1)
[clap_builder::parser::parser]Parser::parse_opt_value; Checking for val...
[clap_builder::parser::parser]Parser::parse_opt_value: More arg vals required...
[clap_builder::parser::parser]Parser::get_matches_with: After parse_short_arg Opt("name")
[clap_builder::parser::parser]Parser::resolve_pending: id="name"
[clap_builder::parser::parser]Parser::react action=Set, identifier=Some(Short), source=CommandLine
[clap_builder::builder::command]Command::color: Color setting...
[clap_builder::builder::command]Auto
[clap_builder::builder::command]Command::color: Color setting...
[clap_builder::builder::command]Auto
(InvalidArg, String("--name <NAME>"))
(InvalidValue, String(""))
(ValidValue, Strings([]))
epage commented 3 weeks ago

Huh, I thought we had an issue for this but I wonder if I'm thinking of #791 which is related but still different.

This and #791 are blocked on #3048 as we'd need to carry forward what argument was used to report it back.