cmake_parser/doc/command/scripting/
list.rs

1use cmake_parser_derive::CMake;
2
3use crate::{
4    doc::command_scope::{CommandScope, ToCommandScope},
5    Token,
6};
7
8/// List operations.
9///
10/// Reference: <https://cmake.org/cmake/help/v3.26/command/list.html>
11#[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}