Tholp's bespoke website generator
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Better errors and warns

Tholp1 478cd07f 4f40cfb3

+232 -79
+1
Cargo.toml
··· 5 5 6 6 [dependencies] 7 7 chrono = "0.4.41" 8 + colored = "3.0.0" 8 9 glob = "0.3.2" 9 10 markdown = "1.0.0" 10 11 # markdown = {path = "/home/tholp/Desktop/Code/libs/markdown-rs"}
+43
src/console.rs
··· 1 + use std::process::exit; 2 + 3 + use colored::Colorize; 4 + 5 + use crate::projectparse::{FileIndexing, ProjectContext}; 6 + 7 + pub fn error_generic(msg: String) { 8 + println!("{} {}", "[ERROR]".red(), msg); 9 + exit(1); 10 + } 11 + 12 + pub fn error_skid(context: &ProjectContext, origin_index: usize, origin_line: usize, msg: String) { 13 + println!( 14 + "{} {:?}:{}; {}", 15 + "[ERROR]".red(), 16 + context 17 + .file_for_index(origin_index) 18 + .expect("Panic in the error func.... (file_for_index() was None!)"), 19 + origin_line, 20 + msg 21 + ); 22 + exit(1); 23 + } 24 + 25 + pub fn warn_generic(msg: String) { 26 + println!("{} {}", "[WARN]".yellow(), msg); 27 + } 28 + 29 + pub fn warn_skid(context: &ProjectContext, origin_index: usize, origin_line: usize, msg: String) { 30 + println!( 31 + "{} {:?}:{}; {}", 32 + "[WARN]".yellow(), 33 + context 34 + .file_for_index(origin_index) 35 + .expect("Panic in the warn func.... (file_for_index() was None!)"), 36 + origin_line, 37 + msg 38 + ); 39 + } 40 + 41 + pub fn ok_generic(msg: String) { 42 + println!("{} {}", "[OK]".green(), msg); 43 + }
-10
src/error.rs
··· 1 - pub fn exit_error(msg : String) 2 - { 3 - println!("[Error]" + msg); 4 - exit(1); 5 - } 6 - 7 - pub fn warn(msg: String) 8 - { 9 - 10 - }
+10 -8
src/macros/insert.rs
··· 6 6 }; 7 7 8 8 use crate::{ 9 + console::error_skid, 9 10 projectparse::{FileIndexing, ProjectContext}, 10 11 stringtools::{split_keep_delimiters, split_to_tokens, strings_to_tokens}, 11 12 types::{InputFile, Token}, ··· 24 25 .expect("Macro 'Insert' was given a bad origin index") 25 26 .clone(); 26 27 if args.len() != 1 { 27 - println!( 28 - "[ERROR] {:?}:{} ;Insert only accepts 1 argument, got given {} ({:?})", 29 - origin_file.to_str(), 28 + error_skid( 29 + context, 30 + origin_index, 30 31 origin_line, 31 - args.len(), 32 - args 32 + format!( 33 + "Insert only accepts 1 argument, got given {} ({:?})", 34 + args.len(), 35 + args 36 + ), 33 37 ); 34 - exit(1); 35 38 } 36 39 37 40 let mut arg = args[0].clone(); ··· 67 70 } 68 71 69 72 if !ok { 70 - println!("[ERROR] {:?}: Insert was unable to find the file \"{}\" relative to its origin or in project root.", origin_file.to_str().unwrap(), arg); 71 - exit(1); 73 + error_skid(context, origin_index, origin_line, format!("Insert was unable to find the file \"{}\" relative to its origin or in project root.", arg)); 72 74 } 73 75 74 76 let mut output = fs::read_to_string(&include_file).expect("File unreadable or missing");
+3 -3
src/macros/mod.rs
··· 5 5 use super::types::Macro; 6 6 7 7 use insert::macro_insert; 8 - use simple_blocks::{macro_comment, macro_repeat, macro_section, macro_skip}; 8 + use simple_blocks::{macro_comment, macro_for_each_arg, macro_repeat, macro_section}; 9 9 use simple_macros::{macro_clear, macro_filename, macro_filename_canonical, macro_time}; 10 10 use template::macro_template; 11 11 ··· 58 58 has_scope: true, 59 59 }, 60 60 Macro { 61 - symbol: "skip", 62 - expand: macro_skip, 61 + symbol: "for_each_arg", 62 + expand: macro_for_each_arg, 63 63 has_scope: true, 64 64 }, 65 65 ];
+68 -12
src/macros/simple_blocks.rs
··· 1 1 // This file for implementations of short blocks, im qualifying that as less than 30ish lines 2 2 3 + use std::{env::args, fmt::format, process::exit}; 4 + 3 5 use crate::{ 4 - projectparse::ProjectContext, 6 + console::error_skid, 7 + projectparse::{FileIndexing, ProjectContext}, 8 + stringtools::{find_pattern, split_to_tokens}, 5 9 types::{InputFile, Token}, 6 10 }; 7 11 ··· 31 35 return tokens; 32 36 } 33 37 34 - pub fn macro_skip( 35 - _file: &mut InputFile, 36 - _origin_index: usize, 37 - _origin_line: usize, 38 - _context: &mut ProjectContext, 39 - _args: &Vec<String>, 40 - scope: &[Token], 41 - ) -> Vec<Token> { 42 - Vec::new() 43 - } 44 - 45 38 pub fn macro_repeat( 46 39 _file: &mut InputFile, 47 40 _origin_index: usize, ··· 63 56 } 64 57 return tokens; 65 58 } 59 + 60 + pub fn macro_for_each_arg( 61 + _file: &mut InputFile, 62 + origin_index: usize, 63 + origin_line: usize, 64 + context: &mut ProjectContext, 65 + args: &Vec<String>, 66 + scope: &[Token], 67 + ) -> Vec<Token> { 68 + let mut output = Vec::new(); 69 + let block: Vec<Token> = scope.into(); 70 + 71 + let mut replacement_count: usize = 0; 72 + 73 + let mut replacement_pattern = find_pattern(scope, "[[..1]]".into()); 74 + while replacement_pattern.is_some() { 75 + replacement_count += 1; 76 + replacement_pattern = 77 + find_pattern(scope, format!("[[..{}]]", replacement_count + 1).into()); 78 + } 79 + 80 + if replacement_count == 0 { 81 + for _i in 0..args.iter().count() { 82 + output.append(&mut block.clone()); 83 + } 84 + return output; 85 + } 86 + 87 + if args.len() % replacement_count != 0 { 88 + error_skid(context, origin_index, origin_line, 89 + format!("`for_each_var` was not given a number of arguments({}) that was a multiple of its replacement posistions({}) (got {:?})", 90 + args.len(), 91 + replacement_count, 92 + args)); 93 + } 94 + 95 + let mut replacement_index: usize = 0; 96 + let mut arg_output: Vec<Token> = block.clone(); 97 + for arg in args { 98 + let mut found_pattern = 99 + find_pattern(&arg_output, format!("[[..{}]]", replacement_index + 1)); 100 + 101 + while found_pattern.is_some() { 102 + let (start, len) = found_pattern.unwrap(); 103 + let replacement = split_to_tokens(arg.clone(), origin_index); 104 + arg_output.splice(start..start + len, replacement); 105 + found_pattern = find_pattern(&output, format!("[[..{}]]", replacement_index + 1)); 106 + println!("{}", replacement_index + 1); 107 + } 108 + 109 + println!("{} {}", replacement_index, replacement_count); 110 + replacement_index += 1; 111 + if replacement_index == replacement_count { 112 + replacement_index = 0; 113 + output.append(&mut arg_output); 114 + arg_output = block.clone(); 115 + println!("push"); 116 + } 117 + println!("test"); 118 + } 119 + 120 + return output; 121 + }
+75 -24
src/macros/template.rs
··· 1 - use std::{process::exit, thread::scope}; 1 + use std::{fmt::format, process::exit, thread::scope}; 2 2 3 3 use crate::{ 4 + console::error_skid, 4 5 projectparse::{FileIndexing, ProjectContext}, 5 6 stringtools::{find_pattern, split_to_tokens, strings_to_tokens, WhitespaceChecks}, 6 7 types::{InputFile, Token}, ··· 14 15 pub tokens: Vec<Token>, 15 16 16 17 pub has_scope: bool, 18 + pub allows_trailing_args: bool, 17 19 } 18 20 19 21 impl SkidTemplate { 20 22 pub fn new(name: String, args: &[String], tokens: &[Token]) -> SkidTemplate { 21 23 let scoped: bool = find_pattern(&tokens, "[[{}]]".into()).is_some(); 24 + let trailing: bool = find_pattern(&tokens, "[[..]]".into()).is_some() 25 + || find_pattern(&tokens, "[[\"..\"]]".into()).is_some(); 22 26 23 27 SkidTemplate { 24 28 symbol: name, 25 29 args: args.to_vec(), 26 30 tokens: tokens.to_vec(), 27 31 has_scope: scoped, 32 + allows_trailing_args: trailing, 28 33 } 29 34 } 30 35 ··· 32 37 &self, 33 38 //_file: &mut InputFile, 34 39 origin_index: usize, 35 - _context: &mut ProjectContext, 40 + origin_line: usize, 41 + context: &mut ProjectContext, 36 42 args: &Vec<String>, 37 43 scope: &[Token], 38 44 ) -> Vec<Token> { 39 45 //println!("{:?}", args); 46 + 47 + if !self.allows_trailing_args && args.len() != self.args.len() { 48 + // println!( 49 + // "[ERROR] {:?}:{}; Template \"{}\" requires exactly {} arguments, got given {} ({:?})", 50 + // context.file_for_index(origin_index).unwrap(), 51 + // origin_line, 52 + // self.symbol, 53 + // self.args.len(), 54 + // args.len(), 55 + // args 56 + // ); 57 + // exit(1); 58 + 59 + error_skid( 60 + context, 61 + origin_index, 62 + origin_line, 63 + format!( 64 + "Template \"{}\" requires exactly {} arguments, got given {} ({:?})", 65 + self.symbol, 66 + self.args.len(), 67 + args.len(), 68 + args 69 + ), 70 + ); 71 + } 72 + if self.allows_trailing_args && args.len() < self.args.len() { 73 + error_skid( 74 + context, 75 + origin_index, 76 + origin_line, 77 + format!( 78 + "Template \"{}\" requires at least {} arguments, got given {} ({:?})", 79 + self.symbol, 80 + self.args.len(), 81 + args.len(), 82 + args 83 + ), 84 + ); 85 + } 40 86 41 87 let mut output = self.tokens.clone(); 42 88 ··· 78 124 ) -> Vec<Token> { 79 125 for t in &file.templates { 80 126 if t.symbol == args[0] { 81 - println!( 82 - "[ERROR] {:?}:{} ; Attempted template redefinition of \"{}\"", 83 - context.file_for_index(origin_index).unwrap(), 127 + error_skid( 128 + context, 129 + origin_index, 84 130 origin_line, 85 - args[0] 131 + format!("Attempted template redefinition of \"{}\"", args[0]), 86 132 ); 87 - exit(1); 88 133 } 89 134 } 90 135 91 136 for t in MACRO_LIST { 92 137 if t.symbol == args[0] { 93 - println!( 94 - "[ERROR] {:?}:{} ; Attempted to make a template using a reserved name \"{}\"", 95 - context.file_for_index(origin_index).unwrap(), 138 + error_skid( 139 + context, 140 + origin_index, 96 141 origin_line, 97 - args[0] 142 + format!( 143 + "Attempted to make a template using a reserved name \"{}\"", 144 + args[0] 145 + ), 98 146 ); 99 - exit(1); 100 147 } 101 148 } 102 149 ··· 106 153 used_params += 1; 107 154 } 108 155 if param.contains_whitespace() { 109 - println!( 110 - "[ERROR] {:?}:{} ; Attempted to make a template with a parameter that contains whitespace \"{}\"", 111 - context.file_for_index(origin_index).unwrap(), 156 + error_skid( 157 + context, 158 + origin_index, 112 159 origin_line, 113 - param 160 + format!( 161 + "Attempted to make a template with a parameter that contains whitespace \"{}\"", 162 + param 163 + ), 114 164 ); 115 - exit(1); 116 165 } 117 166 } 118 167 119 168 if used_params < args.len() - 1 { 120 - println!( 121 - "[ERROR] {:?}:{} ; Template definition of \"{}\" has {} paramters but only uses {}", 122 - context.file_for_index(origin_index).unwrap(), 169 + error_skid( 170 + context, 171 + origin_index, 123 172 origin_line, 124 - args[0], 125 - args.len() - 1, 126 - used_params 173 + format!( 174 + "Template definition of \"{}\" has {} paramters but only uses {}", 175 + args[0], 176 + args.len() - 1, 177 + used_params 178 + ), 127 179 ); 128 - exit(1); 129 180 } 130 181 131 182 let template = SkidTemplate::new(args[0].clone(), &args[1..], scope);
+27 -21
src/main.rs
··· 1 + mod console; 1 2 mod macros; 2 3 mod projectparse; 3 4 mod stringtools; 4 5 mod types; 5 6 7 + use console::*; 6 8 use macros::MACRO_LIST; 7 9 use markdown::{to_html_with_options, CompileOptions, Constructs, Options, ParseOptions}; 8 10 use projectparse::{parse_project, FileIndexing, ProjectContext}; ··· 32 34 while !project_path.exists() || project_path.is_dir() { 33 35 let ok = project_folder.pop(); 34 36 if !ok { 35 - println!("[ERROR] No skidmark.toml project file found in this folder or ancestors."); 36 - exit(1); 37 + error_generic( 38 + "No skidmark.toml project file found in this folder or ancestors.".into(), 39 + ); 37 40 } 38 41 project_path = project_folder.clone(); 39 42 project_path.push("skidmark.toml"); ··· 122 125 let block_opt = 123 126 collect_block(&file.tokens[(file.working_index + args_tokcount)..]); 124 127 if block_opt.is_none() { 125 - println!( 126 - "[ERROR] {:?}:{} ;Malformed block", 127 - file.tokens[file.working_index].origin_file, 128 - file.tokens[file.working_index].line_number 128 + error_skid( 129 + context, 130 + file.tokens[file.working_index].template_origin, 131 + file.tokens[file.working_index].line_number, 132 + "Malformed Block".into(), 129 133 ); 130 - exit(1); 131 134 } 132 135 let block: Vec<Token>; 133 136 (block, block_tokcount) = block_opt.unwrap(); ··· 193 196 let block_opt = 194 197 collect_block(&file.tokens[(file.working_index + args_tokcount)..]); 195 198 if block_opt.is_none() { 196 - println!( 197 - "[ERROR] {:?}:{} ;Malformed block", 198 - file.tokens[file.working_index].origin_file, 199 - file.tokens[file.working_index].line_number 199 + error_skid( 200 + context, 201 + file.tokens[file.working_index].template_origin, 202 + file.tokens[file.working_index].line_number, 203 + "Malformed Block".into(), 200 204 ); 201 - exit(1); 202 205 } 203 206 204 207 (block, block_tokcount) = block_opt.unwrap(); ··· 209 212 expansion = m.expand( 210 213 //file, 211 214 file.tokens[file.working_index].origin_file, 212 - //file.tokens[file.working_index].line_number, 215 + file.tokens[file.working_index].line_number, 213 216 context, 214 217 &args, 215 218 &block, ··· 224 227 expansion = m.expand( 225 228 //file, 226 229 file.tokens[file.working_index].origin_file, 227 - //file.tokens[file.working_index].line_number, 230 + file.tokens[file.working_index].line_number, 228 231 context, 229 232 &args, 230 233 &Vec::new()[..], ··· 247 250 } 248 251 } 249 252 if !matched_macro { 250 - println!( 251 - "[WARN] {:?}:{}; Token written as a function but no such function exists \"{}\"", 252 - context.file_for_index(file.tokens[file.working_index].origin_file).unwrap(), 253 + warn_skid( 254 + context, 255 + file.tokens[file.working_index].origin_file, 253 256 file.tokens[file.working_index].line_number, 254 - file.tokens[file.working_index].contents.trim() 257 + format!( 258 + "Token written as a function but no such function exists \"{}\"", 259 + file.tokens[file.working_index].contents.trim() 260 + ), 255 261 ); 256 262 } 257 263 } ··· 290 296 ) 291 297 .unwrap(); 292 298 fs::write(&file.file_htmlout, &html_output).expect("Couldn't write html to file"); 293 - print!( 294 - "[OK] {} written.\n\n", 299 + ok_generic(format!( 300 + "{} written \n\n", 295 301 file.file_htmlout 296 302 .to_str() 297 303 .unwrap_or("Couldnt Unwrap htmlout name") 298 - ); 304 + )); 299 305 }
+5 -1
src/types.rs
··· 5 5 pub struct Token { 6 6 pub contents: String, 7 7 pub origin_file: usize, 8 + pub template_origin: usize, 8 9 pub line_number: usize, 9 10 } 10 11 ··· 52 53 Token { 53 54 contents: contents, 54 55 origin_file: origin_file, 56 + template_origin: origin_file, 55 57 line_number: line_number, 56 58 } 57 59 } ··· 65 67 66 68 impl Clone for Token { 67 69 fn clone(&self) -> Self { 68 - return Token::new( 70 + let mut t = Token::new( 69 71 self.contents.clone(), 70 72 self.origin_file.clone(), 71 73 self.line_number, 72 74 ); 75 + t.template_origin = self.template_origin; 76 + return t; 73 77 } 74 78 }