summary refs log tree commit diff stats
path: root/src/main.rs
blob: 8c2ea62a43342cb92f10ac048da9b2a7f09722bf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
use std::{env, ffi::OsString, fs, path::PathBuf};

use anyhow::{bail, Context};
use clap::Parser;
use log::debug;

use crate::{
    cli::{
        Args,
        Command::New,
        What::{Chapter, Section},
    },
    config_file::Config,
    new::{chapter::generate_new_chapter, section::generate_new_section},
};

pub mod cli;
pub mod config_file;
pub mod new;

// The copyright header tells you, where this file is from.
pub mod file_tree;

fn main() -> anyhow::Result<()> {
    env_logger::init();
    let args = Args::parse();

    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 file_tree = match args.cli {
        New(new_command) => match new_command {
            Section { name, chapter } => {
                let chapter = if let Some(val) = chapter {
                    // The user probably has not added the preceeding 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()?
                };

                generate_new_section(&config, name, &project_root, &chapter)?
            }
            Chapter { name } => generate_new_chapter(config, &project_root, name)?,
        },
    };

    file_tree.materialize()?;

    Ok(())
}

pub fn get_project_root_by_lmp_toml() -> anyhow::Result<PathBuf> {
    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<String> {
    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!")
}