Tholp's bespoke website generator
0
fork

Configure Feed

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

Add lua blocks $[...]

Tholp dbcadd5c a4a03d99

+172 -26
+1 -1
Cargo.toml
··· 5 5 repository = "https://github.com/Tholp1/Skidmark" # for cargo-dist, also available at https://tangled.org/@tholps.site/skidmark 6 6 7 7 [dependencies] 8 - boa_engine = "0.20.0" 9 8 chrono = "0.4.41" 10 9 clap = { version = "4.5.40", features = ["derive"] } 11 10 colored = "3.0.0" 12 11 glob = "0.3.2" 13 12 markdown = "1.0.0" 13 + mlua = { version = "0.11.6", features = [ "lua54", "vendored" ] } 14 14 serde = "1.0.218" 15 15 toml = "0.8.19" 16 16
+18 -14
src/main.rs
··· 8 8 9 9 use crate::{ 10 10 reservednames::RESERVED_NAMES_MISC, 11 - stringtools::TokenTools, 11 + stringtools::{find_and_execute_lua_block, TokenTools}, 12 12 types::{IsScoped, MacroExpand, SkidContext}, 13 13 }; 14 14 ··· 204 204 } 205 205 return None; 206 206 } 207 - 208 - let args_result = collect_arguments(&tokens_in[chars_consumed..]); 207 + let scoped = expander.is_scoped(); 208 + let args_result = 209 + collect_arguments(&tokens_in[chars_consumed..], proj_context, skid_context); 209 210 if args_result.is_none() { 210 211 error_skid( 211 212 proj_context, ··· 220 221 (args, consumed_by_args) = args_result.unwrap(); 221 222 chars_consumed += consumed_by_args; 222 223 223 - if expander.is_scoped() { 224 + if scoped { 224 225 let block_result = collect_block(&tokens_in[chars_consumed..]); 225 226 if block_result.is_none() { 226 227 error_skid( ··· 244 245 match ephemeral_type { 245 246 EphemeralType::Normal => return_empty = false, 246 247 EphemeralType::Ephemeral => { 247 - return_empty = skid_context.file_index != tokens_in[0].origin_index 248 + return_empty = skid_context.file_id != tokens_in[0].origin_index 248 249 } 249 250 EphemeralType::InverseEphemeral => { 250 - return_empty = skid_context.file_index == tokens_in[0].origin_index 251 + return_empty = skid_context.file_id == tokens_in[0].origin_index 251 252 } 252 253 } 253 254 ··· 345 346 } 346 347 } 347 348 348 - // Not a macro or template, look through our closures 349 - // for c in CLOSURE_LIST 350 - // { 351 - // if tokens[working_index].contents.starts_with(c.opener) 352 - // { 353 - 354 - // } 355 - // } 349 + if tokens[working_index] == '$' && !escaped { 350 + let ret = 351 + find_and_execute_lua_block(&tokens[working_index..], proj_context, skid_context); 352 + if ret.is_some() { 353 + let (expansion, consumed) = ret.unwrap(); 354 + tokens.splice(working_index..working_index + consumed, expansion); 355 + } else { 356 + working_index += 1; 357 + } 358 + continue; 359 + } 356 360 357 361 working_index += 1; 358 362
+146 -8
src/stringtools.rs
··· 1 + use mlua::ObjectLike; 2 + 1 3 use super::DELIMITERS; 2 - use crate::types::Token; 4 + use crate::{ 5 + console::error_skid, 6 + process_skid, 7 + project::Project, 8 + types::{SkidContext, Token}, 9 + }; 3 10 4 11 //TODO: Theres a couple functions that are still written like tokens are strings not chars, they work fine 5 12 // for now but they may need to be changed later 6 13 7 - pub fn collect_arguments(tokens: &[Token]) -> Option<(Vec<String>, usize)> { 14 + pub fn collect_arguments( 15 + tokens: &[Token], 16 + proj_context: &mut Project, 17 + skid_context: &mut SkidContext, 18 + ) -> Option<(Vec<String>, usize)> { 8 19 // Returns arguments vec and number of tokens to be consumed 9 20 //let mut output = Vec::new(); 10 21 ··· 14 25 let mut arg = "".to_string(); 15 26 let mut args: Vec<String> = Vec::new(); 16 27 17 - let mut in_token_count = 0; 28 + let mut consumed = 0; 18 29 let mut exited_cleanly = false; 19 30 20 - for tok in tokens { 21 - let c = tok.contents; 31 + while consumed < tokens.len() { 32 + let c = tokens[consumed].contents; 22 33 23 - in_token_count += 1; 34 + consumed += 1; 24 35 if c.is_whitespace() && !entered { 25 36 continue; 26 37 } ··· 34 45 break; 35 46 } 36 47 37 - if !quoted && tok.contents == ')' { 48 + if !quoted && c == ')' { 38 49 exited_cleanly = true; 39 50 if !arg.is_empty() { 40 51 args.push(arg.clone()); ··· 58 69 continue; 59 70 } 60 71 72 + if c == '$' && !escaped && !quoted { 73 + let ret = find_and_execute_lua_block(&tokens[consumed - 1..], proj_context, skid_context); 74 + if ret.is_some() { 75 + let (result, lua_consumed) = ret.unwrap(); 76 + consumed += std::cmp::max(lua_consumed, 1) - 1; 77 + 78 + for t in &result { 79 + arg.push(t.contents); 80 + } 81 + } 82 + else { 83 + println!("was none : ("); 84 + arg.push('$'); 85 + } 86 + continue; 87 + } 88 + 61 89 if c.is_whitespace() && !quoted { 62 90 if !arg.is_empty() { 63 91 args.push(arg.clone()); ··· 69 97 } 70 98 71 99 if !entered || !exited_cleanly { 100 + println!("was none but very bad : ("); 72 101 return None; 73 102 } 74 - return Some((args, in_token_count)); 103 + return Some((args, consumed)); 75 104 } 76 105 77 106 pub fn collect_block(tokens: &[Token]) -> Option<(Vec<Token>, usize)> { ··· 174 203 block.drain(..3); 175 204 block.drain(block.len() - 2..); 176 205 return Some((block, tokens_consumed)); 206 + } 207 + 208 + // Call this when you think it might be a lua block, ie $ is the current token's content 209 + // (Output, consumed) 210 + pub fn find_and_execute_lua_block( 211 + tokens: &[Token], 212 + proj_context: &mut Project, 213 + skid_context: &mut SkidContext, 214 + ) -> Option<(Vec<Token>, usize)> { 215 + if tokens.len() < 3 { 216 + return None; 217 + } 218 + if tokens[0].contents != '$' || tokens[1].contents != '[' { 219 + return None; 220 + } 221 + 222 + #[derive(PartialEq)] 223 + enum QuoteType { 224 + UnQuoted, 225 + DoubledQuoutes, 226 + SingleQuotes, 227 + // Lua also has [[...]] strings for multiline but we don't need to specially keep track of them 228 + } 229 + 230 + let mut quoted = QuoteType::UnQuoted; 231 + let mut escaped = false; 232 + let mut brackets = 0; 233 + let mut consumed: usize = 1; 234 + let mut exited_cleanly = false; 235 + // Look for the end of th $[] block 236 + for t in &tokens[1..] { 237 + consumed += 1; 238 + 239 + if quoted == QuoteType::UnQuoted && t.contents == '[' && !escaped { 240 + brackets += 1; 241 + continue; 242 + } 243 + 244 + if quoted == QuoteType::UnQuoted && t.contents == ']' && !escaped { 245 + brackets -= 1; 246 + if brackets == 0 { 247 + exited_cleanly = true; 248 + break; 249 + } 250 + continue; 251 + } 252 + 253 + if quoted == QuoteType::UnQuoted && t.contents == '"' && !escaped { 254 + quoted = QuoteType::DoubledQuoutes; 255 + continue; 256 + } 257 + 258 + if quoted == QuoteType::UnQuoted && t.contents == '\'' && !escaped { 259 + quoted = QuoteType::SingleQuotes; 260 + continue; 261 + } 262 + 263 + if quoted == QuoteType::DoubledQuoutes && t.contents == '"' && !escaped { 264 + quoted = QuoteType::UnQuoted; 265 + continue; 266 + } 267 + 268 + if quoted == QuoteType::SingleQuotes && t.contents == '\'' && !escaped { 269 + quoted = QuoteType::UnQuoted; 270 + continue; 271 + } 272 + 273 + if t.contents == '\\' && !escaped { 274 + escaped = true; 275 + continue; 276 + } 277 + 278 + if escaped { 279 + escaped = false; 280 + } 281 + } 282 + 283 + if !exited_cleanly { 284 + return None; 285 + } 286 + 287 + // Process embeded macros first 288 + let out = process_skid(&tokens[2..consumed - 1], proj_context, skid_context); 289 + let trimmed = trim_whitespace_tokens(&out); 290 + let mut string: String = "".to_string(); 291 + for t in trimmed { 292 + string.push(t.contents); 293 + } 294 + 295 + let ret: Result<mlua::Value, mlua::Error> = skid_context.lua.load(string).eval(); 296 + if ret.is_err() { 297 + error_skid( 298 + proj_context, 299 + tokens[0].origin_index, 300 + tokens[0].origin_line, 301 + &ret.err()?.to_string(), 302 + ); 303 + return None; 304 + } 305 + 306 + if ret.as_ref().unwrap().is_nil() { 307 + return Some((Vec::new(), consumed)); 308 + } 309 + 310 + let mut return_tokens = split_to_tokens(ret.unwrap().to_string().unwrap(), tokens[0].origin_index); 311 + for t in &mut return_tokens { 312 + t.pre_proccessed = true; 313 + } 314 + Some((return_tokens, consumed)) 177 315 } 178 316 179 317 // Theres no std function to have the delimiters be their own element in the out vector
+7 -3
src/types.rs
··· 1 1 use std::path::PathBuf; 2 2 3 + use mlua::Lua; 4 + 3 5 use crate::{ 4 6 console::error_skid, 5 7 macros::{simple_blocks::macro_comment, template::SkidTemplate}, ··· 30 32 31 33 pub struct SkidContext { 32 34 pub templates: Vec<SkidTemplate>, 33 - pub file_index: usize, 35 + pub file_id: usize, 36 + pub lua: Lua, 34 37 } 35 38 36 39 impl SkidContext { 37 - pub fn new(file_index: usize) -> SkidContext { 40 + pub fn new(file_id: usize) -> SkidContext { 38 41 SkidContext { 39 42 templates: Vec::new(), 40 - file_index, 43 + file_id, 44 + lua: Lua::new(), 41 45 } 42 46 } 43 47 }