bpaf::parsers

Struct ParsePositional

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

Parse a positional item, created with positional

You can add extra information to positional parsers with help, strict, or non_strict on this struct.

Implementations§

source§

impl<T> ParsePositional<T>

source

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

Add a help message to a positional parser

bpaf converts doc comments and string into help by following those rules:

  1. Everything up to the first blank line is included into a “short” help message
  2. Everything is included into a “long” help message
  3. bpaf preserves linebreaks followed by a line that starts with a space
  4. Linebreaks are removed otherwise

You can pass anything that can be converted into Doc, if you are not using documentation generation functionality (doc) this can be &str.

Combinatoric example
#[derive(Debug, Clone)]
pub struct Options {
    verbose: bool,
    crate_name: String,
    feature_name: Option<String>,
}

pub fn options() -> OptionParser<Options> {
    let verbose = short('v')
        .long("verbose")
        .help("Display detailed information")
        .switch();

    let crate_name = positional("CRATE").help("Crate name to use");

    let feature_name = positional("FEATURE")
        .help("Display information about this feature")
        .optional();

    construct!(Options {
        verbose,
        // You must place positional items and commands after
        // all other parsers
        crate_name,
        feature_name
    })
    .to_options()
}

fn main() {
    println!("{:?}", options().run())
}
Derive example
#[derive(Debug, Clone, Bpaf)]
#[bpaf(options)]
pub struct Options {
    /// Display detailed information
    #[bpaf(short, long)]
    verbose: bool,

    // You must place positional items and commands after
    // all other parsers
    #[bpaf(positional("CRATE"))]
    /// Crate name to use
    crate_name: String,

    #[bpaf(positional("FEATURE"))]
    /// Display information about this feature
    feature_name: Option<String>,
}

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

Positional items show up in a separate group of arguments if they contain a help message, otherwise they will show up only in Usage part.

$ app --help

Usage: app [-v] CRATE [FEATURE]

Available positional items:
CRATE
Crate name to use
FEATURE
Display information about this feature

Available options:
-v, --verbose
Display detailed information
-h, --help
Prints help information

You can mix positional items with regular items

$ app --verbose bpaf
Options { verbose: true, crate_name: "bpaf", feature_name: None }

And since bpaf API expects to have non positional items consumed before positional ones - you can use them in a different order. In this example bpaf corresponds to a crate_name field and --verbose – to verbose.

$ app bpaf --verbose
Options { verbose: true, crate_name: "bpaf", feature_name: None }

In previous examples optional field feature was missing, this one contains it.

$ app bpaf autocomplete
Options { verbose: false, crate_name: "bpaf", feature_name: Some("autocomplete") }

Users can use -- to tell bpaf to treat remaining items as positionals - this might be required to handle unusual items.

$ app bpaf -- --verbose
Options { verbose: false, crate_name: "bpaf", feature_name: Some("--verbose") }
$ app -- bpaf --verbose
Options { verbose: false, crate_name: "bpaf", feature_name: Some("--verbose") }

Without using -- bpaf would only accept items that don’t start with - as positional.

$ app --detailed
Error: expected CRATE, got --detailed. Pass --help for usage information
$ app --verbose
Error: expected CRATE, pass --help for usage information

You can use any to work around this restriction.

Examples found in repository?
examples/find.rs (line 34)
31
32
33
34
35
36
37
38
39
fn user() -> impl Parser<Option<String>> {
    // match only literal "-user"
    let tag = literal("-user").anywhere();
    let value = positional("USER").help("User name");
    construct!(tag, value)
        .adjacent()
        .map(|pair| pair.1)
        .optional()
}
More examples
Hide additional examples
examples/numeric_prefix.rs (line 23)
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()
}
examples/xorg.rs (line 37)
28
29
30
31
32
33
34
35
36
37
38
39
fn extension() -> impl Parser<(String, bool)> {
    let state = any("(+|-)ext", |s: String| match s.as_str() {
        "-ext" => Some(false),
        "+ext" => Some(true),
        _ => None,
    })
    .anywhere();

    let name = positional::<String>("EXT")
        .help("Extension to enable or disable, see documentation for the full list");
    construct!(state, name).adjacent().map(|(a, b)| (b, a))
}
examples/cat.rs (line 17)
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
fn main() {
    let file = positional::<OsString>("FILE")
        .help("File name to concatenate, with no FILE or when FILE is -, read standard input")
        .optional()
        .parse::<_, Box<dyn Read>, std::io::Error>(|path| {
            Ok(if let Some(path) = path {
                if path == "-" {
                    Box::new(stdin())
                } else {
                    Box::new(File::open(path)?)
                }
            } else {
                Box::new(stdin())
            })
        })
        .to_options()
        .descr("Concatenate a file to standard output")
        .run();

    let reader = BufReader::new(file);

    for line in reader.lines() {
        println!("{}", line.unwrap());
    }
}
source

pub fn strict(self) -> ParsePositional<T>

Changes positional parser to be a “strict” positional

Usually positional items can appear anywhere on a command line:

$ ls -d bpaf
$ ls bpaf -d

here ls takes a positional item bpaf and a flag -d

But in some cases it might be useful to have a stricter separation between positonal items and flags, such as passing arguments to a subprocess:

$ cargo run --example basic -- --help

here cargo takes a --help as a positional item and passes it to the example

bpaf allows to require user to pass -- for positional items with strict annotation. bpaf would display such positional elements differently in usage line as well.

Combinatoric example
#[derive(Debug, Clone)]
pub struct Options {
    verbose: bool,
    binary: String,
    args: Vec<String>,
}

pub fn options() -> OptionParser<Options> {
    let verbose = short('v')
        .long("verbose")
        .help("Produce detailed report")
        .switch();
    let binary = long("bin").help("Binary to execute").argument("BIN");
    let args = positional("ARG")
        .help("Arguments for the binary")
        .strict()
        .many();
    construct!(Options {
        verbose,
        binary,
        args
    })
    .to_options()
}

fn main() {
    println!("{:?}", options().run())
}
Derive example
#[derive(Debug, Clone, Bpaf)]
#[bpaf(options)]
pub struct Options {
    #[bpaf(short, long)]
    /// Produce detailed report
    verbose: bool,
    #[bpaf(long("bin"), argument("BIN"))]
    /// Binary to execute
    binary: String,
    #[bpaf(positional("ARG"), strict, many)]
    /// Arguments for the binary
    args: Vec<String>,
}

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

Usage line for a cargo-run like app that takes an app name and possibly many strictly positional child arguments can look like this:

$ app --help

Usage: app [-v] --bin=BIN -- [ARG]...

Available positional items:
ARG
Arguments for the binary

Available options:
-v, --verbose
Produce detailed report
--bin=BIN
Binary to execute
-h, --help
Prints help information

Here any argument passed before double dash goes to the parser itself

$ app --bin dd --verbose
Options { verbose: true, binary: "dd", args: [] }

Anything after it - collected into strict arguments

$ app --bin dd -- --verbose
Options { verbose: false, binary: "dd", args: ["--verbose"] }
source

pub fn non_strict(self) -> Self

Changes positional parser to be a “not strict” positional

Ensures the parser always rejects “strict” positions to the right of the separator, --. Essentially the inverse operation to ParsePositional::strict, which can be used to ensure adjacent strict and nonstrict args never conflict with eachother.

Trait Implementations§

source§

impl<T: Clone> Clone for ParsePositional<T>

source§

fn clone(&self) -> ParsePositional<T>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<T> Parser<T> for ParsePositional<T>
where T: FromStr + 'static, <T as FromStr>::Err: Display,

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 Read more
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 ParsePositional<T>

§

impl<T> RefUnwindSafe for ParsePositional<T>
where T: RefUnwindSafe,

§

impl<T> Send for ParsePositional<T>
where T: Send,

§

impl<T> Sync for ParsePositional<T>
where T: Sync,

§

impl<T> Unpin for ParsePositional<T>
where T: Unpin,

§

impl<T> UnwindSafe for ParsePositional<T>
where T: 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> CloneToUninit for T
where T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. 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> ToOwned for T
where T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

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

source§

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>,

source§

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.