aboutsummaryrefslogtreecommitdiff
path: root/mingling_picker/src/picker/patterns.rs
blob: 9c42a4693dbbdbb23028bb812b7e5e4e1ff89719 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use mingling_picker_macros::internal_repeat;

use crate::{Pickable, Picker, PickerArgs, PickerFlag, PickerResult};

internal_repeat!(1..=32 => {
    pub struct PickerPattern$<'a, (T$,+)>
    where (T$: Pickable + Default,+)
    {
        pub args: PickerArgs<'a>,
        (
            pub flag_$: &'a PickerFlag<'a, T$>,
            pub result_$: PickerResult<T$>,
            pub default_$: Option<Box<dyn FnOnce() -> T$>>,
            pub post_$: Option<Box<dyn FnOnce(T$) -> T$>>,
        +)
    }
});

internal_repeat!(1..=32 => {
    impl<'a, (T$,+)> PickerPattern$<'a, (T$,+)>
    where (T$: Pickable + Default,+)
    {
        /// Sets a default value provider for this flag.
        ///
        /// If the flag is not provided by the user at runtime, the given closure will be
        /// called to produce a default value. The closure is expected to return `T$`.
        ///
        /// # Example
        ///
        /// ```ignore
        /// let pattern = picker
        ///     .pick(&my_flag)
        ///     .or(|| 42);
        /// ```
        #[allow(clippy::type_complexity)]
        pub fn or<F>(mut self, func: F) -> Self
        where
            F: FnMut() -> T$,
            F: 'static,
        {
            self.default_$ = Some(Box::new(func));
            self
        }

        /// Attaches a post-processing function to this flag.
        ///
        /// After the flag's value is parsed (or defaulted), the given closure will be
        /// invoked with the parsed value and its return value will be used as the final
        /// result. This allows transforming or validating the parsed value.
        ///
        /// # Example
        ///
        /// ```ignore
        /// let pattern = picker
        ///     .pick(&my_flag)
        ///     .post(|val| val * 2);
        /// ```
        #[allow(clippy::type_complexity)]
        pub fn post<F>(mut self, func: F) -> Self
        where
            F: FnMut(T$) -> T$,
            F: 'static,
        {
            self.post_$ = Some(Box::new(func));
            self
        }
    }
});

internal_repeat!(1..32 => {
   impl<'a, (T$,+)> PickerPattern$<'a, (T$,+)>
   where (T$: Pickable + Default,+)
   {
       #[allow(clippy::type_complexity)]
       /// Adds a new flag to the picking chain, returning a new `PickerPattern` with one more type parameter.
       ///
       /// This method extends the current picking pattern by appending an additional flag.
       /// The previous flags and their results are preserved as part of the new pattern.
       /// The new flag's result is initially `Unparsed`.
       pub fn pick<N>(self, flag: &'a PickerFlag<'a, N>) -> PickerPattern$+<'a, (T$,+), N>
       where
           N: Pickable + Default,
       {
           PickerPattern$+ {
               // Args
               args: self.args,

               // Current
               flag_$+: flag,
               result_$+: PickerResult::Unparsed,
               default_$+: None,
               post_$+: None,

               // Prev
               (
                   flag_$: self.flag_$,
                   result_$: self.result_$,
                   default_$: self.default_$,
                   post_$: self.post_$,
                +)
           }
       }
   }
});

impl<'a> Picker<'a> {
    /// Creates a `PickerPattern1` from the given flag to start a picking chain.
    ///
    /// This method initiates a parameter picking chain with one flag.
    /// The result is initially `Unparsed`.
    pub fn pick<N>(self, flag: &'a PickerFlag<'a, N>) -> PickerPattern1<'a, N>
    where
        N: Pickable + Default,
    {
        PickerPattern1 {
            args: self.args,
            flag_1: flag,
            result_1: PickerResult::Unparsed,
            default_1: None,
            post_1: None,
        }
    }
}