hello_error/
hello-error.rs

1use lexarg_error::LexError;
2
3struct Args {
4    thing: String,
5    number: u32,
6    shout: bool,
7}
8
9fn parse_args() -> Result<Args, String> {
10    #![allow(clippy::enum_glob_use)]
11    use lexarg_parser::Arg::*;
12
13    let mut thing = None;
14    let mut number = 1;
15    let mut shout = false;
16    let raw = std::env::args_os().collect::<Vec<_>>();
17    let mut parser = lexarg_parser::Parser::new(&raw);
18    let bin_name = parser
19        .next_raw()
20        .expect("nothing parsed yet so no attached lingering")
21        .expect("always at least one");
22    while let Some(arg) = parser.next_arg() {
23        match arg {
24            Short("n") | Long("number") => {
25                let value = parser.next_flag_value().ok_or_else(|| {
26                    LexError::msg("missing required value")
27                        .within(arg)
28                        .to_string()
29                })?;
30                number = value
31                    .to_str()
32                    .ok_or_else(|| {
33                        LexError::msg("invalid number")
34                            .unexpected(Value(value))
35                            .within(arg)
36                            .to_string()
37                    })?
38                    .parse()
39                    .map_err(|e| {
40                        LexError::msg(e)
41                            .unexpected(Value(value))
42                            .within(arg)
43                            .to_string()
44                    })?;
45            }
46            Long("shout") => {
47                shout = true;
48            }
49            Value(val) if thing.is_none() => {
50                thing =
51                    Some(val.to_str().ok_or_else(|| {
52                        LexError::msg("invalid string").unexpected(arg).to_string()
53                    })?);
54            }
55            Short("h") | Long("help") => {
56                println!("Usage: hello [-n|--number=NUM] [--shout] THING");
57                std::process::exit(0);
58            }
59            _ => {
60                return Err(LexError::msg("unexpected argument")
61                    .unexpected(arg)
62                    .to_string());
63            }
64        }
65    }
66
67    Ok(Args {
68        thing: thing
69            .ok_or_else(|| {
70                LexError::msg("missing argument THING")
71                    .within(Value(bin_name))
72                    .to_string()
73            })?
74            .to_owned(),
75        number,
76        shout,
77    })
78}
79
80fn main() -> Result<(), String> {
81    let args = parse_args()?;
82    let mut message = format!("Hello {}", args.thing);
83    if args.shout {
84        message = message.to_uppercase();
85    }
86    for _ in 0..args.number {
87        println!("{message}");
88    }
89    Ok(())
90}