All report text types rendered in color with tests

This commit is contained in:
Chad Stearns 2020-03-22 21:56:22 -04:00
parent 3ea27dab39
commit 57cf650ac7
2 changed files with 295 additions and 24 deletions

View file

@ -13,17 +13,39 @@ pub struct Report {
pub struct Palette {
pub primary: Color,
pub code_block: Color,
pub variable: Color,
pub flex_var: Color,
pub rigid_var: Color,
pub structure: Color,
pub alias: Color,
pub error: Color,
pub line_number: Color,
pub gutter_bar: Color,
}
#[derive(Copy, Clone)]
pub enum Color {
White,
Red,
Blue,
Yellow,
Green,
Cyan,
Magenta,
}
pub const DEFAULT_PALETTE: Palette = Palette {
pub const TEST_PALETTE: Palette = Palette {
primary: Color::White,
code_block: Color::White,
variable: Color::Blue,
flex_var: Color::Yellow,
rigid_var: Color::Yellow,
structure: Color::Green,
alias: Color::Yellow,
error: Color::Red,
line_number: Color::Cyan,
gutter_bar: Color::Magenta,
};
impl Color {
@ -33,6 +55,11 @@ impl Color {
match self {
Red => red(str),
White => white(str),
Blue => blue(str),
Yellow => yellow(str),
Green => green(str),
Cyan => cyan(str),
Magenta => magenta(str),
}
}
}
@ -99,31 +126,78 @@ pub fn plain_text(str: &str) -> ReportText {
Plain(Box::from(str))
}
pub fn em_text(str: &str) -> ReportText {
use ReportText::*;
EmText(Box::from(str))
}
pub fn url(str: &str) -> ReportText {
use ReportText::*;
Url(Box::from(str))
}
fn newline() -> ReportText {
plain_text("\n")
}
pub const RED_CODE: &str = "\u{001b}[31m";
pub const WHITE_CODE: &str = "\u{001b}[31m";
pub const WHITE_CODE: &str = "\u{001b}[37m";
pub const BLUE_CODE: &str = "\u{001b}[34m";
pub const YELLOW_CODE: &str = "\u{001b}[33m";
pub const GREEN_CODE: &str = "\u{001b}[42m";
pub const CYAN_CODE: &str = "\u{001b}[36m";
pub const MAGENTA_CODE: &str = "\u{001b}[35m";
fn red(str: &str) -> String {
pub const BOLD_CODE: &str = "\u{001b}[1m";
pub const UNDERLINE_CODE: &str = "\u{001b}[4m";
fn code(code_str: &str, str: &str) -> String {
let mut buf = String::new();
buf.push_str(RED_CODE);
buf.push_str(code_str);
buf.push_str(str);
buf.push_str(RESET_CODE);
buf
}
pub fn underline(str: &str) -> String {
code(UNDERLINE_CODE, str)
}
pub fn bold(str: &str) -> String {
code(BOLD_CODE, str)
}
fn cyan(str: &str) -> String {
code(CYAN_CODE, str)
}
fn magenta(str: &str) -> String {
code(MAGENTA_CODE, str)
}
fn green(str: &str) -> String {
code(GREEN_CODE, str)
}
fn yellow(str: &str) -> String {
code(YELLOW_CODE, str)
}
fn blue(str: &str) -> String {
code(BLUE_CODE, str)
}
fn red(str: &str) -> String {
code(RED_CODE, str)
}
fn white(str: &str) -> String {
let mut buf = String::new();
buf.push_str(WHITE_CODE);
buf.push_str(str);
buf.push_str(RESET_CODE);
buf
code(WHITE_CODE, str)
}
pub const RESET_CODE: &str = "\u{001b}[0m";
@ -206,21 +280,94 @@ impl ReportText {
/// Render to a color terminal using ANSI escape sequences
pub fn render_color_terminal(
&self,
self,
buf: &mut String,
_subs: &mut Subs,
_home: ModuleId,
_src_lines: &[&str],
_interns: &Interns,
palette: Palette,
subs: &mut Subs,
home: ModuleId,
src_lines: &[&str],
interns: &Interns,
palette: &Palette,
) {
use ReportText::*;
match self {
Plain(string) => {
buf.push_str(&palette.primary.render(string));
buf.push_str(&palette.primary.render(&string));
}
EmText(string) => {
buf.push_str(&bold(&string));
}
Url(url) => {
buf.push_str(&underline(&url));
}
Value(symbol) => {
if symbol.module_id() == home {
// Render it unqualified if it's in the current module.
buf.push_str(&palette.variable.render(symbol.ident_string(interns)));
} else {
let mut module_str = String::new();
module_str.push_str(symbol.module_string(interns));
module_str.push('.');
module_str.push_str(symbol.ident_string(interns));
buf.push_str(&palette.variable.render(&module_str));
}
}
Type(content) => match content {
Content::FlexVar(flex_var) => buf.push_str(&palette.flex_var.render(
content_to_string(Content::FlexVar(flex_var), subs, home, interns).as_str(),
)),
Content::RigidVar(rigid_var) => buf.push_str(&palette.rigid_var.render(
content_to_string(Content::RigidVar(rigid_var), subs, home, interns).as_str(),
)),
Content::Structure(structure) => buf.push_str(&palette.structure.render(
// TODO give greater specificity to how structures are colored. Empty record colored differently than tags, etc.
content_to_string(Content::Structure(structure), subs, home, interns).as_str(),
)),
Content::Alias(symbol, vars, var) => buf.push_str(
&palette.alias.render(
content_to_string(Content::Alias(symbol, vars, var), subs, home, interns)
.as_str(),
),
),
Content::Error => {}
},
Region(region) => {
let max_line_number_length = region.end_line.to_string().len();
for i in region.start_line..=region.end_line {
let i_one_indexed = i + 1;
let line_number_string = i_one_indexed.to_string();
let line_number = line_number_string.as_str();
let this_line_number_length = line_number.len();
buf.push_str(
" ".repeat(max_line_number_length - this_line_number_length)
.as_str(),
);
buf.push_str(&palette.line_number.render(line_number));
buf.push_str(&palette.gutter_bar.render(""));
let line = src_lines[i as usize];
if !line.trim().is_empty() {
buf.push_str(" ");
buf.push_str(&palette.code_block.render(src_lines[i as usize]));
}
if i != region.end_line {
buf.push('\n');
}
}
}
Batch(report_texts) => {
for report_text in report_texts {
report_text.render_color_terminal(buf, subs, home, src_lines, interns, palette);
}
}
_ => panic!("TODO implement more ReportTexts in render color terminal"),
}
}