yogurt/dispatcher/
builder.rs1use super::{ExecContext, NodeType};
2use crate::argument::parser::ArgumentParser;
3use crate::argument::Argument;
4use crate::{Command, Dispatcher, Error, Result};
5use std::fmt::Debug;
6
7#[allow(clippy::type_complexity)]
8pub struct CommandBuilder<C: Debug, O> {
9 children: Vec<Command<C, O>>,
10 node: NodeType,
11 exec: Option<fn(&mut ExecContext<C>) -> Result<O>>,
12}
13
14impl<C: Debug, O> CommandBuilder<C, O> {
15 pub fn literal(name: impl Into<String>) -> Self {
16 Self {
17 children: vec![],
18 node: NodeType::Literal(name.into()),
19 exec: None,
20 }
21 }
22
23 pub fn argument(parser: impl ArgumentParser, name: impl Into<String>, required: bool) -> Self {
24 Self::argument_validator(parser.validator(), name, required)
25 }
26
27 pub fn argument_validator(
28 validator: fn(&str) -> bool,
29 name: impl Into<String>,
30 required: bool,
31 ) -> Self {
32 Self {
33 children: vec![],
34 exec: None,
35 node: NodeType::Argument(Argument::new(validator, name.into(), required)),
36 }
37 }
38
39 pub fn exec(mut self, exec: fn(&mut ExecContext<C>) -> Result<O>) -> Self {
40 self.exec = Some(exec);
41 self
42 }
43
44 pub fn child(mut self, child: impl Into<Command<C, O>>) -> Self {
45 self.children.push(child.into());
46 self
47 }
48
49 pub fn build(self) -> Command<C, O> {
50 let (mut literals, arguments): (Vec<_>, Vec<_>) =
51 self.children.into_iter().partition(|c| c.is_literal());
52 literals.extend(arguments);
53 Command {
54 children: literals,
55 node: self.node,
56 exec: self.exec,
57 }
58 }
59}
60
61pub struct DispatcherBuilder<C: Debug, O, B> {
62 root: CommandBuilder<C, O>,
63 prefix: Option<String>,
64 context_factory: Option<fn(&B) -> C>,
65 base_context: Option<B>,
66}
67
68impl<C: Debug, O, B> DispatcherBuilder<C, O, B> {
69 pub fn new() -> Self {
70 Self {
71 root: CommandBuilder::literal(""),
72 prefix: None,
73 context_factory: None,
74 base_context: None,
75 }
76 }
77
78 pub fn prefix(mut self, prefix: impl Into<String>) -> Self {
79 self.prefix = Some(prefix.into());
80 self
81 }
82
83 pub fn context_factory(mut self, factory: fn(&B) -> C) -> Self {
84 self.context_factory = Some(factory);
85 self
86 }
87
88 pub fn base_context(mut self, context: B) -> Self {
89 self.base_context = Some(context);
90 self
91 }
92
93 pub fn child(mut self, child: impl Into<Command<C, O>>) -> Self {
94 self.root.children.push(child.into());
95 self
96 }
97
98 pub fn build(self) -> Result<Dispatcher<C, O, B>> {
99 Ok(Dispatcher {
100 root: self.root.build(),
101 prefix: self.prefix.unwrap_or_default(),
102 context_factory: self.context_factory.ok_or(Error::IncompleteBuilder)?,
103 base_context: self.base_context.ok_or(Error::IncompleteBuilder)?,
104 })
105 }
106}
107
108impl<C: Debug, O, B> Default for DispatcherBuilder<C, O, B> {
109 fn default() -> Self {
110 Self {
111 root: CommandBuilder::literal(""),
112 prefix: None,
113 context_factory: None,
114 base_context: None,
115 }
116 }
117}