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

Argument with default_values conflict when inside groups #1906

Closed
2 tasks done
Tracked by #2897
pksunkara opened this issue May 5, 2020 · 4 comments · Fixed by #2950
Closed
2 tasks done
Tracked by #2897

Argument with default_values conflict when inside groups #1906

pksunkara opened this issue May 5, 2020 · 4 comments · Fixed by #2950
Assignees
Labels
A-parsing Area: Parser's logic and needs it changed somehow. C-bug Category: Updating dependencies

Comments

@pksunkara
Copy link
Member

Make sure you completed the following tasks

Code

use clap::{App, Arg};

fn main() {
    let result = App::new("conflict")
        .arg(
            Arg::with_name("opt")
                .long("opt")
                .default_value("default")
                .group("one"),
        )
        .arg(Arg::with_name("flag").long("flag").conflicts_with("one"))
        .get_matches_from(vec!["myprog", "--flag"]);

    eprintln!("{:#?}", result);
}

Version

With master branch.

Actual Behavior Summary

error: The argument '--opt <opt>' cannot be used with one or more of the other specified arguments

USAGE:
    myprog [FLAGS] [OPTIONS]

For more information try --help

Expected Behavior Summary

Should work.

Additional context

Related to #1605 which was recently fixed.

Debug output

Compile clap with debug feature:

[dependencies]
clap = { version = "*", features = ["debug"] }

The output may be very long, so feel free to link to a gist or attach a text file

Debug Output

[            clap::build::app] 	App::_do_parse
[            clap::build::app] 	App::_build
[            clap::build::app] 	App::_derive_display_order:conflict
[            clap::build::app] 	App::_create_help_and_version
[            clap::build::app] 	App::_create_help_and_version: Building --help
[            clap::build::app] 	App::_create_help_and_version: Building --version
[            clap::build::app] 	App::_debug_asserts
[            clap::build::arg] 	Arg::_debug_asserts:opt
[            clap::build::arg] 	Arg::_debug_asserts:flag
[            clap::build::arg] 	Arg::_debug_asserts:help
[            clap::build::arg] 	Arg::_debug_asserts:version
[         clap::parse::parser] 	Parser::get_matches_with
[         clap::parse::parser] 	Parser::_build
[         clap::parse::parser] 	Parser::_verify_positionals
[         clap::parse::parser] 	Parser::get_matches_with: Begin parsing '"--flag"' ([45, 45, 102, 108, 97, 103])
[         clap::parse::parser] 	Parser::is_new_arg: "--flag":NotFound
[         clap::parse::parser] 	Parser::is_new_arg: arg_allows_tac=false
[         clap::parse::parser] 	Parser::is_new_arg: -- found
[         clap::parse::parser] 	Parser::is_new_arg: starts_new_arg=true
[         clap::parse::parser] 	Parser::possible_subcommand: arg="--flag"
[         clap::parse::parser] 	Parser::get_matches_with: possible_sc=false, sc=None
[         clap::parse::parser] 	Parser::parse_long_arg
[         clap::parse::parser] 	Parser::parse_long_arg: Does it contain '='...
[         clap::parse::parser] 	No
[         clap::parse::parser] 	Parser::parse_long_arg: Found valid opt or flag '--flag'
[         clap::parse::parser] 	Parser::check_for_help_and_version_str
[         clap::parse::parser] 	Parser::check_for_help_and_version_str: Checking if --"flag" is help or version...
[         clap::parse::parser] 	Neither
[         clap::parse::parser] 	Parser::parse_flag
[    clap::parse::arg_matcher] 	ArgMatcher::inc_occurrence_of: arg=flag
[    clap::parse::arg_matcher] 	ArgMatcher::inc_occurrence_of: first instance
[         clap::parse::parser] 	groups_for_arg: name=flag
[         clap::parse::parser] 	Parser::get_matches_with: After parse_long_arg Flag(flag)
[         clap::parse::parser] 	Parser::maybe_inc_pos_counter: arg = flag
[         clap::parse::parser] 	Parser::maybe_inc_pos_counter: is it positional?
[         clap::parse::parser] 	No
[         clap::parse::parser] 	groups_for_arg: name=flag
[         clap::parse::parser] 	Parser::remove_overrides
[         clap::parse::parser] 	Parser::remove_overrides:iter:flag
[      clap::parse::validator] 	Validator::validate
[         clap::parse::parser] 	Parser::add_defaults
[         clap::parse::parser] 	Parser::add_defaults:iter:opt:
[         clap::parse::parser] 	Parser::add_value: doesn't have conditional defaults
[         clap::parse::parser] 	Parser::add_value:iter:opt: has default vals
[         clap::parse::parser] 	Parser::add_value:iter:opt: wasn't used
[         clap::parse::parser] 	Parser::add_val_to_arg; arg=opt, val="default"
[         clap::parse::parser] 	Parser::add_val_to_arg; trailing_vals=false, DontDelimTrailingVals=false
[         clap::parse::parser] 	Parser::add_single_val_to_arg: adding val..."default"
[         clap::parse::parser] 	groups_for_arg: name=opt
[    clap::parse::arg_matcher] 	ArgMatcher::needs_more_vals: o=opt
[      clap::parse::validator] 	Validator::validate_conflicts
[      clap::parse::validator] 	Validator::validate_exclusive
[      clap::parse::validator] 	Validator::validate_exclusive:iter:flag
[      clap::parse::validator] 	Validator::validate_exclusive:iter:opt
[      clap::parse::validator] 	Validator::validate_exclusive:iter:one
[      clap::parse::validator] 	Validator::gather_conflicts
[      clap::parse::validator] 	Validator::gather_conflicts:iter: id=flag
[      clap::parse::validator] 	groups_for_arg: name=flag
[      clap::parse::validator] 	Validator::gather_conflicts:iter: id=opt
[      clap::parse::validator] 	Validator::gather_conflicts:iter: This is default value, skipping.
[      clap::parse::validator] 	Validator::gather_conflicts:iter: id=one
[      clap::parse::validator] 	Validator::gather_conflicts:iter: This is default value, skipping.
[      clap::parse::validator] 	Validator::validate_conflicts:iter:one
[            clap::build::app] 	App::unroll_args_in_group: group=one
[            clap::build::app] 	App::unroll_args_in_group:iter: entity=opt
[            clap::build::app] 	App::unroll_args_in_group:iter: this is an arg
[      clap::parse::validator] 	Validator::build_conflict_err: name=one
[         clap::output::usage] 	Usage::create_usage_with_title
[         clap::output::usage] 	Usage::create_usage_no_title
[         clap::output::usage] 	Usage::create_help_usage; incl_reqs=true
[         clap::output::usage] 	Usage::get_required_usage_from: incls=[], matcher=false, incl_last=false
[         clap::output::usage] 	Usage::get_required_usage_from: ret_val=[]
[         clap::output::usage] 	Usage::needs_flags_tag
[         clap::output::usage] 	Usage::needs_flags_tag:iter: f=flag
[         clap::output::usage] 	groups_for_arg: name=flag
[         clap::output::usage] 	Usage::needs_flags_tag:iter: [FLAGS] required
[         clap::output::usage] 	Usage::create_help_usage: usage=myprog [FLAGS] [OPTIONS]
[            clap::build::app] 	App::unroll_args_in_group: group=one
[            clap::build::app] 	App::unroll_args_in_group:iter: entity=opt
[            clap::build::app] 	App::unroll_args_in_group:iter: this is an arg
[      clap::parse::validator] 	Validator::build_conflict_err: c_with=None:group
[            clap::build::app] 	App::color: Color setting...
[            clap::build::app] 	Auto
[           clap::output::fmt] 	is_a_tty: stderr=true

@pksunkara pksunkara added the C-bug Category: Updating dependencies label May 5, 2020
@pksunkara pksunkara added this to the 3.0 milestone May 5, 2020
@pksunkara
Copy link
Member Author

@CreepySkeleton You might want to look into this.

@CreepySkeleton CreepySkeleton self-assigned this May 5, 2020
@pksunkara pksunkara added C: arg groups A-parsing Area: Parser's logic and needs it changed somehow. labels May 6, 2020
@pksunkara
Copy link
Member Author

There is one more snippet that is giving the same issue. Might be just common bug or different.

use clap::{App, Arg};

fn main() {
    let result = App::new("conflict")
        .arg(
            Arg::with_name("opt")
                .long("opt")
                .default_value("default")
                .group("one"),
        )
        .arg(
            Arg::with_name("bar")
                .long("bar")
                .default_value("foo")
                .group("one")
        )
        .arg(Arg::with_name("flag").long("flag").conflicts_with("one"))
        .get_matches_from(vec!["myprog", "--flag"]);

    eprintln!("{:#?}", result);
}

resulted in

error: The argument '--opt <opt>' cannot be used with '--bar <bar>'

USAGE:
    myprog [FLAGS] [OPTIONS]

For more information try --help
Debug Output

[            clap::build::app] 	App::_do_parse
[            clap::build::app] 	App::_build
[            clap::build::app] 	App::_derive_display_order:conflict
[            clap::build::app] 	App::_create_help_and_version
[            clap::build::app] 	App::_create_help_and_version: Building --help
[            clap::build::app] 	App::_create_help_and_version: Building --version
[            clap::build::app] 	App::_debug_asserts
[            clap::build::arg] 	Arg::_debug_asserts:opt
[            clap::build::arg] 	Arg::_debug_asserts:bar
[            clap::build::arg] 	Arg::_debug_asserts:flag
[            clap::build::arg] 	Arg::_debug_asserts:help
[            clap::build::arg] 	Arg::_debug_asserts:version
[         clap::parse::parser] 	Parser::get_matches_with
[         clap::parse::parser] 	Parser::_build
[         clap::parse::parser] 	Parser::_verify_positionals
[         clap::parse::parser] 	Parser::get_matches_with: Begin parsing '"--flag"' ([45, 45, 102, 108, 97, 103])
[         clap::parse::parser] 	Parser::is_new_arg: "--flag":NotFound
[         clap::parse::parser] 	Parser::is_new_arg: arg_allows_tac=false
[         clap::parse::parser] 	Parser::is_new_arg: -- found
[         clap::parse::parser] 	Parser::is_new_arg: starts_new_arg=true
[         clap::parse::parser] 	Parser::possible_subcommand: arg="--flag"
[         clap::parse::parser] 	Parser::get_matches_with: possible_sc=false, sc=None
[         clap::parse::parser] 	Parser::parse_long_arg
[         clap::parse::parser] 	Parser::parse_long_arg: Does it contain '='...
[         clap::parse::parser] 	No
[         clap::parse::parser] 	Parser::parse_long_arg: Found valid opt or flag '--flag'
[         clap::parse::parser] 	Parser::check_for_help_and_version_str
[         clap::parse::parser] 	Parser::check_for_help_and_version_str: Checking if --"flag" is help or version...
[         clap::parse::parser] 	Neither
[         clap::parse::parser] 	Parser::parse_flag
[    clap::parse::arg_matcher] 	ArgMatcher::inc_occurrence_of: arg=flag
[    clap::parse::arg_matcher] 	ArgMatcher::inc_occurrence_of: first instance
[         clap::parse::parser] 	groups_for_arg: name=flag
[         clap::parse::parser] 	Parser::get_matches_with: After parse_long_arg Flag(flag)
[         clap::parse::parser] 	Parser::maybe_inc_pos_counter: arg = flag
[         clap::parse::parser] 	Parser::maybe_inc_pos_counter: is it positional?
[         clap::parse::parser] 	No
[         clap::parse::parser] 	groups_for_arg: name=flag
[         clap::parse::parser] 	Parser::remove_overrides
[         clap::parse::parser] 	Parser::remove_overrides:iter:flag
[      clap::parse::validator] 	Validator::validate
[         clap::parse::parser] 	Parser::add_defaults
[         clap::parse::parser] 	Parser::add_defaults:iter:opt:
[         clap::parse::parser] 	Parser::add_value: doesn't have conditional defaults
[         clap::parse::parser] 	Parser::add_value:iter:opt: has default vals
[         clap::parse::parser] 	Parser::add_value:iter:opt: wasn't used
[         clap::parse::parser] 	Parser::add_val_to_arg; arg=opt, val="default"
[         clap::parse::parser] 	Parser::add_val_to_arg; trailing_vals=false, DontDelimTrailingVals=false
[         clap::parse::parser] 	Parser::add_single_val_to_arg: adding val..."default"
[         clap::parse::parser] 	groups_for_arg: name=opt
[    clap::parse::arg_matcher] 	ArgMatcher::needs_more_vals: o=opt
[         clap::parse::parser] 	Parser::add_defaults:iter:bar:
[         clap::parse::parser] 	Parser::add_value: doesn't have conditional defaults
[         clap::parse::parser] 	Parser::add_value:iter:bar: has default vals
[         clap::parse::parser] 	Parser::add_value:iter:bar: wasn't used
[         clap::parse::parser] 	Parser::add_val_to_arg; arg=bar, val="foo"
[         clap::parse::parser] 	Parser::add_val_to_arg; trailing_vals=false, DontDelimTrailingVals=false
[         clap::parse::parser] 	Parser::add_single_val_to_arg: adding val..."foo"
[         clap::parse::parser] 	groups_for_arg: name=bar
[    clap::parse::arg_matcher] 	ArgMatcher::needs_more_vals: o=bar
[      clap::parse::validator] 	Validator::validate_conflicts
[      clap::parse::validator] 	Validator::validate_exclusive
[      clap::parse::validator] 	Validator::validate_exclusive:iter:flag
[      clap::parse::validator] 	Validator::validate_exclusive:iter:opt
[      clap::parse::validator] 	Validator::validate_exclusive:iter:one
[      clap::parse::validator] 	Validator::validate_exclusive:iter:bar
[      clap::parse::validator] 	Validator::gather_conflicts
[      clap::parse::validator] 	Validator::gather_conflicts:iter: id=flag
[      clap::parse::validator] 	groups_for_arg: name=flag
[      clap::parse::validator] 	Validator::gather_conflicts:iter: id=opt
[      clap::parse::validator] 	Validator::gather_conflicts:iter: This is default value, skipping.
[      clap::parse::validator] 	Validator::gather_conflicts:iter: id=one
[      clap::parse::validator] 	Validator::gather_conflicts:iter: This is default value, skipping.
[      clap::parse::validator] 	Validator::gather_conflicts:iter: id=bar
[      clap::parse::validator] 	Validator::gather_conflicts:iter: This is default value, skipping.
[      clap::parse::validator] 	Validator::validate_conflicts:iter:one
[            clap::build::app] 	App::unroll_args_in_group: group=one
[            clap::build::app] 	App::unroll_args_in_group:iter: entity=opt
[            clap::build::app] 	App::unroll_args_in_group:iter: this is an arg
[            clap::build::app] 	App::unroll_args_in_group:iter: entity=bar
[            clap::build::app] 	App::unroll_args_in_group:iter: this is an arg
[      clap::parse::validator] 	Validator::build_conflict_err: name=one
[         clap::output::usage] 	Usage::create_usage_with_title
[         clap::output::usage] 	Usage::create_usage_no_title
[         clap::output::usage] 	Usage::create_help_usage; incl_reqs=true
[         clap::output::usage] 	Usage::get_required_usage_from: incls=[], matcher=false, incl_last=false
[         clap::output::usage] 	Usage::get_required_usage_from: ret_val=[]
[         clap::output::usage] 	Usage::needs_flags_tag
[         clap::output::usage] 	Usage::needs_flags_tag:iter: f=flag
[         clap::output::usage] 	groups_for_arg: name=flag
[         clap::output::usage] 	Usage::needs_flags_tag:iter: [FLAGS] required
[         clap::output::usage] 	Usage::create_help_usage: usage=myprog [FLAGS] [OPTIONS]
[            clap::build::app] 	App::unroll_args_in_group: group=one
[            clap::build::app] 	App::unroll_args_in_group:iter: entity=opt
[            clap::build::app] 	App::unroll_args_in_group:iter: this is an arg
[            clap::build::app] 	App::unroll_args_in_group:iter: entity=bar
[            clap::build::app] 	App::unroll_args_in_group:iter: this is an arg
[      clap::parse::validator] 	Validator::build_conflict_err: c_with=Some("--bar "):group
[            clap::build::app] 	App::color: Color setting...
[            clap::build::app] 	Auto
[           clap::output::fmt] 	is_a_tty: stderr=true

@CreepySkeleton
Copy link
Contributor

I know what the problem is but fixing it would require changes in the way how the matches stored. Actually, I've been looking into many bugs here, and fixing them would require changes in ArgMatches.

In short, arguments, global arguments, and groups must be stored and processed separately.

@pksunkara
Copy link
Member Author

I think we would need to do it like that anyway to fix a few more global args bugs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-parsing Area: Parser's logic and needs it changed somehow. C-bug Category: Updating dependencies
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants