use std::{env, ffi::OsString, fs, path::PathBuf}; use anyhow::{bail, Context}; use clap::Parser; use cli::{Command, What}; use log::debug; use new::figure::generate_new_figure; use crate::{ cli::Args, config_file::Config, new::{chapter::generate_new_chapter, section::generate_new_section}, }; pub mod bundle; pub mod cli; pub mod config_file; pub mod constants; pub mod new; // The copyright header tells you, where this file is from. pub mod file_tree; fn main() -> anyhow::Result<()> { let args = Args::parse(); stderrlog::new() .module(module_path!()) .quiet(args.quiet) .show_module_names(false) .color(stderrlog::ColorChoice::Auto) .verbosity(args.verbosity as usize) .timestamp(stderrlog::Timestamp::Off) .init() .expect("Let's just hope that this does not panic"); let project_root = get_project_root_by_lmp_toml().context("Looking for the project root")?; let config_file = fs::read_to_string(project_root.join("lpm.toml"))?; let config: Config = toml::from_str(&config_file).context("Reading toml from string")?; let maybe_file_tree = match args.cli { Command::Bundle => { let output = bundle::bundle(config, &project_root)?; print!("{}", output); None } Command::New(new_command) => match new_command { What::Section { name, chapter } => { let chapter = if let Some(val) = chapter { // The user probably has not added the preceding chapter number to the chapter // string if val.starts_with(|c: char| c.is_numeric()) { eprintln!( "Your chapter name starts with a number, assuming \ that you have already added the chapter number" ); val } else { bail!( "Calculating the chapter number is not yet \ implemented, please add it yourself" ); } } else { // The user thinks that they are already inside a chapter get_upwards_chapter()? }; Some(generate_new_section( &config, name, &project_root, &chapter, )?) } What::Chapter { name } => Some(generate_new_chapter(config, &project_root, name)?), What::Figure { name } => Some(generate_new_figure(&config, name, &project_root)?), }, }; if let Some(file_tree) = maybe_file_tree { file_tree.materialize()?; } Ok(()) } pub fn get_project_root_by_lmp_toml() -> anyhow::Result { let path = env::current_dir()?; let mut path_ancestors = path.as_path().ancestors(); while let Some(path_segment) = path_ancestors.next() { if fs::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)); } } bail!("Ran out of places to find lpm.toml") } fn get_upwards_chapter() -> anyhow::Result { let current_path = env::current_dir()?; for anc in current_path.as_path().ancestors() { debug!("Reading directory {}", anc.display()); for dir in fs::read_dir(anc)? { let dir = dir?; debug!("Checking path: {}", dir.file_name().to_string_lossy()); if dir.file_name() == OsString::from("chapter.tex") { match anc .file_name() .expect("This should always be a file") .to_str() { Some(str) => return Ok(str.to_owned()), None => bail!( "Failed to convert your path ('{}') to a string!", dir.file_name().to_string_lossy() ), } } } } bail!("Failed to get a chapter name, please specify one with the `--chapter` flag!") }