Tholp's bespoke website generator
1use crate::{console::*, project::Project, stringtools::*, types::*};
2
3fn for_each_base(
4 identifier: &String,
5 replacements: &[String],
6 proj_context: &mut Project,
7 origin_index: usize,
8 origin_line: usize,
9 scope: &[Token],
10) -> Vec<Token> {
11 let mut output = Vec::new();
12 let block: Vec<Token> = scope.into();
13
14 let mut replacement_count: usize = 0;
15
16 let mut replacement_pattern = find_pattern(scope, format!("[[{}..1]]", identifier));
17
18 if replacement_pattern.is_none() {
19 warn_skid(
20 proj_context,
21 origin_index,
22 origin_line,
23 &format!(
24 "Macro `for_each_arg` given block with no \"[[{}..1]]\", intentional?",
25 identifier
26 ),
27 );
28 }
29
30 while replacement_pattern.is_some() {
31 replacement_count += 1;
32 replacement_pattern = find_pattern(
33 scope,
34 format!("[[{}..{}]]", identifier, replacement_count + 1),
35 );
36 }
37
38 if replacement_count == 0 {
39 for _i in 0..replacements.iter().count() {
40 output.append(&mut block.clone());
41 }
42 return output;
43 }
44
45 if replacements.len() % replacement_count != 0 {
46 error_skid(proj_context, origin_index, origin_line,
47 &format!("`for_each_var` was not given a number of arguments({}) that was a multiple of its replacement posistions({}) (got {:?})",
48 replacements.len(),
49 replacement_count,
50 replacements));
51 }
52
53 let mut replacement_index: usize = 0;
54 let mut arg_output: Vec<Token> = block.clone();
55 for r in replacements {
56 let mut found_pattern = find_pattern(
57 &arg_output,
58 format!("[[{}..{}]]", identifier, replacement_index + 1),
59 );
60
61 while found_pattern.is_some() {
62 let (start, len) = found_pattern.unwrap();
63 let replacement = split_to_tokens(r.clone(), origin_index);
64 arg_output.splice(start..start + len, replacement);
65 found_pattern = find_pattern(
66 &arg_output,
67 format!("[[{}..{}]]", identifier, replacement_index + 1),
68 );
69 //println!("{}", replacement_index + 1);
70 }
71
72 //println!("{} {}", replacement_index, replacement_count);
73 replacement_index += 1;
74 if replacement_index == replacement_count {
75 replacement_index = 0;
76 output.append(&mut arg_output.trim_whitespace().into());
77 arg_output = block.clone();
78 //println!("push");
79 }
80 //println!("test");
81 }
82 return output;
83}
84
85pub fn macro_for_each_arg(
86 origin_index: usize,
87 origin_line: usize,
88 proj_context: &mut Project,
89 _skid_context: &mut SkidContext,
90 args: &Vec<String>,
91 scope: &[Token],
92) -> Vec<Token> {
93 return for_each_base(
94 &args[0],
95 &args[1..],
96 proj_context,
97 origin_index,
98 origin_line,
99 scope,
100 );
101}
102
103pub fn macro_for_each_file_in_group(
104 origin_index: usize,
105 origin_line: usize,
106 proj_context: &mut Project,
107 _skid_context: &mut SkidContext,
108 args: &Vec<String>,
109 scope: &[Token],
110) -> Vec<Token> {
111 let mut files: Vec<String> = Vec::new();
112 for g in &proj_context.filegroups {
113 if g.name == args[1] {
114 for f in &g.files {
115 let path = f
116 .file_input
117 .strip_prefix(&proj_context.input_folder)
118 .unwrap();
119 files.push(path.to_str().unwrap().into());
120 }
121 }
122 }
123 return for_each_base(
124 &args[0],
125 &files,
126 proj_context,
127 origin_index,
128 origin_line,
129 scope,
130 );
131}
132
133pub fn macro_for_each_file_in_group_reverse(
134 origin_index: usize,
135 origin_line: usize,
136 proj_context: &mut Project,
137 _skid_context: &mut SkidContext,
138 args: &Vec<String>,
139 scope: &[Token],
140) -> Vec<Token> {
141 let mut files: Vec<String> = Vec::new();
142 for g in &proj_context.filegroups {
143 if g.name == args[1] {
144 for f in g.files.iter().rev() {
145 let path = f
146 .file_input
147 .strip_prefix(&proj_context.input_folder)
148 .unwrap();
149 files.push(path.to_str().unwrap().into());
150 }
151 }
152 }
153 return for_each_base(
154 &args[0],
155 &files,
156 proj_context,
157 origin_index,
158 origin_line,
159 scope,
160 );
161}