flexar/compile_error/
compile_error_display.rs1use super::CompileError;
2use std::fmt::{self, Display};
3pub use crate::colour_format;
4
5pub const LINE_LIMIT: u8 = 24;
6
7impl Display for CompileError {
8 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9 let ln = self.position.0.ln.to_string();
10 let (line, arrw) = if self.position.0.ln == self.position.1.ln {
11 sample(
12 self.position.0.get_ln().unwrap(), self.position.0.ln_idx,
14 self.position.1.ln_idx,
15 &self.msg,
16 false,
17 )
18 } else {
19 sample(
20 self.position.0.get_ln().unwrap(), self.position.0.ln_idx,
22 self.position.0.get_ln().unwrap().len() as u16, &self.msg,
24 true,
25 )
26 };
27
28 let out = colour_format![
29 red("\nerror["), yellow(self.id), red("]: "), none(self.error_type),
30 blue("\n --> "), cyan(&self.position.0.file_name),
31 blue(":"), yellow(&ln), blue(":"), yellow(&self.position.0.ln_idx.to_string()),
32 none("\n"), yellow(&ln), blue(" | "), none(&line),
33 none("\n"), none(&" ".repeat(ln.len())), blue(" | ") red(&arrw),
34 blue("\n <--"),
35 ];
36
37 write!(f, "{}", out)
38 }
39}
40
41fn sample(line: &str, start_idx: u16, end_idx: u16, msg: &str, multi_line: bool) -> (String, String) {
42 let start_trim = cal_trim(start_idx, 0);
43 let end_trim = cal_trim(line.len() as u16, end_idx);
44
45 let mut sample = line[start_trim as usize..line.len() - end_trim as usize].to_string();
46
47 if start_trim != 0 { sample = colour_format![cyan("..."), none(&sample)]; }
48 if end_trim != 0 { sample = colour_format![none(&sample), cyan("...")]; }
49
50 if multi_line { sample = colour_format![none(&sample), cyan("\\n"), red("...")]; }
51
52 (sample, gen_arrw(start_idx, end_idx, msg, start_trim, 5 * multi_line as u16))
53}
54
55#[inline]
56fn cal_trim(actual: u16, desired: u16) -> u16 {
57 let dif = actual.saturating_sub(desired);
58 if dif > LINE_LIMIT as u16 { dif - LINE_LIMIT as u16 + 3 } else { 0 }
60}
61
62#[inline]
63fn gen_arrw(start_idx: u16, end_idx: u16, msg: &str, start_trim: u16, offset: u16) -> String {
64 let spaces_since_start = if start_trim > 0 {
65 start_idx - start_trim + 2 } else { start_idx -1 };
67
68 let inbetween = end_idx - start_idx + 1 + offset; let mut out = " ".repeat(spaces_since_start as usize);
71 out.push_str(&"^".repeat(inbetween as usize));
72 out.push(' ');
73 out.push_str(&msg.replace('\n', "\x1b[36m\\n\x1b[31m"));
74
75 out
76}
77
78#[macro_export]
86macro_rules! colour_format { ($(
88 $(none($none:expr))?
89 $(blue($blue:expr))?
90 $(pink($pink:expr))?
91 $(white($white:expr))?
92 $(green($green:expr))?
93 $(cyan($cyan:expr))?
94 $(red($red:expr))?
95 $(black($black:expr))?
96 $(yellow($yellow:expr))?
97 ),*) => {{
98 let mut string = String::new();
99 $(
100 $(string.push_str("\x1b[0m"); string.push_str($none);)?
101 $(string.push_str("\x1b[34m"); string.push_str($blue);)?
102 $(string.push_str("\x1b[35m"); string.push_str($pink);)?
103 $(string.push_str("\x1b[37m"); string.push_str($white);)?
104 $(string.push_str("\x1b[32m"); string.push_str($green);)?
105 $(string.push_str("\x1b[36m"); string.push_str($cyan);)?
106 $(string.push_str("\x1b[31m"); string.push_str($red);)?
107 $(string.push_str("\x1b[30m"); string.push_str($black);)?
108 $(string.push_str("\x1b[33m"); string.push_str($yellow);)?
109 )* string.push_str("\x1b[0m");
110 string
111 }}
112}