pub struct NamedArg { /* private fields */ }
Expand description
A named thing used to create flag
, switch
or
argument
Named items (argument
, flag
and switch
) can have up to 2 visible names (one short and one 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
.
Derive usage
Unlike combinatoric API where you forced to specify names for your parsers derive API allows to omit some or all the details:
-
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) -
If
short
orlong
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. -
If
short
orlong
annotation is present with an argument - those are valuesbpaf_derive
would use instead of the original field name -
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§
source§impl NamedArg
impl NamedArg
sourcepub fn short(self, short: char) -> Self
pub fn short(self, short: char) -> Self
Add a short name to a flag/switch/argument
Combinatoric usage
#[derive(Debug, Clone)]
pub struct Options {
switch: bool,
arg: usize,
username: String,
}
pub fn options() -> OptionParser<Options> {
let switch = short('s') // first `short` creates a builder
.short('S') // second switch is a hidden alias
.long("switch") // visible long name
.long("also-switch") // hidden alias
.help("Switch with many names")
.switch(); // `switch` finalizes the builder
let arg = long("argument") // long is also a builder
.short('a')
.short('A')
.long("also-arg")
.help("Argument with names")
.argument::<usize>("ARG");
let username = long("user")
.short('u')
.env("USER1")
.help("Custom user name")
.argument::<String>("USER");
construct!(Options {
switch,
arg,
username
})
.to_options()
}
Derive usage
#[derive(Debug, Clone, Bpaf)]
#[bpaf(options)]
pub struct Options {
#[bpaf(short, long, short('S'), long("also-switch"))]
/// Switch with many names
switch: bool,
#[bpaf(short, long("argument"), short('A'), long("also-arg"))]
/// Argument with names
arg: usize,
#[bpaf(short, long("user"), env("USER1"), argument("USER"))]
/// Custom user name
username: String,
}
Examples
As usual switch is optional, arguments are required
% app -a 42 -u Bobert
Options { switch: false, arg: 42, username: "Bobert" }
Help displays only visible aliases (and a current value for env arguments)
% app --help
Usage: [-s] -a ARG -u USER
Available options:
-s, --switch Switch with many names
-a, --argument <ARG> Argument with names
-u, --user <USER> [env:USER1 = "pacak"]
Custom user name
-h, --help Prints help information
But you can still use hidden aliases, both short and long
% app --also-switch --also-arg 330 --user Bobert
Options { switch: true, arg: 330, username: "Bobert" }
And unless there’s many
or similar modifiers having multiple aliases doesn’t mean
you can specify them multiple times:
% app -A 42 -a 330 -u Bobert
-a is not expected in this context
Also hidden aliases are really hidden and only meant to do backward compatibility stuff, they won’t show up anywhere else in completions or error messages
% app -a 42 -A 330 -u Bobert
No such flag: `-A`, did you mean `-u`?
sourcepub fn long(self, long: &'static str) -> Self
pub fn long(self, long: &'static str) -> Self
Add a long name to a flag/switch/argument
Combinatoric usage
#[derive(Debug, Clone)]
pub struct Options {
switch: bool,
arg: usize,
username: String,
}
pub fn options() -> OptionParser<Options> {
let switch = short('s') // first `short` creates a builder
.short('S') // second switch is a hidden alias
.long("switch") // visible long name
.long("also-switch") // hidden alias
.help("Switch with many names")
.switch(); // `switch` finalizes the builder
let arg = long("argument") // long is also a builder
.short('a')
.short('A')
.long("also-arg")
.help("Argument with names")
.argument::<usize>("ARG");
let username = long("user")
.short('u')
.env("USER1")
.help("Custom user name")
.argument::<String>("USER");
construct!(Options {
switch,
arg,
username
})
.to_options()
}
Derive usage
#[derive(Debug, Clone, Bpaf)]
#[bpaf(options)]
pub struct Options {
#[bpaf(short, long, short('S'), long("also-switch"))]
/// Switch with many names
switch: bool,
#[bpaf(short, long("argument"), short('A'), long("also-arg"))]
/// Argument with names
arg: usize,
#[bpaf(short, long("user"), env("USER1"), argument("USER"))]
/// Custom user name
username: String,
}
Examples
As usual switch is optional, arguments are required
% app -a 42 -u Bobert
Options { switch: false, arg: 42, username: "Bobert" }
Help displays only visible aliases (and a current value for env arguments)
% app --help
Usage: [-s] -a ARG -u USER
Available options:
-s, --switch Switch with many names
-a, --argument <ARG> Argument with names
-u, --user <USER> [env:USER1 = "pacak"]
Custom user name
-h, --help Prints help information
But you can still use hidden aliases, both short and long
% app --also-switch --also-arg 330 --user Bobert
Options { switch: true, arg: 330, username: "Bobert" }
And unless there’s many
or similar modifiers having multiple aliases doesn’t mean
you can specify them multiple times:
% app -A 42 -a 330 -u Bobert
-a is not expected in this context
Also hidden aliases are really hidden and only meant to do backward compatibility stuff, they won’t show up anywhere else in completions or error messages
% app -a 42 -A 330 -u Bobert
No such flag: `-A`, did you mean `-u`?
Examples found in repository?
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
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::<f64>("SPEED")
.fallback(42.0)
}
fn output() -> impl Parser<PathBuf> {
short('o')
.long("output")
.help("output file")
.argument::<PathBuf>("OUTPUT")
}
// no magical name transmogrifications.
fn nb_cars() -> impl Parser<u32> {
short('n').long("nb-cars").argument::<u32>("N")
}
fn files_to_process() -> impl Parser<Vec<PathBuf>> {
short('f')
.long("file")
.help("File to process")
.argument::<PathBuf>("FILE")
.many()
}
More examples
702 703 704 705 706 707 708 709 710 711 712 713 714
fn help() -> impl Parser<ExtraParams> {
short('h')
.long("help")
.help("Prints help information")
.req_flag(ExtraParams::Help)
}
#[inline(never)]
fn ver(version: &'static str) -> impl Parser<ExtraParams> {
short('V')
.long("version")
.help("Prints version information")
.req_flag(ExtraParams::Version(version))
}
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::<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 = command("foo", bar_cmd)
.help("command for doing foo")
.map(Command::Foo)
.to_options()
.run();
println!("{:#?}", opt);
}
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
pub fn options() -> OptionParser<Options> {
let backing = toggle_options("backing", "Backing status").fallback(false);
let xinerama = toggle_options("xinerama", "Xinerama status").fallback(true);
let turbo = short('t')
.long("turbo")
.help("Engage the turbo mode")
.switch();
let extensions = extension().many();
construct!(Options {
turbo,
backing,
xinerama,
extensions,
})
.to_options()
}
sourcepub fn env(self, variable: &'static str) -> Self
pub fn env(self, variable: &'static str) -> Self
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.
For flag
and switch
environment variable being present
gives the same result as the flag being present, allowing to implement things like NO_COLOR
variables:
$ NO_COLOR=1 app --do-something
Combinatoric usage
#[derive(Debug, Clone)]
pub struct Options {
switch: bool,
arg: usize,
username: String,
}
pub fn options() -> OptionParser<Options> {
let switch = short('s') // first `short` creates a builder
.short('S') // second switch is a hidden alias
.long("switch") // visible long name
.long("also-switch") // hidden alias
.help("Switch with many names")
.switch(); // `switch` finalizes the builder
let arg = long("argument") // long is also a builder
.short('a')
.short('A')
.long("also-arg")
.help("Argument with names")
.argument::<usize>("ARG");
let username = long("user")
.short('u')
.env("USER1")
.help("Custom user name")
.argument::<String>("USER");
construct!(Options {
switch,
arg,
username
})
.to_options()
}
Derive usage
#[derive(Debug, Clone, Bpaf)]
#[bpaf(options)]
pub struct Options {
#[bpaf(short, long, short('S'), long("also-switch"))]
/// Switch with many names
switch: bool,
#[bpaf(short, long("argument"), short('A'), long("also-arg"))]
/// Argument with names
arg: usize,
#[bpaf(short, long("user"), env("USER1"), argument("USER"))]
/// Custom user name
username: String,
}
Examples
As usual switch is optional, arguments are required
% app -a 42 -u Bobert
Options { switch: false, arg: 42, username: "Bobert" }
Help displays only visible aliases (and a current value for env arguments)
% app --help
Usage: [-s] -a ARG -u USER
Available options:
-s, --switch Switch with many names
-a, --argument <ARG> Argument with names
-u, --user <USER> [env:USER1 = "pacak"]
Custom user name
-h, --help Prints help information
But you can still use hidden aliases, both short and long
% app --also-switch --also-arg 330 --user Bobert
Options { switch: true, arg: 330, username: "Bobert" }
And unless there’s many
or similar modifiers having multiple aliases doesn’t mean
you can specify them multiple times:
% app -A 42 -a 330 -u Bobert
-a is not expected in this context
Also hidden aliases are really hidden and only meant to do backward compatibility stuff, they won’t show up anywhere else in completions or error messages
% app -a 42 -A 330 -u Bobert
No such flag: `-A`, did you mean `-u`?
Examples found in repository?
More examples
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
pub fn main() {
let field1 = long("field1")
.env("FIELD1")
.help("Field 1")
.argument::<u32>("ARG")
.fallback(DEFAULT_CONFIG.field1);
let field2 = long("field2")
.env("FIELD2")
.help("Field 2")
.argument::<u64>("ARG")
.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);
}
sourcepub fn help<M>(self, help: M) -> Selfwhere
M: Into<String>,
pub fn help<M>(self, help: M) -> Selfwhere
M: Into<String>,
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:
- It skips blank lines, if present.
- 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 NamedArg
for more details
Examples found in repository?
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
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::<f64>("SPEED")
.fallback(42.0)
}
fn output() -> impl Parser<PathBuf> {
short('o')
.long("output")
.help("output file")
.argument::<PathBuf>("OUTPUT")
}
// no magical name transmogrifications.
fn nb_cars() -> impl Parser<u32> {
short('n').long("nb-cars").argument::<u32>("N")
}
fn files_to_process() -> impl Parser<Vec<PathBuf>> {
short('f')
.long("file")
.help("File to process")
.argument::<PathBuf>("FILE")
.many()
}
More examples
702 703 704 705 706 707 708 709 710 711 712 713 714
fn help() -> impl Parser<ExtraParams> {
short('h')
.long("help")
.help("Prints help information")
.req_flag(ExtraParams::Help)
}
#[inline(never)]
fn ver(version: &'static str) -> impl Parser<ExtraParams> {
short('V')
.long("version")
.help("Prints version information")
.req_flag(ExtraParams::Version(version))
}
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
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::<PathBuf>("PATH")
.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))
}
sourcepub fn switch(self) -> impl Parser<bool>
pub fn switch(self) -> impl Parser<bool>
Simple boolean flag
A special case of a flag
that gets decoded into a bool
, mostly serves as a convenient
shortcut to .flag(true, false)
.
Combinatoric usage
#[derive(Debug, Clone)]
pub struct Options {
decision: bool,
}
fn parse_decision() -> impl Parser<bool> {
long("decision").help("Positive decision").switch()
}
pub fn options() -> OptionParser<Options> {
let decision = parse_decision();
construct!(Options { decision }).to_options()
}
Derive usage
#[derive(Debug, Clone, Bpaf)]
#[bpaf(options)]
pub struct Options {
decision: bool,
}
Examples
Presense of a long name is decoded into true
% app --decision
Options { decision: true }
Absense is false
% app
Options { decision: false }
Examples found in repository?
More examples
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()
.descr("I am a program and I do things")
.header("Sometimes they even work.")
.footer("Beware `-d`, dragons be here")
.usage("You can call it with following flags: {usage}")
.run();
println!("{:?}", opt);
}
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::<String>("USER");
let group = short('g').help("daemon group").argument::<String>("GROUP");
let daemon_opts = construct!(DaemonOpts { user, group });
let opt = construct!(Cmdline {
verbose,
daemon_opts
})
.to_options()
.run();
println!("{:?}", opt);
}
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
pub fn options() -> OptionParser<Options> {
let backing = toggle_options("backing", "Backing status").fallback(false);
let xinerama = toggle_options("xinerama", "Xinerama status").fallback(true);
let turbo = short('t')
.long("turbo")
.help("Engage the turbo mode")
.switch();
let extensions = extension().many();
construct!(Options {
turbo,
backing,
xinerama,
extensions,
})
.to_options()
}
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
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::short('s')
.long("speed")
.help("Set speed")
.argument::<f64>("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);
}
sourcepub fn flag<T>(self, present: T, absent: T) -> impl Parser<T>where
T: Clone + 'static,
pub fn flag<T>(self, present: T, absent: T) -> impl Parser<T>where
T: Clone + 'static,
Flag with custom present/absent values
More generic version of switch
that uses arbitrary type instead of
bool
.
Combinatoric usage
#[derive(Debug, Clone)]
pub struct Options {
decision: Decision,
}
#[derive(Debug, Clone)]
pub enum Decision {
Yes,
No,
}
fn parse_decision() -> impl Parser<Decision> {
long("decision")
.help("Positive decision")
.flag(Decision::Yes, Decision::No)
}
pub fn options() -> OptionParser<Options> {
let decision = parse_decision();
construct!(Options { decision }).to_options()
}
Derive usage
#[derive(Debug, Clone, Bpaf)]
#[bpaf(options)]
pub struct Options {
#[bpaf(flag(Decision::Yes, Decision::No))]
decision: Decision,
}
#[derive(Debug, Clone)]
pub enum Decision {
Yes,
No,
}
Examples
Presense of a long name is decoded into Yes
% app --decision
Options { decision: Yes }
Absense is No
% app
Options { decision: No }
Examples found in repository?
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);
}
sourcepub fn req_flag<T>(self, present: T) -> impl Parser<T>where
T: Clone + 'static,
pub fn req_flag<T>(self, present: T) -> impl Parser<T>where
T: Clone + 'static,
Required flag with custom value
Similar to flag
takes no option arguments, but would only
succeed if user specifies it on a command line.
Not very useful by itself and works best in combination with other parsers.
Using req_flag
to implement 3-state options.
In derive mode bpaf
would transform field-less enum variants into req_flag
In addition to naming annotations (short
, long
and env
) such variants also
accepts 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. To better convey the meaning you might want to use a combination of
skip
and fallback
annotations, see examples.
Additionally bpaf_derive
handles ()
fields as req_flag
see
adjacent
for more details.
See NamedArg
for more details
Combinatoric usage
#[derive(Debug, Clone)]
pub struct Options {
decision: Decision,
}
#[derive(Debug, Clone)]
pub 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").help("Positive decision").req_flag(Decision::On);
let off = long("off")
.help("Negative decision")
.req_flag(Decision::Off);
construct!([on, off]).fallback(Decision::Undecided)
}
pub fn options() -> OptionParser<Options> {
let decision = parse_decision();
construct!(Options { decision }).to_options()
}
Derive usage
#[derive(Debug, Clone, Bpaf)]
#[bpaf(options)]
pub struct Options {
#[bpaf(external)]
decision: Decision,
}
#[derive(Debug, Clone, Bpaf)]
#[bpaf(fallback(Decision::Undecided))]
pub enum Decision {
/// Positive decision
On,
/// Negative decision
Off,
#[bpaf(skip)]
Undecided,
}
Examples
This example implements a tri-state switch: wether decision was made
positive, negative or not at all. Alternative implementation can use
optional
and None
to indicate “no decision” case.
A case with positive decision:
% app --on
Options { decision: On }
A case with no decision:
% app
Options { decision: Undecided }
--on
and --off
are mutually exclusive:
% app --on --off
--off is not expected in this context: --off cannot be used at the same time as --on
help
% app --help
Usage: [--on | --off]
Available options:
--on Positive decision
--off Negative decision
-h, --help Prints help information
Examples found in repository?
702 703 704 705 706 707 708 709 710 711 712 713 714
fn help() -> impl Parser<ExtraParams> {
short('h')
.long("help")
.help("Prints help information")
.req_flag(ExtraParams::Help)
}
#[inline(never)]
fn ver(version: &'static str) -> impl Parser<ExtraParams> {
short('V')
.long("version")
.help("Prints version information")
.req_flag(ExtraParams::Version(version))
}
More examples
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
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::<PathBuf>("PATH")
.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))
}
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)
})
}
sourcepub fn argument<T>(self, metavar: &'static str) -> ParseArgument<T>where
T: FromStr + 'static,
pub fn argument<T>(self, metavar: &'static str) -> ParseArgument<T>where
T: FromStr + 'static,
Argument
A short (-a
) or long (--name
) name 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 =
. For short flags value
can follow immediately: -fbar
.
When using combinatoring API you can specify the type with turbofish, for parsing types
that don’t implement FromStr
you can use consume a String
/OsString
first and parse
it by hands.
fn parse_arg() -> impl Parser<usize> {
short('a').argument::<usize>("ARG")
}
Combinatoric usage
#[derive(Debug, Clone)]
pub struct Options {
value: isize,
shorty: u64,
}
pub fn options() -> OptionParser<Options> {
let value = long("value").argument::<isize>("ARG").fallback(100);
// in many cases rustc is able to deduct exact type for the argument
// you are trying to consume, alternatively you can always specify it
// with turbofish to `argument:`
// let shorty = short('s').argument::<u64>("ARG");
let shorty = short('s').argument("ARG");
construct!(Options { value, shorty }).to_options()
}
Derive usage
#[derive(Debug, Clone, Bpaf)]
#[bpaf(options)]
pub struct Options {
#[bpaf(fallback(100))]
value: isize,
// in many cases rustc is able to deduct exact type for the argument
// you are trying to consume, alternatively you can always specify it
// with turbofish to `argument:`
// #[bpaf(short, argument::<u64>("ARG"))]
#[bpaf(short, argument("ARG"))]
shorty: u64,
}
Examples
Names for arguments could be short or long, and they can be parsed as mutiple different
types, this example uses isize
and u64
% app --value 50 -s=18446744073709551615
Options { value: 50, shorty: 18446744073709551615 }
Value can be separated from the flag by space, =
or for short ones - be immediately adjacent
% app --value=1 -s42
Options { value: 1, shorty: 42 }
You can apply fallback and other transformation
% app -s0
Options { value: 100, shorty: 0 }
But if there’s no fallback - the value is required
% app --value 1
Expected -s ARG, pass --help for usage information
Argument is required
% app -s
-s requires an argument
Examples found in repository?
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
fn speed() -> impl Parser<f64> {
short('s')
.long("speed")
.help("Set speed")
.argument::<f64>("SPEED")
.fallback(42.0)
}
fn output() -> impl Parser<PathBuf> {
short('o')
.long("output")
.help("output file")
.argument::<PathBuf>("OUTPUT")
}
// no magical name transmogrifications.
fn nb_cars() -> impl Parser<u32> {
short('n').long("nb-cars").argument::<u32>("N")
}
fn files_to_process() -> impl Parser<Vec<PathBuf>> {
short('f')
.long("file")
.help("File to process")
.argument::<PathBuf>("FILE")
.many()
}
More examples
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::<String>("USER");
let group = short('g').help("daemon group").argument::<String>("GROUP");
let daemon_opts = construct!(DaemonOpts { user, group });
let opt = construct!(Cmdline {
verbose,
daemon_opts
})
.to_options()
.run();
println!("{:?}", opt);
}
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::<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 = command("foo", bar_cmd)
.help("command for doing foo")
.map(Command::Foo)
.to_options()
.run();
println!("{:#?}", opt);
}