Tholp's bespoke website generator

better errors and warns, fix escaping in blocks

Tholp1 db26e9ab c33bb7c2

+8 -8
src/macros/insert.rs
···
pub fn macro_insert(
_file: &mut InputFile,
-
_origin_index: usize,
+
origin_index: usize,
origin_line: usize,
-
_context: &mut ProjectContext,
+
context: &mut ProjectContext,
args: &Vec<String>,
_scope: &[Token],
) -> Vec<Token> {
-
let origin_file = _context
-
.file_for_index(_origin_index)
+
let origin_file = context
+
.file_for_index(origin_index)
.expect("Macro 'Insert' was given a bad origin index")
.clone();
if args.len() != 1 {
println!(
-
"{:?}:{} ;Insert only accepts 1 argument, got given {} ({:?})",
+
"[ERROR] {:?}:{} ;Insert only accepts 1 argument, got given {} ({:?})",
origin_file.to_str(),
origin_line,
args.len(),
···
}
if search_from_root {
-
let mut include_path = _context.input_folder.clone();
+
let mut include_path = context.input_folder.clone();
include_path.push(&arg);
if include_path.exists() && include_path.is_file() {
···
}
if !ok {
-
println!("\"{:?}\": Insert was unable to find the file \"{}\" relative to its origin or in project root.", origin_file.to_str(), arg);
+
println!("[ERROR] \"{:?}\": Insert was unable to find the file \"{}\" relative to its origin or in project root.", origin_file.to_str(), arg);
exit(1);
}
···
let split_output = split_keep_delimiters(output);
return strings_to_tokens(
split_output,
-
_context.index_of_file(&PathBuf::from(&include_file)),
+
context.index_of_file(&PathBuf::from(&include_file)),
);
}
+7 -2
src/macros/mod.rs
···
use super::types::Macro;
use insert::macro_insert;
-
use simple_blocks::{macro_comment, macro_section, macro_repeat};
+
use simple_blocks::{macro_comment, macro_repeat, macro_section, macro_skip};
use simple_macros::{macro_clear, macro_time};
use template::macro_template;
-
pub static MACRO_LIST: [Macro<'_>; 7] = [
+
pub static MACRO_LIST: &'static [Macro<'_>] = &[
// Unscoped
Macro {
symbol: "insert", // Inserts another file
···
Macro {
symbol: "template",
expand: macro_template,
+
has_scope: true,
+
},
+
Macro {
+
symbol: "skip",
+
expand: macro_skip,
has_scope: true,
},
];
+1 -2
src/macros/simple_blocks.rs
···
return tokens;
}
-
pub fn macro_preformatted(
+
pub fn macro_skip(
_file: &mut InputFile,
_origin_index: usize,
_origin_line: usize,
···
_args: &Vec<String>,
scope: &[Token],
) -> Vec<Token> {
-
Vec::new()
}
+5 -5
src/macros/template.rs
···
for t in &file.templates {
if t.symbol == args[0] {
println!(
-
"{:?}:{} ; Attempted template redefinition of \"{}\"",
+
"[ERROR] {:?}:{} ; Attempted template redefinition of \"{}\"",
context.file_for_index(origin_index).unwrap(),
origin_line,
args[0]
···
}
}
-
for t in &MACRO_LIST {
+
for t in MACRO_LIST {
if t.symbol == args[0] {
println!(
-
"{:?}:{} ; Attempted to make a template using a reserved name \"{}\"",
+
"[ERROR] {:?}:{} ; Attempted to make a template using a reserved name \"{}\"",
context.file_for_index(origin_index).unwrap(),
origin_line,
args[0]
···
}
if param.contains_whitespace() {
println!(
-
"{:?}:{} ; Attempted to make a template with a parameter that contains whitespace \"{}\"",
+
"[ERROR] {:?}:{} ; Attempted to make a template with a parameter that contains whitespace \"{}\"",
context.file_for_index(origin_index).unwrap(),
origin_line,
param
···
if used_params < args.len() - 1 {
println!(
-
"{:?}:{} ; Template definition of \"{}\" has {} paramters but only uses {}",
+
"[ERROR] {:?}:{} ; Template definition of \"{}\" has {} paramters but only uses {}",
context.file_for_index(origin_index).unwrap(),
origin_line,
args[0],
+35 -9
src/main.rs
···
};
use types::{InputFile, Macro, Token};
-
static DELIMITERS: [char; 12] = [
-
' ', '\n', '\t', '(', ')', '{', '}', '[', ']', '\\', '\'', '\"',
+
static DELIMITERS: &'static [char] = &[
+
' ', '\n', '\t', '(', ')', '{', '}', '[', ']', '\\', '\'', '\"', ';',
];
fn main() {
···
while !project_path.exists() || project_path.is_dir() {
let ok = project_folder.pop();
if !ok {
-
println!("No skidmark.toml project file found in this folder or ancestors.");
+
println!("[ERROR] No skidmark.toml project file found in this folder or ancestors.");
exit(1);
}
project_path = project_folder.clone();
···
while file.working_index < file.tokens.len() {
//look for macros or blocks
//println!(">\"{}\"<", file.tokens[file.working_index].contents);
+
+
if file.tokens[file.working_index].contents.len() == 0 {
+
file.working_index += 1;
+
continue;
+
}
if file.tokens[file.working_index].contents == "\\" {
+
file.tokens[file.working_index].contents = "".into();
file.working_index += 2;
+
//println!("Hit backslash");
continue;
}
···
}
// Check if its a macro
-
for m in &MACRO_LIST {
+
for m in MACRO_LIST {
if &symbol[prefix_len..] == m.symbol {
matched_macro = true;
//println!("Found a macro ({})", m.symbol);
···
collect_arguments(&file.tokens[file.working_index..]);
let expansion: Vec<Token>;
let block_tokcount: usize;
-
if m.has_scope {
//println!("is scoped.");
-
let block: Vec<Token>;
-
(block, block_tokcount) =
+
+
let block_opt =
collect_block(&file.tokens[(file.working_index + args_tokcount)..]);
+
if block_opt.is_none() {
+
println!(
+
"[ERROR] {:?}:{} ;Malformed block",
+
file.tokens[file.working_index].origin_file,
+
file.tokens[file.working_index].line_number
+
);
+
exit(1);
+
}
+
let block: Vec<Token>;
+
(block, block_tokcount) = block_opt.unwrap();
if ephemeral {
expansion = Vec::new();
···
if m.has_scope {
//println!("is scoped.");
let block: Vec<Token>;
-
(block, block_tokcount) =
+
let block_opt =
collect_block(&file.tokens[(file.working_index + args_tokcount)..]);
+
if block_opt.is_none() {
+
println!(
+
"[ERROR] {:?}:{} ;Malformed block",
+
file.tokens[file.working_index].origin_file,
+
file.tokens[file.working_index].line_number
+
);
+
exit(1);
+
}
+
+
(block, block_tokcount) = block_opt.unwrap();
if ephemeral {
expansion = Vec::new();
···
.unwrap();
fs::write(&file.file_htmlout, &html_output).expect("Couldn't write html to file");
print!(
-
"{} written.\n\n",
+
"[OK] {} written.\n\n",
file.file_htmlout
.to_str()
.unwrap_or("Couldnt Unwrap htmlout name")
+41 -19
src/stringtools.rs
···
return (args, in_token_count);
}
-
pub fn collect_block(tokens: &[Token]) -> (Vec<Token>, usize) {
+
pub fn collect_block(tokens: &[Token]) -> Option<(Vec<Token>, usize)> {
let mut entered = false;
let mut tokens_consumed: usize = 0;
let mut entering_bracket_count = 0;
···
// We dont really care about doing anything that in the block right now
// maybe have the Token struct contain scope level later?
+
let mut escaped_tok: Token = Token::new("\\".into(), 0, 0);
for tok in tokens {
tokens_consumed += 1;
if !entered {
···
// print!("{} ", t.contents);
// }
// exit(1);
-
return (Vec::new(), 0);
+
return None;
}
}
-
if escaped {
-
escaped = false;
-
entering_bracket_count = 0;
-
exiting_bracket_count = 0;
-
block.push(tok.clone());
-
continue;
-
}
+
let mut escaped_used = false;
// Scope Start
-
if tok.contents == "{" {
+
if tok.contents == "{" && !escaped {
entering_bracket_count += 1;
if entering_bracket_count == 3 {
···
}
} else {
entering_bracket_count = 0;
+
if escaped {
+
escaped_used = true;
+
}
}
// Scope End
-
if tok.contents == "}" {
+
if tok.contents == "}" && !escaped {
exiting_bracket_count += 1;
if exiting_bracket_count == 3 {
scope_count -= 1;
···
}
} else {
exiting_bracket_count = 0;
+
if escaped {
+
escaped_used = true;
+
}
+
}
+
+
if escaped_used {
+
escaped = false;
+
block.push(escaped_tok.clone());
}
if tok.contents == "\\" {
escaped = true;
+
escaped_tok = tok.clone();
} else {
block.push(tok.clone());
}
}
+
if scope_count != 0 {
+
return None;
+
}
+
// if block.len() == 6
// // things get ugly if its empty
// {
···
// pop brackets, bad and ugly but idgaf
block.drain(..3);
block.drain(block.len() - 3..);
-
return (block, tokens_consumed);
+
return Some((block, tokens_consumed));
}
// Theres no std function to have the delimiters be their own element in the out vector
···
output.push(token.to_string());
}
output.push(ending.to_string());
+
//println!("({}, {})", token.to_string(), ending.to_string())
} else {
output.push(s.to_string());
}
···
let mut line_count = 1;
for str in in_strings {
+
if str.len() == 0 {
+
continue;
+
}
+
let current_line = line_count;
for char in str.chars() {
if char == '\n' {
···
let split = split_keep_delimiters(instr);
let mut new_split: Vec<String> = Vec::new();
for s in split {
-
let prefix_offset = s.find(&['!', '&']).unwrap_or(s.len() + 1);
-
if prefix_offset != 0 && prefix_offset != s.len() + 1 {
-
let (first, second) = s.split_at(prefix_offset);
-
println!("\"{}\", \"{}\"", first, second);
-
new_split.push(first.to_string());
-
new_split.push(second.to_string());
+
let prefix_offset = s.find(&['!', '&']);
+
if prefix_offset.is_some() {
+
let (first, second) = s.split_at(prefix_offset.unwrap());
+
//println!("\"{}\", \"{}\"", first, second);
+
if first.len() > 0 {
+
new_split.push(first.to_string());
+
}
+
if second.len() > 0 {
+
new_split.push(second.to_string());
+
}
} else {
-
new_split.push(s);
+
if s.len() > 0 {
+
new_split.push(s);
+
}
}
//sleep(std::time::Duration::from_millis(10));
}