1use bpaf::*;
4
5#[derive(Debug, Clone)]
6enum Value {
7 Bool(bool),
8 Number(usize),
9 String(String),
10}
11
12fn number(name: &'static str) -> impl Parser<(String, Value)> {
13 let label = name.to_string();
14 long(name)
15 .argument::<usize>("NUM")
16 .map(move |n| (label.clone(), Value::Number(n)))
17}
18
19fn bool(name: &'static str) -> impl Parser<(String, Value)> {
20 let label = name.to_string();
21 long(name)
22 .switch()
23 .map(move |n| (label.clone(), Value::Bool(n)))
24}
25
26fn string(name: &'static str) -> impl Parser<(String, Value)> {
27 let label = name.to_string();
28 long(name)
29 .help("this can use a help message")
30 .argument::<String>("NUM")
31 .map(move |n| (label.clone(), Value::String(n)))
32}
33
34fn cons<T>(acc: Box<dyn Parser<Vec<T>>>, cur: Box<dyn Parser<T>>) -> Box<dyn Parser<Vec<T>>>
35where
36 T: 'static,
37{
38 construct!(acc, cur)
39 .map(|(mut acc, cur)| {
40 acc.push(cur);
41 acc
42 })
43 .boxed()
44}
45
46enum Ty {
47 Bool,
48 Number,
49 String,
50}
51
52fn main() {
53 let items = &[
54 ("banana", Ty::Bool),
55 ("width", Ty::Number),
56 ("name", Ty::String),
57 ];
58
59 let mut parser = pure(Vec::<(String, Value)>::new()).boxed();
60 for (name, ty) in items {
61 parser = cons(
62 parser,
63 match ty {
64 Ty::Bool => bool(name).boxed(),
65 Ty::Number => number(name).boxed(),
66 Ty::String => string(name).boxed(),
67 },
68 )
69 }
70
71 let options = parser.run();
72 println!("{:?}", options);
73}