Tholp's bespoke website generator

Small refactor

+122 -123
+3 -2
src/macros/insert.rs
··· 2 2 3 3 use crate::{ 4 4 console::error_skid, 5 + macros::template::SkidTemplate, 5 6 project::{FileIndexing, ProjectContext}, 6 7 stringtools::split_to_tokens, 7 - types::{InputFile, Token}, 8 + types::Token, 8 9 }; 9 10 10 11 pub fn macro_insert( 11 - _file: &mut InputFile, 12 12 origin_index: usize, 13 13 origin_line: usize, 14 14 context: &mut ProjectContext, 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 - use simple_macros::{macro_clear, macro_filename, macro_filename_canonical, macro_time}; 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 - }, 23 - Macro { 24 - symbol: "clear", // Clears text buffer 25 - expansion: macro_clear, 26 - has_scope: false, 27 - min_args: 0, 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 + macros::template::SkidTemplate, 5 6 project::ProjectContext, 6 7 stringtools::{find_pattern, split_to_tokens, TokenTools}, 7 - types::{InputFile, Token}, 8 + types::Token, 8 9 }; 9 10 10 11 pub fn macro_comment( 11 - _file: &mut InputFile, 12 12 _origin_index: usize, 13 13 _origin_line: usize, 14 14 _context: &mut ProjectContext, 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 - _file: &mut InputFile, 23 23 _origin_index: usize, 24 24 _origin_line: usize, 25 25 _context: &mut ProjectContext, 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 - _file: &mut InputFile, 38 38 _origin_index: usize, 39 39 _origin_line: usize, 40 40 _context: &mut ProjectContext, 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 - _file: &mut InputFile, 60 60 origin_index: usize, 61 61 origin_line: usize, 62 62 context: &mut ProjectContext, 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 + macros::template::SkidTemplate, 8 9 project::{FileIndexing, ProjectContext}, 9 10 stringtools::split_to_tokens, 10 - types::{InputFile, Token}, 11 + types::Token, 11 12 }; 12 13 13 - pub fn macro_clear( 14 - _file: &mut InputFile, 15 - _origin_index: usize, 16 - _origin_line: usize, 17 - _context: &mut ProjectContext, 18 - _args: &Vec<String>, 19 - _scope: &[Token], 20 - ) -> Vec<Token> { 21 - _file.tokens = _file.tokens.split_off(_file.working_index); 22 - _file.working_index = 0; 23 - return Vec::new(); 24 - } 25 - 26 14 pub fn macro_time( 27 - file: &mut InputFile, 28 15 origin_index: usize, 29 16 origin_line: usize, 30 17 context: &mut ProjectContext, 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 - _file: &mut InputFile, 55 42 origin_index: usize, 56 - _origin_line: usize, 43 + origin_line: usize, 57 44 context: &mut ProjectContext, 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 - _file: &mut InputFile, 74 61 origin_index: usize, 75 62 _origin_line: usize, 76 63 context: &mut ProjectContext, 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 - _file: &mut InputFile, 93 80 origin_index: usize, 94 81 origin_line: usize, 95 82 context: &mut ProjectContext, 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 - types::{InputFile, Token}, 6 + types::Token, 7 7 }; 8 8 9 9 use super::MACRO_LIST; ··· 130 130 } 131 131 132 132 pub fn macro_template( 133 - file: &mut InputFile, 134 133 origin_index: usize, 135 134 origin_line: usize, 136 135 context: &mut ProjectContext, 136 + templates: &mut Vec<SkidTemplate>, 137 137 args: &Vec<String>, 138 138 scope: &[Token], 139 139 ) -> Vec<Token> { 140 - for t in &file.templates { 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 - file.templates.push(template); 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 - args::ProgramArgs, project::FileGroup, reservednames::RESERVED_NAMES_MISC, types::Expand, 10 + args::ProgramArgs, macros::template::SkidTemplate, project::FileGroup, 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 + 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 - println!("Operatting with {:?}", &project_path.as_os_str()); 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 + // for group in &mut project.filegroups { 63 + // for infile in &mut group.files { 64 + // process_skid(infile, group.convert_html, &mut project.context); 65 + // } 66 + // } 67 + 60 68 for group in &mut project.filegroups { 61 69 for infile in &mut group.files { 62 - process_file(infile, group.convert_html, &mut project.context); 70 + let contents = 71 + fs::read_to_string(&infile.file_input).expect("File unreadable or missing"); 72 + infile.tokens = 73 + split_to_tokens(contents, project.context.index_of_file(&infile.file_input)); 74 + 75 + process_skid( 76 + &mut infile.tokens, 77 + project.context.index_of_file(&infile.file_input), 78 + &mut project.context, 79 + Vec::new(), 80 + ); 63 81 } 64 82 } 65 83 } 66 84 67 - fn process_file(file: &mut InputFile, convert_html: bool, context: &mut ProjectContext) { 85 + fn process_skid( 86 + tokens_in: &mut [Token], 87 + file_index: usize, 88 + context: &mut ProjectContext, 89 + templates_base: Vec<SkidTemplate>, 90 + ) -> Vec<Token> { 68 91 //}, context: &mut ProjectContext) { 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 - file.tokens = split_to_tokens(contents, context.index_of_file(&file.file_input)); 95 + 74 96 //let mut escaped = false; 97 + let mut tokens = tokens_in.to_vec(); 98 + let mut templates = templates_base; 75 99 76 - while file.working_index < file.tokens.len() { 100 + let mut working_index = 0; 101 + 102 + while working_index < tokens.len() { 77 103 //look for macros or blocks 78 - //println!(">\"{}\"<", file.tokens[file.working_index].contents); 104 + //println!(">\"{}\"<", tokens[working_index].contents); 79 105 80 - if file.tokens[file.working_index].contents.len() == 0 { 81 - file.working_index += 1; 106 + if tokens[working_index].contents.len() == 0 { 107 + working_index += 1; 82 108 continue; 83 109 } 84 110 85 - if file.tokens[file.working_index].contents == "\\" { 86 - file.tokens[file.working_index].contents = "".into(); 87 - file.working_index += 2; 111 + if tokens[working_index].contents == "\\" { 112 + tokens[working_index].contents = "".into(); 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 - if file.tokens[file.working_index] 94 - .contents 95 - .starts_with(['!', '&']) 96 - { 119 + if tokens[working_index].contents.starts_with(['!', '&']) { 97 120 let mut prefix_len = 1; 98 - let mut symbol = file.tokens[file.working_index].contents.clone(); 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 - let same_file = file.tokens[file.working_index].origin_file 104 - != context.index_of_file(&file.file_input); 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 - let (args, args_tokcount) = 123 - collect_arguments(&file.tokens[file.working_index..]); 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 - collect_block(&file.tokens[(file.working_index + args_tokcount)..]); 151 + collect_block(&tokens[(working_index + args_tokcount)..]); 131 152 if block_opt.is_none() { 132 153 error_skid( 133 154 context, 134 - file.tokens[file.working_index].template_origin, 135 - file.tokens[file.working_index].line_number, 155 + tokens[working_index].template_origin, 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 - file, 147 - file.tokens[file.working_index].origin_file, 148 - file.tokens[file.working_index].line_number, 167 + tokens[working_index].origin_file, 168 + tokens[working_index].line_number, 149 169 context, 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 - file, 162 - file.tokens[file.working_index].origin_file, 163 - file.tokens[file.working_index].line_number, 182 + tokens[working_index].origin_file, 183 + tokens[working_index].line_number, 164 184 context, 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 - file.tokens.remove(file.working_index); 174 - file.tokens.splice( 175 - file.working_index 176 - ..(file.working_index + args_tokcount + block_tokcount - 1), 194 + tokens.remove(working_index); 195 + tokens.splice( 196 + working_index..(working_index + args_tokcount + block_tokcount - 1), 177 197 trimmed.iter().cloned(), 178 198 ); 179 - if expansion.len() == 0 && file.working_index > 0 { 180 - file.working_index -= 1; 199 + if expansion.len() == 0 && working_index > 0 { 200 + working_index -= 1; 181 201 } 182 202 } 183 203 } 184 204 185 205 // check for templates 186 206 // todo maybe deduplicate this 187 - for m in &mut file.templates { 188 - if &symbol[prefix_len..] == m.symbol { 207 + for t in &templates { 208 + if &symbol[prefix_len..] == t.symbol { 189 209 matched_macro = true; 190 210 //println!("Found a macro ({})", m.symbol); 191 211 192 - let (args, args_tokcount) = 193 - collect_arguments(&file.tokens[file.working_index..]); 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 - if m.has_scope { 216 + if t.has_scope { 198 217 //println!("is scoped."); 199 218 let block: Vec<Token>; 200 219 let block_opt = 201 - collect_block(&file.tokens[(file.working_index + args_tokcount)..]); 220 + collect_block(&tokens[(working_index + args_tokcount)..]); 202 221 if block_opt.is_none() { 203 222 error_skid( 204 223 context, 205 - file.tokens[file.working_index].template_origin, 206 - file.tokens[file.working_index].line_number, 224 + tokens[working_index].template_origin, 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 - expansion = m.expand( 235 + expansion = t.expand( 217 236 //file, 218 - file.tokens[file.working_index].origin_file, 219 - file.tokens[file.working_index].line_number, 237 + tokens[working_index].origin_file, 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 - expansion = m.expand( 250 + expansion = t.expand( 232 251 //file, 233 - file.tokens[file.working_index].origin_file, 234 - file.tokens[file.working_index].line_number, 252 + tokens[working_index].origin_file, 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 - file.tokens.remove(file.working_index); 245 - file.tokens.splice( 246 - file.working_index 247 - ..(file.working_index + args_tokcount + block_tokcount - 1), 263 + tokens.remove(working_index); 264 + tokens.splice( 265 + working_index..(working_index + args_tokcount + block_tokcount - 1), 248 266 trimmed.iter().cloned(), 249 267 ); 250 - if expansion.len() == 0 && file.working_index > 0 { 251 - file.working_index -= 1; 268 + if expansion.len() == 0 && working_index > 0 { 269 + working_index -= 1; 252 270 } 253 271 } 254 272 } 255 273 } 256 274 if !matched_macro { 257 - let name = file.tokens[file.working_index] 258 - .contents 259 - .trim() 260 - .to_lowercase(); 275 + let name = tokens[working_index].contents.trim().to_lowercase(); 261 276 let mut dont_error = name.len() <= 1; 262 277 { 263 - if !dont_error && convert_html { 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 - file.tokens[file.working_index].origin_file, 285 - file.tokens[file.working_index].line_number, 299 + tokens[working_index].origin_file, 300 + tokens[working_index].line_number, 286 301 &format!( 287 302 "Token written as a function but no such function exists \"{}\"", 288 - file.tokens[file.working_index].contents.trim() 303 + tokens[working_index].contents.trim() 289 304 ), 290 305 ); 291 306 } 292 307 } 293 308 } 294 309 if !matched_macro { 295 - file.working_index += 1; 310 + working_index += 1; 296 311 } 297 312 } 298 - //println!("{:?}", file.tokens); 313 + 314 + return tokens; 315 + } 316 + 317 + fn write_file(file: InputFile, convert_html: bool) { 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 - // pub struct ProjectSettings { 25 - 26 - // } 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 - 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 - pub working_index: usize, 22 - pub templates: Vec<SkidTemplate>, 23 21 } 24 22 25 - type MacroExpansion = 26 - fn(&mut InputFile, usize, usize, &mut ProjectContext, &Vec<String>, &[Token]) -> Vec<Token>; 23 + type MacroExpansion = fn( 24 + usize, 25 + usize, 26 + &mut ProjectContext, 27 + &mut Vec<SkidTemplate>, 28 + &Vec<String>, 29 + &[Token], 30 + ) -> Vec<Token>; 27 31 // ( 28 - // _file: &mut InputFile, 29 32 // origin_index: usize, 30 33 // origin_line: usize, 31 34 // context: &mut ProjectContext, 35 + // templates: &mut Vec<SkidTemplate>, 32 36 // args: &Vec<String>, 33 - // _scope: &[Token], 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 - pub has_scope: bool, //takes blocks of text input as well as parameters using {{...}} 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 - input_file: &mut InputFile, 48 51 origin_index: usize, 49 52 origin_line: usize, 50 53 context: &mut ProjectContext, 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 - input_file: &mut InputFile, 62 65 origin_index: usize, 63 66 origin_line: usize, 64 67 context: &mut ProjectContext, 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 - (self.expansion)(input_file, origin_index, origin_line, context, args, scope) 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 - working_index: 0, 96 - templates: Vec::new(), 97 99 } 98 100 } 99 101 }