Function bpaf::positional
source · [−]Expand description
Positional argument in utf8 (String
) encoding
For named flags and arguments ordering generally doesn’t matter: most programs would
understand -O2 -v
the same way as -v -O2
, but for positional items order matters: in unix
cat hello world
and cat world hello
would display contents of the same two files but in
different order.
Important restriction
When parsing positional arguments from command lines you should have parsers for all your
named values and command before parsers for positional items. In derive API fields parsed as
positional should be at the end of your struct
/enum
. Same rule applies for positional
fields nested inside other structures: such structures should go to the end as well.
Failing to do can result in behavior confusing for the end user.
Combinatoric usage
fn input() -> impl Parser<String> {
positional("INPUT")
}
Derive usage
bpaf_derive
converts fields in tuple-like structures into positional items
#[derive(Debug, Clone, Bpaf)]
struct Options(String);
positional
and positional_os
annotations also accept an optional metavar name
#[derive(Debug, Clone, Bpaf)]
struct Options {
#[bpaf(positional("INPUT"))]
input: String,
}
See also positional_os
- a simiar function
Examples found in repository?
More examples
16 17 18 19 20 21 22 23 24 25 26 27 28
fn main() {
// defining a parser in a usual way
let width = short('w').argument("WIDTH").from_str().fallback(10);
let height = short('h').argument("HEIGHT").from_str().fallback(10);
let parser = construct!(Opts { width, height });
let cmd = positional("").guard(|s| s == "cmd", "").optional().hide();
let combined_parser = construct!(cmd, parser).map(|x| x.1);
let opts = combined_parser.to_options().run();
println!("{:?}", opts);
}
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);
}
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 73 74 75
fn main() {
let token = long("token")
.help("Token used for complex commands")
.argument("TOKEN")
.optional();
// start with defining 3 commands: simple, complex1 and complex2
let simple_parser = pure(PreCommand::Simple).to_options();
let simple = command("simple", simple_parser);
let complex1_parser = positional("ARG").from_str::<i32>();
let complex1 = command(
"complex1",
construct!(PreCommand::Complex1(complex1_parser))
.to_options()
.descr("This is complex command 1"),
);
let complex2_parser = positional("ARG").from_str::<i16>();
let complex2 = command(
"complex1",
construct!(PreCommand::Complex2(complex2_parser))
.to_options()
.descr("This is complex command 2"),
);
// compose then to accept any of those
let preparser = construct!([simple, complex1, complex2]);
// make a parser that accepts optional token and one of incomplete commands
// then create complete command or fail
let parser = construct!(token, preparser).parse(|(token, cmd)| match cmd {
PreCommand::Simple => Ok(Command::Simple),
PreCommand::Complex1(a) => match token {
Some(token) => Ok(Command::Complex1(token, a)),
None => Err("You must specify token to use with --token"),
},
PreCommand::Complex2(a) => match token {
Some(token) => Ok(Command::Complex2(token, a)),
None => Err("You must specify token to use with --token"),
},
});
let cmd = parser.to_options().run();
println!("{:?}", cmd);
}