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);
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 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";
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
}