tangled
alpha
login
or
join now
tholps.site
/
skidmark
0
fork
atom
Tholp's bespoke website generator
0
fork
atom
overview
issues
pulls
pipelines
Small refactor
tholps.site
5 months ago
87c71047
46765f9e
+122
-123
8 changed files
expand all
collapse all
unified
split
src
macros
insert.rs
mod.rs
simple_blocks.rs
simple_macros.rs
template.rs
main.rs
project.rs
types.rs
+3
-2
src/macros/insert.rs
···
2
2
3
3
use crate::{
4
4
console::error_skid,
5
5
+
macros::template::SkidTemplate,
5
6
project::{FileIndexing, ProjectContext},
6
7
stringtools::split_to_tokens,
7
7
-
types::{InputFile, Token},
8
8
+
types::Token,
8
9
};
9
10
10
11
pub fn macro_insert(
11
11
-
_file: &mut InputFile,
12
12
origin_index: usize,
13
13
origin_line: usize,
14
14
context: &mut ProjectContext,
15
15
+
_templates: &mut Vec<SkidTemplate>,
15
16
args: &Vec<String>,
16
17
_scope: &[Token],
17
18
) -> Vec<Token> {
+1
-8
src/macros/mod.rs
···
8
8
9
9
use insert::macro_insert;
10
10
use simple_blocks::{macro_comment, macro_for_each_arg, macro_repeat, macro_section};
11
11
-
use simple_macros::{macro_clear, macro_filename, macro_filename_canonical, macro_time};
11
11
+
use simple_macros::{macro_filename, macro_filename_canonical, macro_time};
12
12
use template::macro_template;
13
13
14
14
pub static MACRO_LIST: &'static [Macro] = &[
···
19
19
has_scope: false,
20
20
min_args: 1,
21
21
max_args: 1,
22
22
-
},
23
23
-
Macro {
24
24
-
symbol: "clear", // Clears text buffer
25
25
-
expansion: macro_clear,
26
26
-
has_scope: false,
27
27
-
min_args: 0,
28
28
-
max_args: 0,
29
22
},
30
23
Macro {
31
24
symbol: "time",
+6
-5
src/macros/simple_blocks.rs
···
2
2
3
3
use crate::{
4
4
console::{error_skid, warn_skid},
5
5
+
macros::template::SkidTemplate,
5
6
project::ProjectContext,
6
7
stringtools::{find_pattern, split_to_tokens, TokenTools},
7
7
-
types::{InputFile, Token},
8
8
+
types::Token,
8
9
};
9
10
10
11
pub fn macro_comment(
11
11
-
_file: &mut InputFile,
12
12
_origin_index: usize,
13
13
_origin_line: usize,
14
14
_context: &mut ProjectContext,
15
15
+
_templates: &mut Vec<SkidTemplate>,
15
16
_args: &Vec<String>,
16
17
_scope: &[Token],
17
18
) -> Vec<Token> {
···
19
20
}
20
21
21
22
pub fn macro_section(
22
22
-
_file: &mut InputFile,
23
23
_origin_index: usize,
24
24
_origin_line: usize,
25
25
_context: &mut ProjectContext,
26
26
+
_templates: &mut Vec<SkidTemplate>,
26
27
_args: &Vec<String>,
27
28
scope: &[Token],
28
29
) -> Vec<Token> {
···
34
35
}
35
36
36
37
pub fn macro_repeat(
37
37
-
_file: &mut InputFile,
38
38
_origin_index: usize,
39
39
_origin_line: usize,
40
40
_context: &mut ProjectContext,
41
41
+
_templates: &mut Vec<SkidTemplate>,
41
42
args: &Vec<String>,
42
43
scope: &[Token],
43
44
) -> Vec<Token> {
···
56
57
}
57
58
58
59
pub fn macro_for_each_arg(
59
59
-
_file: &mut InputFile,
60
60
origin_index: usize,
61
61
origin_line: usize,
62
62
context: &mut ProjectContext,
63
63
+
_templates: &mut Vec<SkidTemplate>,
63
64
args: &Vec<String>,
64
65
scope: &[Token],
65
66
) -> Vec<Token> {
+7
-19
src/macros/simple_macros.rs
···
5
5
6
6
use crate::{
7
7
console::{error_skid, reminder_skid},
8
8
+
macros::template::SkidTemplate,
8
9
project::{FileIndexing, ProjectContext},
9
10
stringtools::split_to_tokens,
10
10
-
types::{InputFile, Token},
11
11
+
types::Token,
11
12
};
12
13
13
13
-
pub fn macro_clear(
14
14
-
_file: &mut InputFile,
15
15
-
_origin_index: usize,
16
16
-
_origin_line: usize,
17
17
-
_context: &mut ProjectContext,
18
18
-
_args: &Vec<String>,
19
19
-
_scope: &[Token],
20
20
-
) -> Vec<Token> {
21
21
-
_file.tokens = _file.tokens.split_off(_file.working_index);
22
22
-
_file.working_index = 0;
23
23
-
return Vec::new();
24
24
-
}
25
25
-
26
14
pub fn macro_time(
27
27
-
file: &mut InputFile,
28
15
origin_index: usize,
29
16
origin_line: usize,
30
17
context: &mut ProjectContext,
18
18
+
_templates: &mut Vec<SkidTemplate>,
31
19
args: &Vec<String>,
32
20
_scope: &[Token],
33
21
) -> Vec<Token> {
···
51
39
}
52
40
53
41
pub fn macro_filename(
54
54
-
_file: &mut InputFile,
55
42
origin_index: usize,
56
56
-
_origin_line: usize,
43
43
+
origin_line: usize,
57
44
context: &mut ProjectContext,
45
45
+
_templates: &mut Vec<SkidTemplate>,
58
46
_args: &Vec<String>,
59
47
_scope: &[Token],
60
48
) -> Vec<Token> {
···
70
58
}
71
59
72
60
pub fn macro_filename_canonical(
73
73
-
_file: &mut InputFile,
74
61
origin_index: usize,
75
62
_origin_line: usize,
76
63
context: &mut ProjectContext,
64
64
+
_templates: &mut Vec<SkidTemplate>,
77
65
_args: &Vec<String>,
78
66
_scope: &[Token],
79
67
) -> Vec<Token> {
···
89
77
}
90
78
91
79
pub fn macro_reminder(
92
92
-
_file: &mut InputFile,
93
80
origin_index: usize,
94
81
origin_line: usize,
95
82
context: &mut ProjectContext,
83
83
+
_templates: &mut Vec<SkidTemplate>,
96
84
args: &Vec<String>,
97
85
_scope: &[Token],
98
86
) -> Vec<Token> {
+4
-4
src/macros/template.rs
···
3
3
project::ProjectContext,
4
4
reservednames::{RESERVED_NAMES_HTML, RESERVED_NAMES_MISC},
5
5
stringtools::{find_pattern, split_to_tokens, WhitespaceChecks},
6
6
-
types::{InputFile, Token},
6
6
+
types::Token,
7
7
};
8
8
9
9
use super::MACRO_LIST;
···
130
130
}
131
131
132
132
pub fn macro_template(
133
133
-
file: &mut InputFile,
134
133
origin_index: usize,
135
134
origin_line: usize,
136
135
context: &mut ProjectContext,
136
136
+
templates: &mut Vec<SkidTemplate>,
137
137
args: &Vec<String>,
138
138
scope: &[Token],
139
139
) -> Vec<Token> {
140
140
-
for t in &file.templates {
140
140
+
for t in templates.iter().as_ref() {
141
141
if t.symbol == args[0] {
142
142
error_skid(
143
143
context,
···
237
237
}
238
238
239
239
let template = SkidTemplate::new(args[0].clone(), &args[1..], scope);
240
240
-
file.templates.push(template);
240
240
+
templates.push(template);
241
241
242
242
return Vec::new();
243
243
}
+87
-67
src/main.rs
···
7
7
mod types;
8
8
9
9
use crate::{
10
10
-
args::ProgramArgs, project::FileGroup, reservednames::RESERVED_NAMES_MISC, types::Expand,
10
10
+
args::ProgramArgs, macros::template::SkidTemplate, project::FileGroup,
11
11
+
reservednames::RESERVED_NAMES_MISC, types::Expand,
11
12
};
12
13
use clap::Parser;
13
14
use console::*;
···
19
20
env,
20
21
fs::{self},
21
22
path::PathBuf,
23
23
+
task::Context,
22
24
};
23
25
use stringtools::{collect_arguments, collect_block, split_to_tokens, trim_whitespace_tokens};
24
26
use types::{InputFile, Token};
···
45
47
project_path = project_folder.clone();
46
48
project_path.push("skidmark.toml");
47
49
}
48
48
-
println!("Operatting with {:?}", &project_path.as_os_str());
50
50
+
println!("Operatting on {:?}", &project_path.as_os_str());
49
51
assert!(env::set_current_dir(&project_folder).is_ok());
50
52
51
53
let mut project = parse_project(&project_path);
···
57
59
}
58
60
59
61
println!("Proccesing {} files.", num);
62
62
+
// for group in &mut project.filegroups {
63
63
+
// for infile in &mut group.files {
64
64
+
// process_skid(infile, group.convert_html, &mut project.context);
65
65
+
// }
66
66
+
// }
67
67
+
60
68
for group in &mut project.filegroups {
61
69
for infile in &mut group.files {
62
62
-
process_file(infile, group.convert_html, &mut project.context);
70
70
+
let contents =
71
71
+
fs::read_to_string(&infile.file_input).expect("File unreadable or missing");
72
72
+
infile.tokens =
73
73
+
split_to_tokens(contents, project.context.index_of_file(&infile.file_input));
74
74
+
75
75
+
process_skid(
76
76
+
&mut infile.tokens,
77
77
+
project.context.index_of_file(&infile.file_input),
78
78
+
&mut project.context,
79
79
+
Vec::new(),
80
80
+
);
63
81
}
64
82
}
65
83
}
66
84
67
67
-
fn process_file(file: &mut InputFile, convert_html: bool, context: &mut ProjectContext) {
85
85
+
fn process_skid(
86
86
+
tokens_in: &mut [Token],
87
87
+
file_index: usize,
88
88
+
context: &mut ProjectContext,
89
89
+
templates_base: Vec<SkidTemplate>,
90
90
+
) -> Vec<Token> {
68
91
//}, context: &mut ProjectContext) {
69
69
-
let contents = fs::read_to_string(&file.file_input).expect("File unreadable or missing");
70
92
//println!("{}\n {}", f.filename_out, contents);
71
93
72
94
//file.tokens = strings_to_tokens(split_keep_delimiters(contents), file.filename_input.clone());
73
73
-
file.tokens = split_to_tokens(contents, context.index_of_file(&file.file_input));
95
95
+
74
96
//let mut escaped = false;
97
97
+
let mut tokens = tokens_in.to_vec();
98
98
+
let mut templates = templates_base;
75
99
76
76
-
while file.working_index < file.tokens.len() {
100
100
+
let mut working_index = 0;
101
101
+
102
102
+
while working_index < tokens.len() {
77
103
//look for macros or blocks
78
78
-
//println!(">\"{}\"<", file.tokens[file.working_index].contents);
104
104
+
//println!(">\"{}\"<", tokens[working_index].contents);
79
105
80
80
-
if file.tokens[file.working_index].contents.len() == 0 {
81
81
-
file.working_index += 1;
106
106
+
if tokens[working_index].contents.len() == 0 {
107
107
+
working_index += 1;
82
108
continue;
83
109
}
84
110
85
85
-
if file.tokens[file.working_index].contents == "\\" {
86
86
-
file.tokens[file.working_index].contents = "".into();
87
87
-
file.working_index += 2;
111
111
+
if tokens[working_index].contents == "\\" {
112
112
+
tokens[working_index].contents = "".into();
113
113
+
working_index += 2;
88
114
//println!("Hit backslash");
89
115
continue;
90
116
}
91
117
92
118
let mut matched_macro: bool = false;
93
93
-
if file.tokens[file.working_index]
94
94
-
.contents
95
95
-
.starts_with(['!', '&'])
96
96
-
{
119
119
+
if tokens[working_index].contents.starts_with(['!', '&']) {
97
120
let mut prefix_len = 1;
98
98
-
let mut symbol = file.tokens[file.working_index].contents.clone();
121
121
+
let mut symbol = tokens[working_index].contents.clone();
99
122
symbol = symbol.trim().to_string();
100
123
101
124
if symbol.len() > 2 {
102
125
let mut ephemeral = false;
103
103
-
let same_file = file.tokens[file.working_index].origin_file
104
104
-
!= context.index_of_file(&file.file_input);
126
126
+
let same_file = tokens[working_index].origin_file != file_index;
105
127
106
128
// Inversely Ephemeral
107
129
if symbol.starts_with("!&") {
···
119
141
matched_macro = true;
120
142
//println!("Found a macro ({})", m.symbol);
121
143
122
122
-
let (args, args_tokcount) =
123
123
-
collect_arguments(&file.tokens[file.working_index..]);
144
144
+
let (args, args_tokcount) = collect_arguments(&tokens[working_index..]);
124
145
let expansion: Vec<Token>;
125
146
let block_tokcount: usize;
126
147
if m.has_scope {
127
148
//println!("is scoped.");
128
149
129
150
let block_opt =
130
130
-
collect_block(&file.tokens[(file.working_index + args_tokcount)..]);
151
151
+
collect_block(&tokens[(working_index + args_tokcount)..]);
131
152
if block_opt.is_none() {
132
153
error_skid(
133
154
context,
134
134
-
file.tokens[file.working_index].template_origin,
135
135
-
file.tokens[file.working_index].line_number,
155
155
+
tokens[working_index].template_origin,
156
156
+
tokens[working_index].line_number,
136
157
&"Malformed Block".into(),
137
158
);
138
159
}
···
143
164
expansion = Vec::new();
144
165
} else {
145
166
expansion = m.expand(
146
146
-
file,
147
147
-
file.tokens[file.working_index].origin_file,
148
148
-
file.tokens[file.working_index].line_number,
167
167
+
tokens[working_index].origin_file,
168
168
+
tokens[working_index].line_number,
149
169
context,
170
170
+
&mut templates,
150
171
&args,
151
172
&block,
152
173
);
···
158
179
expansion = Vec::new();
159
180
} else {
160
181
expansion = m.expand(
161
161
-
file,
162
162
-
file.tokens[file.working_index].origin_file,
163
163
-
file.tokens[file.working_index].line_number,
182
182
+
tokens[working_index].origin_file,
183
183
+
tokens[working_index].line_number,
164
184
context,
185
185
+
&mut templates,
165
186
&args,
166
187
&Vec::new()[..],
167
188
);
···
170
191
171
192
let trimmed = trim_whitespace_tokens(&expansion);
172
193
173
173
-
file.tokens.remove(file.working_index);
174
174
-
file.tokens.splice(
175
175
-
file.working_index
176
176
-
..(file.working_index + args_tokcount + block_tokcount - 1),
194
194
+
tokens.remove(working_index);
195
195
+
tokens.splice(
196
196
+
working_index..(working_index + args_tokcount + block_tokcount - 1),
177
197
trimmed.iter().cloned(),
178
198
);
179
179
-
if expansion.len() == 0 && file.working_index > 0 {
180
180
-
file.working_index -= 1;
199
199
+
if expansion.len() == 0 && working_index > 0 {
200
200
+
working_index -= 1;
181
201
}
182
202
}
183
203
}
184
204
185
205
// check for templates
186
206
// todo maybe deduplicate this
187
187
-
for m in &mut file.templates {
188
188
-
if &symbol[prefix_len..] == m.symbol {
207
207
+
for t in &templates {
208
208
+
if &symbol[prefix_len..] == t.symbol {
189
209
matched_macro = true;
190
210
//println!("Found a macro ({})", m.symbol);
191
211
192
192
-
let (args, args_tokcount) =
193
193
-
collect_arguments(&file.tokens[file.working_index..]);
212
212
+
let (args, args_tokcount) = collect_arguments(&tokens[working_index..]);
194
213
let expansion: Vec<Token>;
195
214
let block_tokcount: usize;
196
215
197
197
-
if m.has_scope {
216
216
+
if t.has_scope {
198
217
//println!("is scoped.");
199
218
let block: Vec<Token>;
200
219
let block_opt =
201
201
-
collect_block(&file.tokens[(file.working_index + args_tokcount)..]);
220
220
+
collect_block(&tokens[(working_index + args_tokcount)..]);
202
221
if block_opt.is_none() {
203
222
error_skid(
204
223
context,
205
205
-
file.tokens[file.working_index].template_origin,
206
206
-
file.tokens[file.working_index].line_number,
224
224
+
tokens[working_index].template_origin,
225
225
+
tokens[working_index].line_number,
207
226
&"Malformed Block".into(),
208
227
);
209
228
}
···
213
232
if ephemeral {
214
233
expansion = Vec::new();
215
234
} else {
216
216
-
expansion = m.expand(
235
235
+
expansion = t.expand(
217
236
//file,
218
218
-
file.tokens[file.working_index].origin_file,
219
219
-
file.tokens[file.working_index].line_number,
237
237
+
tokens[working_index].origin_file,
238
238
+
tokens[working_index].line_number,
220
239
context,
221
240
&args,
222
241
&block,
···
228
247
if ephemeral {
229
248
expansion = Vec::new();
230
249
} else {
231
231
-
expansion = m.expand(
250
250
+
expansion = t.expand(
232
251
//file,
233
233
-
file.tokens[file.working_index].origin_file,
234
234
-
file.tokens[file.working_index].line_number,
252
252
+
tokens[working_index].origin_file,
253
253
+
tokens[working_index].line_number,
235
254
context,
236
255
&args,
237
256
&Vec::new()[..],
···
241
260
242
261
let trimmed = trim_whitespace_tokens(&expansion);
243
262
244
244
-
file.tokens.remove(file.working_index);
245
245
-
file.tokens.splice(
246
246
-
file.working_index
247
247
-
..(file.working_index + args_tokcount + block_tokcount - 1),
263
263
+
tokens.remove(working_index);
264
264
+
tokens.splice(
265
265
+
working_index..(working_index + args_tokcount + block_tokcount - 1),
248
266
trimmed.iter().cloned(),
249
267
);
250
250
-
if expansion.len() == 0 && file.working_index > 0 {
251
251
-
file.working_index -= 1;
268
268
+
if expansion.len() == 0 && working_index > 0 {
269
269
+
working_index -= 1;
252
270
}
253
271
}
254
272
}
255
273
}
256
274
if !matched_macro {
257
257
-
let name = file.tokens[file.working_index]
258
258
-
.contents
259
259
-
.trim()
260
260
-
.to_lowercase();
275
275
+
let name = tokens[working_index].contents.trim().to_lowercase();
261
276
let mut dont_error = name.len() <= 1;
262
277
{
263
263
-
if !dont_error && convert_html {
278
278
+
if !dont_error {
264
279
for reserved in RESERVED_NAMES_HTML {
265
280
if name[1..].starts_with(reserved) {
266
281
dont_error = true;
···
281
296
if !dont_error {
282
297
warn_skid(
283
298
context,
284
284
-
file.tokens[file.working_index].origin_file,
285
285
-
file.tokens[file.working_index].line_number,
299
299
+
tokens[working_index].origin_file,
300
300
+
tokens[working_index].line_number,
286
301
&format!(
287
302
"Token written as a function but no such function exists \"{}\"",
288
288
-
file.tokens[file.working_index].contents.trim()
303
303
+
tokens[working_index].contents.trim()
289
304
),
290
305
);
291
306
}
292
307
}
293
308
}
294
309
if !matched_macro {
295
295
-
file.working_index += 1;
310
310
+
working_index += 1;
296
311
}
297
312
}
298
298
-
//println!("{:?}", file.tokens);
313
313
+
314
314
+
return tokens;
315
315
+
}
316
316
+
317
317
+
fn write_file(file: InputFile, convert_html: bool) {
318
318
+
//println!("{:?}", tokens);
299
319
let mut skid_output: String = "".to_string();
300
320
for t in &file.tokens {
301
321
skid_output += &t.contents;
-6
src/project.rs
···
21
21
pub output_extention: String,
22
22
}
23
23
24
24
-
// pub struct ProjectSettings {
25
25
-
26
26
-
// }
27
27
-
28
24
pub struct ProjectContext {
29
25
pub input_folder: PathBuf,
30
26
pub output_folder: PathBuf,
···
32
28
pub global_post_insert: PathBuf,
33
29
34
30
pub filemap: Vec<PathBuf>, // mapped to index
35
35
-
36
36
-
//variables later
37
31
}
38
32
39
33
macro_rules! get_table_bool_or_default {
+14
-12
src/types.rs
···
18
18
pub file_skidout: PathBuf,
19
19
pub file_out: PathBuf,
20
20
pub tokens: Vec<Token>,
21
21
-
pub working_index: usize,
22
22
-
pub templates: Vec<SkidTemplate>,
23
21
}
24
22
25
25
-
type MacroExpansion =
26
26
-
fn(&mut InputFile, usize, usize, &mut ProjectContext, &Vec<String>, &[Token]) -> Vec<Token>;
23
23
+
type MacroExpansion = fn(
24
24
+
usize,
25
25
+
usize,
26
26
+
&mut ProjectContext,
27
27
+
&mut Vec<SkidTemplate>,
28
28
+
&Vec<String>,
29
29
+
&[Token],
30
30
+
) -> Vec<Token>;
27
31
// (
28
28
-
// _file: &mut InputFile,
29
32
// origin_index: usize,
30
33
// origin_line: usize,
31
34
// context: &mut ProjectContext,
35
35
+
// templates: &mut Vec<SkidTemplate>,
32
36
// args: &Vec<String>,
33
33
-
// _scope: &[Token],
37
37
+
// scope: &[Token],
34
38
// ) -> Vec<Token>
35
39
36
40
pub struct Macro {
37
41
pub symbol: &'static str,
38
42
pub expansion: MacroExpansion,
39
39
-
pub has_scope: bool, //takes blocks of text input as well as parameters using {{...}}
43
43
+
pub has_scope: bool, //takes blocks of text input as well as parameters using [[{}]]
40
44
pub min_args: usize,
41
45
pub max_args: usize,
42
46
}
···
44
48
pub trait Expand {
45
49
fn expand(
46
50
&self,
47
47
-
input_file: &mut InputFile,
48
51
origin_index: usize,
49
52
origin_line: usize,
50
53
context: &mut ProjectContext,
54
54
+
templates: &mut Vec<SkidTemplate>,
51
55
args: &Vec<String>,
52
56
scope: &[Token],
53
57
) -> Vec<Token>;
···
58
62
impl Expand for Macro {
59
63
fn expand(
60
64
&self,
61
61
-
input_file: &mut InputFile,
62
65
origin_index: usize,
63
66
origin_line: usize,
64
67
context: &mut ProjectContext,
68
68
+
templates: &mut Vec<SkidTemplate>,
65
69
args: &Vec<String>,
66
70
scope: &[Token],
67
71
) -> Vec<Token> {
···
70
74
self.symbol, args.len(), self.min_args, if self.max_args == usize::max_value() {"No Limit".to_string()} else {format!("{}", self.max_args)}));
71
75
Vec::new()
72
76
} else {
73
73
-
(self.expansion)(input_file, origin_index, origin_line, context, args, scope)
77
77
+
(self.expansion)(origin_index, origin_line, context, templates, args, scope)
74
78
}
75
79
}
76
80
···
92
96
file_skidout: "".into(),
93
97
file_out: "".into(),
94
98
tokens: Vec::new(),
95
95
-
working_index: 0,
96
96
-
templates: Vec::new(),
97
99
}
98
100
}
99
101
}