tree_morph/
engine_builder.rs

1//! A builder type for constructing and configuring [`Engine`] instances.
2
3use crate::engine::Engine;
4use crate::events::EventHandlers;
5use crate::helpers::{SelectorFn, select_first};
6use crate::prelude::Rule;
7
8use paste::paste;
9use uniplate::Uniplate;
10
11/// A builder type for constructing and configuring [`Engine`] instances.
12pub struct EngineBuilder<T, M, R>
13where
14    T: Uniplate,
15    R: Rule<T, M>,
16{
17    event_handlers: EventHandlers<T, M>,
18
19    /// Groups of rules, each with a selector function.
20    rule_groups: Vec<Vec<R>>,
21
22    selector: SelectorFn<T, M, R>,
23}
24
25macro_rules! add_handler_fns {
26    (
27        directions: [$($dir:ident),*]
28    ) => {
29        paste! {$(
30            /// Register an event handler to be called before moving $dir in the tree.
31            pub fn [<add_before_ $dir>](mut self, handler: fn(&T, &mut M)) -> Self {
32                self.event_handlers.[<add_before_ $dir>](handler);
33                self
34            }
35
36            /// Register an event handler to be called after moving $dir one node in the tree.
37            pub fn [<add_after_ $dir>](mut self, handler: fn(&T, &mut M)) -> Self {
38                self.event_handlers.[<add_after_ $dir>](handler);
39                self
40            }
41        )*}
42    };
43}
44
45impl<T, M, R> EngineBuilder<T, M, R>
46where
47    T: Uniplate,
48    R: Rule<T, M>,
49{
50    /// Creates a new builder instance with the default [`select_first`] selector.
51    pub fn new() -> Self {
52        EngineBuilder {
53            event_handlers: EventHandlers::new(),
54            rule_groups: Vec::new(),
55            selector: select_first,
56        }
57    }
58
59    /// Consumes the builder and returns the constructed [`Engine`] instance.
60    pub fn build(self) -> Engine<T, M, R> {
61        Engine {
62            event_handlers: self.event_handlers,
63            rule_groups: self.rule_groups,
64            selector: self.selector,
65        }
66    }
67
68    /// Adds a collection of rules with the same priority.
69    ///
70    /// These rules will have a lower priority than previously added groups.
71    pub fn add_rule_group(mut self, rules: Vec<R>) -> Self {
72        self.rule_groups.push(rules);
73        self
74    }
75
76    /// Adds a single rule in a group by itself.
77    ///
78    /// This is a special case of [`add_rule_group`](EngineBuilder::add_rule_group).
79    pub fn add_rule(self, rule: R) -> Self {
80        self.add_rule_group(vec![rule])
81    }
82
83    /// Adds a collection of rule groups to the existing one.
84    ///
85    /// Rule groups maintain the same order and will be lower priority than existing groups.
86    pub fn append_rule_groups(mut self, groups: Vec<Vec<R>>) -> Self {
87        self.rule_groups.extend(groups);
88        self
89    }
90
91    add_handler_fns! {
92        directions: [up, down, right]
93    }
94
95    /// Sets the selector function to be used when multiple rules are applicable to the same node.
96    ///
97    /// See the [`morph`](Engine::morph) method of the Engine type for more information.
98    pub fn set_selector(mut self, selector: SelectorFn<T, M, R>) -> Self {
99        self.selector = selector;
100        self
101    }
102}
103
104impl<T, M, R> Default for EngineBuilder<T, M, R>
105where
106    T: Uniplate,
107    R: Rule<T, M>,
108{
109    fn default() -> Self {
110        Self::new()
111    }
112}
113
114impl<T, M, R> From<EngineBuilder<T, M, R>> for Engine<T, M, R>
115where
116    T: Uniplate,
117    R: Rule<T, M>,
118{
119    fn from(val: EngineBuilder<T, M, R>) -> Self {
120        val.build()
121    }
122}