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}