pub fn positional(metavar: &'static str) -> Positional<String>
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?
examples/derive_commands.rs (line 34)
33
34
35
36
37
38
39
40
41
42
43
fn feature_if() -> impl Parser<Option<String>> {
    positional("FEATURE")
        .guard(move |s| !is_version(s), "")
        .optional()
}

fn version_if() -> impl Parser<Option<String>> {
    positional("VERSION")
        .guard(move |s| is_version(s), "")
        .optional()
}
More examples
Hide additional examples
examples/cargo-cmd.rs (line 22)
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);
}
examples/git.rs (line 27)
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);
}
examples/confusing.rs (line 40)
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);
}