Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ArgMatcher with max_values consumes one more argument than it should #1480

Closed
sphynx opened this issue May 28, 2019 · 0 comments · Fixed by #1802
Closed

ArgMatcher with max_values consumes one more argument than it should #1480

sphynx opened this issue May 28, 2019 · 0 comments · Fixed by #1802
Labels
C-bug Category: Updating dependencies
Milestone

Comments

@sphynx
Copy link
Contributor

sphynx commented May 28, 2019

Rust Version

rustc-1.36.0-nightly

Affected Version of clap

2.33.0

Bug or Feature Request Summary

If I set max_values = 1 for an option I expect that the option should consume only one argument and leave the rest for the next parsers. However, due to one-off error in ArgMatcher, it now consumes two arguments (and then fails validation, because it took one more than it should).

For example, I expect that:

prog --field 1 FILE

Should be parsed correct if --field has max-values=1 and FILE is a positional arguments. However, FILE is consumed by ArgMatcher as the second value for the --file option, which then leads to validation error.

Steps to Reproduce the issue

cargo run

Sample Code or Link to Sample Code

use clap::{App, Arg};

fn main() {
    let res = App::new("prog")
        .arg(
            Arg::with_name("field")
                .takes_value(true)
                .multiple(false)
                .max_values(1)
                .long("field"),
        )
        .arg(
            Arg::with_name("positional")
                .required(true)
                .index(1),
        )
        .get_matches_from_safe(vec!["prog", "--field", "1", "file"]);

    assert!(res.is_ok());
}

Debug output

Compile clap with cargo features "debug" such as:

[dependencies]
clap = { version = "2", features = ["debug"] }
Debug Output

DEBUG:clap:Parser::propagate_settings: self=prog, g_settings=AppFlags(
(empty),
)
DEBUG:clap:Parser::get_matches_with;
DEBUG:clap:Parser::create_help_and_version;
DEBUG:clap:Parser::create_help_and_version: Building --help
DEBUG:clap:Parser::create_help_and_version: Building --version
DEBUG:clap:Parser::get_matches_with: Begin parsing '"--field"' ([45, 45, 102, 105, 101, 108, 100])
DEBUG:clap:Parser::is_new_arg:"--field":NotFound
DEBUG:clap:Parser::is_new_arg: arg_allows_tac=false
DEBUG:clap:Parser::is_new_arg: -- found
DEBUG:clap:Parser::is_new_arg: starts_new_arg=true
DEBUG:clap:Parser::possible_subcommand: arg="--field"
DEBUG:clap:Parser::get_matches_with: possible_sc=false, sc=None
DEBUG:clap:ArgMatcher::process_arg_overrides:None;
DEBUG:clap:Parser::parse_long_arg;
DEBUG:clap:Parser::parse_long_arg: Does it contain '='...No
DEBUG:clap:OptBuilder::fmt:field
DEBUG:clap:Parser::parse_long_arg: Found valid opt '--field '
DEBUG:clap:Parser::parse_opt; opt=field, val=None
DEBUG:clap:Parser::parse_opt; opt.settings=ArgFlags(EMPTY_VALS | TAKES_VAL | DELIM_NOT_SET)
DEBUG:clap:Parser::parse_opt; Checking for val...None
DEBUG:clap:ArgMatcher::inc_occurrence_of: arg=field
DEBUG:clap:ArgMatcher::inc_occurrence_of: first instance
DEBUG:clap:Parser::groups_for_arg: name=field
DEBUG:clap:Parser::groups_for_arg: No groups defined
DEBUG:clap:Parser::parse_opt: More arg vals required...
DEBUG:clap:Parser:get_matches_with: After parse_long_arg Opt("field")
DEBUG:clap:Parser::get_matches_with: Begin parsing '"1"' ([49])
DEBUG:clap:Parser::is_new_arg:"1":Opt("field")
DEBUG:clap:Parser::is_new_arg: arg_allows_tac=false
DEBUG:clap:Parser::is_new_arg: probably value
DEBUG:clap:Parser::is_new_arg: starts_new_arg=false
DEBUG:clap:Parser::add_val_to_arg; arg=field, val="1"
DEBUG:clap:Parser::add_val_to_arg; trailing_vals=false, DontDelimTrailingVals=false
DEBUG:clap:Parser::add_single_val_to_arg;
DEBUG:clap:Parser::add_single_val_to_arg: adding val..."1"
DEBUG:clap:Parser::groups_for_arg: name=field
DEBUG:clap:Parser::groups_for_arg: No groups defined
DEBUG:clap:ArgMatcher::needs_more_vals: o=field
DEBUG:clap:ArgMatcher::needs_more_vals: max_vals...1
DEBUG:clap:Parser::get_matches_with: Begin parsing '"file"' ([102, 105, 108, 101])
DEBUG:clap:Parser::is_new_arg:"file":Opt("field")
DEBUG:clap:Parser::is_new_arg: arg_allows_tac=false
DEBUG:clap:Parser::is_new_arg: probably value
DEBUG:clap:Parser::is_new_arg: starts_new_arg=false
DEBUG:clap:Parser::add_val_to_arg; arg=field, val="file"
DEBUG:clap:Parser::add_val_to_arg; trailing_vals=false, DontDelimTrailingVals=false
DEBUG:clap:Parser::add_single_val_to_arg;
DEBUG:clap:Parser::add_single_val_to_arg: adding val..."file"
DEBUG:clap:Parser::groups_for_arg: name=field
DEBUG:clap:Parser::groups_for_arg: No groups defined
DEBUG:clap:ArgMatcher::needs_more_vals: o=field
DEBUG:clap:ArgMatcher::needs_more_vals: max_vals...1
DEBUG:clap:ArgMatcher::process_arg_overrides:Some("field");
DEBUG:clap:Parser::remove_overrides:[];
DEBUG:clap:Validator::validate;
DEBUG:clap:Parser::add_defaults;
DEBUG:clap:Parser::add_defaults:iter:field: doesn't have conditional defaults
DEBUG:clap:Parser::add_defaults:iter:field: doesn't have default vals
DEBUG:clap:Parser::add_defaults:iter:positional: doesn't have conditional defaults
DEBUG:clap:Parser::add_defaults:iter:positional: doesn't have default vals
DEBUG:clap:Validator::validate_blacklist;
DEBUG:clap:Validator::validate_blacklist:iter:field;
DEBUG:clap:Parser::groups_for_arg: name=field
DEBUG:clap:Parser::groups_for_arg: No groups defined
DEBUG:clap:Validator::validate_required: required=["positional"];
DEBUG:clap:Validator::validate_required:iter:positional:
DEBUG:clap:Validator::is_missing_required_ok: a=positional
DEBUG:clap:Validator::validate_arg_conflicts: a="positional";
DEBUG:clap:Validator::validate_required_unless: a="positional";
DEBUG:clap:Validator::missing_required_error: extra=None
DEBUG:clap:Parser::color;
DEBUG:clap:Parser::color: Color setting...Auto
DEBUG:clap:is_a_tty: stderr=true
DEBUG:clap:Validator::missing_required_error: reqs=[
"positional",
]
DEBUG:clap:usage::get_required_usage_from: reqs=["positional"], extra=None
DEBUG:clap:usage::get_required_usage_from: after init desc_reqs=[]
DEBUG:clap:usage::get_required_usage_from: no more children
DEBUG:clap:usage::get_required_usage_from: final desc_reqs=["positional"]
DEBUG:clap:usage::get_required_usage_from: args_in_groups=[]
DEBUG:clap:Colorizer::error;
DEBUG:clap:Validator::missing_required_error: req_args="\n \u{1b}[1;31m\u{1b}[0m"
DEBUG:clap:usage::create_usage_with_title;
DEBUG:clap:usage::create_usage_no_title;
DEBUG:clap:usage::smart_usage;
DEBUG:clap:usage::get_required_usage_from: reqs=["positional", "field"], extra=None
DEBUG:clap:usage::get_required_usage_from: after init desc_reqs=[]
DEBUG:clap:usage::get_required_usage_from: no more children
DEBUG:clap:usage::get_required_usage_from: final desc_reqs=["field", "positional"]
DEBUG:clap:usage::get_required_usage_from: args_in_groups=[]
DEBUG:clap:usage::get_required_usage_from:iter:field:
DEBUG:clap:OptBuilder::fmt:field
DEBUG:clap:Parser::color;
DEBUG:clap:Parser::color: Color setting...Auto
DEBUG:clap:is_a_tty: stderr=true
DEBUG:clap:Colorizer::error;
DEBUG:clap:Colorizer::good;
thread 'main' panicked at 'assertion failed: res.is_ok()', src/main.rs:19:5
note: Run with RUST_BACKTRACE=1 environment variable to display a backtrace.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: Updating dependencies
Projects
None yet
2 participants