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.
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.
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"));
}
}
$ ./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
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.
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
InferSubcommandsdoesn'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.