Tholp's bespoke website generator

templates

Tholp1 3349e4c1 0bb5d81b

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