tangled
alpha
login
or
join now
tholps.site
/
skidmark
0
fork
atom
Tholp's bespoke website generator
0
fork
atom
overview
issues
pulls
pipelines
templates
Tholp1
10 months ago
3349e4c1
0bb5d81b
+277
-13
7 changed files
expand all
collapse all
unified
split
src
macros
clear.rs
insert.rs
simple_blocks.rs
template.rs
main.rs
stringtools.rs
types.rs
+1
src/macros/clear.rs
···
7
7
pub fn macro_clear(
8
8
_file: &mut InputFile,
9
9
_origin_index: usize,
10
10
+
_origin_line: usize,
10
11
_context: &mut ProjectContext,
11
12
_args: &Vec<String>,
12
13
_scope: &[Token],
+4
-2
src/macros/insert.rs
···
14
14
pub fn macro_insert(
15
15
_file: &mut InputFile,
16
16
_origin_index: usize,
17
17
+
origin_line: usize,
17
18
_context: &mut ProjectContext,
18
19
args: &Vec<String>,
19
20
_scope: &[Token],
20
21
) -> Vec<Token> {
21
21
-
let mut origin_file = _context
22
22
+
let origin_file = _context
22
23
.file_for_index(_origin_index)
23
24
.expect("Macro 'Insert' was given a bad origin index")
24
25
.clone();
25
26
if args.len() != 1 {
26
27
println!(
27
27
-
"\"{:?}\":Insert only accepts 1 argument, got given {} ({:?})",
28
28
+
"{:?}:{} ;Insert only accepts 1 argument, got given {} ({:?})",
28
29
origin_file.to_str(),
30
30
+
origin_line,
29
31
args.len(),
30
32
args
31
33
);
+3
src/macros/simple_blocks.rs
···
6
6
pub fn macro_comment(
7
7
_file: &mut InputFile,
8
8
_origin_index: usize,
9
9
+
_origin_line: usize,
9
10
_context: &mut ProjectContext,
10
11
_args: &Vec<String>,
11
12
_scope: &[Token],
···
16
17
pub fn macro_null(
17
18
_file: &mut InputFile,
18
19
_origin_index: usize,
20
20
+
_origin_line: usize,
19
21
_context: &mut ProjectContext,
20
22
_args: &Vec<String>,
21
23
scope: &[Token],
···
30
32
pub fn macro_repeat(
31
33
_file: &mut InputFile,
32
34
_origin_index: usize,
35
35
+
_origin_line: usize,
33
36
_context: &mut ProjectContext,
34
37
args: &Vec<String>,
35
38
scope: &[Token],
+134
src/macros/template.rs
···
1
1
+
use std::{process::exit, thread::scope};
2
2
+
3
3
+
use crate::{
4
4
+
projectparse::{FileIndexing, ProjectContext},
5
5
+
stringtools::{find_pattern, split_to_tokens, strings_to_tokens, WhitespaceChecks},
6
6
+
types::{InputFile, Token},
7
7
+
};
8
8
+
9
9
+
use super::MACRO_LIST;
10
10
+
11
11
+
pub struct SkidTemplate {
12
12
+
pub symbol: String,
13
13
+
pub args: Vec<String>,
14
14
+
pub tokens: Vec<Token>,
15
15
+
16
16
+
pub has_scope: bool,
17
17
+
}
18
18
+
19
19
+
impl SkidTemplate {
20
20
+
pub fn new(name: String, args: &[String], tokens: &[Token]) -> SkidTemplate {
21
21
+
let scoped: bool = find_pattern(&tokens, "[[{}]]".into()).is_some();
22
22
+
23
23
+
SkidTemplate {
24
24
+
symbol: name,
25
25
+
args: args.to_vec(),
26
26
+
tokens: tokens.to_vec(),
27
27
+
has_scope: scoped,
28
28
+
}
29
29
+
}
30
30
+
31
31
+
pub fn expand(
32
32
+
&self,
33
33
+
//_file: &mut InputFile,
34
34
+
origin_index: usize,
35
35
+
_context: &mut ProjectContext,
36
36
+
args: &Vec<String>,
37
37
+
scope: &[Token],
38
38
+
) -> Vec<Token> {
39
39
+
println!("{:?}", args);
40
40
+
41
41
+
let mut output = self.tokens.clone();
42
42
+
43
43
+
let mut args_index: usize = 0;
44
44
+
for param in &self.args {
45
45
+
let mut found_pattern = find_pattern(&output, format!("[[{}]]", param));
46
46
+
while found_pattern.is_some() {
47
47
+
let (start, len) = found_pattern.unwrap();
48
48
+
let replacement = split_to_tokens(args[args_index].clone(), origin_index);
49
49
+
found_pattern = find_pattern(
50
50
+
&output[start + replacement.len()..],
51
51
+
format!("[[{}]]", param),
52
52
+
);
53
53
+
output.splice(start..start + len, replacement);
54
54
+
}
55
55
+
args_index += 1;
56
56
+
}
57
57
+
58
58
+
let mut found_pattern = find_pattern(&output, "[[{}]]".into());
59
59
+
while found_pattern.is_some() {
60
60
+
let (start, len) = found_pattern.unwrap();
61
61
+
let replacement = scope.to_vec();
62
62
+
found_pattern = find_pattern(&output[start + replacement.len()..], "[[{}]]".into());
63
63
+
output.splice(start..start + len, replacement);
64
64
+
}
65
65
+
66
66
+
output
67
67
+
}
68
68
+
}
69
69
+
70
70
+
pub fn macro_template(
71
71
+
file: &mut InputFile,
72
72
+
origin_index: usize,
73
73
+
origin_line: usize,
74
74
+
context: &mut ProjectContext,
75
75
+
args: &Vec<String>,
76
76
+
scope: &[Token],
77
77
+
) -> Vec<Token> {
78
78
+
for t in &file.templates {
79
79
+
if t.symbol == args[0] {
80
80
+
println!(
81
81
+
"{:?}:{} ; Attempted template redefinition of \"{}\"",
82
82
+
context.file_for_index(origin_index).unwrap(),
83
83
+
origin_line,
84
84
+
args[0]
85
85
+
);
86
86
+
exit(1);
87
87
+
}
88
88
+
}
89
89
+
90
90
+
for t in &MACRO_LIST {
91
91
+
if t.symbol == args[0] {
92
92
+
println!(
93
93
+
"{:?}:{} ; Attempted to make a template using a reserved name \"{}\"",
94
94
+
context.file_for_index(origin_index).unwrap(),
95
95
+
origin_line,
96
96
+
args[0]
97
97
+
);
98
98
+
exit(1);
99
99
+
}
100
100
+
}
101
101
+
102
102
+
let mut used_params = 0;
103
103
+
for param in &args[1..] {
104
104
+
if find_pattern(scope, format!("[[{}]]", param)).is_some() {
105
105
+
used_params += 1;
106
106
+
}
107
107
+
if param.contains_whitespace() {
108
108
+
println!(
109
109
+
"{:?}:{} ; Attempted to make a template with a parameter that contains whitespace \"{}\"",
110
110
+
context.file_for_index(origin_index).unwrap(),
111
111
+
origin_line,
112
112
+
param
113
113
+
);
114
114
+
exit(1);
115
115
+
}
116
116
+
}
117
117
+
118
118
+
if used_params < args.len() - 1 {
119
119
+
println!(
120
120
+
"{:?}:{} ; Template definition of \"{}\" has {} paramters but only uses {}",
121
121
+
context.file_for_index(origin_index).unwrap(),
122
122
+
origin_line,
123
123
+
args[0],
124
124
+
args.len() - 1,
125
125
+
used_params
126
126
+
);
127
127
+
exit(1);
128
128
+
}
129
129
+
130
130
+
let template = SkidTemplate::new(args[0].clone(), &args[1..], scope);
131
131
+
file.templates.push(template);
132
132
+
133
133
+
return Vec::new();
134
134
+
}
+65
-4
src/main.rs
···
122
122
expansion = (m.expand)(
123
123
file,
124
124
file.tokens[file.working_index].origin_file,
125
125
+
file.tokens[file.working_index].line_number,
125
126
context,
126
127
&args,
127
127
-
&block[3..block.len() - 3],
128
128
+
&block,
128
129
);
129
130
}
130
131
} else {
···
136
137
expansion = (m.expand)(
137
138
file,
138
139
file.tokens[file.working_index].origin_file,
140
140
+
file.tokens[file.working_index].line_number,
139
141
context,
140
142
&args,
141
143
&Vec::new()[..],
···
156
158
}
157
159
}
158
160
}
159
159
-
// Check if its a block
160
160
-
// for b in &BLOCK_LIST {}}
161
161
+
162
162
+
// Make this less copied
163
163
+
// check for templates
164
164
+
for m in &mut file.templates {
165
165
+
if &symbol[prefix_len..] == m.symbol {
166
166
+
matched_macro = true;
167
167
+
println!("Found a macro ({})", m.symbol);
168
168
+
169
169
+
let (args, args_tokcount) =
170
170
+
collect_arguments(&file.tokens[file.working_index..]);
171
171
+
let expansion: Vec<Token>;
172
172
+
let block_tokcount: usize;
173
173
+
174
174
+
if m.has_scope {
175
175
+
println!("is scoped.");
176
176
+
let block: Vec<Token>;
177
177
+
(block, block_tokcount) =
178
178
+
collect_block(&file.tokens[(file.working_index + args_tokcount)..]);
179
179
+
180
180
+
if ephemeral {
181
181
+
expansion = Vec::new();
182
182
+
} else {
183
183
+
expansion = m.expand(
184
184
+
//file,
185
185
+
file.tokens[file.working_index].origin_file,
186
186
+
//file.tokens[file.working_index].line_number,
187
187
+
context,
188
188
+
&args,
189
189
+
&block,
190
190
+
);
191
191
+
}
192
192
+
} else {
193
193
+
block_tokcount = 0;
194
194
+
195
195
+
if ephemeral {
196
196
+
expansion = Vec::new();
197
197
+
} else {
198
198
+
expansion = m.expand(
199
199
+
//file,
200
200
+
file.tokens[file.working_index].origin_file,
201
201
+
//file.tokens[file.working_index].line_number,
202
202
+
context,
203
203
+
&args,
204
204
+
&Vec::new()[..],
205
205
+
);
206
206
+
}
207
207
+
}
208
208
+
209
209
+
let trimmed = trim_whitespace_tokens(&expansion);
210
210
+
211
211
+
file.tokens.remove(file.working_index);
212
212
+
file.tokens.splice(
213
213
+
file.working_index
214
214
+
..(file.working_index + args_tokcount + block_tokcount - 1),
215
215
+
trimmed.iter().cloned(),
216
216
+
);
217
217
+
if expansion.len() == 0 && file.working_index > 0 {
218
218
+
file.working_index -= 1;
219
219
+
}
220
220
+
}
221
221
+
}
161
222
}
162
223
if !matched_macro {
163
224
println!(
···
190
251
allow_any_img_src: true,
191
252
..CompileOptions::gfm()
192
253
},
193
193
-
..Options::default()
254
254
+
..Options::gfm()
194
255
},
195
256
)
196
257
.unwrap();
+55
-3
src/stringtools.rs
···
104
104
// Scope Start
105
105
if tok.contents == "{" {
106
106
entering_bracket_count += 1;
107
107
+
107
108
if entering_bracket_count == 3 {
108
109
scope_count += 1;
109
110
entering_bracket_count = 0;
···
127
128
} else {
128
129
exiting_bracket_count = 0;
129
130
}
131
131
+
130
132
if tok.contents == "\\" {
131
133
escaped = true;
132
134
} else {
133
135
block.push(tok.clone());
134
136
}
135
137
}
138
138
+
139
139
+
// if block.len() == 6
140
140
+
// // things get ugly if its empty
141
141
+
// {
142
142
+
// let mut emptyblock = Vec::new();
143
143
+
// emptyblock.push(Token::new(
144
144
+
// "".into(),
145
145
+
// tokens[0].origin_file,
146
146
+
// tokens[0].line_number,
147
147
+
// ));
148
148
+
// return (emptyblock, tokens_consumed);
149
149
+
// }
150
150
+
// pop brackets, bad and ugly but idgaf
151
151
+
block.drain(..3);
152
152
+
block.drain(block.len() - 3..);
136
153
return (block, tokens_consumed);
137
154
}
138
155
···
158
175
159
176
pub fn strings_to_tokens(in_strings: Vec<String>, origin_file: usize) -> Vec<Token> {
160
177
let mut tokens = Vec::new();
161
161
-
let mut line_count: u32 = 1;
178
178
+
let mut line_count = 1;
162
179
163
180
for str in in_strings {
164
181
let current_line = line_count;
···
225
242
return &tokens[start..end];
226
243
}
227
244
228
228
-
pub trait OnlyWhitespace {
245
245
+
pub fn find_pattern(tokens: &[Token], pat: String) -> Option<(usize, usize)> {
246
246
+
// (startpoint, length)
247
247
+
let split_pattern = split_to_tokens(pat, 0);
248
248
+
let mut pattern_index: usize = 0;
249
249
+
let mut token_index: usize = 0;
250
250
+
let mut working_pattern_index: usize = 0;
251
251
+
252
252
+
for t in tokens {
253
253
+
if t.contents == split_pattern[pattern_index].contents {
254
254
+
pattern_index += 1;
255
255
+
} else {
256
256
+
pattern_index = 0;
257
257
+
working_pattern_index = token_index + 1;
258
258
+
}
259
259
+
260
260
+
if pattern_index == split_pattern.len() {
261
261
+
return Some((working_pattern_index, split_pattern.len()));
262
262
+
}
263
263
+
264
264
+
token_index += 1;
265
265
+
}
266
266
+
267
267
+
None
268
268
+
}
269
269
+
270
270
+
pub trait WhitespaceChecks {
229
271
fn is_only_whitespace(&self) -> bool;
272
272
+
fn contains_whitespace(&self) -> bool;
230
273
}
231
274
232
232
-
impl OnlyWhitespace for String {
275
275
+
impl WhitespaceChecks for String {
233
276
fn is_only_whitespace(&self) -> bool {
234
277
for c in self.chars() {
235
278
if !c.is_whitespace() {
···
237
280
}
238
281
}
239
282
return true;
283
283
+
}
284
284
+
285
285
+
fn contains_whitespace(&self) -> bool {
286
286
+
for c in self.chars() {
287
287
+
if c.is_whitespace() {
288
288
+
return true;
289
289
+
}
290
290
+
}
291
291
+
return false;
240
292
}
241
293
}
+15
-4
src/types.rs
···
1
1
use std::path::PathBuf;
2
2
3
3
-
use crate::projectparse::ProjectContext;
3
3
+
use crate::{macros::template::SkidTemplate, projectparse::ProjectContext};
4
4
5
5
pub struct Token {
6
6
pub contents: String,
7
7
pub origin_file: usize,
8
8
-
pub line_number: u32,
8
8
+
pub line_number: usize,
9
9
}
10
10
11
11
pub struct InputFile {
···
14
14
pub file_htmlout: PathBuf,
15
15
pub tokens: Vec<Token>,
16
16
pub working_index: usize,
17
17
+
pub templates: Vec<SkidTemplate>,
17
18
}
18
19
19
20
type MacroExpansion =
20
20
-
fn(&mut InputFile, usize, &mut ProjectContext, &Vec<String>, &[Token]) -> Vec<Token>;
21
21
+
fn(&mut InputFile, usize, usize, &mut ProjectContext, &Vec<String>, &[Token]) -> Vec<Token>;
22
22
+
// (
23
23
+
// _file: &mut InputFile,
24
24
+
// origin_index: usize,
25
25
+
// origin_line: usize,
26
26
+
// context: &mut ProjectContext,
27
27
+
// args: &Vec<String>,
28
28
+
// _scope: &[Token],
29
29
+
// ) -> Vec<Token>
30
30
+
21
31
pub struct Macro<'a> {
22
32
pub symbol: &'a str,
23
33
pub expand: MacroExpansion,
···
32
42
file_htmlout: "".into(),
33
43
tokens: Vec::new(),
34
44
working_index: 0,
45
45
+
templates: Vec::new(),
35
46
}
36
47
}
37
48
}
38
49
39
50
impl Token {
40
40
-
pub fn new(contents: String, origin_file: usize, line_number: u32) -> Token {
51
51
+
pub fn new(contents: String, origin_file: usize, line_number: usize) -> Token {
41
52
Token {
42
53
contents: contents,
43
54
origin_file: origin_file,