1#[rustfmt::skip]
2macro_rules! all_the_tuples {
3 ($name:ident) => {
4 $name!([], T1);
5 $name!([T1], T2);
6 $name!([T1, T2], T3);
7 $name!([T1, T2, T3], T4);
8 $name!([T1, T2, T3, T4], T5);
9 $name!([T1, T2, T3, T4, T5], T6);
10 $name!([T1, T2, T3, T4, T5, T6], T7);
11 $name!([T1, T2, T3, T4, T5, T6, T7], T8);
12 $name!([T1, T2, T3, T4, T5, T6, T7, T8], T9);
13 $name!([T1, T2, T3, T4, T5, T6, T7, T8, T9], T10);
14 $name!([T1, T2, T3, T4, T5, T6, T7, T8, T9, T10], T11);
15 $name!([T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], T12);
16 $name!([T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], T13);
17 $name!([T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], T14);
18 $name!([T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], T15);
19 $name!([T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], T16);
20 };
21}
22
23#[macro_export]
41macro_rules! named_parameters {
42 ( $vis:vis $param_name:ident { $($key:ident = $value:ty),* $(,)? }) => {
43 #[derive(Debug, Clone)]
44 $vis struct $param_name {
45 $($key: $value),*
46 }
47
48 impl<H> $crate::argument::ParseArguments<H> for $param_name {
49 fn parse(_: &$crate::TestDsl<H>, node: &$crate::kdl::KdlNode) -> Result<Self, $crate::error::TestErrorCase> {
50 $(
51 let $key: $value = $crate::argument::VerbArgument::from_value(node.entry(stringify!($key)).unwrap()).unwrap();
52 )*
53
54 Ok($param_name {
55 $(
56 $key
57 ),*
58 })
59 }
60 }
61 };
62}
63
64#[macro_export]
65#[cfg(not(doc))]
66#[expect(missing_docs, reason = "This is documented further below")]
67macro_rules! named_parameters_verb {
68 ($($input:tt)*) => {{
69 $crate::__inner_named_parameters_verb!(@impl { $($input)* })
70 }};
71}
72
73#[doc(hidden)]
74#[macro_export]
75macro_rules! __inner_named_parameters_verb {
76 (@impl { |$name:ident : &mut $ty:ty $(, $param_name:ident : $param_type:ty)* $(,)?| $rest:block }) => {{
77 #[derive(Debug, Clone)]
78 struct __NamedVerb {
79 $($param_name : $param_type),*
80 }
81
82 let verb = $crate::verb::FunctionVerb::<_, __NamedVerb>::new({
83 #[derive(Clone)]
84 struct __Caller;
85
86 impl $crate::verb::CallableVerb<$ty, __NamedVerb> for __Caller {
87 fn call(&self, harness: &mut $ty, node: &__NamedVerb) -> $crate::miette::Result<()> {
88
89 let verb = |$name : &mut $ty $(, $param_name : $param_type)*,| {
90 $rest
91 };
92
93 $(
94 let $param_name: $param_type = node.$param_name.clone();
95 )*
96
97 verb(harness, $($param_name),*)
98 }
99 }
100
101 __Caller
102 });
103
104 impl<H> $crate::argument::ParseArguments<H> for __NamedVerb {
105 fn parse(_: &$crate::TestDsl<H>, node: &$crate::kdl::KdlNode) -> Result<Self, $crate::error::TestErrorCase> {
106 $(
107 let $param_name: $param_type = $crate::argument::VerbArgument::from_value(node.entry(stringify!($param_name)).unwrap()).unwrap();
108 )*
109
110 Ok({
111 __NamedVerb {
112 $($param_name),*
113 }
114 })
115 }
116 }
117
118 verb
119 }};
120}
121
122#[cfg(doc)]
137#[macro_export]
138macro_rules! named_parameters_verb {
139 ($($input:tt)*) => {};
140}
141
142#[cfg(test)]
143mod tests {
144 use crate::TestDsl;
145 use crate::argument::ParseArguments;
146
147 #[test]
148 fn simple_kv() {
149 named_parameters!(CoolIntegers {
150 pi = usize,
151 name = String
152 });
153
154 let dsl = TestDsl::<()>::new();
155
156 let node = kdl::KdlNode::parse("foo pi=4 name=PI { other stuff }").unwrap();
157
158 let ints = CoolIntegers::parse(&dsl, &node).unwrap();
159
160 assert_eq!(ints.pi, 4);
161 assert_eq!(ints.name, "PI");
162 }
163
164 #[test]
165 fn simple_named_closure() {
166 let mut dsl = TestDsl::<()>::new();
167
168 dsl.add_verb(
169 "test",
170 named_parameters_verb!(|_harness: &mut (), name: String, pi: usize| {
171 println!("{name} = {pi}");
172 Ok(())
173 }),
174 );
175
176 dsl.add_verb(
177 "test_many",
178 named_parameters_verb!(|_harness: &mut (),
179 _name: String,
180 _pi: usize,
181 _pi1: usize,
182 _pi2: usize,
183 _pi3: usize,
184 _pi4: usize,
185 _pi5: usize,
186 _pi6: usize,
187 _pi7: usize,
188 _pi8: usize,
189 _pi9: usize,
190 _pi10: usize,
191 _pi11: usize,
192 _pi12: usize,
193 _pi13: usize,
194 _pi14: usize,
195 _pi15: usize,
196 _pi16: usize,
197 _pi17: usize,
198 _pi18: usize,
199 _pi19: usize,
200 _pi20: usize,
201 _pi21: usize,
202 _pi22: usize,
203 _pi23: usize,
204 _pi24: usize| { Ok(()) }),
205 );
206 }
207}