Tholp's bespoke website generator

prep

+170 -54
+1
Cargo.toml
··· 4 4 edition = "2021" 5 5 6 6 [dependencies] 7 + boa_engine = "0.20.0" 7 8 chrono = "0.4.41" 8 9 clap = { version = "4.5.40", features = ["derive"] } 9 10 colored = "3.0.0"
+78
src/closures.rs
··· 1 + // Closures are essentally blocked macros that change behavior on symbol instead of name 2 + // Instances of most types of closures can be named as sections ... 3 + // ... to work with !insert() to pick certain parts out of a file 4 + 5 + use boa_engine::Context; 6 + 7 + use crate::{ 8 + project::ProjectContext, 9 + types::{SkidContext, Token}, 10 + }; 11 + 12 + type ClosureFunction = fn(&[Token], &mut ProjectContext, &mut SkidContext) -> Vec<Token>; 13 + 14 + pub struct Closure { 15 + pub opener: &'static str, 16 + pub opener2: &'static str, 17 + pub closer: &'static str, 18 + pub function: ClosureFunction, 19 + } 20 + 21 + // (opener) name (opener2) ... (closer) 22 + 23 + // << js ! .. >> 24 + // <!-- comment --> 25 + // [ name {{ .. }}] 26 + 27 + // <!-- ... --> comment 28 + // ?name<< >> named js 29 + // ?name[[ ]] named section 30 + // ?<< >> js 31 + // ?[[ ]] section 32 + // ?name^[[]] named emphemeral section 33 + // ?name-[[]] named inverted section 34 + 35 + pub static CLOSURE_LIST: &'static [Closure] = &[ 36 + Closure { 37 + opener: "?", 38 + opener2: "<<", 39 + closer: ">>", 40 + function: closure_js, 41 + }, 42 + Closure { 43 + opener: "<!--", 44 + opener2: "", // blank means it doesnt accept a name 45 + closer: "-->", 46 + function: closure_comment, 47 + }, 48 + Closure { 49 + opener: "?", 50 + opener2: "{{", 51 + closer: "}}", 52 + function: closure_section, 53 + }, 54 + ]; 55 + 56 + fn closure_comment( 57 + _tokens: &[Token], 58 + _project_context: &mut ProjectContext, 59 + _skid_context: &mut SkidContext, 60 + ) -> Vec<Token> { 61 + Vec::new() 62 + } 63 + 64 + fn closure_section( 65 + tokens: &[Token], 66 + _project_context: &mut ProjectContext, 67 + _skid_context: &mut SkidContext, 68 + ) -> Vec<Token> { 69 + tokens.to_vec() 70 + } 71 + 72 + fn closure_js( 73 + tokens: &[Token], 74 + project_context: &mut ProjectContext, 75 + skid_context: &mut SkidContext, 76 + ) -> Vec<Token> { 77 + Vec::new() 78 + }
+1 -1
src/console.rs
··· 2 2 3 3 use colored::Colorize; 4 4 5 - use crate::project::{FileIndexing, ProjectContext}; 5 + use crate::project::{Indexing, ProjectContext}; 6 6 7 7 pub fn error_generic(msg: &String) { 8 8 println!("{} {}", "[ERROR]".red(), msg);
+3 -3
src/macros/insert.rs
··· 3 3 use crate::{ 4 4 console::error_skid, 5 5 macros::template::SkidTemplate, 6 - project::{FileIndexing, ProjectContext}, 6 + project::{Indexing, ProjectContext}, 7 7 stringtools::split_to_tokens, 8 - types::Token, 8 + types::{SkidContext, Token}, 9 9 }; 10 10 11 11 pub fn macro_insert( 12 12 origin_index: usize, 13 13 origin_line: usize, 14 14 context: &mut ProjectContext, 15 - _templates: &mut Vec<SkidTemplate>, 15 + _skid_context: &mut SkidContext, 16 16 args: &Vec<String>, 17 17 _scope: &[Token], 18 18 ) -> Vec<Token> {
+5 -5
src/macros/simple_blocks.rs
··· 5 5 macros::template::SkidTemplate, 6 6 project::ProjectContext, 7 7 stringtools::{find_pattern, split_to_tokens, TokenTools}, 8 - types::Token, 8 + types::{SkidContext, Token}, 9 9 }; 10 10 11 11 pub fn macro_comment( 12 12 _origin_index: usize, 13 13 _origin_line: usize, 14 14 _context: &mut ProjectContext, 15 - _templates: &mut Vec<SkidTemplate>, 15 + _skid_context: &mut SkidContext, 16 16 _args: &Vec<String>, 17 17 _scope: &[Token], 18 18 ) -> Vec<Token> { ··· 23 23 _origin_index: usize, 24 24 _origin_line: usize, 25 25 _context: &mut ProjectContext, 26 - _templates: &mut Vec<SkidTemplate>, 26 + _skid_context: &mut SkidContext, 27 27 _args: &Vec<String>, 28 28 scope: &[Token], 29 29 ) -> Vec<Token> { ··· 38 38 _origin_index: usize, 39 39 _origin_line: usize, 40 40 _context: &mut ProjectContext, 41 - _templates: &mut Vec<SkidTemplate>, 41 + _skid_context: &mut SkidContext, 42 42 args: &Vec<String>, 43 43 scope: &[Token], 44 44 ) -> Vec<Token> { ··· 60 60 origin_index: usize, 61 61 origin_line: usize, 62 62 context: &mut ProjectContext, 63 - _templates: &mut Vec<SkidTemplate>, 63 + _skid_context: &mut SkidContext, 64 64 args: &Vec<String>, 65 65 scope: &[Token], 66 66 ) -> Vec<Token> {
+6 -6
src/macros/simple_macros.rs
··· 6 6 use crate::{ 7 7 console::{error_skid, reminder_skid}, 8 8 macros::template::SkidTemplate, 9 - project::{FileIndexing, ProjectContext}, 9 + project::{Indexing, ProjectContext}, 10 10 stringtools::split_to_tokens, 11 - types::Token, 11 + types::{SkidContext, Token}, 12 12 }; 13 13 14 14 pub fn macro_time( 15 15 origin_index: usize, 16 16 origin_line: usize, 17 17 context: &mut ProjectContext, 18 - _templates: &mut Vec<SkidTemplate>, 18 + _skid_context: &mut SkidContext, 19 19 args: &Vec<String>, 20 20 _scope: &[Token], 21 21 ) -> Vec<Token> { ··· 42 42 origin_index: usize, 43 43 origin_line: usize, 44 44 context: &mut ProjectContext, 45 - _templates: &mut Vec<SkidTemplate>, 45 + _skid_context: &mut SkidContext, 46 46 _args: &Vec<String>, 47 47 _scope: &[Token], 48 48 ) -> Vec<Token> { ··· 61 61 origin_index: usize, 62 62 _origin_line: usize, 63 63 context: &mut ProjectContext, 64 - _templates: &mut Vec<SkidTemplate>, 64 + _skid_context: &mut SkidContext, 65 65 _args: &Vec<String>, 66 66 _scope: &[Token], 67 67 ) -> Vec<Token> { ··· 80 80 origin_index: usize, 81 81 origin_line: usize, 82 82 context: &mut ProjectContext, 83 - _templates: &mut Vec<SkidTemplate>, 83 + _skid_context: &mut SkidContext, 84 84 args: &Vec<String>, 85 85 _scope: &[Token], 86 86 ) -> Vec<Token> {
+15 -15
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::Token, 6 + types::{SkidContext, Token}, 7 7 }; 8 8 9 9 use super::MACRO_LIST; ··· 37 37 //_file: &mut InputFile, 38 38 origin_index: usize, 39 39 origin_line: usize, 40 - context: &mut ProjectContext, 40 + project_context: &mut ProjectContext, 41 41 args: &Vec<String>, 42 42 scope: &[Token], 43 43 ) -> Vec<Token> { ··· 45 45 46 46 if !self.allows_trailing_args && args.len() != self.args.len() { 47 47 error_skid( 48 - context, 48 + project_context, 49 49 origin_index, 50 50 origin_line, 51 51 &format!( ··· 59 59 } 60 60 if self.allows_trailing_args && args.len() < self.args.len() { 61 61 error_skid( 62 - context, 62 + project_context, 63 63 origin_index, 64 64 origin_line, 65 65 &format!( ··· 132 132 pub fn macro_template( 133 133 origin_index: usize, 134 134 origin_line: usize, 135 - context: &mut ProjectContext, 136 - templates: &mut Vec<SkidTemplate>, 135 + project_context: &mut ProjectContext, 136 + skid_context: &mut SkidContext, 137 137 args: &Vec<String>, 138 138 scope: &[Token], 139 139 ) -> Vec<Token> { 140 - for t in templates.iter().as_ref() { 140 + for t in skid_context.templates.iter().as_ref() { 141 141 if t.symbol == args[0] { 142 142 error_skid( 143 - context, 143 + project_context, 144 144 origin_index, 145 145 origin_line, 146 146 &format!("Attempted template redefinition of \"{}\"", args[0]), ··· 151 151 for t in MACRO_LIST { 152 152 if t.symbol == args[0] { 153 153 error_skid( 154 - context, 154 + project_context, 155 155 origin_index, 156 156 origin_line, 157 157 &format!( ··· 165 165 for r in RESERVED_NAMES_HTML { 166 166 if **r == args[0] { 167 167 error_skid( 168 - context, 168 + project_context, 169 169 origin_index, 170 170 origin_line, 171 171 &format!( ··· 179 179 for r in RESERVED_NAMES_MISC { 180 180 if **r == args[0] { 181 181 error_skid( 182 - context, 182 + project_context, 183 183 origin_index, 184 184 origin_line, 185 185 &format!( ··· 193 193 for arg in args { 194 194 if arg == ".." || arg == "\"..\"" { 195 195 error_skid( 196 - context, 196 + project_context, 197 197 origin_index, 198 198 origin_line, 199 199 &format!( ··· 211 211 } 212 212 if param.contains_whitespace() { 213 213 error_skid( 214 - context, 214 + project_context, 215 215 origin_index, 216 216 origin_line, 217 217 &format!( ··· 224 224 225 225 if used_params < args.len() - 1 { 226 226 error_skid( 227 - context, 227 + project_context, 228 228 origin_index, 229 229 origin_line, 230 230 &format!( ··· 237 237 } 238 238 239 239 let template = SkidTemplate::new(args[0].clone(), &args[1..], scope); 240 - templates.push(template); 240 + skid_context.templates.push(template); 241 241 242 242 return Vec::new(); 243 243 }
+29 -11
src/main.rs
··· 1 1 mod args; 2 + mod closures; 2 3 mod console; 3 4 mod macros; 4 5 mod project; ··· 7 8 mod types; 8 9 9 10 use crate::{ 10 - args::ProgramArgs, macros::template::SkidTemplate, project::FileGroup, 11 - reservednames::RESERVED_NAMES_MISC, types::Expand, 11 + args::ProgramArgs, 12 + closures::CLOSURE_LIST, 13 + macros::template::SkidTemplate, 14 + project::FileGroup, 15 + reservednames::RESERVED_NAMES_MISC, 16 + types::{Expand, SkidContext}, 12 17 }; 13 18 use clap::Parser; 14 19 use console::*; 15 20 use macros::MACRO_LIST; 16 21 use markdown::{CompileOptions, Constructs, Options, ParseOptions}; 17 - use project::{parse_project, FileIndexing, ProjectContext}; 22 + use project::{parse_project, Indexing, ProjectContext}; 18 23 use reservednames::RESERVED_NAMES_HTML; 19 24 use std::{ 20 25 env, ··· 25 30 use stringtools::{collect_arguments, collect_block, split_to_tokens, trim_whitespace_tokens}; 26 31 use types::{InputFile, Token}; 27 32 33 + // really need to change this whole thing to work with characters rather than 34 + // strings split on kind of abitrary chars.. 28 35 static DELIMITERS: &'static [char] = &[ 29 - ' ', '\n', '\t', '(', ')', '{', '}', '[', ']', '<', '>', '\\', '\'', '\"', ';', 36 + ' ', '\n', '\t', '(', ')', '{', '}', '[', ']', '<', '>', '\\', '\'', '\"', ';', '?', '^', '-', 30 37 ]; 31 38 32 39 fn main() { ··· 72 79 infile.tokens = 73 80 split_to_tokens(contents, project.context.index_of_file(&infile.file_input)); 74 81 82 + let mut skid_context = SkidContext::new(); 75 83 process_skid( 76 84 &mut infile.tokens, 77 85 project.context.index_of_file(&infile.file_input), 78 86 &mut project.context, 79 - Vec::new(), 87 + &mut skid_context, 80 88 ); 81 89 } 82 90 } ··· 86 94 tokens_in: &mut [Token], 87 95 file_index: usize, 88 96 context: &mut ProjectContext, 89 - templates_base: Vec<SkidTemplate>, 97 + skid_context: &mut SkidContext, 90 98 ) -> Vec<Token> { 91 99 //}, context: &mut ProjectContext) { 92 100 //println!("{}\n {}", f.filename_out, contents); ··· 95 103 96 104 //let mut escaped = false; 97 105 let mut tokens = tokens_in.to_vec(); 98 - let mut templates = templates_base; 106 + let mut starting_template_count = skid_context.templates.len(); 99 107 100 108 let mut working_index = 0; 101 109 ··· 167 175 tokens[working_index].origin_file, 168 176 tokens[working_index].line_number, 169 177 context, 170 - &mut templates, 178 + skid_context, 171 179 &args, 172 180 &block, 173 181 ); ··· 182 190 tokens[working_index].origin_file, 183 191 tokens[working_index].line_number, 184 192 context, 185 - &mut templates, 193 + skid_context, 186 194 &args, 187 195 &Vec::new()[..], 188 196 ); ··· 204 212 205 213 // check for templates 206 214 // todo maybe deduplicate this 207 - for t in &templates { 215 + for t in &skid_context.templates { 208 216 if &symbol[prefix_len..] == t.symbol { 209 217 matched_macro = true; 210 218 //println!("Found a macro ({})", m.symbol); ··· 306 314 } 307 315 } 308 316 } 317 + 318 + // Not a macro or template, look through our closures 319 + // for c in CLOSURE_LIST 320 + // { 321 + // if tokens[working_index].contents.starts_with(c.opener) 322 + // { 323 + 324 + // } 325 + // } 326 + 309 327 if !matched_macro { 310 328 working_index += 1; 311 329 } 312 330 } 313 - 331 + skid_context.templates.truncate(starting_template_count); 314 332 return tokens; 315 333 } 316 334
+5 -2
src/project.rs
··· 164 164 return project; 165 165 } 166 166 167 - pub trait FileIndexing { 167 + pub trait Indexing { 168 168 fn index_of_file(&mut self, f: &PathBuf) -> usize; 169 169 fn file_for_index(&self, i: usize) -> Option<PathBuf>; 170 170 fn file_for_index_canonical(&self, i: usize) -> Option<&PathBuf>; 171 + 172 + // fn index_of_section_name(&mut self, name: String) -> usize; 173 + // fn section_name_for_index(&self, index: usize) -> String; 171 174 } 172 175 173 - impl FileIndexing for ProjectContext { 176 + impl Indexing for ProjectContext { 174 177 fn index_of_file(&mut self, f: &PathBuf) -> usize { 175 178 let cannonical = f.canonicalize().unwrap(); 176 179 let mut index = 0;
+27 -11
src/types.rs
··· 1 + use boa_engine::Context; 1 2 use std::path::PathBuf; 2 3 3 4 use crate::{ ··· 11 12 pub origin_file: usize, 12 13 pub template_origin: usize, 13 14 pub line_number: usize, 15 + pub section_name_index: usize, 14 16 } 15 17 16 18 pub struct InputFile { ··· 20 22 pub tokens: Vec<Token>, 21 23 } 22 24 23 - type MacroExpansion = fn( 24 - usize, 25 - usize, 26 - &mut ProjectContext, 27 - &mut Vec<SkidTemplate>, 28 - &Vec<String>, 29 - &[Token], 30 - ) -> Vec<Token>; 25 + pub struct SkidContext { 26 + pub templates: Vec<SkidTemplate>, 27 + } 28 + 29 + impl SkidContext { 30 + pub fn new() -> SkidContext { 31 + SkidContext { 32 + templates: Vec::new(), 33 + } 34 + } 35 + } 36 + 37 + type MacroExpansion = 38 + fn(usize, usize, &mut ProjectContext, &mut SkidContext, &Vec<String>, &[Token]) -> Vec<Token>; 31 39 // ( 32 40 // origin_index: usize, 33 41 // origin_line: usize, ··· 51 59 origin_index: usize, 52 60 origin_line: usize, 53 61 context: &mut ProjectContext, 54 - templates: &mut Vec<SkidTemplate>, 62 + skid_context: &mut SkidContext, 55 63 args: &Vec<String>, 56 64 scope: &[Token], 57 65 ) -> Vec<Token>; ··· 65 73 origin_index: usize, 66 74 origin_line: usize, 67 75 context: &mut ProjectContext, 68 - templates: &mut Vec<SkidTemplate>, 76 + skid_context: &mut SkidContext, 69 77 args: &Vec<String>, 70 78 scope: &[Token], 71 79 ) -> Vec<Token> { ··· 74 82 self.symbol, args.len(), self.min_args, if self.max_args == usize::max_value() {"No Limit".to_string()} else {format!("{}", self.max_args)})); 75 83 Vec::new() 76 84 } else { 77 - (self.expansion)(origin_index, origin_line, context, templates, args, scope) 85 + (self.expansion)( 86 + origin_index, 87 + origin_line, 88 + context, 89 + skid_context, 90 + args, 91 + scope, 92 + ) 78 93 } 79 94 } 80 95 ··· 107 122 origin_file: origin_file, 108 123 template_origin: origin_file, 109 124 line_number: line_number, 125 + section_name_index: 0, 110 126 } 111 127 } 112 128 }