aboutsummaryrefslogtreecommitdiffstats
path: root/src/new
diff options
context:
space:
mode:
Diffstat (limited to 'src/new')
-rw-r--r--src/new/chapter.rs172
-rw-r--r--src/new/mod.rs35
-rw-r--r--src/new/section.rs11
3 files changed, 168 insertions, 50 deletions
diff --git a/src/new/chapter.rs b/src/new/chapter.rs
index 749202f..887855b 100644
--- a/src/new/chapter.rs
+++ b/src/new/chapter.rs
@@ -1,36 +1,130 @@
-use std::{fs, path::Path};
+use std::{fmt::Display, fs, path::Path};
-use convert_case::{Case, Casing};
+use anyhow::{Context, Result};
use crate::{
config_file::Config,
file_tree::{FileTree, GeneratedFile},
};
+use super::MangledName;
+
+pub struct ChapterName {
+ name: MangledName,
+ number: u32,
+}
+
+impl Display for ChapterName {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.write_fmt(format_args!("{:02}_{}", self.number, self.name))
+ }
+}
+
+impl ChapterName {
+ pub fn from_str(name: &str, last_chapter_number: u32) -> Self {
+ let name = MangledName::new(name);
+ Self {
+ name,
+ number: last_chapter_number + 1,
+ }
+ }
+ pub fn new(name: MangledName, last_chapter_number: u32) -> Self {
+ Self {
+ name,
+ number: last_chapter_number + 1,
+ }
+ }
+ pub fn to_components(self) -> (MangledName, u32) {
+ (self.name, self.number)
+ }
+
+ fn from_components(name: MangledName, number: u32) -> Self {
+ Self { name, number }
+ }
+}
+
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));
+
+ let (last_chapter_name, last_chapter_number) = get_last_chapter_name(project_root)
+ .context("Failed to get information on last chapter")?
+ .unwrap_or(ChapterName {
+ name: MangledName::from_str_unsafe("static"),
+ number: 0,
+ })
+ .to_components();
+
+ file_tree.add_file(new_main_file(
+ project_root,
+ &config,
+ &name,
+ last_chapter_number,
+ last_chapter_name,
+ )?);
+ file_tree.add_file(new_chapter_file(
+ &config,
+ &name,
+ project_root,
+ last_chapter_number,
+ ));
Ok(file_tree)
}
-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;
+fn get_last_chapter_name(project_root: &Path) -> anyhow::Result<Option<ChapterName>> {
+ let chapter_dirs = project_root.join("content");
- GeneratedFile::new(
- project_root.join("lpm.toml"),
- toml::to_string(&config).expect("We changed it ourselfes, the conversion should work"),
- )
+ let mut chapter_names = fs::read_dir(chapter_dirs)?
+ .filter_map(|path| -> Option<Result<String>> {
+ let path = match path.context("Failed to read a path") {
+ Ok(ok) => ok,
+ Err(err) => return Some(Err(err)),
+ };
+
+ let os_file_name = path.file_name();
+ let file_name = os_file_name
+ .to_str()
+ .expect("All chapter should be converted to ascii");
+
+ if file_name == "static" {
+ None
+ } else {
+ Some(Ok(file_name.to_owned()))
+ }
+ })
+ .collect::<Result<Vec<String>>>()?;
+
+ // There are no chapters, besides the default `static` one, which was sorted out
+ if chapter_names.is_empty() {
+ return Ok(None);
+ }
+
+ // The names are prefixed with a number
+ chapter_names.sort();
+
+ let raw_components = chapter_names[chapter_names.len() - 1]
+ .split_once('_')
+ .expect("Exits");
+
+ let number: u32 = raw_components.0.parse().expect("Will be a number");
+
+ // The name is already mangled
+ assert!(MangledName::check_mangled(raw_components.1));
+ let name: MangledName = MangledName::from_str_unsafe(raw_components.1);
+
+ Ok(Some(ChapterName::from_components(name, number)))
}
-fn new_chapter_file(config: &Config, name: &str, project_root: &Path) -> GeneratedFile {
+fn new_chapter_file(
+ config: &Config,
+ name: &str,
+ project_root: &Path,
+ last_chapter_number: u32,
+) -> GeneratedFile {
let chapter_text = config
.templates
.chapter
@@ -39,7 +133,7 @@ fn new_chapter_file(config: &Config, name: &str, project_root: &Path) -> Generat
GeneratedFile::new(
project_root
.join("content")
- .join(format! {"{:02}_{}", config.last_chapter.number + 1, name.to_case(Case::Snake)})
+ .join(ChapterName::from_str(name, last_chapter_number).to_string())
.join("chapter.tex"),
chapter_text,
)
@@ -49,60 +143,44 @@ fn new_main_file(
project_root: &Path,
config: &Config,
name: &str,
+ last_chapter_number: u32,
+ last_chapter_name: MangledName,
) -> anyhow::Result<GeneratedFile> {
- let mut main_text = fs::read_to_string(project_root.join("main.tex"))?;
+ let main_path = project_root.join(&config.main_file);
+ let mut main_text = fs::read_to_string(&main_path)?;
+
+ let chapter_includeonly: String = format!(
+ "\\includeonly{{content/{}/{}}}",
+ ChapterName::from_str(name, last_chapter_number).to_string(),
+ "chapter.tex",
+ );
- if &config.last_chapter.user_name == "static" && config.last_chapter.number == 0 {
+ if &last_chapter_name.as_str() == &"static" && 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",
- ),
- )
+ main_text = main_text.replace("\\includeonly{}", &chapter_includeonly)
} 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)
- ),
+ ChapterName::new(last_chapter_name, last_chapter_number - 1).to_string(),
"chapter.tex",
),
+ &chapter_includeonly,
)
};
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 ",
- &format!(
- "{:02}_{}",
- config.last_chapter.number + 1,
- &name.to_case(Case::Snake)
- ),
+ ChapterName::from_str(name, last_chapter_number).to_string(),
"chapter.tex",
),
);
- Ok(GeneratedFile::new(project_root.join("main.tex"), main_text))
+ Ok(GeneratedFile::new(main_path, main_text))
}
diff --git a/src/new/mod.rs b/src/new/mod.rs
index a85187c..8d8193c 100644
--- a/src/new/mod.rs
+++ b/src/new/mod.rs
@@ -1,2 +1,37 @@
+use std::fmt::Display;
+
+use convert_case::{Case, Casing};
+use deunicode::deunicode;
+
pub mod chapter;
pub mod section;
+
+#[derive(PartialEq, Eq, PartialOrd, Ord)]
+pub struct MangledName(String);
+
+impl MangledName {
+ pub fn new(name: &str) -> Self {
+ let ascii_name = deunicode(&name);
+ Self(ascii_name.to_case(Case::Snake))
+ }
+
+ pub fn from_str_unsafe(name: &str) -> Self {
+ Self(name.to_owned())
+ }
+
+ pub fn check_mangled(name: &str) -> bool {
+ let mangled = Self::new(name);
+ let normal = Self::from_str_unsafe(name);
+
+ mangled == normal
+ }
+
+ pub fn as_str(&self) -> &str {
+ &self.0
+ }
+}
+impl Display for MangledName {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.write_str(&self.0)
+ }
+}
diff --git a/src/new/section.rs b/src/new/section.rs
index a359fb0..86d347c 100644
--- a/src/new/section.rs
+++ b/src/new/section.rs
@@ -1,4 +1,8 @@
-use std::{fs, path::Path, time::SystemTime};
+use std::{
+ fs,
+ path::Path,
+ time::{SystemTime, UNIX_EPOCH},
+};
use anyhow::Context;
use chrono::{DateTime, Local};
@@ -8,6 +12,7 @@ use log::debug;
use crate::{
config_file::Config,
file_tree::{FileTree, GeneratedFile},
+ new::MangledName,
};
pub fn generate_new_section(
@@ -37,7 +42,7 @@ pub fn generate_new_section(
let new_section_file = GeneratedFile::new(
chapter_root
.join("sections")
- .join(format!("{}.tex", name.to_case(Case::Snake))),
+ .join(format!("{}.tex", MangledName::new(&name))),
new_section_text,
);
file_tree.add_file(new_section_file);
@@ -53,7 +58,7 @@ pub fn generate_new_section(
chapter_file_text.push_str(&format!(
"\\input{{content/{}/sections/{}}}\n",
chapter_name,
- &name.to_case(Case::Snake)
+ &MangledName::new(&name)
));
let chapter_file = GeneratedFile::new(chapter_file_path, chapter_file_text);