vesti 0.2.3

A preprocessor that compiles into LaTeX
use super::{Error, VestiErr};
use crate::location::Span;
use std::path::Path;

const BOLD_TEXT: &str = "\x1b[1m";
const ERR_COLOR: &str = "\x1b[38;5;9m";
const ERR_TITLE_COLOR: &str = "\x1b[38;5;15m";
const BLUE_COLOR: &str = "\x1b[38;5;12m";
const RESET_COLOR: &str = "\x1b[0m";

pub fn pretty_print(
    source: Option<&str>,
    vesti_error: VestiErr,
    filepath: Option<&Path>,
) -> String {
    let lines = source.map(|inner| inner.lines());
    let err_code = vesti_error.err_code();
    let err_str = vesti_error.err_str();
    let mut output = String::with_capacity(400);

    // Make error code and error title format
    output = output + BOLD_TEXT + ERR_COLOR;
    output += &format!(
        " error[E{0:04X}]{color:}: {1}",
        err_code,
        err_str,
        color = ERR_TITLE_COLOR
    );
    output = output + RESET_COLOR + "\n";

    if let VestiErr::ParseErr {
        location: Span { start, end },
        ..
    } = &vesti_error
    {
        let start_row_num = format!("{} ", start.row());

        // If the filepath of the given input one is found, print it with error location
        if let Some(m_filepath) = filepath {
            output = output
                + &" ".repeat(start_row_num.len())
                + BOLD_TEXT
                + BLUE_COLOR
                + "--> "
                + RESET_COLOR
                + m_filepath.to_str().unwrap()
                + &format!(":{}:{}\n", start.row(), start.column())
        }

        output = output
            + BOLD_TEXT
            + BLUE_COLOR
            + &" ".repeat(start_row_num.len().saturating_add(1))
            + "|\n "
            + &start_row_num
            + "|   "
            + RESET_COLOR;
        if let Some(mut inner) = lines {
            output += inner.nth(start.row() - 1).unwrap();
        }
        output += "\n";

        // Print an error message with multiple lines
        let padding_space = end.column().saturating_sub(start.column()) + 1;
        output = output
            + BOLD_TEXT
            + BLUE_COLOR
            + &" ".repeat(start_row_num.len().saturating_add(1))
            + "|   "
            + &" ".repeat(start.column().saturating_sub(1))
            + ERR_COLOR
            + &"^".repeat(end.column().saturating_sub(start.column()))
            + " ";

        for (i, msg) in vesti_error.err_detail_str().iter().enumerate() {
            if i == 0 {
                output = output + msg + "\n";
            } else {
                output = output
                    + BOLD_TEXT
                    + BLUE_COLOR
                    + &" ".repeat(start_row_num.len().saturating_add(1))
                    + "|   "
                    + &" ".repeat(start.column().saturating_sub(1))
                    + ERR_COLOR
                    + &" ".repeat(padding_space)
                    + msg
                    + "\n";
            }
        }
    }
    output += RESET_COLOR;

    output
}