From 96c6c8d94d7c6cb142164e426e967c67a96960c5 Mon Sep 17 00:00:00 2001 From: quirinecker Date: Sun, 12 Mar 2023 23:13:08 +0100 Subject: [PATCH] refactored building of documents --- src/app/{builder => build}/asciidoctor.rs | 62 ++++----- src/app/build/mod.rs | 55 ++++++++ src/app/builder/mod.rs | 5 - .../commands/executions/build_execution.rs | 130 +++++------------- src/app/commands/serve.rs | 17 +-- src/app/fs_util/mod.rs | 1 + src/app/mod.rs | 2 +- 7 files changed, 119 insertions(+), 153 deletions(-) rename src/app/{builder => build}/asciidoctor.rs (63%) create mode 100644 src/app/build/mod.rs delete mode 100644 src/app/builder/mod.rs diff --git a/src/app/builder/asciidoctor.rs b/src/app/build/asciidoctor.rs similarity index 63% rename from src/app/builder/asciidoctor.rs rename to src/app/build/asciidoctor.rs index e18b680..f3a17c5 100644 --- a/src/app/builder/asciidoctor.rs +++ b/src/app/build/asciidoctor.rs @@ -2,8 +2,6 @@ use std::process; use regex::Regex; -use super::Builder; - fn exec_command(command: &mut process::Command) -> Result<(), String> { let result = command.output(); @@ -11,11 +9,13 @@ fn exec_command(command: &mut process::Command) -> Result<(), String> { if success.stderr.len() == 0 { return Ok(()); } else { - return Err(AsciiDoctorDocsBuilder::from_utf8(success.stderr)); + return Err(from_utf8(success.stderr)); } } else { println!("{}", result.unwrap_err()); - return Err("asciidoctor not installed. For more information run docki health!".to_string()); + return Err( + "asciidoctor not installed. For more information run docki health!".to_string(), + ); } } @@ -50,30 +50,34 @@ fn parent_path(child_path: &str) -> String { } pub fn path_between(from: String, to: String) -> String { - let from_segments = transform_input_to_clone_split(&from); + let from_segments = transform_input_to_clone_split(&from); let to_segments = transform_input_to_clone_split(&to); let last_matching_index = matching_from_start(&from_segments, &to_segments); let number_of_backs = from_segments.len() - last_matching_index; let mut path_between = path_back(number_of_backs); let path_to_to_path = &to_segments[last_matching_index..]; path_between.push_str(&path_to_to_path.join("/")); - return path_between; + return path_between; } fn transform_input_to_clone_split(input: &String) -> Vec { let regex = Regex::new(r"/$").unwrap(); let first_transformation = input.clone().replace("./", ""); - return regex.replace_all(&first_transformation, "") - .to_string().split("/") + return regex + .replace_all(&first_transformation, "") + .to_string() + .split("/") .collect::>() - .iter().map(|s| s.to_string()).collect() + .iter() + .map(|s| s.to_string()) + .collect(); } fn path_back(count: usize) -> String { let mut path = "".to_string(); - for _ in 0..count { - path.push_str("../"); + for _ in 0..count { + path.push_str("../"); } return path; @@ -81,8 +85,8 @@ fn path_back(count: usize) -> String { pub fn matching_from_start(from_segments: &Vec, to_segments: &Vec) -> usize { for (index, from_segment) in from_segments.iter().enumerate() { - if let Some(to_segment) = to_segments.get(index){ - if from_segment != to_segment { + if let Some(to_segment) = to_segments.get(index) { + if from_segment != to_segment { return index; } } else { @@ -93,29 +97,19 @@ pub fn matching_from_start(from_segments: &Vec, to_segments: &Vec Result<(), String> { - let mut command = asciidoctor_docs(in_path, out_path); - return exec_command(&mut command); - } +pub fn build_doc(in_path: &str, out_path: &str) -> Result<(), String> { + let mut command = asciidoctor_docs(in_path, out_path); + return exec_command(&mut command); } -impl AsciiDoctorDocsBuilder { - fn from_utf8(input: Vec) -> String { - return match String::from_utf8(input) { - Ok(m) => m, - Err(e) => panic!("could not print error message: {}", e), - }; - } +pub fn build_slide(in_path: &str, out_path: &str) -> Result<(), String> { + let mut command = asciidoctor_slides(in_path, out_path); + return exec_command(&mut command); } -pub struct AsciiDoctorSlideBuilder; - -impl Builder for AsciiDoctorSlideBuilder { - fn build(&self, in_path: &str, out_path: &str) -> Result<(), String> { - let mut command = asciidoctor_slides(in_path, out_path); - return exec_command(&mut command); - } +fn from_utf8(input: Vec) -> String { + return match String::from_utf8(input) { + Ok(m) => m, + Err(e) => panic!("could not print error message: {}", e), + }; } diff --git a/src/app/build/mod.rs b/src/app/build/mod.rs new file mode 100644 index 0000000..5ff595a --- /dev/null +++ b/src/app/build/mod.rs @@ -0,0 +1,55 @@ +use std::fs; + +use self::asciidoctor::{build_doc, build_slide}; + +use super::fs_util; + +pub mod asciidoctor; + +pub trait Builder { + fn build(&self, in_path: &str, out_path: &str) -> Result<(), String>; +} + +pub fn docki_build(in_path: &str) -> DockiBuildResult { + let out_path = in_path.replace("/docs/", "/dist/"); + let convert_out_path = out_path.replace(".adoc", ".html"); + + if in_path.starts_with("./docs/slides/") && in_path.ends_with(".adoc") { + if let Err(err) = build_slide(&in_path, &convert_out_path) { + return DockiBuildResult::Err(err); + } + + DockiBuildResult::Slide(convert_out_path) + } else if in_path.ends_with(".adoc") { + if let Err(err) = build_doc(&in_path, &convert_out_path) { + return DockiBuildResult::Err(err); + } + + DockiBuildResult::Doc(convert_out_path) + } else { + if let Err(err) = copy(&in_path, &out_path) { + return DockiBuildResult::Err(err); + } + + DockiBuildResult::Copy(out_path) + } +} + +fn copy(in_path: &str, out_path: &str) -> Result<(), String> { + let segments: &Vec<&str> = &out_path.split("/").collect(); + let parent_dir = &segments[0..segments.len() - 1].join("/"); + fs_util::create_dir_recursive(parent_dir); + + if let Err(err) = fs::copy(in_path, out_path) { + return Err(err.to_string()) + } + + Ok(()) +} + +pub enum DockiBuildResult { + Slide(String), + Doc(String), + Copy(String), + Err(String), +} diff --git a/src/app/builder/mod.rs b/src/app/builder/mod.rs deleted file mode 100644 index 6f4cdff..0000000 --- a/src/app/builder/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod asciidoctor; - -pub trait Builder { - fn build(&self, in_path: &str, out_path: &str) -> Result<(), String>; -} diff --git a/src/app/commands/executions/build_execution.rs b/src/app/commands/executions/build_execution.rs index 8604cc0..f30cc92 100644 --- a/src/app/commands/executions/build_execution.rs +++ b/src/app/commands/executions/build_execution.rs @@ -1,18 +1,16 @@ -use std::{fs, path::{Path, PathBuf}, io::Cursor}; +use std::{ + io::Cursor, + path::PathBuf +}; use crate::app::{ - builder::{ - asciidoctor::{AsciiDoctorDocsBuilder, AsciiDoctorSlideBuilder}, - Builder, - }, + build::{docki_build, DockiBuildResult}, fs_util, }; pub struct BuildExecution { progress: usize, goal: usize, - doc_builder: Box, - slide_builder: Box, } impl BuildExecution { @@ -20,95 +18,35 @@ impl BuildExecution { return BuildExecution { progress: 0, goal: 0, - slide_builder: Box::new(AsciiDoctorSlideBuilder {}), - doc_builder: Box::new(AsciiDoctorDocsBuilder {}), }; } pub async fn execute(&mut self) -> Result<(), String> { let path = "./docs/".to_string(); - if !Self::directory_exists(&path) { - return Err("docs directory does not exist it. Create it or use the template".to_string()) + if !fs_util::directory_exists(&path) { + return Err( + "docs directory does not exist it. Create it or use the template".to_string(), + ); } if let Err(error) = Self::prepare().await { return Err(error); - } + } return self.build_dir(&path); } - fn build_file( - &self, - builder: &Box, - in_path: &str, - out_path: &str, - ) -> Result<(), String> { - return builder.build(&in_path, &out_path); - } - - fn build_file_and_status( - &self, - builder: &Box, - in_path: &str, - out_path: &str, - conversion_type: &str, - ) { - let result = self.build_file(builder, in_path, out_path); - if result.is_ok() { - self.display_status(in_path, out_path, conversion_type) - } else { - self.display_status(in_path, out_path, "error"); - let error = result.unwrap_err(); - println!("{error}"); - } - } - - fn copy(&self, in_path: &str, out_path: &str) { - let segments: &Vec<&str> = &out_path.split("/").collect(); - let parent_dir = &segments[0..segments.len() - 1].join("/"); - Self::create_dir_recursive(parent_dir); - let result = fs::copy(in_path, out_path); - if result.is_ok() { - self.display_status(in_path, out_path, "copy"); - } else { - self.display_status(in_path, out_path, "error"); - let error = result.unwrap_err(); - println!("{error}"); - } - } - - fn create_dir_recursive(path: &str) { - let mut validated_path = "./".to_string(); - for segment in path.split("/") { - validated_path.push_str(format!("{segment}/").as_str()); - if !Self::directory_exists(&validated_path) { - fs::create_dir(&validated_path).unwrap() - } - } - } - - fn display_status(&self, in_path: &str, out_path: &str, conversion_type: &str) -> () { - println!( - "({} / {}) [{}] {} -> {}", - self.progress, self.goal, conversion_type, in_path, out_path - ); - } - - fn build_doc(&self, in_path: &str, out_path: &str) { - self.build_file_and_status(&self.doc_builder, in_path, out_path, "doc"); - } async fn prepare() -> Result<(), String> { let reveal_version = "3.9.2"; let target = format!("https://github.com/hakimel/reveal.js/archive/{reveal_version}.zip"); - let Ok(response) = reqwest::blocking::get(target) else { + let Ok(response) = reqwest::get(target).await else { return Err("could not downlaod revealjs".to_string()) }; - let Ok(bytes) = response.bytes() else { + let Ok(bytes) = response.bytes().await else { return Err("could not extract bytes".to_string()) }; @@ -118,15 +56,7 @@ impl BuildExecution { return Err("could not write extracted archive to disk".to_string()); } - return Ok(()) - } - - fn build_slide(&self, in_path: &str, out_path: &str) { - self.build_file_and_status(&self.slide_builder, in_path, out_path, "slide"); - } - - fn directory_exists(path: &String) -> bool { - Path::new(path).is_dir() + return Ok(()); } fn build_dir(&mut self, path: &str) -> Result<(), String> { @@ -136,28 +66,30 @@ impl BuildExecution { return Err(result.unwrap_err()) }; - for (index, path) in paths.iter().enumerate() { + for (index, in_path) in paths.iter().enumerate() { self.progress = index + 1; self.goal = paths.len(); + let result = docki_build(&in_path); - if path.ends_with(".adoc") && path.starts_with("./docs/slides") { - let out_path = path - .clone() - .replace("adoc", "html") - .replace("/docs/", "/dist/"); - self.build_slide(&path, &out_path) - } else if path.ends_with(".adoc") { - let out_path = path - .clone() - .replace("adoc", "html") - .replace("/docs/", "/dist/"); - self.build_doc(&path, &out_path) - } else { - let out_path = path.clone().replace("/docs/", "/dist/"); - self.copy(&path, &out_path) + match result { + DockiBuildResult::Err(err) => { + self.display_status("Error", in_path, ""); + println!("{}", err) + }, + DockiBuildResult::Copy(out_path) => self.display_status("Copy", &in_path, &out_path), + DockiBuildResult::Slide(out_path) => self.display_status("Slide", &in_path, &out_path), + DockiBuildResult::Doc(out_path) => self.display_status("Doc", &in_path, &out_path) } } return Ok(()); } + + fn display_status(&self, status_type: &str, in_path: &str, out_path: &str) -> () { + println!( + "({} / {}) [{}] {} -> {}", + self.progress, self.goal, status_type, in_path, out_path + ); + } + } diff --git a/src/app/commands/serve.rs b/src/app/commands/serve.rs index b1475d5..cdff8f7 100644 --- a/src/app/commands/serve.rs +++ b/src/app/commands/serve.rs @@ -7,10 +7,7 @@ use notify::{ }; use std::{env, path::Path}; -use crate::app::{builder::{ - asciidoctor::{AsciiDoctorDocsBuilder, AsciiDoctorSlideBuilder}, - Builder, -}, watcher::watcher}; +use crate::app::{ watcher::watcher, build::docki_build}; pub async fn serve() { @@ -63,19 +60,11 @@ fn build_file(paths: Vec) -> Result<(), String> { .expect(invalid_path_message) .replace(¤t_dir(), "") .replace("/./", "./"); - let out_path = in_path - .replace("./docs/", "./dist/") - .replace(".adoc", ".html"); println!("{} {}", "[Rebuilding]".green(), in_path); - if in_path.starts_with("./docs/slides") { - let slide_builder = AsciiDoctorSlideBuilder {}; - slide_builder.build(&in_path, &out_path) - } else { - let doc_builder = AsciiDoctorDocsBuilder {}; - doc_builder.build(&in_path, &out_path) - } + docki_build(&in_path); + return Ok(()) } fn current_dir() -> String { diff --git a/src/app/fs_util/mod.rs b/src/app/fs_util/mod.rs index e01d58e..2c6799c 100644 --- a/src/app/fs_util/mod.rs +++ b/src/app/fs_util/mod.rs @@ -82,3 +82,4 @@ pub fn docki_path_env() -> String { let current = env::var("PATH").unwrap_or("".to_string()); return expand_path(format!("{}:~/.docki/", current)); } + diff --git a/src/app/mod.rs b/src/app/mod.rs index 2f01bea..b0c7416 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -1,5 +1,5 @@ mod commands; -pub mod builder; +pub mod build; pub mod fs_util; pub mod watcher; mod args;