From d0fe56f4e98fa552c5e271713a815d2382e614f7 Mon Sep 17 00:00:00 2001 From: Benedikt Peetz Date: Sun, 29 Sep 2024 10:11:35 +0200 Subject: feat(templates): Provide a consistent syntax for replacements All replacements now start with `lpm::` and thus provide a future way to extend them. This change also adds the ability to access the chapter name in a new section and the current data in a new chapter. --- example/example.tex | 21 +++++++++++++++++ example/lpm.toml | 12 ++++------ example/main.tex | 21 ----------------- src/constants.rs | 5 ++++ src/main.rs | 1 + src/new/chapter.rs | 7 ++---- src/new/mod.rs | 5 ++++ src/new/replacement.rs | 47 +++++++++++++++++++++++++++++++++++++ src/new/section.rs | 63 +++++++++++--------------------------------------- 9 files changed, 99 insertions(+), 83 deletions(-) create mode 100644 example/example.tex delete mode 100644 example/main.tex create mode 100644 src/constants.rs create mode 100644 src/new/replacement.rs diff --git a/example/example.tex b/example/example.tex new file mode 100644 index 0000000..d5f0d2f --- /dev/null +++ b/example/example.tex @@ -0,0 +1,21 @@ +% LTeX: language=en-GB +\documentclass[a4paper, 12pt]{report} +\input{headers/preamble.tex} +\input{headers/preamble_local.tex} + + +\title{\textbf{Some Title}} +\author{Some Author} +\authors{name\inst} +\years{2024} +\date{\Today} + +\includeonly{} + +\begin{document} + \input{content/static/title} + + % NEXT_CHAPTER + + \printbibliography\relax +\end{document} diff --git a/example/lpm.toml b/example/lpm.toml index 5a3565d..7c4aaad 100644 --- a/example/lpm.toml +++ b/example/lpm.toml @@ -1,19 +1,17 @@ -[last_chapter] -user_name = "static" -number = 0 +main_file = "example.tex" [templates] section = ''' -%! TEX root = ../../../main.tex +%! TEX root = ../../../example.tex % LTeX: language=en-GB -\section{REPLACMENT_SECTION_TITLE} % DATE +\section{lpm::new_section_name} % lpm::current_date (lpm::current_chapter_name::title_case) This is some text ''' chapter = ''' -%! TEX root = ../../main.tex +%! TEX root = ../../example.tex % LTeX: language=en-GB -\chapter{REPLACEMENT_CHAPTER} +\chapter{lpm::new_chapter_name} % lpm::current_date ''' diff --git a/example/main.tex b/example/main.tex deleted file mode 100644 index d5f0d2f..0000000 --- a/example/main.tex +++ /dev/null @@ -1,21 +0,0 @@ -% LTeX: language=en-GB -\documentclass[a4paper, 12pt]{report} -\input{headers/preamble.tex} -\input{headers/preamble_local.tex} - - -\title{\textbf{Some Title}} -\author{Some Author} -\authors{name\inst} -\years{2024} -\date{\Today} - -\includeonly{} - -\begin{document} - \input{content/static/title} - - % NEXT_CHAPTER - - \printbibliography\relax -\end{document} diff --git a/src/constants.rs b/src/constants.rs new file mode 100644 index 0000000..2cdec2d --- /dev/null +++ b/src/constants.rs @@ -0,0 +1,5 @@ +pub const REPLACEMENT_CHAPTER: &str = "lpm::new_chapter_name"; + +pub const REPLACEMENT_CHAPTER_SECTION: &str = "lpm::current_chapter_name::title_case"; +pub const REPLACMENT_SECTION_TITLE: &str = "lpm::new_section_name"; +pub const DATE: &str = "lpm::current_date"; diff --git a/src/main.rs b/src/main.rs index 5ea9a74..ce886bf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,6 +18,7 @@ pub mod bundle; pub mod cli; pub mod config_file; pub mod new; +pub mod constants; // The copyright header tells you, where this file is from. pub mod file_tree; diff --git a/src/new/chapter.rs b/src/new/chapter.rs index 887855b..fcc075d 100644 --- a/src/new/chapter.rs +++ b/src/new/chapter.rs @@ -7,7 +7,7 @@ use crate::{ file_tree::{FileTree, GeneratedFile}, }; -use super::MangledName; +use super::{replacement::untemplatize_chapter, MangledName}; pub struct ChapterName { name: MangledName, @@ -125,10 +125,7 @@ fn new_chapter_file( project_root: &Path, last_chapter_number: u32, ) -> GeneratedFile { - let chapter_text = config - .templates - .chapter - .replace("REPLACEMENT_CHAPTER", &name); + let chapter_text = untemplatize_chapter(&config.templates.chapter, &name); GeneratedFile::new( project_root diff --git a/src/new/mod.rs b/src/new/mod.rs index 8d8193c..04b75ef 100644 --- a/src/new/mod.rs +++ b/src/new/mod.rs @@ -4,6 +4,7 @@ use convert_case::{Case, Casing}; use deunicode::deunicode; pub mod chapter; +pub mod replacement; pub mod section; #[derive(PartialEq, Eq, PartialOrd, Ord)] @@ -29,6 +30,10 @@ impl MangledName { pub fn as_str(&self) -> &str { &self.0 } + + pub fn try_unmangle(self) -> String { + self.0.to_case(Case::Title) + } } impl Display for MangledName { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { diff --git a/src/new/replacement.rs b/src/new/replacement.rs new file mode 100644 index 0000000..6878e61 --- /dev/null +++ b/src/new/replacement.rs @@ -0,0 +1,47 @@ +use std::time::{SystemTime, UNIX_EPOCH}; + +use chrono::{Local, TimeDelta, TimeZone}; +use log::debug; + +use crate::constants::{ + DATE, REPLACEMENT_CHAPTER, REPLACEMENT_CHAPTER_SECTION, REPLACMENT_SECTION_TITLE, +}; + +fn get_current_date() -> String { + let start = SystemTime::now(); + let seconds_since_epoch: TimeDelta = TimeDelta::from_std( + start + .duration_since(UNIX_EPOCH) + .expect("Time went backwards"), + ) + .expect("Time does not go backwards"); + + debug!( + "Adding a date with timestamp: {}", + seconds_since_epoch.num_seconds() + ); + + let our_date = format!( + "{}", + Local + .timestamp_opt(seconds_since_epoch.num_seconds(), 0) + // only has unwrap, no expect. But should always work + .unwrap() + .format("%Y-%m-%d %H:%M:%S%.f %:z") + ); + + our_date +} + +pub fn untemplatize_section(input: &str, new_section_name: &str, new_chapter_name: &str) -> String { + input + .replace(REPLACEMENT_CHAPTER_SECTION, &new_chapter_name) + .replace(REPLACMENT_SECTION_TITLE, &new_section_name) + .replace(DATE, &get_current_date()) +} + +pub fn untemplatize_chapter(input: &str, new_chapter_name: &str) -> String { + input + .replace(REPLACEMENT_CHAPTER, &new_chapter_name) + .replace(DATE, &get_current_date()) +} diff --git a/src/new/section.rs b/src/new/section.rs index 5e9f08c..a350f71 100644 --- a/src/new/section.rs +++ b/src/new/section.rs @@ -1,57 +1,14 @@ -use std::{ - fs, - path::Path, - time::{SystemTime, UNIX_EPOCH}, -}; +use std::{fs, path::Path}; use anyhow::Context; -use chrono::{Local, TimeDelta, TimeZone}; use log::debug; use crate::{ config_file::Config, file_tree::{FileTree, GeneratedFile}, - new::MangledName, + new::{replacement::untemplatize_section, MangledName}, }; -fn get_current_date() -> String { - let start = SystemTime::now(); - let seconds_since_epoch: TimeDelta = TimeDelta::from_std( - start - .duration_since(UNIX_EPOCH) - .expect("Time went backwards"), - ) - .expect("Time does not go backwards"); - - debug!( - "Adding a date with timestamp: {}", - seconds_since_epoch.num_seconds() - ); - - let our_date = format!( - "{}", - Local - .timestamp_opt(seconds_since_epoch.num_seconds(), 0) - // only has unwrap, no expect. But should always work - .unwrap() - .format("%Y-%m-%d %H:%M:%S%.f %:z") - ); - - // let date = Command::new("date") - // .args(["-d", &format!("@{}", seconds_since_epoch.num_seconds())]) - // .output() - // .unwrap() - // .stdout; - - // info!( - // "This is dated: '{}' vs. our date: '{}'", - // String::from_utf8(date).unwrap().strip_suffix('\n').unwrap(), - // our_date - // ); - - our_date -} - pub fn generate_new_section( config: &Config, name: String, @@ -63,11 +20,17 @@ pub fn generate_new_section( let mut file_tree = FileTree::new(); - let new_section_text = config - .templates - .section - .replace("REPLACMENT_SECTION_TITLE", &name) - .replace("DATE", &get_current_date()); + let display_chapter_name = MangledName::from_str_unsafe( + chapter_name + .chars() + .skip_while(|a: &char| a.is_digit(10) || *(a) == '_') + .collect::() + .as_str(), + ) + .try_unmangle(); + + let new_section_text = + untemplatize_section(&config.templates.section, &name, &display_chapter_name); file_tree.add_file(GeneratedFile::new_clobber( chapter_root -- cgit 1.4.1