Function bpaf::command

source · []
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
Hide additional 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);
}