Struct bpaf::params::ParseCommand

source ·
pub struct ParseCommand<T> { /* private fields */ }
Expand description

Builder structure for the [command]

Created with [command], implements parser for the inner structure, gives access to help.

Implementations§

source§

impl<P> ParseCommand<P>

source

pub fn help<M>(self, help: M) -> Self
where M: Into<Doc>,

Add a brief description to a command

bpaf uses this description along with the command name in help output so it shouldn’t exceed one or two lines. If help isn’t specified bpaf falls back to descr from the inner parser.

§Combinatoric usage
fn inner() -> OptionParser<bool> {
    short('i')
        .help("Mysterious inner switch")
        .switch()
        .to_options()
        .descr("performs an operation")
}

fn mysterious_parser() -> impl Parser<bool> {
    inner().command("mystery")
        .help("This command performs a mystery operation")
}
§Derive usage

bpaf_derive uses doc comments for inner parser, no specific options are available. See descr for more details

/// This command performs a mystery operation
#[derive(Debug, Clone, Bpaf)]
#[bpaf(command)]
struct Mystery {
    #[bpaf(short)]
    /// Mysterious inner switch
    inner: bool,
}
§Example
$ app --help
    <skip>
Available commands:
    mystery  This command performs a mystery operation
Examples found in repository?
examples/enum_tuple.rs (line 28)
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
fn main() {
    let bar = short('b')
        .long("bar")
        .help("some bar command")
        .argument::<String>("BAR")
        .optional();

    let bar_cmd = construct!(Foo { bar })
        .to_options()
        .descr("This command will try to do foo given a bar argument");

    let opt = bar_cmd
        .command("foo")
        .help("command for doing foo")
        .map(Command::Foo)
        .to_options()
        .run();

    println!("{:#?}", opt);
}
More examples
Hide additional examples
examples/git.rs (line 51)
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
58
59
fn main() {
    let dry_run = long("dry_run").switch();
    let all = long("all").switch();
    let repository = positional::<String>("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 = fetch.command("fetch");

    let interactive = short('i').switch();
    let all = long("all").switch();
    let files = positional::<PathBuf>("FILE").many();
    let add = construct!(Opt::Add {
        interactive,
        all,
        files
    })
    .to_options()
    .descr("add files to the staging area");

    let add_cmd = add.command("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);
}
source

pub fn short(self, short: char) -> Self

Add a custom short alias for a command

Behavior is similar to short, only first short name is visible.

source

pub fn long(self, long: &'static str) -> Self

Add a custom hidden long alias for a command

Behavior is similar to long, but since you had to specify the first long name when making the command - this one becomes a hidden alias.

source

pub fn adjacent(self) -> Self

Allow for the command to succeed even if there are non consumed items present

Normally a subcommand parser should handle the rest of the unconsumed elements thus allowing only “vertical” chaining of commands. adjacent modifier lets command parser to succeed if there are leftovers for as long as all comsumed items form a single adjacent block. This opens possibilities to chain commands sequentially.

Let’s consider two examples with consumed items marked in bold :

  • cmd -a -b -c -d
  • cmd -a -c -b -d

In the first example -b breaks the adjacency for all the consumed items so parsing will fail, while here in the second one the name and all the consumed items are adjacent to each other so parsing will succeed.

Combinatoric example
#[derive(Debug, Clone)]
pub struct Options {
    premium: bool,
    commands: Vec<Cmd>,
}

#[derive(Debug, Clone)]
// shape of the variants doesn't really matter, let's use all of them :)
enum Cmd {
    Eat(String),
    Drink { coffee: bool },
    Sleep { time: usize },
}

fn cmd() -> impl Parser<Cmd> {
    let eat = positional::<String>("FOOD")
        .to_options()
        .descr("Performs eating action")
        .command("eat")
        .adjacent()
        .map(Cmd::Eat);

    let coffee = long("coffee")
        .help("Are you going to drink coffee?")
        .switch();
    let drink = construct!(Cmd::Drink { coffee })
        .to_options()
        .descr("Performs drinking action")
        .command("drink")
        .adjacent();

    let time = long("time").argument::<usize>("HOURS");
    let sleep = construct!(Cmd::Sleep { time })
        .to_options()
        .descr("Performs taking a nap action")
        .command("sleep")
        .adjacent();

    construct!([eat, drink, sleep])
}

pub fn options() -> OptionParser<Options> {
    let premium = short('p')
        .long("premium")
        .help("Opt in for premium serivces")
        .switch();
    let commands = cmd().many();
    construct!(Options { premium, commands }).to_options()
}

fn main() {
    println!("{:?}", options().run())
}
Derive example
#[derive(Debug, Clone, Bpaf)]
#[bpaf(options)]
pub struct Options {
    #[bpaf(short, long)]
    /// Opt in for premium serivces
    pub premium: bool,
    #[bpaf(external(cmd), many)]
    pub commands: Vec<Cmd>,
}

#[derive(Debug, Clone, Bpaf)]
pub enum Cmd {
    #[bpaf(command, adjacent)]
    /// Performs eating action
    Eat(#[bpaf(positional("FOOD"))] String),
    #[bpaf(command, adjacent)]
    /// Performs drinking action
    Drink {
        /// Are you going to drink coffee?
        coffee: bool,
    },
    #[bpaf(command, adjacent)]
    /// Performs taking a nap action
    Sleep {
        #[bpaf(argument("HOURS"))]
        time: usize,
    },
}

fn main() {
    println!("{:?}", options().run())
}
Output

Example implements a parser that supports one of three possible commands:

$ app --help

Usage: app [-p] [COMMAND ...]...

Available options:
-p, --premium
Opt in for premium serivces
-h, --help
Prints help information

Available commands:
eat
Performs eating action
drink
Performs drinking action
sleep
Performs taking a nap action

As usual every command comes with its own help

$ app drink --help

Performs drinking action

Usage: app drink [--coffee]

Available options:
--coffee
Are you going to drink coffee?
-h, --help
Prints help information

Normally you can use one command at a time, but making commands adjacent lets parser to succeed after consuming an adjacent block only and leaving leftovers for the rest of the parser, consuming them as a Vec<Cmd> with many allows to chain multiple items sequentially

$ app eat Fastfood drink --coffee sleep --time=5
Options { premium: false, commands: [Eat("Fastfood"), Drink { coffee: true }, Sleep { time: 5 }] }

The way this works is by running parsers for each command. In the first iteration eat succeeds, it consumes eat fastfood portion and appends its value to the resulting vector. Then second iteration runs on leftovers, in this case it will be drink --coffee sleep --time=5. Here drink succeeds and consumes drink --coffee portion, then sleep parser runs, etc.

You can mix chained commands with regular arguments that belong to the top level parser

$ app sleep --time 10 --premium eat 'Bak Kut Teh' drink
Options { premium: true, commands: [Sleep { time: 10 }, Eat("Bak Kut Teh"), Drink { coffee: false }] }

But not inside the command itself since values consumed by the command are not going to be adjacent

$ app sleep --time 10 eat --premium 'Bak Kut Teh' drink
Error: expected FOOD, pass --help for usage information

Trait Implementations§

source§

impl<T> Parser<T> for ParseCommand<T>

source§

fn many(self) -> ParseMany<Self>
where Self: Sized,

Consume zero or more items from a command line and collect them into a Vec Read more
source§

fn collect<C>(self) -> ParseCollect<Self, C, T>
where C: FromIterator<T>, Self: Sized,

Transform parser into a collection parser Read more
source§

fn some(self, message: &'static str) -> ParseSome<Self>
where Self: Sized + Parser<T>,

Consume one or more items from a command line and collect them into a Vec Read more
source§

fn optional(self) -> ParseOptional<Self>
where Self: Sized + Parser<T>,

Turn a required argument into an optional one Read more
source§

fn count(self) -> ParseCount<Self, T>
where Self: Sized + Parser<T>,

Count how many times the inner parser succeeds, and return that number. Read more
source§

fn last(self) -> ParseLast<Self>
where Self: Sized + Parser<T>,

Apply the inner parser as many times as it succeeds, return the last value Read more
source§

fn parse<F, R, E>(self, f: F) -> ParseWith<T, Self, F, E, R>
where Self: Sized + Parser<T>, F: Fn(T) -> Result<R, E>, E: ToString,

Apply a failing transformation to a contained value Read more
source§

fn map<F, R>(self, map: F) -> ParseMap<T, Self, F, R>
where Self: Sized + Parser<T>, F: Fn(T) -> R + 'static,

Apply a pure transformation to a contained value Read more
source§

fn guard<F>(self, check: F, message: &'static str) -> ParseGuard<Self, F>
where Self: Sized + Parser<T>, F: Fn(&T) -> bool,

Validate or fail with a message Read more
source§

fn fallback(self, value: T) -> ParseFallback<Self, T>
where Self: Sized + Parser<T>,

Use this value as default if the value isn’t present on a command line Read more
source§

fn fallback_with<F, E>(self, fallback: F) -> ParseFallbackWith<T, Self, F, E>
where Self: Sized + Parser<T>, F: Fn() -> Result<T, E>, E: ToString,

Use value produced by this function as default if the value isn’t present Read more
source§

fn hide(self) -> ParseHide<Self>
where Self: Sized + Parser<T>,

Ignore this parser during any sort of help generation Read more
source§

fn hide_usage(self) -> ParseUsage<Self>
where Self: Sized + Parser<T>,

Ignore this parser when generating a usage line Read more
source§

fn custom_usage<M>(self, usage: M) -> ParseUsage<Self>
where M: Into<Doc>, Self: Sized + Parser<T>,

Customize how this parser looks like in the usage line
source§

fn group_help<M: Into<Doc>>(self, message: M) -> ParseGroupHelp<Self>
where Self: Sized + Parser<T>,

Attach a help message to a complex parser Read more
source§

fn with_group_help<F>(self, f: F) -> ParseWithGroupHelp<Self, F>
where Self: Sized + Parser<T>, F: Fn(MetaInfo<'_>) -> Doc,

Make a help message for a complex parser from its MetaInfo Read more
source§

fn complete<M, F>(self, op: F) -> ParseComp<Self, F>
where M: Into<String>, F: Fn(&T) -> Vec<(M, Option<M>)>, Self: Sized + Parser<T>,

Available on crate feature autocomplete only.
Dynamic shell completion Read more
source§

fn complete_shell(self, op: ShellComp) -> ParseCompShell<Self>
where Self: Sized + Parser<T>,

Available on crate feature autocomplete only.
Static shell completion Read more
source§

fn to_options(self) -> OptionParser<T>
where Self: Sized + Parser<T> + 'static,

Transform Parser into OptionParser to get ready to run it Read more
source§

fn run(self) -> T
where Self: Sized + Parser<T> + 'static,

Finalize and run the parser Read more
source§

fn boxed(self) -> Box<dyn Parser<T>>
where Self: Sized + Parser<T> + 'static,

Create a boxed representation for a parser Read more

Auto Trait Implementations§

§

impl<T> Freeze for ParseCommand<T>

§

impl<T> !RefUnwindSafe for ParseCommand<T>

§

impl<T> !Send for ParseCommand<T>

§

impl<T> !Sync for ParseCommand<T>

§

impl<T> Unpin for ParseCommand<T>

§

impl<T> !UnwindSafe for ParseCommand<T>

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.