dynamic_tree/
dynamic-tree.rs

1//! This example constructs dynamic command tree from a structure
2
3use bpaf::*;
4
5#[derive(Debug, Clone)]
6enum Cog {
7    Command {
8        help: &'static str,
9        name: &'static str,
10        operation: &'static str,
11    },
12    Group {
13        name: &'static str,
14        help: &'static str,
15        nested: Vec<Cog>,
16    },
17}
18
19fn config() -> Cog {
20    let echo1 = Cog::Command {
21        help: "First echo command",
22        name: "echoCommand",
23        operation: "echo 'some text'",
24    };
25
26    let echo2 = Cog::Command {
27        help: "Second echo command",
28        name: "anotherEchoCmd",
29        operation: "echo 'another text'",
30    };
31    let sleep = Cog::Command {
32        name: "sleepCommand",
33        help: "sleep for a bit",
34        operation: "sleep 5",
35    };
36    let group1 = Cog::Group {
37        name: "commandGroup",
38        help: "contains a single sleep",
39        nested: vec![sleep],
40    };
41    Cog::Group {
42        name: "commands",
43        help: "contains all the commands, can be flattened with choose but effort :)",
44        nested: vec![echo1, echo2, group1],
45    }
46}
47
48fn choose<T>(xs: Vec<Box<dyn Parser<T> + 'static>>) -> Box<dyn Parser<T>>
49where
50    T: 'static,
51{
52    let mut items = xs.into_iter();
53
54    let mut res = items.next().unwrap();
55    for next in items {
56        res = construct!([res, next]).boxed()
57    }
58    res
59}
60
61fn make_parser(item: &Cog) -> Box<dyn Parser<&'static str>> {
62    match item {
63        Cog::Command {
64            help,
65            name,
66            operation,
67        } => Box::new(pure(*operation).to_options().descr(*help).command(name)),
68        Cog::Group { name, help, nested } => {
69            let nested = nested.iter().map(make_parser).collect::<Vec<_>>();
70            let inner = choose(nested);
71            inner.to_options().descr(*help).command(name).boxed()
72        }
73    }
74}
75
76fn main() {
77    let cfg = config();
78    let command = make_parser(&cfg).to_options().run();
79    println!("{:?}", command);
80}