pub fn command<T>(name: &'static str, subparser: OptionParser<T>) -> Command<T> where
T: 'static,
Expand description
Subcommand parser
Subcommands allow to use a totally independent parser inside a current one. Inner parser can have its own help message, description, version and so on. You can nest them arbitrarily too.
Alternatively you can create commands using command
Combinatoric use
Structure Command
you get by calling this method is a builder that allows to add additional
aliases with short
, long
(only first short and first
long names are visible to --help
) and override help
. Without help override
bpaf would use first line from the description
#[derive(Debug, Clone)]
enum Cmd {
Check {
workspace: bool,
}
};
// First of all you need an inner parser
fn check_workspace() -> OptionParser<Cmd> {
// Define a parser to use in a subcommand in a usual way.
// This parser accepts a single --workspace switch
let workspace = long("workspace")
.help("Check all packages in the workspace")
.switch();
// and attach some meta information to it in a usual way
construct!(Cmd::Check { workspace })
.to_options()
// description to use for command's help
.descr("Check a package for errors")
}
// Convert subparser into a parser.
fn check_workspace_command() -> impl Parser<Cmd> {
command("check", check_workspace())
// help to use to list the command
.help("Check a package command")
}
Derive usage
#[derive(Clone, Debug, Bpaf)]
enum Cmd {
#[bpaf(command)]
/// Check a package command
Check {
/// Check all the packages in the workspace
workspace: bool
}
}
Example
$ app --help
// displays global help, not listed in this example
$ app check --help
// displays help for check: "Check a package command"
$ app check
// Cmd::Check(CheckWorkspace(false))
$ app check --workspace
// Cmd::Check(CheckWorkspace(true))
Examples found in repository?
examples/enum_tuple.rs (line 26)
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
fn main() {
let bar = short('b')
.long("bar")
.help("some bar command")
.argument("BAR")
.optional();
let bar_cmd = construct!(Foo { bar })
.to_options()
.descr("This command will try to do foo given a bar argument");
let opt = command("foo", bar_cmd)
.help("command for doing foo")
.map(Command::Foo)
.to_options()
.run();
println!("{:#?}", opt);
}
More examples
examples/git.rs (line 36)
≺ ≻
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
fn main() {
let dry_run = long("dry_run").switch();
let all = long("all").switch();
let repository = positional("SRC").fallback("origin".to_string());
let fetch = construct!(Opt::Fetch {
dry_run,
all,
repository
})
.to_options()
.descr("fetches branches from remote repository");
let fetch_cmd = command("fetch", fetch);
let interactive = short('i').switch();
let all = long("all").switch();
let files = positional("FILE").many();
let add = construct!(Opt::Add {
interactive,
all,
files
})
.to_options()
.descr("add files to the staging area");
let add_cmd = command("add", add).help("add files to the staging area");
let opt = construct!([fetch_cmd, add_cmd])
.to_options()
.descr("The stupid content tracker")
.run();
println!("{:?}", opt);
}
examples/confusing.rs (line 38)
≺ ≻
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
fn main() {
let token = long("token")
.help("Token used for complex commands")
.argument("TOKEN")
.optional();
// start with defining 3 commands: simple, complex1 and complex2
let simple_parser = pure(PreCommand::Simple).to_options();
let simple = command("simple", simple_parser);
let complex1_parser = positional("ARG").from_str::<i32>();
let complex1 = command(
"complex1",
construct!(PreCommand::Complex1(complex1_parser))
.to_options()
.descr("This is complex command 1"),
);
let complex2_parser = positional("ARG").from_str::<i16>();
let complex2 = command(
"complex1",
construct!(PreCommand::Complex2(complex2_parser))
.to_options()
.descr("This is complex command 2"),
);
// compose then to accept any of those
let preparser = construct!([simple, complex1, complex2]);
// make a parser that accepts optional token and one of incomplete commands
// then create complete command or fail
let parser = construct!(token, preparser).parse(|(token, cmd)| match cmd {
PreCommand::Simple => Ok(Command::Simple),
PreCommand::Complex1(a) => match token {
Some(token) => Ok(Command::Complex1(token, a)),
None => Err("You must specify token to use with --token"),
},
PreCommand::Complex2(a) => match token {
Some(token) => Ok(Command::Complex2(token, a)),
None => Err("You must specify token to use with --token"),
},
});
let cmd = parser.to_options().run();
println!("{:?}", cmd);
}