app/
app.rs

1#![allow(dead_code)]
2
3const HELP: &str = "\
4App
5
6USAGE:
7  app [OPTIONS] --number NUMBER [INPUT]
8
9FLAGS:
10  -h, --help            Prints help information
11
12OPTIONS:
13  --number NUMBER       Sets a number
14  --opt-number NUMBER   Sets an optional number
15  --width WIDTH         Sets width [default: 10]
16  --output PATH         Sets an output path
17
18ARGS:
19  <INPUT>
20";
21
22#[derive(Debug)]
23struct AppArgs {
24    number: u32,
25    opt_number: Option<u32>,
26    width: u32,
27    input: std::path::PathBuf,
28    output: Option<std::path::PathBuf>,
29}
30
31fn main() {
32    let args = match parse_args() {
33        Ok(v) => v,
34        Err(e) => {
35            eprintln!("Error: {}.", e);
36            std::process::exit(1);
37        }
38    };
39
40    println!("{:#?}", args);
41}
42
43fn parse_args() -> Result<AppArgs, pico_args::Error> {
44    let mut pargs = pico_args::Arguments::from_env();
45
46    // Help has a higher priority and should be handled separately.
47    if pargs.contains(["-h", "--help"]) {
48        print!("{}", HELP);
49        std::process::exit(0);
50    }
51
52    let args = AppArgs {
53        // Parses a required value that implements `FromStr`.
54        // Returns an error if not present.
55        number: pargs.value_from_str("--number")?,
56        // Parses an optional value that implements `FromStr`.
57        opt_number: pargs.opt_value_from_str("--opt-number")?,
58        // Parses an optional value from `&str` using a specified function.
59        width: pargs.opt_value_from_fn("--width", parse_width)?.unwrap_or(10),
60        // Parses an optional value from `&OsStr` using a specified function.
61        output: pargs.opt_value_from_os_str("--input", parse_path)?,
62        // Parses a required free-standing/positional argument.
63        input: pargs.free_from_str()?,
64    };
65
66    // It's up to the caller what to do with the remaining arguments.
67    let remaining = pargs.finish();
68    if !remaining.is_empty() {
69        eprintln!("Warning: unused arguments left: {:?}.", remaining);
70    }
71
72    Ok(args)
73}
74
75fn parse_width(s: &str) -> Result<u32, &'static str> {
76    s.parse().map_err(|_| "not a number")
77}
78
79fn parse_path(s: &std::ffi::OsStr) -> Result<std::path::PathBuf, &'static str> {
80    Ok(s.into())
81}