diff options
Diffstat (limited to 'src/new')
-rw-r--r-- | src/new/chapter.rs | 143 | ||||
-rw-r--r-- | src/new/mod.rs | 95 | ||||
-rw-r--r-- | src/new/project.rs | 111 | ||||
-rw-r--r-- | src/new/section.rs | 102 |
4 files changed, 143 insertions, 308 deletions
diff --git a/src/new/chapter.rs b/src/new/chapter.rs index 88f2a85..749202f 100644 --- a/src/new/chapter.rs +++ b/src/new/chapter.rs @@ -1,67 +1,108 @@ -use std::{ - fs::{self, File}, - io::{self, Write}, -}; +use std::{fs, path::Path}; use convert_case::{Case, Casing}; -use crate::data::Data; +use crate::{ + config_file::Config, + file_tree::{FileTree, GeneratedFile}, +}; -use super::{get_project_root, CHAPTER}; +pub fn generate_new_chapter( + config: Config, + project_root: &Path, + name: String, +) -> anyhow::Result<FileTree> { + let mut file_tree = FileTree::new(); + file_tree.add_file(new_main_file(project_root, &config, &name)?); + file_tree.add_file(new_chapter_file(&config, &name, project_root)); + file_tree.add_file(new_lpm_toml_file(config, name, project_root)); -pub fn generate_new_chapter(name: String) -> io::Result<()> { - let project_root = get_project_root().unwrap(); + Ok(file_tree) +} - let raw_data_file = fs::read_to_string(project_root.join("lpm.toml")).unwrap(); - let mut data_file: Data = toml::from_str(&raw_data_file).unwrap(); - let mut main_file = fs::read_to_string(project_root.join("main.tex")).unwrap(); +fn new_lpm_toml_file(mut config: Config, name: String, project_root: &Path) -> GeneratedFile { + config.last_chapter.user_name = name.to_case(Case::Snake); + config.last_chapter.number += 1; - fs::create_dir(project_root.join(format!("content/{}", name.to_case(Case::Snake),))).unwrap(); - let mut new_chapter = File::create(project_root.join(format!( - "content/{}/chapter_{:02}.tex", - name.to_case(Case::Snake), - data_file.last_chapter.number + 1 - ))) - .unwrap(); - new_chapter - .write_all(CHAPTER.replace("REPLACEMENT_CHAPTER", &name).as_bytes()) - .unwrap(); + GeneratedFile::new( + project_root.join("lpm.toml"), + toml::to_string(&config).expect("We changed it ourselfes, the conversion should work"), + ) +} - fs::create_dir(project_root.join(format!("content/{}/sections", name.to_case(Case::Snake),))) - .unwrap(); +fn new_chapter_file(config: &Config, name: &str, project_root: &Path) -> GeneratedFile { + let chapter_text = config + .templates + .chapter + .replace("REPLACEMENT_CHAPTER", &name); - main_file = main_file.replace( - &format!( - "\\includeonly{{content/{}/{}}}", - &data_file.last_chapter.user_name, - &format!("chapter_{:02}", data_file.last_chapter.number) - ), - &format!( - "\\includeonly{{content/{}/{}}}", - name.to_case(Case::Snake), - &format!("chapter_{:02}", data_file.last_chapter.number + 1) - ), - ); - let find_index = main_file.find("% NEXT_CHAPTER").unwrap(); - main_file.insert_str( + GeneratedFile::new( + project_root + .join("content") + .join(format! {"{:02}_{}", config.last_chapter.number + 1, name.to_case(Case::Snake)}) + .join("chapter.tex"), + chapter_text, + ) +} + +fn new_main_file( + project_root: &Path, + config: &Config, + name: &str, +) -> anyhow::Result<GeneratedFile> { + let mut main_text = fs::read_to_string(project_root.join("main.tex"))?; + + if &config.last_chapter.user_name == "static" && config.last_chapter.number == 0 { + // This is the first added chapter; The `\includeonly` will be empty. + main_text = main_text.replace( + "\\includeonly{}", + &format!( + "\\includeonly{{content/{}/{}}}", + &format!( + "{:02}_{}", + config.last_chapter.number + 1, + &name.to_case(Case::Snake) + ), + "chapter.tex", + ), + ) + } else { + main_text = main_text.replace( + &format!( + "\\includeonly{{content/{}/{}}}", + &format!( + "{:02}_{}", + config.last_chapter.number, &config.last_chapter.user_name + ), + "chapter.tex", + ), + &format!( + "\\includeonly{{content/{}/{}}}", + &format!( + "{:02}_{}", + config.last_chapter.number + 1, + &name.to_case(Case::Snake) + ), + "chapter.tex", + ), + ) + }; + + let find_index = main_text + .find("% NEXT_CHAPTER") + .expect("The % NEXT_CHAPTER maker must exist"); + main_text.insert_str( find_index, &format!( "\\include{{content/{}/{}}}\n ", - name.to_case(Case::Snake), - &format!("chapter_{:02}", data_file.last_chapter.number + 1) + &format!( + "{:02}_{}", + config.last_chapter.number + 1, + &name.to_case(Case::Snake) + ), + "chapter.tex", ), ); - data_file.last_chapter.user_name = name.to_case(Case::Snake); - data_file.last_chapter.number += 1; - - fs::write( - project_root.join("lpm.toml"), - toml::to_string(&data_file).expect("We changed it ourselfes, the conversion should work"), - ) - .unwrap(); - - fs::write(project_root.join("main.tex"), main_file).unwrap(); - - Ok(()) + Ok(GeneratedFile::new(project_root.join("main.tex"), main_text)) } diff --git a/src/new/mod.rs b/src/new/mod.rs index 33783c4..a85187c 100644 --- a/src/new/mod.rs +++ b/src/new/mod.rs @@ -1,97 +1,2 @@ pub mod chapter; -pub mod project; pub mod section; - -use std::{ - env, - ffi::OsString, - fs::read_dir, - io::{self, ErrorKind}, - path::PathBuf, -}; - -const SECTION: &'static str = r#"%! TEX root = ../../../main.tex -% LTeX: language=de-DE - -\lesson{REPLACMENT_SECTION_TITLE}{DATE}{} -Dies ist etwas Text -"#; - -const CHAPTER: &'static str = r#"%! TEX root = ../main.tex -% LTeX: language=de-DE - -\chapter{REPLACEMENT_CHAPTER} -"#; - -const TITLE_FILE: &'static str = r#"% LTeX: language=de-DE - -\maketitle -\tableofcontents -\vspace*{\fill} -\makeatletter -Copyright \textcopyright{} \@authors{} \@years{}\\ -\ \\ -Dieses Werk ist lizenziert unter den Bedingungen der CC BY-SA 4.0. -Der Lizenztext ist online unter \url{http://creativecommons.org/licenses/by-sa/4.0/legalcode} abrufbar. -\makeatother -\clearpage -"#; - -const MAIN_FILE: &'static str = r#"%\documentclass[a4paper, 12pt, nosolutions]{report} -\documentclass[a4paper, 12pt]{report} -% LTeX: language=de-DE -\input{headers/preamble.tex} -\input{headers/preamble_local.tex} - - -\title{\textbf{Titel}} -\author{Name\thanks{Beispiel}} -\authors{Name} -\years{2022 - 2023} -\date{\DTMDate{2002-12-4}} - -\includeonly{content/REPLACEMENT_CHAPTER/chapter_01} - -\begin{document} - \input{content/static/title} - - \include{content/REPLACEMENT_CHAPTER/chapter_01} - % NEXT_CHAPTER - - \printbibliography\relax -\end{document} -"#; - -pub fn get_project_root() -> io::Result<PathBuf> { - let path = env::current_dir()?; - let mut path_ancestors = path.as_path().ancestors(); - - while let Some(path_segment) = path_ancestors.next() { - if read_dir(path_segment)?.into_iter().any(|path_segment| { - path_segment - .expect("The read_dir shouldn't error out here") - .file_name() - == OsString::from("lpm.toml") - }) { - return Ok(PathBuf::from(path_segment)); - } - } - Err(io::Error::new( - ErrorKind::NotFound, - "Ran out of places to find lpm.toml", - )) -} - -pub fn get_all_chapters() -> io::Result<Vec<String>> { - let path = get_project_root()?; - let output = read_dir(path.join("content"))? - .map(|path| { - path.expect("The values sholud be fine") - .file_name() - .to_str() - .expect("all names should be valid utf-8") - .to_owned() - }) - .collect(); - Ok(output) -} diff --git a/src/new/project.rs b/src/new/project.rs deleted file mode 100644 index 56edead..0000000 --- a/src/new/project.rs +++ /dev/null @@ -1,111 +0,0 @@ -use std::{ - env, - fs::{self, File}, - io::{self, Write}, - path::PathBuf, - process::Command, -}; - -use convert_case::{Case, Casing}; - -use crate::data::Data; - -use super::{CHAPTER, MAIN_FILE, TITLE_FILE}; - -const NEEDED_DIRECTORYS: &'static [&'static str] = - &["build", "content", "headers", "references", "resources"]; - -pub fn generate_new_project( - name: String, - first_chapter: String, - //first_section: String, - preamble_path: PathBuf, - resource_path: PathBuf, -) -> io::Result<()> { - fs::create_dir(&name).unwrap(); - env::set_current_dir(&name).unwrap(); - let project_root = env::current_dir().unwrap(); - - for directory in NEEDED_DIRECTORYS { - fs::create_dir(directory).unwrap(); - } - - // content - env::set_current_dir(project_root.join("content")).unwrap(); - fs::create_dir(&first_chapter.to_case(Case::Snake)).unwrap(); - fs::create_dir("static").unwrap(); - - env::set_current_dir("static").unwrap(); - let mut title_file = File::create("title.tex").unwrap(); - title_file.write_all(TITLE_FILE.as_bytes()).unwrap(); - - env::set_current_dir( - project_root - .join("content") - .join(&first_chapter.to_case(Case::Snake)), - ) - .unwrap(); - fs::create_dir("sections").unwrap(); - let mut chapter_file = File::create("chapter_01.tex").unwrap(); - chapter_file - .write_all( - CHAPTER - .replace("REPLACEMENT_CHAPTER", &first_chapter) - .as_bytes(), - ) - .unwrap(); - - //env::set_current_dir("sections").unwrap(); - //let mut section_file = File::create(format!("{}.tex", &first_section)).unwrap(); - //section_file - // .write_all(SECTION.as_bytes()) - // .unwrap(); - - // headers - env::set_current_dir(project_root.join("headers")).unwrap(); - File::create("preamble_local.tex").unwrap(); - fs::copy(fs::canonicalize(preamble_path).unwrap(), "preamble.tex").unwrap(); - - // resources - env::set_current_dir(project_root.join("resources")).unwrap(); - fs::canonicalize(resource_path) - .unwrap() - .read_dir() - .unwrap() - .map(|path| path.expect("The provided path should work")) - .for_each(|path| { - fs::copy(path.path(), path.file_name()).unwrap(); - }); - - // root files - env::set_current_dir(project_root).unwrap(); - let mut main_file = File::create("main.tex").unwrap(); - main_file - .write_all( - MAIN_FILE - .replace("REPLACEMENT_CHAPTER", &first_chapter.to_case(Case::Snake)) - .as_bytes(), - ) - .unwrap(); - - let data_file = Data { - last_chapter: crate::data::LastChapter { - user_name: first_chapter.to_case(Case::Snake), - number: 1, - }, - }; - let mut lpm_file = File::create("lpm.toml").unwrap(); - lpm_file - .write_all(toml::to_string(&data_file).unwrap().as_bytes()) - .unwrap(); - - Command::new("git") - .arg("init") - .output() - .expect("failed to execute process"); - - let mut lpm_file = File::create(".gitignore").unwrap(); - lpm_file.write_all(b"/build").unwrap(); - - Ok(()) -} diff --git a/src/new/section.rs b/src/new/section.rs index 31742c2..a359fb0 100644 --- a/src/new/section.rs +++ b/src/new/section.rs @@ -1,63 +1,63 @@ -use std::{ - env, - fs::{self, read_dir}, - io::{self, ErrorKind}, - path::PathBuf, - time::SystemTime, -}; +use std::{fs, path::Path, time::SystemTime}; +use anyhow::Context; use chrono::{DateTime, Local}; use convert_case::{Case, Casing}; +use log::debug; -use super::SECTION; +use crate::{ + config_file::Config, + file_tree::{FileTree, GeneratedFile}, +}; -pub fn generate_new_section(name: String) -> io::Result<()> { - let chapter_root = get_section_root()?; - let chapter_main_file_path = read_dir(&chapter_root)? - .into_iter() - .map(|path| path.unwrap()) - .filter(|path| path.file_name().to_str().unwrap().contains("chapter_")) - .last() - .unwrap() - .path(); - let mut main_file = fs::read_to_string(&chapter_main_file_path).unwrap(); +pub fn generate_new_section( + config: &Config, + name: String, + project_root: &Path, + chapter_name: &str, +) -> anyhow::Result<FileTree> { + let chapter_root = project_root.join("content").join(chapter_name); + debug!("Chapter root is: {}", chapter_root.display()); - main_file.push_str(&format!( - "\\input{{content/{}/sections/{}}}\n", - chapter_root.file_name().unwrap().to_str().unwrap(), - &name.to_case(Case::Snake) - )); - fs::write(chapter_main_file_path, main_file)?; - fs::write( - chapter_root.join(format!("sections/{}.tex", name.to_case(Case::Snake))), - SECTION.replace("REPLACMENT_SECTION_TITLE", &name).replace( + let mut file_tree = FileTree::new(); + + let new_section_text = config + .templates + .section + .replace("REPLACMENT_SECTION_TITLE", &name) + .replace( "DATE", &format!( "{}", - DateTime::<Local>::from(SystemTime::now()).format("%Y-%m-%d") + // FIXME: The time is not really precise enough to display the time. <2024-03-31> + DateTime::<Local>::from(SystemTime::now()).format("%Y-%m-%d (%_H:%_S)") ), - ), - )?; - Ok(()) -} + ); + + let new_section_file = GeneratedFile::new( + chapter_root + .join("sections") + .join(format!("{}.tex", name.to_case(Case::Snake))), + new_section_text, + ); + file_tree.add_file(new_section_file); + + let chapter_file_path = chapter_root.join("chapter.tex"); + let mut chapter_file_text = fs::read_to_string(&chapter_file_path).with_context(|| { + format!( + "Failed to read the chapter main file ('{}') to string", + &chapter_file_path.display(), + ) + })?; + + chapter_file_text.push_str(&format!( + "\\input{{content/{}/sections/{}}}\n", + chapter_name, + &name.to_case(Case::Snake) + )); + + let chapter_file = GeneratedFile::new(chapter_file_path, chapter_file_text); + file_tree.add_file(chapter_file); -pub fn get_section_root() -> io::Result<PathBuf> { - let path = env::current_dir()?; - let mut path_ancestors = path.as_path().ancestors(); - - while let Some(path_segment) = path_ancestors.next() { - if read_dir(path_segment)?.into_iter().any(|path| { - path.expect("The read_dir shouldn't error out here") - .file_name() - .to_str() - .unwrap() - .contains("chapter_") - }) { - return Ok(PathBuf::from(path_segment)); - } - } - Err(io::Error::new( - ErrorKind::NotFound, - "Ran out of places to find chapter_root", - )) + Ok(file_tree) } |