Tholp's bespoke website generator

more filegroup options, basic universal macro arg count error checking

Tholp1 141d8a02 29599d68

+31 -11
src/macros/mod.rs
···
use simple_macros::{macro_clear, macro_filename, macro_filename_canonical, macro_time};
use template::macro_template;
-
pub static MACRO_LIST: &'static [Macro<'_>] = &[
+
pub static MACRO_LIST: &'static [Macro] = &[
// Unscoped
Macro {
symbol: "insert", // Inserts another file
-
expand: macro_insert,
+
expansion: macro_insert,
has_scope: false,
+
min_args: 1,
+
max_args: 1,
},
Macro {
symbol: "clear", // Clears text buffer
-
expand: macro_clear,
+
expansion: macro_clear,
has_scope: false,
+
min_args: 0,
+
max_args: 0,
},
Macro {
symbol: "time",
-
expand: macro_time,
+
expansion: macro_time,
has_scope: false,
+
min_args: 1,
+
max_args: 1,
},
Macro {
symbol: "filename",
-
expand: macro_filename,
+
expansion: macro_filename,
has_scope: false,
+
min_args: 0,
+
max_args: 0,
},
Macro {
symbol: "filename_canonical",
-
expand: macro_filename_canonical,
+
expansion: macro_filename_canonical,
has_scope: false,
+
min_args: 0,
+
max_args: 0,
},
// Scoped
Macro {
symbol: "comment", // Nothing
-
expand: macro_comment,
+
expansion: macro_comment,
has_scope: true,
+
min_args: 0,
+
max_args: 0,
},
Macro {
symbol: "repeat", // Outputs what its give x number of times
-
expand: macro_repeat,
+
expansion: macro_repeat,
has_scope: true,
+
min_args: 1,
+
max_args: 1,
},
Macro {
symbol: "section",
-
expand: macro_section,
+
expansion: macro_section,
has_scope: true,
+
min_args: 0,
+
max_args: 1,
},
Macro {
symbol: "template",
-
expand: macro_template,
+
expansion: macro_template,
has_scope: true,
+
min_args: 1,
+
max_args: usize::max_value(),
},
Macro {
symbol: "for_each_arg",
-
expand: macro_for_each_arg,
+
expansion: macro_for_each_arg,
has_scope: true,
+
min_args: 1,
+
max_args: usize::max_value(),
},
];
+4 -4
src/macros/simple_blocks.rs
···
let replacement = split_to_tokens(arg.clone(), origin_index);
arg_output.splice(start..start + len, replacement);
found_pattern = find_pattern(&arg_output, format!("[[..{}]]", replacement_index + 1));
-
println!("{}", replacement_index + 1);
+
//println!("{}", replacement_index + 1);
}
-
println!("{} {}", replacement_index, replacement_count);
+
//println!("{} {}", replacement_index, replacement_count);
replacement_index += 1;
if replacement_index == replacement_count {
replacement_index = 0;
output.append(&mut arg_output.trim_whitespace().into());
arg_output = block.clone();
-
println!("push");
+
//println!("push");
}
-
println!("test");
+
//println!("test");
}
return output;
+8 -8
src/macros/template.rs
···
args_index += 1;
}
-
let mut found_block_pattern = find_pattern(&output, "[[{}]]".into());
-
while found_block_pattern.is_some() {
-
let (start, len) = found_block_pattern.unwrap();
-
let replacement = scope.to_vec();
-
output.splice(start..start + len, replacement);
-
found_block_pattern = find_pattern(&output, "[[{}]]".into());
-
}
-
//replace [[..]] with space seperated remaining args
let mut found_trailing_pattern = find_pattern(&output, "[[..]]".into());
while found_trailing_pattern.is_some() {
···
}
output.splice(start..start + len, replacement);
found_trailing_pattern = find_pattern(&output, "[[\"..\"]]".into());
+
}
+
+
let mut found_block_pattern = find_pattern(&output, "[[{}]]".into());
+
while found_block_pattern.is_some() {
+
let (start, len) = found_block_pattern.unwrap();
+
let replacement = scope.to_vec();
+
output.splice(start..start + len, replacement);
+
found_block_pattern = find_pattern(&output, "[[{}]]".into());
}
output
+49 -35
src/main.rs
···
use console::*;
use macros::MACRO_LIST;
use markdown::{to_html_with_options, CompileOptions, Constructs, Options, ParseOptions};
-
use projectparse::{parse_project, FileIndexing, ProjectContext};
+
use projectparse::{parse_project, FileGroup, FileIndexing, ProjectContext};
use std::{
-
env,
+
convert, env,
fs::{self, File},
io::Write,
path::PathBuf,
···
trim_whitespace_tokens,
};
use types::{InputFile, Macro, Token};
+
+
use crate::types::Expand;
static DELIMITERS: &'static [char] = &[
' ', '\n', '\t', '(', ')', '{', '}', '[', ']', '<', '>', '\\', '\'', '\"', ';',
···
println!("Proccesing {} files.", num);
for group in &mut project.filegroups {
for infile in &mut group.files {
-
process_file(infile, &mut project.context);
+
process_file(infile, group.convert_html, &mut project.context);
}
}
}
-
fn process_file(file: &mut InputFile, context: &mut ProjectContext) {
+
fn process_file(file: &mut InputFile, convert_html: bool, context: &mut ProjectContext) {
//}, context: &mut ProjectContext) {
let contents = fs::read_to_string(&file.file_input).expect("File unreadable or missing");
//println!("{}\n {}", f.filename_out, contents);
···
if ephemeral {
expansion = Vec::new();
} else {
-
expansion = (m.expand)(
+
expansion = m.expand(
file,
file.tokens[file.working_index].origin_file,
file.tokens[file.working_index].line_number,
···
if ephemeral {
expansion = Vec::new();
} else {
-
expansion = (m.expand)(
+
expansion = m.expand(
file,
file.tokens[file.working_index].origin_file,
file.tokens[file.working_index].line_number,
···
for t in &file.tokens {
skid_output += &t.contents;
}
-
fs::write(&file.file_skidout, &skid_output).expect("Couldn't write skid to file");
-
//let html_output = markdown::to_html(&skid_output);
-
let html_output = markdown::to_html_with_options(
-
&skid_output,
-
&Options {
-
compile: CompileOptions {
-
allow_dangerous_html: true,
-
allow_dangerous_protocol: true,
-
gfm_tagfilter: false,
-
// gfm_footnote_clobber_prefix:
-
gfm_task_list_item_checkable: true,
-
allow_any_img_src: true,
-
..CompileOptions::gfm()
-
},
-
parse: ParseOptions {
-
constructs: Constructs {
-
code_indented: false,
-
..Constructs::gfm()
+
if convert_html {
+
fs::write(&file.file_skidout, &skid_output).expect("Couldn't write skid to file");
+
+
//let html_output = markdown::to_html(&skid_output);
+
let html_output = markdown::to_html_with_options(
+
&skid_output,
+
&Options {
+
compile: CompileOptions {
+
allow_dangerous_html: true,
+
allow_dangerous_protocol: true,
+
gfm_tagfilter: false,
+
// gfm_footnote_clobber_prefix:
+
gfm_task_list_item_checkable: true,
+
allow_any_img_src: true,
+
..CompileOptions::gfm()
},
-
..ParseOptions::default()
+
parse: ParseOptions {
+
constructs: Constructs {
+
code_indented: false,
+
//html_flow: false,
+
..Constructs::gfm()
+
},
+
..ParseOptions::default()
+
},
},
-
},
-
)
-
.unwrap();
-
fs::write(&file.file_htmlout, &html_output).expect("Couldn't write html to file");
-
ok_generic(format!(
-
"\"{}\" written \n\n",
-
file.file_htmlout
-
.to_str()
-
.unwrap_or("Couldnt Unwrap htmlout name")
-
));
+
)
+
.unwrap();
+
fs::write(&file.file_out, &html_output).expect("Couldn't write output to file");
+
ok_generic(format!(
+
"\"{}\" written \n\n",
+
file.file_out
+
.to_str()
+
.unwrap_or("Couldnt Unwrap file_out name")
+
));
+
} else {
+
fs::write(&file.file_out, &skid_output).expect("Couldn't write output to file");
+
ok_generic(format!(
+
"\"{}\" written \n\n",
+
file.file_out
+
.to_str()
+
.unwrap_or("Couldnt Unwrap file_out name")
+
));
+
}
}
+12 -5
src/projectparse.rs
···
pub pre_insert: PathBuf,
pub post_insert: PathBuf,
pub process: bool,
+
pub convert_html: bool,
+
pub output_extention: String,
}
// pub struct ProjectSettings {
···
continue;
}
let filegroup_def: &toml::map::Map<String, toml::Value> = v.as_table().unwrap();
-
let name = k.clone();
+
let pre_insert = get_table_string_or_default!(filegroup_def, "preInsert", "");
let post_insert = get_table_string_or_default!(filegroup_def, "postInsert", "");
let process = get_table_bool_or_default!(filegroup_def, "process", false);
+
let convert_html = get_table_bool_or_default!(filegroup_def, "convertHTML", true);
+
let extention = get_table_string_or_default!(filegroup_def, "outputExtention", "html");
let recurse_find = get_table_bool_or_default!(filegroup_def, "recursiveFind", false);
···
pre_insert: pre_insert.into(),
post_insert: post_insert.into(),
process,
+
convert_html,
+
output_extention: extention.into(),
};
if filegroup_def.contains_key("files") {
···
k
)
});
+
let mut new_file = crate::types::InputFile::new();
new_file.file_input = project.context.input_folder.clone();
new_file.file_input.push(filename);
-
new_file.file_htmlout = project.context.output_folder.clone();
-
new_file.file_htmlout.push(filename);
-
new_file.file_htmlout.set_extension("html");
+
new_file.file_out = project.context.output_folder.clone();
+
new_file.file_out.push(filename);
+
new_file.file_out.set_extension(extention);
-
new_file.file_skidout = new_file.file_htmlout.clone();
+
new_file.file_skidout = new_file.file_out.clone();
new_file.file_skidout.set_extension("sko");
group.files.push(new_file);
+3
src/stringtools.rs
···
pub fn find_pattern(tokens: &[Token], pat: String) -> Option<(usize, usize)> {
// (startpoint, length)
+
// FIXME: this fucks up when the begining of a pattern is repeated
+
// ex. searching for "[[hello]]" in "[[[[hello]]" yeilds None
+
// ALSO, this is a coarse search, operating on tokens only, not the characters within
let split_pattern = split_to_tokens(pat, 0);
let mut pattern_index: usize = 0;
let mut token_index: usize = 0;
+56 -6
src/types.rs
···
use std::path::PathBuf;
-
use crate::{macros::template::SkidTemplate, projectparse::ProjectContext};
+
use crate::{
+
console::error_skid,
+
macros::{simple_blocks::macro_comment, template::SkidTemplate},
+
projectparse::ProjectContext,
+
};
pub struct Token {
pub contents: String,
···
pub struct InputFile {
pub file_input: PathBuf,
pub file_skidout: PathBuf,
-
pub file_htmlout: PathBuf,
+
pub file_out: PathBuf,
pub tokens: Vec<Token>,
pub working_index: usize,
pub templates: Vec<SkidTemplate>,
···
// _scope: &[Token],
// ) -> Vec<Token>
-
pub struct Macro<'a> {
-
pub symbol: &'a str,
-
pub expand: MacroExpansion,
+
pub struct Macro {
+
pub symbol: &'static str,
+
pub expansion: MacroExpansion,
pub has_scope: bool, //takes blocks of text input as well as parameters using {{...}}
+
pub min_args: usize,
+
pub max_args: usize,
+
}
+
+
pub trait Expand {
+
fn expand(
+
&self,
+
input_file: &mut InputFile,
+
origin_index: usize,
+
origin_line: usize,
+
context: &mut ProjectContext,
+
args: &Vec<String>,
+
scope: &[Token],
+
) -> Vec<Token>;
+
+
fn default() -> Macro;
+
}
+
+
impl Expand for Macro {
+
fn expand(
+
&self,
+
input_file: &mut InputFile,
+
origin_index: usize,
+
origin_line: usize,
+
context: &mut ProjectContext,
+
args: &Vec<String>,
+
scope: &[Token],
+
) -> Vec<Token> {
+
if (args.len() > self.max_args) || (args.len() < self.min_args) {
+
error_skid(context, origin_index, origin_line, format!("Macro \'{}\' was given a number of arguments ({}) not in its acceptable range ({}-{})",
+
self.symbol, args.len(), self.min_args, if self.max_args == usize::max_value() {"No Limit".to_string()} else {format!("{}", self.max_args)}));
+
Vec::new()
+
} else {
+
(self.expansion)(input_file, origin_index, origin_line, context, args, scope)
+
}
+
}
+
+
fn default() -> Macro {
+
Macro {
+
symbol: "default_symbol",
+
expansion: macro_comment,
+
has_scope: true,
+
min_args: 0,
+
max_args: usize::max_value(),
+
}
+
}
}
impl InputFile {
···
InputFile {
file_input: "".into(),
file_skidout: "".into(),
-
file_htmlout: "".into(),
+
file_out: "".into(),
tokens: Vec::new(),
working_index: 0,
templates: Vec::new(),