use criterion::{black_box, criterion_group, criterion_main, Criterion};
-use metaforge::Options;
-pub fn build_site_benchmark(c: &mut Criterion) {
+pub fn build_file_benchmark(c: &mut Criterion) {
let dir = std::path::PathBuf::from("files/site")
.canonicalize()
.unwrap();
- let mut opts = Options::new();
+ let mut opts = metaforge::Options::new();
opts.root = dir.clone();
opts.source = dir.join("source");
opts.build = dir.join("build");
opts.pattern = dir.join("pattern");
opts.clean = true;
- todo!("implement with DirNode")
- // c.bench_function("build test site", |b| {
- // b.iter(|| build_site(black_box(&opts)))
- // });
+ let source = opts.source.join("benchmark.meta");
+
+ c.bench_function("build benchmark file", |b| {
+ b.iter(|| {
+ let string = std::fs::read_to_string(black_box(&source)).unwrap();
+ let file = metaforge::parse_file(string, black_box(&opts)).unwrap();
+ let mut path = opts
+ .build
+ .join(source.strip_prefix(black_box(&opts.source)).unwrap());
+ path.set_extension("html");
+ std::fs::write(path, metaforge::build_metafile(&file).unwrap()).unwrap();
+ })
+ });
}
-criterion_group!(benches, build_site_benchmark);
+criterion_group!(benches, build_file_benchmark);
criterion_main!(benches);
--- /dev/null
+use criterion::{black_box, criterion_group, criterion_main, Criterion};
+
+pub fn map_dir_benchmark(c: &mut Criterion) {
+ let dir = std::path::PathBuf::from("files/site")
+ .canonicalize()
+ .unwrap();
+
+ let mut opts = metaforge::Options::new();
+ opts.root = dir.clone();
+ opts.source = dir.join("source");
+ opts.build = dir.join("build");
+ opts.pattern = dir.join("pattern");
+ opts.clean = true;
+
+ c.bench_function("build benchmark file", |b| {
+ b.iter(|| {
+ let mut dir =
+ metaforge::DirNode::build(black_box(opts.source.clone()), black_box(&opts))
+ .unwrap();
+ let tmp = metaforge::MetaFile::new(black_box(&opts));
+ dir.map(&tmp).unwrap();
+ })
+ });
+}
+
+criterion_group!(benches, map_dir_benchmark);
+criterion_main!(benches);
--- /dev/null
+<body>
+ &{header}
+ ${bench_variable}
+ &{SOURCE}
+ &{footer}
+<body>
--- /dev/null
+@{
+ link.url = ['a.com','a.com','a.com','a.com','a.com','a.com','a.com','a.com','a.com','a.com']
+ link.title = ['a','a','a','a','a','a','a','a','a','a']
+}
+
+&{
+ list.item = 'bench'
+}
+
+&{list}
+
--- /dev/null
+<li>&{link}</li>
--- /dev/null
+#{ filetype = 'html' }
+
+${
+ var = 'variables'
+ inline = 'inline variables'
+ bench_variable = 'this is a really long variable that contains multiple lines
+ and other interesting features to test how well metaforge deals long variables
+ \t this is a list:
+ - to
+ - see
+ - how
+ - flexible
+ - variables
+ - are
+ pretty cool!'
+
+}
+
+@{
+ single = ['single value arrays']
+ footer.array = ['1','2','3','4','5','6','7','8','9','10']
+}
+
+&{
+ body = 'bench'
+ header = 'bench'
+ footer = 'bench'
+}
+
+# THIS IS THE BENCHMARK FILE FOR METAFORGE
+
+*it has __${var}* and @{single}__
+
+<p>Some inline html with ${inline}</p>
+
+-{comments before a line} ### Other Tests
+
+a bunch of symbols !@#$%^&*())_
+
+code blocks:
+```
+let f = "foo"
+```
pub fn build_metafile(file: &MetaFile) -> Result<String> {
let html = get_source_html(file, file.opts)?;
- let pattern = get_pattern("base", &file)?;
+ let pattern = get_pattern("base", file)?;
let mut base = parse_file(pattern, file.opts)?;
- base.merge(&file);
+ base.merge(file);
base.patterns.insert("SOURCE".to_string(), html);
let output = metafile_to_string(&base)?;
pub fn write_file(path: &Path, html: String, opts: &Options) -> Result<()> {
let dest = find_dest(path, opts)?;
// want newline to end file
- fs::write(&dest, html + "\n")?;
+ fs::write(dest, html + "\n")?;
Ok(())
}
let mut pattern = MetaFile::build(path, file.opts)?;
// copy over maps for expanding contained variables
- pattern.merge(&file);
+ pattern.merge(file);
metafile_to_string(&pattern)
}
-fn get_variable(key: &str, file: &MetaFile) -> Result<String> {
+fn get_variable(_key: &str, _file: &MetaFile) -> Result<String> {
todo!()
}
fn find_dest(path: &Path, opts: &Options) -> Result<PathBuf> {
let path = path.canonicalize()?;
- let path = opts.build.join(path.strip_prefix(&opts.source)?);
- let mut path = PathBuf::from(path);
-
+ let mut path = opts.build.join(path.strip_prefix(&opts.source)?);
path.set_extension("html");
Ok(path)
})
// make a hash map of [keys in source] -> [defined arrays]
.map(|key| {
- let y: String;
// concat array to pattern name to get key in HashMap
let name = file.name().unwrap();
let long_key = name + "." + key;
pub use metafile::*;
pub use options::*;
pub use parser::*;
+
+use clap::Parser;
+use color_eyre::Result;
+
+pub fn get_opts() -> Result<Options> {
+ let opts = Options::try_from(Opts::parse())?;
+
+ log!(
+ opts,
+ format!("cleaning build directory: {}", opts.build.display()),
+ 1
+ );
+ if opts.clean && opts.build.exists() {
+ std::fs::remove_dir_all(&opts.build)?;
+ }
+
+ if !opts.build.exists() {
+ std::fs::create_dir(&opts.build)?;
+ }
+
+ Ok(opts)
+}
+
+pub fn build_dir(opts: &Options) -> Result<()> {
+ let mut source = DirNode::build(opts.source.clone(), opts)?;
+
+ let global_init = MetaFile::new(&opts);
+
+ source.map(&global_init)?;
+
+ Ok(())
+}
-use clap::Parser;
-use color_eyre::Result;
-use metaforge::{log, Options, Opts};
-
-fn main() -> Result<()> {
+fn main() -> color_eyre::Result<()> {
color_eyre::install()?;
- let opts = Options::try_from(Opts::parse())?;
-
- log!(
- opts,
- format!("cleaning build directory: {}", opts.build.display()),
- 1
- );
- if opts.clean && opts.build.exists() {
- std::fs::remove_dir_all(&opts.build)?;
- }
-
- if !opts.build.exists() {
- std::fs::create_dir(&opts.build)?;
- }
+ let opts = metaforge::get_opts()?;
- todo!("implement DirNode chain")
+ metaforge::build_dir(&opts)
}
pub fn build(path: PathBuf, opts: &'a Options) -> Result<Self> {
let str = fs::read_to_string(&path)?;
let mut metafile = parse_file(str, opts)?;
- metafile.path = path.to_path_buf();
+ metafile.path = path;
metafile.opts = opts;
Ok(metafile)
}
pub fn name(&self) -> Result<String> {
if self.path.starts_with(&self.opts.source) {
+ // in source dir, we want the file name
let name = self.path.strip_prefix(&self.opts.source)?;
let name = name.to_string_lossy().to_string().replace('/', ".");
Ok(name)
} else {
+ // in pattern dir, we want the parent dir
let name = self.path.strip_prefix(&self.opts.pattern)?;
- let name = name.to_string_lossy().to_string().replace('/', ".");
+ let name = name
+ .parent()
+ .unwrap()
+ .to_string_lossy()
+ .to_string()
+ .replace('/', ".");
Ok(name)
}
}
let global = MetaFile::new(opts);
Ok(Self {
- path: path.to_path_buf(),
+ path,
opts,
global,
files,
// parses all contained files and directories and pushes
// parsed structures into the files and directories vectors
pub fn map(&mut self, global: &'a MetaFile) -> Result<()> {
- for f in fs::read_dir(&self.path)?.into_iter() {
+ for f in fs::read_dir(&self.path)? {
let file = f?.path();
if file.is_dir() {
#[grammar = "meta.pest"]
pub struct MetaParser;
-pub fn parse_file<'a>(file: String, opts: &'a Options) -> Result<MetaFile<'a>> {
+pub fn parse_file(file: String, opts: &Options) -> Result<MetaFile> {
let meta_source = MetaParser::parse(Rule::file, &file)
.wrap_err("parser error")?
.next()
fn map_source_map() {
test_str!(r#"${var='v'} Some text @{array = ['a']}"#);
}
+
+ #[test]
+ #[should_panic]
+ fn header_not_first() {
+ test_str!(r#"${v='v'} #{ type = 'html'} @{a=['a']}"#);
+ }
}