Struct bpaf::parsers::ParseOptional

source ·
pub struct ParseOptional<P> { /* private fields */ }
Expand description

Apply inner parser, return a value in Some if items requested by it are all present, restore and return None if any are missing. Created with optional. Implements catch

Implementations§

source§

impl<P> ParseOptional<P>

source

pub fn catch(self) -> Self

Handle parse failures for optional parsers

Can be useful to decide to skip parsing of some items on a command line. When parser succeeds - catch version would return a value as usual if it fails - catch would restore all the consumed values and return None.

There’s several structures that implement this attribute: ParseOptional, ParseMany and ParseSome, behavior should be identical for all of them.

Those examples are very artificial and designed to show what difference catch makes, to actually parse arguments like in examples you should parse or construct enum with alternative branches

Combinatoric example
#[derive(Debug, Clone)]
pub struct Options {
    height: Option<usize>,
    height_str: Option<String>,
    width: Option<usize>,
    width_str: Option<String>,
}

pub fn options() -> OptionParser<Options> {
    // contains catch
    let height = long("height")
        .help("Height of a rectangle")
        .argument::<usize>("PX")
        .optional()
        .catch();

    let height_str = long("height").argument::<String>("PX").optional().hide();

    // contains no catch
    let width = long("width")
        .help("Width of a rectangle")
        .argument::<usize>("PX")
        .optional();

    let width_str = long("width").argument::<String>("PX").optional().hide();

    construct!(Options {
        height,
        height_str,
        width,
        width_str
    })
    .to_options()
}

fn main() {
    println!("{:?}", options().run())
}
Derive example
#[derive(Debug, Clone, Bpaf)]
#[bpaf(options)]
pub struct Options {
    #[bpaf(long, argument("PX"), optional, catch)]
    /// Height of a rectangle
    height: Option<usize>,

    #[bpaf(long("height"), argument("PX"), optional, hide)]
    height_str: Option<String>,

    #[bpaf(long, argument("PX"), optional)]
    /// Width of a rectangle
    width: Option<usize>,

    #[bpaf(long("width"), argument("PX"), optional, hide)]
    width_str: Option<String>,
}

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

Despite parser producing a funky value - help looks like you would expect from a parser that takes two values

$ app --help

Usage: app [--height=PX] [--width=PX]

Available options:
--height=PX
Height of a rectangle
--width=PX
Width of a rectangle
-h, --help
Prints help information

When executed with no parameters it produces four None values - all parsers succeed by the nature of them being optional

$ app
Options { height: None, height_str: None, width: None, width_str: None }

When executed with expected parameters fields with usize get their values

$ app --height 100 --width 100
Options { height: Some(100), height_str: None, width: Some(100), width_str: None }

With incorrect value for --height parameter inner part of height parser fails, optional combined with catch handles this failure and produces None without consuming value from the command line. Parser height_str runs next and consumes the value as a string

$ app --height ten
Options { height: None, height_str: Some("ten"), width: None, width_str: None }

In case of wrong --width - parser width fails, parser for optional sees this as a “value is present but not correct” and propagates the error outside, execution never reaches width_str parser

$ app --width ten
Error: couldn't parse ten: invalid digit found in string
Examples found in repository?
examples/numeric_prefix.rs (line 25)
21
22
23
24
25
26
27
28
29
pub fn options() -> OptionParser<Options> {
    let prefix = positional::<usize>("PREFIX")
        .help("Optional numeric command prefix")
        .optional()
        .catch();
    let command = positional::<String>("COMMAND").help("Required command name");

    construct!(Options { prefix, command }).to_options()
}
More examples
Hide additional examples
examples/derive_commands.rs (line 43)
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
fn feature_if() -> impl Parser<Option<String>> {
    // here feature starts as any string on a command line that does not start with a dash
    positional::<String>("FEATURE")
        // guard restricts it such that it can't be a valid version
        .guard(move |s| !is_version(s), "")
        // last two steps describe what to do with strings in this position but are actually
        // versions.
        // optional allows parser to represent an ignored value with None
        .optional()
        // and catch lets optional to handle parse failures coming from guard
        .catch()
}

fn version_if() -> impl Parser<Option<String>> {
    positional::<String>("VERSION")
        .guard(move |s| is_version(s), "")
        .optional()
        .catch()
}

Trait Implementations§

source§

impl<T, P> Parser<Option<T>> for ParseOptional<P>
where P: Parser<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<P> Freeze for ParseOptional<P>
where P: Freeze,

§

impl<P> RefUnwindSafe for ParseOptional<P>
where P: RefUnwindSafe,

§

impl<P> Send for ParseOptional<P>
where P: Send,

§

impl<P> Sync for ParseOptional<P>
where P: Sync,

§

impl<P> Unpin for ParseOptional<P>
where P: Unpin,

§

impl<P> UnwindSafe for ParseOptional<P>
where P: UnwindSafe,

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.