1use cmake_parser_derive::CMake;
2
3use crate::{
4 doc::command_scope::{CommandScope, ToCommandScope},
5 Token,
6};
7
8#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
12#[cmake(pkg = "crate", untagged)]
13pub enum List<'t> {
14 Reading(ListReading<'t>),
15 Search(ListSearch<'t>),
16 Modification(ListModification<'t>),
17 Ordering(ListOrdering<'t>),
18}
19
20impl<'t> ToCommandScope for List<'t> {
21 fn to_command_scope(&self) -> CommandScope {
22 CommandScope::Scripting
23 }
24}
25
26#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
27#[cmake(pkg = "crate", untagged, transparent)]
28pub enum ListReading<'t> {
29 Length(ListLength<'t>),
30 Get(ListGet<'t>),
31 Join(ListJoin<'t>),
32}
33
34#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
35#[cmake(pkg = "crate", positional)]
36pub struct ListLength<'t> {
37 pub list: Token<'t>,
38 pub out_var: Token<'t>,
39}
40
41#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
42#[cmake(pkg = "crate", positional)]
43pub struct ListGet<'t> {
44 pub list: Token<'t>,
45 pub element_index: Vec<Token<'t>>,
46 #[cmake(last)]
47 pub out_var: Token<'t>,
48}
49
50#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
51#[cmake(pkg = "crate", positional)]
52pub struct ListJoin<'t> {
53 pub list: Token<'t>,
54 pub glue: Token<'t>,
55 pub out_var: Token<'t>,
56}
57
58#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
59#[cmake(pkg = "crate", untagged, transparent)]
60pub enum ListSearch<'t> {
61 Find(ListFind<'t>),
62}
63
64#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
65#[cmake(pkg = "crate", positional)]
66pub struct ListFind<'t> {
67 pub list: Token<'t>,
68 pub value: Token<'t>,
69 pub out_var: Token<'t>,
70}
71
72#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
73#[cmake(pkg = "crate", untagged, transparent)]
74pub enum ListModification<'t> {
75 Append(ListAppend<'t>),
76 Filter(ListFilter<'t>),
77 Insert(ListInsert<'t>),
78 PopBack(ListPopBack<'t>),
79 PopFront(ListPopFront<'t>),
80 Prepend(ListPrepend<'t>),
81 RemoveItem(ListRemoveItem<'t>),
82 RemoveAt(ListRemoveAt<'t>),
83 RemoveDuplicates(ListRemoveDuplicates<'t>),
84 Transform(ListTransform<'t>),
85}
86
87#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
88#[cmake(pkg = "crate", positional)]
89pub struct ListAppend<'t> {
90 pub list: Token<'t>,
91 pub element: Option<Vec<Token<'t>>>,
92}
93
94#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
95#[cmake(pkg = "crate", positional)]
96pub struct ListFilter<'t> {
97 pub list: Token<'t>,
98 pub mode: FilterMode,
99 #[cmake(transparent, rename = "REGEX")]
100 pub regular_expression: Token<'t>,
101}
102
103#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
104#[cmake(pkg = "crate", list)]
105pub enum FilterMode {
106 Include,
107 Exclude,
108}
109
110#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
111#[cmake(pkg = "crate", positional)]
112pub struct ListInsert<'t> {
113 pub list: Token<'t>,
114 pub index: Token<'t>,
115 pub element: Vec<Token<'t>>,
116}
117
118#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
119#[cmake(pkg = "crate", positional)]
120pub struct ListPopBack<'t> {
121 pub list: Token<'t>,
122 pub out_var: Option<Vec<Token<'t>>>,
123}
124
125#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
126#[cmake(pkg = "crate", positional)]
127pub struct ListPopFront<'t> {
128 pub list: Token<'t>,
129 pub out_var: Option<Vec<Token<'t>>>,
130}
131
132#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
133#[cmake(pkg = "crate", positional)]
134pub struct ListPrepend<'t> {
135 pub list: Token<'t>,
136 pub element: Option<Vec<Token<'t>>>,
137}
138
139#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
140#[cmake(pkg = "crate", positional)]
141pub struct ListRemoveItem<'t> {
142 pub list: Token<'t>,
143 pub value: Vec<Token<'t>>,
144}
145
146#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
147#[cmake(pkg = "crate", positional)]
148pub struct ListRemoveAt<'t> {
149 pub list: Token<'t>,
150 pub index: Vec<Token<'t>>,
151}
152
153#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
154#[cmake(pkg = "crate", positional)]
155pub struct ListRemoveDuplicates<'t> {
156 pub list: Token<'t>,
157}
158
159#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
160#[cmake(pkg = "crate")]
161pub struct ListTransform<'t> {
162 #[cmake(positional)]
163 pub list: Token<'t>,
164 #[cmake(positional)]
165 pub action: TransformAction<'t>,
166 pub selector: Option<TransformSelector<'t>>,
167 pub output_variable: Option<Token<'t>>,
168}
169
170#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
171#[cmake(pkg = "crate", list, transparent)]
172pub enum TransformAction<'t> {
173 Append(Token<'t>),
174 Prepend(Token<'t>),
175 #[cmake(rename = "TOLOWER")]
176 ToLower,
177 #[cmake(rename = "TOUPPER")]
178 ToUpper,
179 Strip,
180 GenexStrip,
181 Replace(ReplaceAction<'t>),
182}
183
184#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
185#[cmake(pkg = "crate", positional)]
186pub struct ReplaceAction<'t> {
187 pub regular_expression: Token<'t>,
188 pub replace_expression: Token<'t>,
189}
190
191#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
192#[cmake(pkg = "crate", transparent)]
193pub enum TransformSelector<'t> {
194 At(SelectorAt<'t>),
195 For(SelectorFor<'t>),
196 Regex(SelectorRegex<'t>),
197}
198
199#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
200#[cmake(pkg = "crate", positional)]
201pub struct SelectorAt<'t> {
202 pub index: Token<'t>,
203}
204
205#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
206#[cmake(pkg = "crate", positional)]
207pub struct SelectorFor<'t> {
208 pub start: Token<'t>,
209 pub stop: Token<'t>,
210 pub step: Option<Token<'t>>,
211}
212
213#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
214#[cmake(pkg = "crate", positional)]
215pub struct SelectorRegex<'t> {
216 pub regular_expression: Token<'t>,
217}
218
219#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
220#[cmake(pkg = "crate", untagged, transparent)]
221pub enum ListOrdering<'t> {
222 Reverse(ListReverse<'t>),
223 Sort(ListSort<'t>),
224}
225
226#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
227#[cmake(pkg = "crate", positional)]
228pub struct ListReverse<'t> {
229 pub list: Token<'t>,
230}
231
232#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
233#[cmake(pkg = "crate")]
234pub struct ListSort<'t> {
235 #[cmake(positional)]
236 pub list: Token<'t>,
237 pub compare: Option<SortCompare>,
238 pub case: Option<SortCase>,
239 pub order: Option<SortOrder>,
240}
241
242#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
243#[cmake(pkg = "crate", list)]
244pub enum SortCompare {
245 String,
246 FileBasename,
247 Natural,
248}
249
250#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
251#[cmake(pkg = "crate", list)]
252pub enum SortCase {
253 Sensitive,
254 Insensitive,
255}
256
257#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
258#[cmake(pkg = "crate", list)]
259pub enum SortOrder {
260 Ascending,
261 Descending,
262}
263
264#[cfg(test)]
265mod tests {
266 use super::*;
267 use crate::doc::cmake_parse::tests::{token, tokens_vec};
268 use crate::*;
269 use pretty_assertions::assert_eq;
270
271 #[test]
272 fn list() {
273 let src = include_bytes!("../../../../../fixture/commands/scripting/list");
274 let cmakelists = parse_cmakelists(src).unwrap();
275 let doc = Doc::from(cmakelists);
276 assert_eq!(
277 doc.to_commands_iter().collect::<Vec<_>>(),
278 vec![
279 Ok(Command::List(Box::new(List::Reading(ListReading::Length(
280 ListLength {
281 list: token(b"list1"),
282 out_var: token(b"out_var1"),
283 }
284 ))))),
285 Ok(Command::List(Box::new(List::Reading(ListReading::Get(
286 ListGet {
287 list: token(b"list1"),
288 element_index: tokens_vec([b"index1"]),
289 out_var: token(b"out_var1"),
290 }
291 ))))),
292 Ok(Command::List(Box::new(List::Reading(ListReading::Get(
293 ListGet {
294 list: token(b"list1"),
295 element_index: tokens_vec([b"index1", b"index2"]),
296 out_var: token(b"out_var1"),
297 }
298 ))))),
299 Ok(Command::List(Box::new(List::Reading(ListReading::Join(
300 ListJoin {
301 list: token(b"list1"),
302 glue: token(b"glue1"),
303 out_var: token(b"out_var1"),
304 }
305 ))))),
306 Ok(Command::List(Box::new(List::Search(ListSearch::Find(
307 ListFind {
308 list: token(b"list1"),
309 value: token(b"value1"),
310 out_var: token(b"out_var1"),
311 }
312 ))))),
313 Ok(Command::List(Box::new(List::Modification(
314 ListModification::Append(ListAppend {
315 list: token(b"list1"),
316 element: None,
317 })
318 )))),
319 Ok(Command::List(Box::new(List::Modification(
320 ListModification::Append(ListAppend {
321 list: token(b"list1"),
322 element: Some(tokens_vec([b"element1", b"element2"])),
323 })
324 )))),
325 Ok(Command::List(Box::new(List::Modification(
326 ListModification::Filter(ListFilter {
327 list: token(b"list1"),
328 mode: FilterMode::Include,
329 regular_expression: token(b"regex1"),
330 })
331 )))),
332 Ok(Command::List(Box::new(List::Modification(
333 ListModification::Filter(ListFilter {
334 list: token(b"list1"),
335 mode: FilterMode::Exclude,
336 regular_expression: token(b"regex1"),
337 })
338 )))),
339 Ok(Command::List(Box::new(List::Modification(
340 ListModification::Insert(ListInsert {
341 list: token(b"list1"),
342 index: token(b"5"),
343 element: tokens_vec([b"element1", b"element2"]),
344 })
345 )))),
346 Ok(Command::List(Box::new(List::Modification(
347 ListModification::PopBack(ListPopBack {
348 list: token(b"list1"),
349 out_var: Some(tokens_vec([b"out_var1", b"out_var2"])),
350 })
351 )))),
352 Ok(Command::List(Box::new(List::Modification(
353 ListModification::PopFront(ListPopFront {
354 list: token(b"list1"),
355 out_var: Some(tokens_vec([b"out_var1", b"out_var2"])),
356 })
357 )))),
358 Ok(Command::List(Box::new(List::Modification(
359 ListModification::Prepend(ListPrepend {
360 list: token(b"list1"),
361 element: Some(tokens_vec([b"element1", b"element2"])),
362 })
363 )))),
364 Ok(Command::List(Box::new(List::Modification(
365 ListModification::RemoveItem(ListRemoveItem {
366 list: token(b"list1"),
367 value: tokens_vec([b"value1", b"value2"]),
368 })
369 )))),
370 Ok(Command::List(Box::new(List::Modification(
371 ListModification::RemoveAt(ListRemoveAt {
372 list: token(b"list1"),
373 index: tokens_vec([b"index1", b"index2"]),
374 })
375 )))),
376 Ok(Command::List(Box::new(List::Modification(
377 ListModification::RemoveDuplicates(ListRemoveDuplicates {
378 list: token(b"list1"),
379 })
380 )))),
381 Ok(Command::List(Box::new(List::Modification(
382 ListModification::Transform(ListTransform {
383 list: token(b"list1"),
384 action: TransformAction::Append(token(b"value1")),
385 selector: None,
386 output_variable: None,
387 })
388 )))),
389 Ok(Command::List(Box::new(List::Modification(
390 ListModification::Transform(ListTransform {
391 list: token(b"list1"),
392 action: TransformAction::Prepend(token(b"value1")),
393 selector: None,
394 output_variable: None,
395 })
396 )))),
397 Ok(Command::List(Box::new(List::Modification(
398 ListModification::Transform(ListTransform {
399 list: token(b"list1"),
400 action: TransformAction::ToLower,
401 selector: None,
402 output_variable: None,
403 })
404 )))),
405 Ok(Command::List(Box::new(List::Modification(
406 ListModification::Transform(ListTransform {
407 list: token(b"list1"),
408 action: TransformAction::ToUpper,
409 selector: None,
410 output_variable: None,
411 })
412 )))),
413 Ok(Command::List(Box::new(List::Modification(
414 ListModification::Transform(ListTransform {
415 list: token(b"list1"),
416 action: TransformAction::Strip,
417 selector: None,
418 output_variable: None,
419 })
420 )))),
421 Ok(Command::List(Box::new(List::Modification(
422 ListModification::Transform(ListTransform {
423 list: token(b"list1"),
424 action: TransformAction::GenexStrip,
425 selector: None,
426 output_variable: None,
427 })
428 )))),
429 Ok(Command::List(Box::new(List::Modification(
430 ListModification::Transform(ListTransform {
431 list: token(b"list1"),
432 action: TransformAction::Replace(ReplaceAction {
433 regular_expression: token(b"regular_expression1"),
434 replace_expression: token(b"replace_expression1"),
435 }),
436 selector: None,
437 output_variable: None,
438 })
439 )))),
440 Ok(Command::List(Box::new(List::Modification(
441 ListModification::Transform(ListTransform {
442 list: token(b"list1"),
443 action: TransformAction::ToUpper,
444 selector: Some(TransformSelector::At(SelectorAt {
445 index: token(b"10"),
446 })),
447 output_variable: None,
448 })
449 )))),
450 Ok(Command::List(Box::new(List::Modification(
451 ListModification::Transform(ListTransform {
452 list: token(b"list1"),
453 action: TransformAction::ToUpper,
454 selector: Some(TransformSelector::At(SelectorAt {
455 index: token(b"10"),
456 })),
457 output_variable: Some(token(b"out_var1")),
458 })
459 )))),
460 Ok(Command::List(Box::new(List::Modification(
461 ListModification::Transform(ListTransform {
462 list: token(b"list1"),
463 action: TransformAction::ToUpper,
464 selector: Some(TransformSelector::For(SelectorFor {
465 start: token(b"10"),
466 stop: token(b"20"),
467 step: None,
468 })),
469 output_variable: None,
470 })
471 )))),
472 Ok(Command::List(Box::new(List::Modification(
473 ListModification::Transform(ListTransform {
474 list: token(b"list1"),
475 action: TransformAction::ToUpper,
476 selector: Some(TransformSelector::For(SelectorFor {
477 start: token(b"10"),
478 stop: token(b"20"),
479 step: None,
480 })),
481 output_variable: Some(token(b"out_var1")),
482 })
483 )))),
484 Ok(Command::List(Box::new(List::Modification(
485 ListModification::Transform(ListTransform {
486 list: token(b"list1"),
487 action: TransformAction::ToUpper,
488 selector: Some(TransformSelector::For(SelectorFor {
489 start: token(b"10"),
490 stop: token(b"20"),
491 step: Some(token(b"30")),
492 })),
493 output_variable: None,
494 })
495 )))),
496 Ok(Command::List(Box::new(List::Modification(
497 ListModification::Transform(ListTransform {
498 list: token(b"list1"),
499 action: TransformAction::ToUpper,
500 selector: Some(TransformSelector::For(SelectorFor {
501 start: token(b"10"),
502 stop: token(b"20"),
503 step: Some(token(b"30")),
504 })),
505 output_variable: Some(token(b"out_var1")),
506 })
507 )))),
508 Ok(Command::List(Box::new(List::Modification(
509 ListModification::Transform(ListTransform {
510 list: token(b"list1"),
511 action: TransformAction::ToUpper,
512 selector: Some(TransformSelector::Regex(SelectorRegex {
513 regular_expression: token(b"regex1"),
514 })),
515 output_variable: None,
516 })
517 )))),
518 Ok(Command::List(Box::new(List::Modification(
519 ListModification::Transform(ListTransform {
520 list: token(b"list1"),
521 action: TransformAction::ToUpper,
522 selector: Some(TransformSelector::Regex(SelectorRegex {
523 regular_expression: token(b"regex1"),
524 })),
525 output_variable: Some(token(b"out_var1")),
526 })
527 )))),
528 Ok(Command::List(Box::new(List::Ordering(
529 ListOrdering::Reverse(ListReverse {
530 list: token(b"list1"),
531 })
532 )))),
533 Ok(Command::List(Box::new(List::Ordering(ListOrdering::Sort(
534 ListSort {
535 list: token(b"list1"),
536 compare: Some(SortCompare::Natural),
537 case: Some(SortCase::Sensitive),
538 order: Some(SortOrder::Ascending),
539 }
540 ))))),
541 ]
542 )
543 }
544}