pub struct Named { /* private fields */ }
Expand description

A named thing used to create flag, switch or argument

Create it with short or long.

Ways to consume data

bpaf supports several different ways user can specify values on a command line:

  • flag - a string that consists of two dashes (--flag) and a name and a single dash and a single character (-f) - long and short name respectively. Depending on it present or absent from the command line primitive flag parser takes one of two values. User can combine several short flags in a single invocation: -a -b -c is the same as -abc.
$ app -a -bc
  • switch - similar to flag, but instead of custom values bpaf uses bool. switch mostly serves as a convenient alias to .flag(true, false)
$ app -a -bc
  • argument - a short or long flag followed by either a space or = and then by a string literal. -f foo, --flag bar or -o=- are all valid argument examples. Note, string literal can’t start with - unless separated from the flag with = and should be valid utf8 only. To consume OsString encoded values you can use argument_os.
$ app -o file.txt
  • positional - an arbitrary utf8 string literal (that can’t start with -) passed on a command line, there’s also positional_os variant that deals with OsString named. Usually represents input files such as cat file.txt, but can serve other purposes.
$ cat file.txt
  • command - a fixed utf8 string literal that starts a separate subparser that only gets executed when command name is present. For example cargo build invokes command "build" and after "build" cargo starts accepting values it won’t accept otherwise
$ cargo build --out-dir my_target
// works since command "build" supports --out-dir argument
$ cargo check --out-dir my_target
// fails since --out-dir isn't a valid argument for command "check"

As most of the other parsers bpaf treats anything to the right of -- symbol as positional arguments regardless their names:

$ app -o file.txt -- --those --are --positional --items

Combinatoric usage

Named items (argument, flag and switch) can have up to 2 visible names (short and long) and multiple hidden short and long aliases if needed. It’s also possible to consume items from environment variables using env. You usually start with short or long function, then apply short / long / env / help repeatedly to build a desired set of names then transform it into a parser using flag, switch or positional.

fn an_item() -> impl Parser<String> {
    short('i')
        .long("item")
        .long("also-item") // but hidden
        .env("ITEM")
        .help("A string used by this example")
        .argument("ITEM")
}

Example

$ app --help
    <skip>
    -i --item <ITEM>  [env:ITEM: N/A]
                      A string used by this example
    <skip>

Derive usage

Unlike combinatoric API where you forced to specify names for your parsers derive API allows to omit some or all the details:

  1. If no naming information is present at all - bpaf_derive would use field name as a long name (or a short name if field name consists of a single character)

  2. If short or long annotation is present without an argument - bpaf_derive would use first character or a full name as long and short name respectively. It won’t try to add implicit long or short name from the previous item.

  3. If short or long annotation is present with an argument - those are values bpaf_derive would use instead of the original field name

  4. If env(arg) annotation is present - bpaf_derive would generate .env(arg) method:

    const DB: &str = "top_secret_database";
    
    #[derive(Debug, Clone, Bpaf)]
    #[bpaf(options)]
    pub struct Config {
       /// flag with no annotation
       pub flag_1: bool,
    
       /// explicit short suppresses long
       #[bpaf(short)]
       pub flag_2: bool,
    
       /// explicit short with custom letter
       #[bpaf(short('z'))]
       pub flag_3: bool,
    
       /// explicit short and long
       #[bpaf(short, long)]
       pub deposit: bool,
    
       /// implicit long + env variable from DB constant
       #[bpaf(env(DB))]
       pub database: String,
    
       /// implicit long + env variable "USER"
       #[bpaf(env("USER"))]
       pub user: String,
    }

Example

$ app --help
   <skip>
        --flag-1         flag with no annotation
   -f                    explicit short suppresses long
   -z                    explicit short with custom letter
   -d, --deposit         explicit short and long
       --database <ARG>  [env:top_secret_database: N/A]
                         implicit long + env variable from DB constant
       --user <ARG>      [env:USER = "pacak"]
                         implicit long + env variable "USER"
   <skip>

Implementations

Add a short name to a flag/switch/argument

You can specify it multiple times, bpaf would use items past the first one as hidden aliases.

fn parse_bool() -> impl Parser<bool> {
    short('f')
        .short('F')
        .long("flag")
        .help("a flag that does a thing")
        .switch()
}

See Named for more details

Examples found in repository?
examples/enum_in_args.rs (line 27)
25
26
27
28
29
30
31
32
33
34
35
fn main() {
    let opt = long("baz")
        .short('b')
        .help("choose between foo, bar or foobar")
        .argument("CMD")
        .from_str::<Baz>()
        .to_options()
        .run();

    println!("{:#?}", opt);
}

Add a long name to a flag/switch/argument

You can specify it multiple times, bpaf would use items past the first one as hidden aliases.

fn parse_bool() -> impl Parser<bool> {
    short('f')
        .long("flag")
        .long("Flag")
        .help("a flag that does a thing")
        .switch()
}

See Named for more details

Examples found in repository?
examples/top_to_bottom.rs (line 35)
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
76
77
78
79
80
fn debug() -> impl Parser<bool> {
    short('d')
        .long("debug")
        .help("Activate debug mode")
        .switch()
}
// number of occurrences of the v/verbose flag capped at 3
fn verbose() -> impl Parser<usize> {
    short('v')
        .long("verbose")
        .help("Increase the verbosity\nYou can specify it up to 3 times\neither as -v -v -v or as -vvv")
        .req_flag(())
        .many()
        .map(|xs| xs.len())
        .guard(|&x| x <= 3, "It doesn't get any more verbose than this")
}

// an argument, parsed and with default value
fn speed() -> impl Parser<f64> {
    short('s')
        .long("speed")
        .help("Set speed")
        .argument("SPEED")
        .from_str()
        .fallback(42.0)
}

fn output() -> impl Parser<PathBuf> {
    short('o')
        .long("output")
        .help("output file")
        .argument_os("OUTPUT")
        .map(PathBuf::from)
}

// no magical name transmogrifications.
fn nb_cars() -> impl Parser<u32> {
    short('n').long("nb-cars").argument("N").from_str()
}

fn files_to_process() -> impl Parser<Vec<PathBuf>> {
    short('f')
        .long("file")
        .help("File to process")
        .argument_os("FILE")
        .map(PathBuf::from)
        .many()
}
More examples
Hide additional examples
examples/derive_show_asm.rs (line 44)
42
43
44
45
46
47
48
49
fn verbosity() -> impl Parser<usize> {
    short('v')
        .long("verbose")
        .help("more verbose output, can be specified multiple times")
        .req_flag(())
        .many()
        .map(|v| v.len())
}
examples/derive.rs (line 30)
27
28
29
30
31
32
33
34
35
36
fn verbose() -> impl Parser<usize> {
    // number of occurrences of the v/verbose flag capped at 3
    short('v')
        .long("verbose")
        .help("Increase the verbosity\nYou can specify it up to 3 times\neither as -v -v -v or as -vvv")
        .req_flag(())
        .many()
        .map(|xs| xs.len())
        .guard(|&x| x <= 3, "It doesn't get any more verbose than this")
}
examples/enum_tuple.rs (line 17)
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);
}
examples/simple.rs (line 13)
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
fn opts() -> Opts {
    let speed = short('k')
        .long("speed") // give it a name
        .help("speed in KPH") // and help message
        .argument("SPEED") // it's an argument with metavar
        .from_str::<f64>() // that is parsed from string as f64
        .map(|s| s / 0.62); // and converted to mph

    let distance = short('d')
        .long("distance")
        .help("distance in miles")
        .argument("DISTANCE")
        .from_str::<f64>();

    (construct!(Opts { speed, distance }))
        .to_options()
        .descr("Accept speed and distance, print them.")
        .run()
}
examples/no_import.rs (line 13)
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
fn main() {
    // A flag, true if used in the command line. Can be required, this one is optional
    let debug = bpaf::short('d')
        .long("debug")
        .help("Activate debug mode")
        .switch();

    // an argument, parsed and with default value
    let speed = bpaf::Parser::fallback(
        bpaf::Parser::from_str::<f64>(
            bpaf::short('s')
                .long("speed")
                .help("Set speed")
                .argument("SPEED"),
        ),
        42.0,
    );

    // packing things in a struct assumes parser for each field is in scope.
    let opt = bpaf::Parser::to_options(bpaf::construct!(Out { debug, speed })).run();

    println!("{:#?}", opt);
}

Environment variable fallback

If named value isn’t present - try to fallback to this environment variable. You can specify it multiple times, bpaf would use items past the first one as hidden aliases.

fn parse_string() -> impl Parser<String> {
    short('k')
        .long("key")
        .env("API_KEY")
        .help("Use this API key to access the API")
        .argument("KEY")
}

See Named and env for more details and examples

Examples found in repository?
examples/env_variable.rs (line 13)
11
12
13
14
15
16
17
18
19
20
pub fn main() {
    let key = long("key")
        .env("ACCESS_KEY")
        .help("access key to use")
        .argument("KEY");

    let opts = construct!(Opts { key }).to_options().run();

    println!("{:?}", opts);
}
More examples
Hide additional examples
examples/multiple_fallback.rs (line 27)
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
pub fn main() {
    let field1 = long("field1")
        .env("FIELD1")
        .help("Field 1")
        .argument("ARG")
        .from_str::<u32>()
        .fallback(DEFAULT_CONFIG.field1);
    let field2 = long("field2")
        .env("FIELD2")
        .help("Field 2")
        .argument("ARG")
        .from_str::<u64>()
        .fallback(DEFAULT_CONFIG.field2);

    let opts = construct!(Config { field1, field2 }).to_options().run();

    // At this point if you get opts - it should be taken from one of
    // - the command line argument
    // - the environmental variable
    // - the config file
    // - the hard-coded default (from config parser)
    println!("{:?}", opts);
}

Add a help message to a flag/switch/argument

Combinatoric usage
fn parse_bool() -> impl Parser<bool> {
    short('f')
        .long("flag")
        .help("a flag that does a thing")
        .switch()
}
Derive usage

bpaf_derive converts doc comments into option help by following those rules:

  1. It skips blank lines, if present.
  2. It stops parsing after a double blank line.
#[derive(Debug, Clone, Bpaf)]
struct Options {
    /// This line is part of help message
    ///
    /// So is this one
    ///
    ///
    /// But this one isn't
    key: String,
}

See Named for more details

Examples found in repository?
examples/top_to_bottom.rs (line 36)
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
76
77
78
79
80
fn debug() -> impl Parser<bool> {
    short('d')
        .long("debug")
        .help("Activate debug mode")
        .switch()
}
// number of occurrences of the v/verbose flag capped at 3
fn verbose() -> impl Parser<usize> {
    short('v')
        .long("verbose")
        .help("Increase the verbosity\nYou can specify it up to 3 times\neither as -v -v -v or as -vvv")
        .req_flag(())
        .many()
        .map(|xs| xs.len())
        .guard(|&x| x <= 3, "It doesn't get any more verbose than this")
}

// an argument, parsed and with default value
fn speed() -> impl Parser<f64> {
    short('s')
        .long("speed")
        .help("Set speed")
        .argument("SPEED")
        .from_str()
        .fallback(42.0)
}

fn output() -> impl Parser<PathBuf> {
    short('o')
        .long("output")
        .help("output file")
        .argument_os("OUTPUT")
        .map(PathBuf::from)
}

// no magical name transmogrifications.
fn nb_cars() -> impl Parser<u32> {
    short('n').long("nb-cars").argument("N").from_str()
}

fn files_to_process() -> impl Parser<Vec<PathBuf>> {
    short('f')
        .long("file")
        .help("File to process")
        .argument_os("FILE")
        .map(PathBuf::from)
        .many()
}
More examples
Hide additional examples
examples/derive_show_asm.rs (line 45)
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
fn verbosity() -> impl Parser<usize> {
    short('v')
        .long("verbose")
        .help("more verbose output, can be specified multiple times")
        .req_flag(())
        .many()
        .map(|v| v.len())
}

fn parse_manifest_path() -> impl Parser<PathBuf> {
    long("manifest-path")
        .help("Path to Cargo.toml")
        .argument_os("PATH")
        .map(PathBuf::from)
        .parse(|p| {
            if p.is_absolute() {
                Ok(p)
            } else {
                std::env::current_dir()
                    .map(|d| d.join(p))
                    .and_then(|full_path| full_path.canonicalize())
            }
        })
        .fallback_with(|| std::env::current_dir().map(|x| x.join("Cargo.toml")))
}

#[derive(Debug, Clone, Bpaf)]
pub struct Format {
    /// Print interleaved Rust code
    pub rust: bool,

    #[bpaf(external(color_detection))]
    pub color: bool,

    /// include full demangled name instead of just prefix
    pub full_name: bool,
}

#[derive(Debug, Clone, Bpaf)]
pub enum Syntax {
    /// Generate assembly using Intel style
    Intel,
    /// Generate assembly using AT&T style
    Att,
}

impl ToString for Syntax {
    fn to_string(&self) -> String {
        match self {
            Syntax::Intel => String::from("llvm-args=-x86-asm-syntax=intel"),
            Syntax::Att => String::from("llvm-args=-x86-asm-syntax=att"),
        }
    }
}

fn color_detection() -> impl Parser<bool> {
    let yes = long("color")
        .help("Enable color highlighting")
        .req_flag(true);
    let no = long("no-color")
        .help("Disable color highlighting")
        .req_flag(false);
    construct!([yes, no]).fallback_with::<_, &str>(|| Ok(true))
}
examples/env_variable.rs (line 14)
11
12
13
14
15
16
17
18
19
20
pub fn main() {
    let key = long("key")
        .env("ACCESS_KEY")
        .help("access key to use")
        .argument("KEY");

    let opts = construct!(Opts { key }).to_options().run();

    println!("{:?}", opts);
}
examples/enum_in_args.rs (line 28)
25
26
27
28
29
30
31
32
33
34
35
fn main() {
    let opt = long("baz")
        .short('b')
        .help("choose between foo, bar or foobar")
        .argument("CMD")
        .from_str::<Baz>()
        .to_options()
        .run();

    println!("{:#?}", opt);
}
examples/positional.rs (line 14)
12
13
14
15
16
17
18
19
20
21
22
fn main() {
    let value = long("value")
        .help("Mysterious value")
        .argument("VAL")
        .from_str::<u32>()
        .fallback(42);
    let files = positional_os("FILE").map(PathBuf::from).many();
    let opts = construct!(Options { value, files }).to_options().run();

    println!("{:#?}", opts);
}
examples/after_help.rs (line 8)
6
7
8
9
10
11
12
13
14
15
16
17
18
fn main() {
    let opt = short('d')
        .help("Release the dragon")
        .switch()
        .to_options()
        // help metadata
        .descr("I am a program and I do things")
        .header("Sometimes they even work.")
        .footer("Beware `-d`, dragons be here")
        .run();

    println!("{:?}", opt);
}

Simple boolean flag

Parser produces true if flag is present in a command line or false otherwise

fn parse_bool() -> impl Parser<bool> {
    short('f')
        .long("flag")
        .help("a flag that does a thing")
        .switch()
}

See Named for more details

Examples found in repository?
examples/top_to_bottom.rs (line 37)
33
34
35
36
37
38
fn debug() -> impl Parser<bool> {
    short('d')
        .long("debug")
        .help("Activate debug mode")
        .switch()
}
More examples
Hide additional examples
examples/after_help.rs (line 9)
6
7
8
9
10
11
12
13
14
15
16
17
18
fn main() {
    let opt = short('d')
        .help("Release the dragon")
        .switch()
        .to_options()
        // help metadata
        .descr("I am a program and I do things")
        .header("Sometimes they even work.")
        .footer("Beware `-d`, dragons be here")
        .run();

    println!("{:?}", opt);
}
examples/flatten.rs (line 25)
24
25
26
27
28
29
30
31
32
33
34
35
36
fn main() {
    let verbose = short('v').help("switch verbosity on").switch();
    let user = short('u').help("daemon user").argument("USER");
    let group = short('g').help("daemon group").argument("GROUP");
    let daemon_opts = construct!(DaemonOpts { user, group });
    let opt = construct!(Cmdline {
        verbose,
        daemon_opts
    })
    .to_options()
    .run();
    println!("{:?}", opt);
}
examples/no_import.rs (line 15)
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
fn main() {
    // A flag, true if used in the command line. Can be required, this one is optional
    let debug = bpaf::short('d')
        .long("debug")
        .help("Activate debug mode")
        .switch();

    // an argument, parsed and with default value
    let speed = bpaf::Parser::fallback(
        bpaf::Parser::from_str::<f64>(
            bpaf::short('s')
                .long("speed")
                .help("Set speed")
                .argument("SPEED"),
        ),
        42.0,
    );

    // packing things in a struct assumes parser for each field is in scope.
    let opt = bpaf::Parser::to_options(bpaf::construct!(Out { debug, speed })).run();

    println!("{:#?}", opt);
}
examples/rectangle.rs (line 38)
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
fn main() {
    let width = short('w')
        .long("width")
        .help("Width of the rectangle")
        .argument("PX")
        .from_str::<usize>();

    let height = short('h')
        .long("height")
        .help("Height of the rectangle")
        .argument("PX")
        .from_str::<usize>();

    let rect = construct!(Rect { width, height })
        .group_help("Rectangle is defined by width and height in meters");

    let verbose = short('v')
        .long("verbose")
        .help("Print computation steps")
        .switch();

    let opt = construct!(Out { verbose, rect })
        .to_options()
        .descr("This program calculates rectangle's area")
        .header("vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv")
        .footer("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^")
        .run();
    println!("{:#?}", opt);
}
examples/git.rs (line 25)
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);
}

Flag with custom present/absent values

Combinatoric usage

Parser produces present if flag is present in a command line or absent otherwise

#[derive(Clone)]
enum Flag {
    Absent,
    Present,
}
fn parse_flag() -> impl Parser<Flag> {
    short('f')
        .long("flag")
        .help("a flag that does a thing")
        .flag(Flag::Present, Flag::Absent)
}
Derive usage

Currently available only with external annotation

#[derive(Debug, Clone)]
enum Flag {
    Absent,
    Present,
}

fn flag() -> impl Parser<Flag> {
    short('f')
        .long("flag")
        .help("a flag that does a thing")
        .flag(Flag::Present, Flag::Absent)
}

#[derive(Debug, Clone, Bpaf)]
struct Options {
    #[bpaf(external)]
    pub flag: Flag,
}

See Named for more details

Examples found in repository?
examples/verbose.rs (line 40)
12
13
14
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
fn main() {
    // program takes one or more -v or --verbose flags, more flags = higher verbosity.
    // parser handles number and produces a single flag.
    //
    // let's create it without using any single purpose magical functions

    // Let's staty by creating a simple parser that handles a single -v / --verbose
    // and fails otherwise;
    let verbose = short('v').long("verbose").req_flag(());

    // .many() tries to appy parser as many times as possible and collects the results.
    // We can't use non failing parse with .many() since it will loop forever.
    let verbose = verbose.many();

    // Then count how many times parser succeeded
    let verbose = verbose.map(|v| v.len());

    // And add a simple sanity checker.
    // By this time when this parser succeeds - it will contain verbosity in 0..3 range, inclusive.
    let verbose = verbose.guard(|&x| x <= 3, "it doesn't get any more verbose than 3");

    // program takes --trimor --no-trimflag, but not both at once. If none is given -
    // fallback value is to disable trimming. Trim enum is set accordingly

    // this flag succeeds iff --no-trim is given and produces Trim::Off
    let trim_off = long("no-trim").req_flag(Trim::Off);

    // this flag handles two remaining cases: --trim is given (Trim::On) an fallback (Trim::Off)
    let trim_on = long("trim").flag(Trim::On, Trim::Off);

    // combination of previous two.
    // if trim_off succeeds - trim_on never runs, otherwise trim_on tries to handle the remaining
    // case before falling back to Trim:Off.
    // If both --trim and --no-trim are given trim_off succeeds, trim_off never runs and --trim
    // remains unused - parser fails
    let trim = construct!([trim_off, trim_on]);

    let parser = construct!(verbose, trim);

    let opt = parser.to_options().run();
    println!("{:#?}", opt);
}

Required flag with custom value

Parser produces a value if present and fails otherwise. Not very useful by itself and works best in combination with other parsers.

Combinatoric usage
#[derive(Clone)]
enum Decision {
    On,
    Off,
    Undecided
}

// user can specify either --on or --off, parser would fallback to `Undecided`
fn parse_decision() -> impl Parser<Decision> {
    let on = long("on").req_flag(Decision::On);
    let off = long("off").req_flag(Decision::Off);
    on.or_else(off).fallback(Decision::Undecided)
}
Example
$ app --on
// Decision::On
$ app
// Decision::Undecided
// counts number of flags `-v` on the command line
fn verbosity() -> impl Parser<usize> {
    short('v').req_flag(()).many().map(|v| v.len())
}
Example
$ app
// 0
$ app -vv -v
// 3
Derive usage

bpaf would transform field-less enum variants into values combined by req_flag. In addition to naming annotations (short, long and env) such variants also accept hide and default annotations. Former hides it from --help (see hide, later makes it a default choice if preceeding variants fail to parse. You shoud only use default annotation on the last variant of enum.

#[derive(Debug, Clone, Bpaf)]
enum Decision {
    On,
    Off,
    #[bpaf(long, hide, default)]
    Undecided,
}

See Named for more details

Examples found in repository?
examples/derive_show_asm.rs (line 46)
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
fn verbosity() -> impl Parser<usize> {
    short('v')
        .long("verbose")
        .help("more verbose output, can be specified multiple times")
        .req_flag(())
        .many()
        .map(|v| v.len())
}

fn parse_manifest_path() -> impl Parser<PathBuf> {
    long("manifest-path")
        .help("Path to Cargo.toml")
        .argument_os("PATH")
        .map(PathBuf::from)
        .parse(|p| {
            if p.is_absolute() {
                Ok(p)
            } else {
                std::env::current_dir()
                    .map(|d| d.join(p))
                    .and_then(|full_path| full_path.canonicalize())
            }
        })
        .fallback_with(|| std::env::current_dir().map(|x| x.join("Cargo.toml")))
}

#[derive(Debug, Clone, Bpaf)]
pub struct Format {
    /// Print interleaved Rust code
    pub rust: bool,

    #[bpaf(external(color_detection))]
    pub color: bool,

    /// include full demangled name instead of just prefix
    pub full_name: bool,
}

#[derive(Debug, Clone, Bpaf)]
pub enum Syntax {
    /// Generate assembly using Intel style
    Intel,
    /// Generate assembly using AT&T style
    Att,
}

impl ToString for Syntax {
    fn to_string(&self) -> String {
        match self {
            Syntax::Intel => String::from("llvm-args=-x86-asm-syntax=intel"),
            Syntax::Att => String::from("llvm-args=-x86-asm-syntax=att"),
        }
    }
}

fn color_detection() -> impl Parser<bool> {
    let yes = long("color")
        .help("Enable color highlighting")
        .req_flag(true);
    let no = long("no-color")
        .help("Disable color highlighting")
        .req_flag(false);
    construct!([yes, no]).fallback_with::<_, &str>(|| Ok(true))
}
More examples
Hide additional examples
examples/at_least_two.rs (line 9)
7
8
9
10
11
12
13
14
15
16
fn main() {
    let opt = short('f')
        .req_flag(())
        .many()
        .guard(|x| x.len() >= 2, "at least two arguments are required")
        .to_options()
        .run();

    println!("{:?}", opt);
}
examples/top_to_bottom.rs (line 44)
40
41
42
43
44
45
46
47
48
fn verbose() -> impl Parser<usize> {
    short('v')
        .long("verbose")
        .help("Increase the verbosity\nYou can specify it up to 3 times\neither as -v -v -v or as -vvv")
        .req_flag(())
        .many()
        .map(|xs| xs.len())
        .guard(|&x| x <= 3, "It doesn't get any more verbose than this")
}
examples/env_logger.rs (line 31)
28
29
30
31
32
33
34
35
36
37
38
39
fn verbose() -> impl Parser<LevelFilter> {
    short('v')
        .help("Verbosity level, use multiple times for more verbosity")
        .req_flag(())
        .many()
        .map(|v| {
            use LevelFilter::*;
            *[Off, Error, Warn, Info, Debug, Trace]
                .get(v.len())
                .unwrap_or(&Trace)
        })
}
examples/derive.rs (line 32)
27
28
29
30
31
32
33
34
35
36
fn verbose() -> impl Parser<usize> {
    // number of occurrences of the v/verbose flag capped at 3
    short('v')
        .long("verbose")
        .help("Increase the verbosity\nYou can specify it up to 3 times\neither as -v -v -v or as -vvv")
        .req_flag(())
        .many()
        .map(|xs| xs.len())
        .guard(|&x| x <= 3, "It doesn't get any more verbose than this")
}
examples/basic.rs (line 29)
17
18
19
20
21
22
23
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
fn main() {
    // A flag, true if used in the command line. Can be required, this one is optional
    let debug = short('d')
        .long("debug")
        .help("Activate debug mode")
        .switch();

    // number of occurrences of the v/verbose flag capped at 3 with an error here but you can also
    // use `max` inside `map`
    let verbose = short('v')
        .long("verbose")
        .help("Increase the verbosity\nYou can specify it up to 3 times\neither as -v -v -v or as -vvv")
        .req_flag(())
        .many()
        .map(|xs| xs.len())
        .guard(|&x| x <= 3, "It doesn't get any more verbose than this");

    // an argument, parsed and with default value
    let speed = short('s')
        .long("speed")
        .help("Set speed")
        .argument("SPEED")
        .from_str()
        .fallback(42.0);

    let output = short('o')
        .long("output")
        .help("output file")
        .argument_os("OUTPUT")
        .map(PathBuf::from);

    // no magical name transmogrifications in combinatoric API
    let nb_cars = short('n').long("nb-cars").argument("N").from_str();

    // a parser that consumes one argument
    let file_to_proces = short('f')
        .long("file")
        .help("File to process")
        .argument_os("FILE")
        .map(PathBuf::from);
    let files_to_process = file_to_proces.many();

    // packing things in a struct assumes parser for each field is in scope.
    let opt = construct!(Out {
        debug,
        verbose,
        speed,
        output,
        nb_cars,
        files_to_process
    })
    .to_options()
    .run();

    println!("{:#?}", opt);
}

Named argument in utf8 (String) encoding

Argument must contain only valid utf8 characters. For OS specific encoding see argument_os.

fn parse_string() -> impl Parser<String> {
    short('n')
        .long("name")
        .argument("NAME")
}

See Named for more details

Examples found in repository?
examples/top_to_bottom.rs (line 55)
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
fn speed() -> impl Parser<f64> {
    short('s')
        .long("speed")
        .help("Set speed")
        .argument("SPEED")
        .from_str()
        .fallback(42.0)
}

fn output() -> impl Parser<PathBuf> {
    short('o')
        .long("output")
        .help("output file")
        .argument_os("OUTPUT")
        .map(PathBuf::from)
}

// no magical name transmogrifications.
fn nb_cars() -> impl Parser<u32> {
    short('n').long("nb-cars").argument("N").from_str()
}
More examples
Hide additional examples
examples/env_variable.rs (line 15)
11
12
13
14
15
16
17
18
19
20
pub fn main() {
    let key = long("key")
        .env("ACCESS_KEY")
        .help("access key to use")
        .argument("KEY");

    let opts = construct!(Opts { key }).to_options().run();

    println!("{:?}", opts);
}
examples/enum_in_args.rs (line 29)
25
26
27
28
29
30
31
32
33
34
35
fn main() {
    let opt = long("baz")
        .short('b')
        .help("choose between foo, bar or foobar")
        .argument("CMD")
        .from_str::<Baz>()
        .to_options()
        .run();

    println!("{:#?}", opt);
}
examples/positional.rs (line 15)
12
13
14
15
16
17
18
19
20
21
22
fn main() {
    let value = long("value")
        .help("Mysterious value")
        .argument("VAL")
        .from_str::<u32>()
        .fallback(42);
    let files = positional_os("FILE").map(PathBuf::from).many();
    let opts = construct!(Options { value, files }).to_options().run();

    println!("{:#?}", opts);
}
examples/flatten.rs (line 26)
24
25
26
27
28
29
30
31
32
33
34
35
36
fn main() {
    let verbose = short('v').help("switch verbosity on").switch();
    let user = short('u').help("daemon user").argument("USER");
    let group = short('g').help("daemon group").argument("GROUP");
    let daemon_opts = construct!(DaemonOpts { user, group });
    let opt = construct!(Cmdline {
        verbose,
        daemon_opts
    })
    .to_options()
    .run();
    println!("{:?}", opt);
}
examples/enum_tuple.rs (line 19)
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);
}

Named argument in OS specific encoding

If you prefer to panic on non utf8 encoding see argument.

fn parse_osstring() -> impl Parser<std::ffi::OsString> {
    short('n')
        .long("name")
        .argument_os("NAME")
}

See Named for more details

Examples found in repository?
examples/top_to_bottom.rs (line 64)
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
fn output() -> impl Parser<PathBuf> {
    short('o')
        .long("output")
        .help("output file")
        .argument_os("OUTPUT")
        .map(PathBuf::from)
}

// no magical name transmogrifications.
fn nb_cars() -> impl Parser<u32> {
    short('n').long("nb-cars").argument("N").from_str()
}

fn files_to_process() -> impl Parser<Vec<PathBuf>> {
    short('f')
        .long("file")
        .help("File to process")
        .argument_os("FILE")
        .map(PathBuf::from)
        .many()
}
More examples
Hide additional examples
examples/derive_show_asm.rs (line 54)
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
fn parse_manifest_path() -> impl Parser<PathBuf> {
    long("manifest-path")
        .help("Path to Cargo.toml")
        .argument_os("PATH")
        .map(PathBuf::from)
        .parse(|p| {
            if p.is_absolute() {
                Ok(p)
            } else {
                std::env::current_dir()
                    .map(|d| d.join(p))
                    .and_then(|full_path| full_path.canonicalize())
            }
        })
        .fallback_with(|| std::env::current_dir().map(|x| x.join("Cargo.toml")))
}
examples/basic.rs (line 45)
17
18
19
20
21
22
23
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
fn main() {
    // A flag, true if used in the command line. Can be required, this one is optional
    let debug = short('d')
        .long("debug")
        .help("Activate debug mode")
        .switch();

    // number of occurrences of the v/verbose flag capped at 3 with an error here but you can also
    // use `max` inside `map`
    let verbose = short('v')
        .long("verbose")
        .help("Increase the verbosity\nYou can specify it up to 3 times\neither as -v -v -v or as -vvv")
        .req_flag(())
        .many()
        .map(|xs| xs.len())
        .guard(|&x| x <= 3, "It doesn't get any more verbose than this");

    // an argument, parsed and with default value
    let speed = short('s')
        .long("speed")
        .help("Set speed")
        .argument("SPEED")
        .from_str()
        .fallback(42.0);

    let output = short('o')
        .long("output")
        .help("output file")
        .argument_os("OUTPUT")
        .map(PathBuf::from);

    // no magical name transmogrifications in combinatoric API
    let nb_cars = short('n').long("nb-cars").argument("N").from_str();

    // a parser that consumes one argument
    let file_to_proces = short('f')
        .long("file")
        .help("File to process")
        .argument_os("FILE")
        .map(PathBuf::from);
    let files_to_process = file_to_proces.many();

    // packing things in a struct assumes parser for each field is in scope.
    let opt = construct!(Out {
        debug,
        verbose,
        speed,
        output,
        nb_cars,
        files_to_process
    })
    .to_options()
    .run();

    println!("{:#?}", opt);
}

Trait Implementations

Returns a copy of the value. Read more

Performs copy-assignment from source. Read more

Formats the value using the given formatter. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

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

The resulting type after obtaining ownership.

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

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

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.