summary refs log tree commit diff stats
path: root/src/main.rs
blob: 5ea9a747ae38e91132e3fe17548eaab1b9c3b5f2 (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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use std::{env, ffi::OsString, fs, path::PathBuf};

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

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

pub mod bundle;
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<()> {
    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 {
            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()?
                };

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

    if let Some(file_tree) = maybe_file_tree {
        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!")
}