From f13d24bee095d9c99b115a6a0ed5d1f78fefba8a Mon Sep 17 00:00:00 2001 From: quirinecker Date: Tue, 24 Jan 2023 14:12:37 +0100 Subject: [PATCH] reworked code and added ability to build slides --- .gitignore | 1 - docs/core/functions.adoc | 0 docs/core/index.adoc | 0 docs/fail.txt | 0 docs/functions.adoc | 0 docs/index.adoc | 0 src/app/builder/asciidoctor.rs | 46 +++++++++----- src/app/commands/build.rs | 112 +++++++++++++++++---------------- src/app/fs_util/mod.rs | 74 ++++++++++++++++++++++ src/app/mod.rs | 1 + src/test/fs_util.rs | 9 +++ src/test/mod.rs | 15 +---- src/test/rx.rs | 13 ++++ 13 files changed, 187 insertions(+), 84 deletions(-) create mode 100644 docs/core/functions.adoc create mode 100644 docs/core/index.adoc create mode 100644 docs/fail.txt create mode 100644 docs/functions.adoc create mode 100644 docs/index.adoc create mode 100644 src/app/fs_util/mod.rs create mode 100644 src/test/fs_util.rs create mode 100644 src/test/rx.rs diff --git a/.gitignore b/.gitignore index 1733ca8..77fdd3e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ /target dist -docs diff --git a/docs/core/functions.adoc b/docs/core/functions.adoc new file mode 100644 index 0000000..e69de29 diff --git a/docs/core/index.adoc b/docs/core/index.adoc new file mode 100644 index 0000000..e69de29 diff --git a/docs/fail.txt b/docs/fail.txt new file mode 100644 index 0000000..e69de29 diff --git a/docs/functions.adoc b/docs/functions.adoc new file mode 100644 index 0000000..e69de29 diff --git a/docs/index.adoc b/docs/index.adoc new file mode 100644 index 0000000..e69de29 diff --git a/src/app/builder/asciidoctor.rs b/src/app/builder/asciidoctor.rs index 13b48b9..bf37e46 100644 --- a/src/app/builder/asciidoctor.rs +++ b/src/app/builder/asciidoctor.rs @@ -2,28 +2,34 @@ use std::process; use super::Builder; -pub struct AsciiDoctorBuilder; +fn asciidoctor(postfix: &str, in_path: &str, out_path: &str) -> Result<(), String> { + let result = process::Command::new(format!("asciidoctor{postfix}")) + .arg(format!("{in_path}")) + .arg(format!("--out-file={out_path}")) + .output(); -impl Builder for AsciiDoctorBuilder { - fn build(&self, in_path: &str, out_path: &str) -> Result<(), String> { - let result = process::Command::new("asciidoctor") - .arg(format!("{in_path}")) - .arg(format!("--out-file={out_path}")) - .output(); - - if let Ok(success) = result { - if success.stderr.len() == 0 { - return Ok(()); - } else { - return Err(AsciiDoctorBuilder::from_utf8(success.stderr)); - } + if let Ok(success) = result { + if success.stderr.len() == 0 { + return Ok(()); } else { - return Err("command failed to execute".to_string()); + println!("something went wrong"); + return Err(AsciiDoctorDocsBuilder::from_utf8(success.stderr)); } + } else { + println!("{}", result.unwrap_err()); + return Err("asciidoctor not installed. You may need to run docki setup!".to_string()); } } -impl AsciiDoctorBuilder { +pub struct AsciiDoctorDocsBuilder; + +impl Builder for AsciiDoctorDocsBuilder { + fn build(&self, in_path: &str, out_path: &str) -> Result<(), String> { + return asciidoctor("", in_path, out_path); + } +} + +impl AsciiDoctorDocsBuilder { fn from_utf8(input: Vec) -> String { return match String::from_utf8(input) { Ok(m) => m, @@ -31,3 +37,11 @@ impl AsciiDoctorBuilder { }; } } + +pub struct AsciiDoctorSlideBuilder; + +impl Builder for AsciiDoctorSlideBuilder { + fn build(&self, in_path: &str, out_path: &str) -> Result<(), String> { + return asciidoctor("-revealjs-linux", in_path, out_path); + } +} diff --git a/src/app/commands/build.rs b/src/app/commands/build.rs index 68d9f5e..7d43634 100644 --- a/src/app/commands/build.rs +++ b/src/app/commands/build.rs @@ -1,37 +1,54 @@ use std::{collections::HashMap, fs, path::Path}; -use crate::app::builder::{asciidoctor::AsciiDoctorBuilder, Builder}; +use crate::app::{ + builder::{asciidoctor::{AsciiDoctorDocsBuilder, AsciiDoctorSlideBuilder}, Builder}, + fs_util, + rx::Observable, +}; use super::traits::Command; pub struct Build { - builder: Box, + slides_builder: Box, + docs_builder: Box } impl Command for Build { fn execute(&self, _args: &HashMap) -> Result<(), String> { - let path = format!("./docs/"); - let mut error_count = 0; + let path = "./docs/".to_string(); - if !self.docs_directory_exists(&path) { - error_count += 1; - println!( - "docs directory does not exist. Either create it or clone the template from gitlab" - ) - } else { - for result in self.build_dir(&path) { - match result { - Err(e) => { - error_count += 1; - println!("{e}"); - } - Ok(()) => println!("success"), - }; - } + if !Self::docs_directory_exists(&path) { + return Self::docs_directory_missing(); } - if error_count > 0 { - return Err(format!("failed with {} errors", error_count)); + let result = fs_util::fetch_paths_recursive(&path, ".adoc"); + + let Ok(paths) = result else { + return Err(result.unwrap_err()) + }; + + for (index, path) in paths.iter().enumerate() { + if path.starts_with("./docs/slides") { + if self.build_slide(&path).is_ok() { + println!( + "({} / {}) {} -> {}", + index, + paths.len(), + path, + path.replace(".adoc", ".html") + ); + } + } else { + if self.build_doc(&path).is_ok() { + println!( + "({} / {}) {} -> {}", + index, + paths.len(), + path, + path.replace(".adoc", ".html") + ); + } + } } return Ok(()); @@ -42,51 +59,38 @@ impl Command for Build { Self: Sized, { return Build { - builder: Box::new(AsciiDoctorBuilder {}), + slides_builder: Box::new(AsciiDoctorSlideBuilder {}), + docs_builder: Box::new(AsciiDoctorDocsBuilder {}), }; } } impl Build { - fn build_dir(&self, path: &str) -> Vec> { - let mut results = vec![]; - let Ok(dirs) = fs::read_dir(path) else { - return vec![Err(format!("direcotry {path} was not found. The filesystem was maybe updated while build"))] - }; - - for result in dirs { - let Ok(entry) = result else { - return vec![Err("could not read entry".to_string())]; - }; - - let path = entry - .path() - .to_str() - .expect("could not get text path") - .to_string() - .clone(); - - if entry.path().is_dir() { - results = [results, self.build_dir(&path)].concat() - } else { - results.push(self.build_file(&path)); - } - } - - return results; - } - - fn build_file(&self, path: &str) -> Result<(), String> { + fn build_file(&self, builder: &Box, path: &str) -> Result<(), String> { let out_path = path .clone() .replace("docs", "dist") .replace(".adoc", ".html"); - return self.builder.build(&path, &out_path); + return builder.build(&path, &out_path); } - fn docs_directory_exists(&self, path: &String) -> bool { + fn build_doc(&self, path: &str) -> Result<(), String> { + return self.build_file(&self.docs_builder, path); + } + + fn build_slide(&self, path: &str) -> Result<(), String> { + return self.build_file(&self.slides_builder, path); + } + + fn docs_directory_exists(path: &String) -> bool { Path::new(path).is_dir() } -} + fn docs_directory_missing() -> Result<(), String> { + return Err( + "direcotry {path} was not found. The filesystem was maybe updated while build" + .to_string(), + ); + } +} diff --git a/src/app/fs_util/mod.rs b/src/app/fs_util/mod.rs new file mode 100644 index 0000000..320e3d4 --- /dev/null +++ b/src/app/fs_util/mod.rs @@ -0,0 +1,74 @@ +use std::fs; + +struct RecursivePathFetch { + paths: Vec, + ends_with: String, + path: String +} + +impl RecursivePathFetch { + pub fn new_with_extension_filter(path: String, ends_with: String) -> Self { + return Self { + paths: vec![], + ends_with, + path + } + } + + pub fn new(path: String) -> Self { + return Self { + paths: vec![], + ends_with: "".to_string(), + path + } + } + + pub fn fetch(&mut self) -> Result, String> { + if let Err(error) = self.read_dir(self.path.clone()) { + return Err(error); + } else { + return Ok(self.paths.clone()); + } + } + + fn read_dir(&mut self, path: String) -> Result<(), String> { + let Ok(entries) = fs::read_dir(path) else { + return self.dir_not_found(); + }; + + for result in entries { + let entry = result.unwrap(); + let path = entry.path(); + let str_path = path.to_str().unwrap(); + + if path.is_file() { + if str_path.ends_with(&self.ends_with) { + self.paths.push(str_path.to_string()) + } + } else if path.is_dir() { + let read_result = self.read_dir(str_path.to_string()); + if read_result.is_err() { + return read_result; + } + } + } + + return Ok(()) + } + + fn dir_not_found(&self) -> Result<(), String> { + return Err(format!( + "directory {} was not found or was changed while building", + self.path + )) + } +} + +pub fn fetch_paths_recursive(path: &str, ends_with: &str) -> Result, String> { + let mut path_fetch = RecursivePathFetch::new_with_extension_filter( + path.to_string(), + ends_with.to_string() + ); + + return path_fetch.fetch(); +} diff --git a/src/app/mod.rs b/src/app/mod.rs index 1452ddf..9c4bca5 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -1,6 +1,7 @@ mod commands; pub mod builder; pub mod rx; +pub mod fs_util; use std::collections::HashMap; diff --git a/src/test/fs_util.rs b/src/test/fs_util.rs new file mode 100644 index 0000000..fb58b33 --- /dev/null +++ b/src/test/fs_util.rs @@ -0,0 +1,9 @@ +use crate::app::fs_util; + +#[test] +fn test_fetch_asciidoctor_paths_recursive() { + let paths = fs_util::fetch_paths_recursive("docs", ".adoc").unwrap(); + let len = paths.len(); + dbg!(paths); + assert_eq!(len, 4); +} diff --git a/src/test/mod.rs b/src/test/mod.rs index 26d541e..758eddb 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -1,13 +1,2 @@ -use crate::app::rx::Observable; - -#[test] -fn test_observable() { - let mut observable: Observable = Observable::new(); - - observable.subscribe(|value| { - assert_eq!(5, value); - }); - - observable.next(5); -} - +mod rx; +mod fs_util; diff --git a/src/test/rx.rs b/src/test/rx.rs new file mode 100644 index 0000000..26d541e --- /dev/null +++ b/src/test/rx.rs @@ -0,0 +1,13 @@ +use crate::app::rx::Observable; + +#[test] +fn test_observable() { + let mut observable: Observable = Observable::new(); + + observable.subscribe(|value| { + assert_eq!(5, value); + }); + + observable.next(5); +} +