cmake_parser/doc/command/scripting/
foreach.rs1use 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 ForEach<'t> {
14 RangeStop(RangeStop<'t>),
15 RangeStartStop(RangeStartStop<'t>),
16 InZipLists(InZipLists<'t>),
17 In(In<'t>),
18}
19
20impl<'t> ToCommandScope for ForEach<'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", positional, complete)]
28pub struct RangeStop<'t> {
29 #[cmake(keyword_after = "RANGE")]
30 pub loop_var: Token<'t>,
31 pub stop: Token<'t>,
32}
33
34#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
35#[cmake(pkg = "crate", positional, complete)]
36pub struct RangeStartStop<'t> {
37 #[cmake(keyword_after = "RANGE")]
38 pub loop_var: Token<'t>,
39 pub start: Token<'t>,
40 pub stop: Token<'t>,
41 pub step: Option<Token<'t>>,
42}
43
44#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
45#[cmake(pkg = "crate")]
46pub struct In<'t> {
47 #[cmake(positional, keyword_after = "IN")]
48 pub loop_var: Token<'t>,
49 pub lists: Option<Vec<Token<'t>>>,
50 pub items: Option<Vec<Token<'t>>>,
51}
52
53#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
54#[cmake(pkg = "crate", default = "loop_var")]
55pub struct InZipLists<'t> {
56 #[cmake(rename = b"")]
57 pub loop_var: Vec<Token<'t>>,
58 pub zip_lists: ZipLists<'t>,
59}
60
61#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
62pub struct ZipLists<'t> {
63 pub lists: Vec<Token<'t>>,
64}
65
66impl<'t> crate::CMakeParse<'t> for ZipLists<'t> {
67 fn matches_type(_: &[u8], keyword: &[u8], tokens: &[Token<'t>]) -> bool {
68 keyword == b"IN" && tokens.first().map(|x| x.as_bytes()) == Some(b"ZIP_LISTS")
69 }
70
71 fn need_push_keyword(_: &Token<'t>) -> bool {
72 false
73 }
74
75 fn rest<'tv>(tokens: &'tv [Token<'t>]) -> &'tv [Token<'t>] {
76 &tokens[1..]
77 }
78
79 fn parse<'tv>(
80 tokens: &'tv [Token<'t>],
81 ) -> Result<(Self, &'tv [Token<'t>]), crate::CommandParseError> {
82 crate::CMakeParse::parse(tokens).map(|(lists, tokens)| (Self { lists }, tokens))
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89 use crate::doc::cmake_parse::tests::{token, tokens_vec};
90 use crate::*;
91 use pretty_assertions::assert_eq;
92
93 #[test]
94 fn foreach() {
95 let src = include_bytes!("../../../../../fixture/commands/scripting/foreach");
96 let cmakelists = parse_cmakelists(src).unwrap();
97 let doc = Doc::from(cmakelists);
98 assert_eq!(
99 doc.to_commands_iter().collect::<Vec<_>>(),
100 vec![
101 Ok(Command::ForEach(Box::new(ForEach::RangeStop(RangeStop {
102 loop_var: token(b"variable1"),
103 stop: token(b"10"),
104 })))),
105 Ok(Command::ForEach(Box::new(ForEach::RangeStartStop(
106 RangeStartStop {
107 loop_var: token(b"variable1"),
108 start: token(b"1"),
109 stop: token(b"10"),
110 step: None,
111 }
112 )))),
113 Ok(Command::ForEach(Box::new(ForEach::RangeStartStop(
114 RangeStartStop {
115 loop_var: token(b"variable1"),
116 start: token(b"1"),
117 stop: token(b"10"),
118 step: Some(token(b"3")),
119 }
120 )))),
121 Ok(Command::ForEach(Box::new(ForEach::In(In {
122 loop_var: token(b"variable1"),
123 lists: Some(tokens_vec([b"A", b"B", b"C", b"D", b"E", b"F"])),
124 items: None,
125 })))),
126 Ok(Command::ForEach(Box::new(ForEach::In(In {
127 loop_var: token(b"variable1"),
128 lists: None,
129 items: Some(tokens_vec([b"${A}", b"${B}"])),
130 })))),
131 Ok(Command::ForEach(Box::new(ForEach::In(In {
132 loop_var: token(b"variable1"),
133 lists: Some(tokens_vec([b"A", b"B", b"C", b"D", b"E", b"F"])),
134 items: Some(tokens_vec([b"${A}", b"${B}"])),
135 })))),
136 Ok(Command::ForEach(Box::new(ForEach::InZipLists(
137 InZipLists {
138 loop_var: tokens_vec([b"variable1"]),
139 zip_lists: ZipLists {
140 lists: tokens_vec([b"English", b"Bahasa"]),
141 }
142 }
143 )))),
144 Ok(Command::ForEach(Box::new(ForEach::InZipLists(
145 InZipLists {
146 loop_var: tokens_vec([b"en", b"ba"]),
147 zip_lists: ZipLists {
148 lists: tokens_vec([b"English", b"Bahasa"]),
149 }
150 }
151 )))),
152 ]
153 )
154 }
155}