Clap: Default subcommand

Created on 30 May 2017  Â·  3Comments  Â·  Source: clap-rs/clap

Feature request

This is a proposal to add a means to reduce verbosity of command-line calls.

The API presented here is App::default_subcommand() method. It is used to show how this feature can be employed, so feel free to implement the functionality however you find suitable.

Description

Arguments of the default subcommand are merged into arguments of the enclosing app-like entity (subcommands can exploit this behavior regarding inner subcommands too).

Naming conflicts are resolved by preferring the arguments defined in the enclosing entity because otherwise they would be shadowed permanently. In other words, only merge the non-conflicting arguments into the scope, whilst preserving its own conflicting ones.

Inspecting the presence of these arguments is done unambiguously — through the entity where they were defined.

Sample Code

extern crate clap;
use clap::{Arg, App, SubCommand};

fn main() {
    let matches = App::new("test")
        .subcommand(SubCommand::with_name("info")
            .arg(Arg::with_name("verbose")
                .short("v")
                .long("verbose"))
            .arg(Arg::with_name("PARAM")))
        .subcommand(SubCommand::with_name("sync")
            .arg(Arg::with_name("encrypt")
                .short("e")
                .long("encrypt")))
        .default_subcommand("info")    // new method
        .get_matches();

    if let Some(info) = matches.subcommand_matches("info") {
        println!("{:?}", info.is_present("verbose"));
        println!("{:?}", info.value_of("PARAM"));
    }

    if let Some(sync) = matches.subcommand_matches("sync") {
        println!("{:?}", sync.is_present("encrypt"));
    }
}

Expected Behavior Summary

$ ./clap-test    # same as ./clap-test info 
false
None
$ ./clap-test -v    # same as ./clap-test info -v
true
None
$ ./clap-test foo    # same as ./clap-test info foo
false
Some("foo")
$ ./clap-test sync -e    # sync is not default, needs to be explicitly written
true
$ ./clap-test --help    # help message is also affected
test 

USAGE:
    clap-test [SUBCOMMAND]

FLAGS:
    -e, --encrypt    
    -h, --help       Prints help information
    -V, --version    Prints version information

SUBCOMMANDS:
    help    Prints this message or the help of the given subcommand(s)
    info    
    sync    
RFC / question

Most helpful comment

FWIW this feature would be useful to me, I'm porting and application from Python's click which supports this feature and InferSubcommands doesn't quite cut it in my scenario as the default subcommand should be predetermined. In my scenario I am not concerned about confusion with the arguments of the parent command as I only have the default help/options there, though I appreciate in other scenarios this would be more confusing.

All 3 comments

This proposal can be extended to something like App::merge_subcommand() and App::merge_subcommands() methods which can be applied to many subcommands instead of one.

For this case, it should be noted that the order in which subcommands are merged matters. Otherwise, their descriptions are the same as the one for App::default_subcommand().

I think this is an interesting concept, but I'd be worried it could create confusion args from the "default" subcommand are intermixed with args from the parent subcommand such as program --parent --default --parent2 etc.

Using AppSettings::InferSubcommands does almost the same thing, but with less confusion in my mind. As the verbosity is about as minimal as it gets where al these are the same as your examples:

$ ./clap-test i    # same as ./clap-test info 
false
None
$ ./clap-test i -v    # same as ./clap-test info -v
true
None
$ ./clap-test i foo    # same as ./clap-test info foo
false
Some("foo")
$ ./clap-test s -e    # sync is not default, needs to be explicitly written
true

FWIW this feature would be useful to me, I'm porting and application from Python's click which supports this feature and InferSubcommands doesn't quite cut it in my scenario as the default subcommand should be predetermined. In my scenario I am not concerned about confusion with the arguments of the parent command as I only have the default help/options there, though I appreciate in other scenarios this would be more confusing.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

casey picture casey  Â·  25Comments

joshtriplett picture joshtriplett  Â·  41Comments

pickfire picture pickfire  Â·  21Comments

neysofu picture neysofu  Â·  41Comments

casey picture casey  Â·  25Comments