Merge pull request #6525 from roc-lang/fix_text_contrast

less colors and more contrast in terminal
This commit is contained in:
Anton-4 2024-02-20 15:46:13 +01:00 committed by GitHub
commit b5f68bc020
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 99 additions and 104 deletions

1
Cargo.lock generated
View file

@ -2196,6 +2196,7 @@ version = "0.0.1"
dependencies = [ dependencies = [
"bumpalo", "bumpalo",
"indoc", "indoc",
"regex",
"roc_build", "roc_build",
"roc_cli", "roc_cli",
"roc_repl_cli", "roc_repl_cli",

View file

@ -440,6 +440,7 @@ pub fn test(matches: &ArgMatches, triple: Triple) -> io::Result<i32> {
use roc_build::program::report_problems_monomorphized; use roc_build::program::report_problems_monomorphized;
use roc_load::{ExecutionMode, FunctionKind, LoadConfig, LoadMonomorphizedError}; use roc_load::{ExecutionMode, FunctionKind, LoadConfig, LoadMonomorphizedError};
use roc_packaging::cache; use roc_packaging::cache;
use roc_reporting::report::ANSI_STYLE_CODES;
use roc_target::TargetInfo; use roc_target::TargetInfo;
let start_time = Instant::now(); let start_time = Instant::now();
@ -541,7 +542,7 @@ pub fn test(matches: &ArgMatches, triple: Triple) -> io::Result<i32> {
let mut writer = std::io::stdout(); let mut writer = std::io::stdout();
let (failed, passed) = roc_repl_expect::run::run_toplevel_expects( let (failed_count, passed_count) = roc_repl_expect::run::run_toplevel_expects(
&mut writer, &mut writer,
roc_reporting::report::RenderTarget::ColorTerminal, roc_reporting::report::RenderTarget::ColorTerminal,
arena, arena,
@ -555,7 +556,7 @@ pub fn test(matches: &ArgMatches, triple: Triple) -> io::Result<i32> {
let total_time = start_time.elapsed(); let total_time = start_time.elapsed();
if failed == 0 && passed == 0 { if failed_count == 0 && passed_count == 0 {
// TODO print this in a more nicely formatted way! // TODO print this in a more nicely formatted way!
println!("No expectations were found."); println!("No expectations were found.");
@ -566,18 +567,20 @@ pub fn test(matches: &ArgMatches, triple: Triple) -> io::Result<i32> {
// running tests altogether! // running tests altogether!
Ok(2) Ok(2)
} else { } else {
let failed_color = if failed == 0 { let failed_color = if failed_count == 0 {
32 // green ANSI_STYLE_CODES.green
} else { } else {
31 // red ANSI_STYLE_CODES.red
}; };
let passed_color = ANSI_STYLE_CODES.green;
println!( println!(
"\n\x1B[{failed_color}m{failed}\x1B[39m failed and \x1B[32m{passed}\x1B[39m passed in {} ms.\n", "\n{failed_color}{failed_count}\x1B[39m failed and {passed_color}{passed_count}\x1B[39m passed in {} ms.\n",
total_time.as_millis(), total_time.as_millis(),
); );
Ok((failed > 0) as i32) Ok((failed_count > 0) as i32)
} }
} }

View file

@ -210,33 +210,7 @@ fn main() -> io::Result<()> {
threading, threading,
) { ) {
Ok((problems, total_time)) => { Ok((problems, total_time)) => {
println!( problems.print_to_stdout(total_time);
"\x1B[{}m{}\x1B[39m {} and \x1B[{}m{}\x1B[39m {} found in {} ms.",
if problems.errors == 0 {
32 // green
} else {
33 // yellow
},
problems.errors,
if problems.errors == 1 {
"error"
} else {
"errors"
},
if problems.warnings == 0 {
32 // green
} else {
33 // yellow
},
problems.warnings,
if problems.warnings == 1 {
"warning"
} else {
"warnings"
},
total_time.as_millis(),
);
Ok(problems.exit_code()) Ok(problems.exit_code())
} }

View file

@ -11,12 +11,13 @@ extern crate roc_module;
mod cli_run { mod cli_run {
use cli_utils::helpers::{ use cli_utils::helpers::{
extract_valgrind_errors, file_path_from_root, fixture_file, fixtures_dir, has_error, extract_valgrind_errors, file_path_from_root, fixture_file, fixtures_dir, has_error,
known_bad_file, run_cmd, run_roc, run_with_valgrind, strip_colors, Out, ValgrindError, known_bad_file, run_cmd, run_roc, run_with_valgrind, Out, ValgrindError,
ValgrindErrorXWhat, ValgrindErrorXWhat,
}; };
use const_format::concatcp; use const_format::concatcp;
use indoc::indoc; use indoc::indoc;
use roc_cli::{CMD_BUILD, CMD_CHECK, CMD_DEV, CMD_FORMAT, CMD_RUN, CMD_TEST}; use roc_cli::{CMD_BUILD, CMD_CHECK, CMD_DEV, CMD_FORMAT, CMD_RUN, CMD_TEST};
use roc_reporting::report::strip_colors;
use roc_test_utils::assert_multiline_str_eq; use roc_test_utils::assert_multiline_str_eq;
use serial_test::serial; use serial_test::serial;
use std::iter; use std::iter;

View file

@ -98,22 +98,6 @@ pub fn path_to_binary(binary_name: &str) -> PathBuf {
path path
} }
pub fn strip_colors(str: &str) -> String {
use roc_reporting::report::ANSI_STYLE_CODES;
str.replace(ANSI_STYLE_CODES.red, "")
.replace(ANSI_STYLE_CODES.green, "")
.replace(ANSI_STYLE_CODES.yellow, "")
.replace(ANSI_STYLE_CODES.blue, "")
.replace(ANSI_STYLE_CODES.magenta, "")
.replace(ANSI_STYLE_CODES.cyan, "")
.replace(ANSI_STYLE_CODES.white, "")
.replace(ANSI_STYLE_CODES.bold, "")
.replace(ANSI_STYLE_CODES.underline, "")
.replace(ANSI_STYLE_CODES.reset, "")
.replace(ANSI_STYLE_CODES.color_reset, "")
}
pub fn run_roc_with_stdin<I, S>(args: I, stdin_vals: &[&str]) -> Out pub fn run_roc_with_stdin<I, S>(args: I, stdin_vals: &[&str]) -> Out
where where
I: IntoIterator<Item = S>, I: IntoIterator<Item = S>,

View file

@ -462,11 +462,9 @@ mod test_reporting {
fn human_readable(str: &str) -> String { fn human_readable(str: &str) -> String {
str.replace(ANSI_STYLE_CODES.red, "<red>") str.replace(ANSI_STYLE_CODES.red, "<red>")
.replace(ANSI_STYLE_CODES.white, "<white>") .replace(ANSI_STYLE_CODES.white, "<white>")
.replace(ANSI_STYLE_CODES.blue, "<blue>")
.replace(ANSI_STYLE_CODES.yellow, "<yellow>") .replace(ANSI_STYLE_CODES.yellow, "<yellow>")
.replace(ANSI_STYLE_CODES.green, "<green>") .replace(ANSI_STYLE_CODES.green, "<green>")
.replace(ANSI_STYLE_CODES.cyan, "<cyan>") .replace(ANSI_STYLE_CODES.cyan, "<cyan>")
.replace(ANSI_STYLE_CODES.magenta, "<magenta>")
.replace(ANSI_STYLE_CODES.reset, "<reset>") .replace(ANSI_STYLE_CODES.reset, "<reset>")
.replace(ANSI_STYLE_CODES.bold, "<bold>") .replace(ANSI_STYLE_CODES.bold, "<bold>")
.replace(ANSI_STYLE_CODES.underline, "<underline>") .replace(ANSI_STYLE_CODES.underline, "<underline>")
@ -759,7 +757,7 @@ mod test_reporting {
&DEFAULT_PALETTE, &DEFAULT_PALETTE,
); );
assert_eq!(human_readable(&buf), "<blue>activityIndicatorLarge<reset>"); assert_eq!(human_readable(&buf), "<cyan>activityIndicatorLarge<reset>");
} }
#[test] #[test]

View file

@ -26,9 +26,9 @@ use roc_module::symbol::{Interns, ModuleId};
use roc_packaging::cache::RocCacheDir; use roc_packaging::cache::RocCacheDir;
use roc_problem::can::Problem; use roc_problem::can::Problem;
use roc_region::all::LineInfo; use roc_region::all::LineInfo;
use roc_reporting::report::RenderTarget;
use roc_reporting::report::RocDocAllocator; use roc_reporting::report::RocDocAllocator;
use roc_reporting::report::{can_problem, DEFAULT_PALETTE}; use roc_reporting::report::{can_problem, DEFAULT_PALETTE};
use roc_reporting::report::{strip_colors, RenderTarget};
use roc_solve::FunctionKind; use roc_solve::FunctionKind;
use roc_target::TargetInfo; use roc_target::TargetInfo;
use roc_types::pretty_print::name_and_print_var; use roc_types::pretty_print::name_and_print_var;
@ -1218,11 +1218,9 @@ fn non_roc_file_extension() {
I expected a file with extension `.roc` or without extension. I expected a file with extension `.roc` or without extension.
Instead I received a file with extension `.md`." Instead I received a file with extension `.md`."
); );
let color_start = String::from_utf8(vec![27, 91, 51, 54, 109]).unwrap();
let color_end = String::from_utf8(vec![27, 91, 48, 109]).unwrap(); let err = strip_colors(&multiple_modules("non_roc_file_extension", modules).unwrap_err());
let err = multiple_modules("non_roc_file_extension", modules).unwrap_err();
let err = err.replace(&color_start, "");
let err = err.replace(&color_end, "");
assert_eq!(err, expected, "\n{}", err); assert_eq!(err, expected, "\n{}", err);
} }
@ -1255,10 +1253,8 @@ fn roc_file_no_extension() {
The provided file did not start with a shebang `#!` containing the The provided file did not start with a shebang `#!` containing the
string `roc`. Is tmp/roc_file_no_extension/main a Roc file?" string `roc`. Is tmp/roc_file_no_extension/main a Roc file?"
); );
let color_start = String::from_utf8(vec![27, 91, 51, 54, 109]).unwrap();
let color_end = String::from_utf8(vec![27, 91, 48, 109]).unwrap(); let err = strip_colors(&multiple_modules("roc_file_no_extension", modules).unwrap_err());
let err = multiple_modules("roc_file_no_extension", modules).unwrap_err();
let err = err.replace(&color_start, "");
let err = err.replace(&color_end, "");
assert_eq!(err, expected, "\n{}", err); assert_eq!(err, expected, "\n{}", err);
} }

View file

@ -6,7 +6,7 @@ use const_format::concatcp;
use roc_load::MonomorphizedModule; use roc_load::MonomorphizedModule;
use roc_mono::ir::OptLevel; use roc_mono::ir::OptLevel;
use roc_repl_eval::gen::Problems; use roc_repl_eval::gen::Problems;
use roc_repl_ui::colors::{BLUE, END_COL, PINK}; use roc_repl_ui::colors::{CYAN, END_COL};
use roc_repl_ui::repl_state::{ReplAction, ReplState}; use roc_repl_ui::repl_state::{ReplAction, ReplState};
use roc_repl_ui::{format_output, is_incomplete, CONT_PROMPT, PROMPT, SHORT_INSTRUCTIONS, TIPS}; use roc_repl_ui::{format_output, is_incomplete, CONT_PROMPT, PROMPT, SHORT_INSTRUCTIONS, TIPS};
use roc_reporting::report::{ANSI_STYLE_CODES, DEFAULT_PALETTE}; use roc_reporting::report::{ANSI_STYLE_CODES, DEFAULT_PALETTE};
@ -21,11 +21,8 @@ use crate::cli_gen::eval_llvm;
pub const WELCOME_MESSAGE: &str = concatcp!( pub const WELCOME_MESSAGE: &str = concatcp!(
"\n The rockin' ", "\n The rockin' ",
BLUE, CYAN,
"roc repl", "roc repl\n",
END_COL,
"\n",
PINK,
"────────────────────────", "────────────────────────",
END_COL, END_COL,
"\n\n" "\n\n"

View file

@ -23,6 +23,7 @@ bumpalo.workspace = true
indoc.workspace = true indoc.workspace = true
strip-ansi-escapes.workspace = true strip-ansi-escapes.workspace = true
target-lexicon.workspace = true target-lexicon.workspace = true
regex.workspace = true
rustyline.workspace = true rustyline.workspace = true
[features] [features]

View file

@ -1,4 +1,5 @@
use bumpalo::Bump; use bumpalo::Bump;
use regex::Regex;
use roc_wasm_interp::{ use roc_wasm_interp::{
wasi, DefaultImportDispatcher, ImportDispatcher, Instance, Value, WasiDispatcher, wasi, DefaultImportDispatcher, ImportDispatcher, Instance, Value, WasiDispatcher,
}; };
@ -158,11 +159,11 @@ pub fn expect_failure(input: &'static str, expected: &str) {
pub fn expect(input: &'static str, expected: &str) { pub fn expect(input: &'static str, expected: &str) {
let raw_output = run(input); let raw_output = run(input);
// We need to get rid of HTML tags, and we can be quite specific about it! // remove color HTML tags
// If we ever write more complex test cases, we might need regex here. let regx = Regex::new("<span class='color-(.*?)'> : </span>").unwrap();
let without_html = raw_output.replace("<span class='color-magenta'> : </span>", " : "); let without_html = regx.replace_all(&raw_output, " : ");
let clean_output = without_html.trim(); let trimmed_output = without_html.trim();
assert_eq!(clean_output, expected); assert_eq!(trimmed_output, expected);
} }

View file

@ -6,7 +6,6 @@ const STYLE_CODES: StyleCodes = if cfg!(target_family = "wasm") {
ANSI_STYLE_CODES ANSI_STYLE_CODES
}; };
pub const BLUE: &str = STYLE_CODES.blue;
pub const PINK: &str = STYLE_CODES.magenta;
pub const GREEN: &str = STYLE_CODES.green; pub const GREEN: &str = STYLE_CODES.green;
pub const CYAN: &str = STYLE_CODES.cyan;
pub const END_COL: &str = STYLE_CODES.reset; pub const END_COL: &str = STYLE_CODES.reset;

View file

@ -4,19 +4,17 @@ pub mod colors;
pub mod repl_state; pub mod repl_state;
use bumpalo::Bump; use bumpalo::Bump;
use colors::{BLUE, END_COL, PINK}; use colors::{CYAN, END_COL, GREEN};
use const_format::concatcp; use const_format::concatcp;
use repl_state::{parse_src, ParseOutcome}; use repl_state::{parse_src, ParseOutcome};
use roc_parse::ast::{Expr, ValueDef}; use roc_parse::ast::{Expr, ValueDef};
use roc_repl_eval::gen::{Problems, ReplOutput}; use roc_repl_eval::gen::{Problems, ReplOutput};
use roc_reporting::report::StyleCodes; use roc_reporting::report::StyleCodes;
use crate::colors::GREEN;
// TODO add link to repl tutorial (does not yet exist). // TODO add link to repl tutorial (does not yet exist).
pub const TIPS: &str = concatcp!( pub const TIPS: &str = concatcp!(
"\nEnter an expression to evaluate, or a definition (like ", "\nEnter an expression to evaluate, or a definition (like ",
BLUE, CYAN,
"x = 1", "x = 1",
END_COL, END_COL,
") to use later.\n\n", ") to use later.\n\n",
@ -25,25 +23,25 @@ pub const TIPS: &str = concatcp!(
} else { } else {
// We use ctrl-v + ctrl-j for newlines because on Unix, terminals cannot distinguish between Shift-Enter and Enter // We use ctrl-v + ctrl-j for newlines because on Unix, terminals cannot distinguish between Shift-Enter and Enter
concatcp!( concatcp!(
BLUE, CYAN,
" - ", " - ",
END_COL, END_COL,
PINK, GREEN,
"ctrl-v", "ctrl-v",
END_COL, END_COL,
" + ", " + ",
PINK, GREEN,
"ctrl-j", "ctrl-j",
END_COL, END_COL,
" makes a newline\n", " makes a newline\n",
BLUE, CYAN,
" - ", " - ",
END_COL, END_COL,
GREEN, GREEN,
":q", ":q",
END_COL, END_COL,
" quits\n", " quits\n",
BLUE, CYAN,
" - ", " - ",
END_COL, END_COL,
GREEN, GREEN,
@ -57,8 +55,8 @@ pub const TIPS: &str = concatcp!(
// For when nothing is entered in the repl // For when nothing is entered in the repl
// TODO add link to repl tutorial(does not yet exist). // TODO add link to repl tutorial(does not yet exist).
pub const SHORT_INSTRUCTIONS: &str = "Enter an expression, or :help, or :q to quit.\n\n"; pub const SHORT_INSTRUCTIONS: &str = "Enter an expression, or :help, or :q to quit.\n\n";
pub const PROMPT: &str = concatcp!(BLUE, "»", END_COL, " "); pub const PROMPT: &str = concatcp!(CYAN, "»", END_COL, " ");
pub const CONT_PROMPT: &str = concatcp!(BLUE, "", END_COL, " "); pub const CONT_PROMPT: &str = concatcp!(CYAN, "", END_COL, " ");
pub fn is_incomplete(input: &str) -> bool { pub fn is_incomplete(input: &str) -> bool {
let arena = Bump::new(); let arena = Bump::new();
@ -116,7 +114,7 @@ pub fn format_output(
{ {
buf.push('\n'); buf.push('\n');
buf.push_str(&expr); buf.push_str(&expr);
buf.push_str(style_codes.magenta); // Color for the type separator buf.push_str(style_codes.green); // Color for the type separator
buf.push_str(EXPR_TYPE_SEPARATOR); buf.push_str(EXPR_TYPE_SEPARATOR);
buf.push_str(style_codes.reset); buf.push_str(style_codes.reset);
buf.push_str(&expr_type); buf.push_str(&expr_type);

View file

@ -6,6 +6,8 @@ use roc_problem::can::Problem;
use roc_region::all::LineInfo; use roc_region::all::LineInfo;
use roc_solve_problem::TypeError; use roc_solve_problem::TypeError;
use crate::report::ANSI_STYLE_CODES;
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub struct Problems { pub struct Problems {
pub fatally_errored: bool, pub fatally_errored: bool,
@ -26,11 +28,11 @@ impl Problems {
} }
pub fn print_to_stdout(&self, total_time: std::time::Duration) { pub fn print_to_stdout(&self, total_time: std::time::Duration) {
const GREEN: usize = 32; const GREEN: &str = ANSI_STYLE_CODES.green;
const YELLOW: usize = 33; const YELLOW: &str = ANSI_STYLE_CODES.yellow;
print!( print!(
"\x1B[{}m{}\x1B[39m {} and \x1B[{}m{}\x1B[39m {} found in {} ms", "{}{}\x1B[39m {} and {}{}\x1B[39m {} found in {} ms",
match self.errors { match self.errors {
0 => GREEN, 0 => GREEN,
_ => YELLOW, _ => YELLOW,
@ -54,6 +56,39 @@ impl Problems {
} }
} }
// prints e.g. `1 error and 0 warnings found in 63 ms.`
pub fn print_error_warning_count(
error_count: usize,
warning_count: usize,
total_time: std::time::Duration,
) {
const GREEN: &str = ANSI_STYLE_CODES.green;
const YELLOW: &str = ANSI_STYLE_CODES.yellow;
print!(
"{}{}\x1B[39m {} and {}{}\x1B[39m {} found in {} ms",
match error_count {
0 => GREEN,
_ => YELLOW,
},
error_count,
match error_count {
1 => "error",
_ => "errors",
},
match warning_count {
0 => GREEN,
_ => YELLOW,
},
warning_count,
match warning_count {
1 => "warning",
_ => "warnings",
},
total_time.as_millis()
);
}
pub fn report_problems( pub fn report_problems(
sources: &MutMap<ModuleId, (PathBuf, Box<str>)>, sources: &MutMap<ModuleId, (PathBuf, Box<str>)>,
interns: &Interns, interns: &Interns,

View file

@ -219,7 +219,7 @@ const fn default_palette_from_style_codes(codes: StyleCodes) -> Palette {
code_block: codes.white, code_block: codes.white,
keyword: codes.green, keyword: codes.green,
ellipsis: codes.green, ellipsis: codes.green,
variable: codes.blue, variable: codes.cyan,
type_variable: codes.yellow, type_variable: codes.yellow,
structure: codes.green, structure: codes.green,
alias: codes.yellow, alias: codes.yellow,
@ -249,8 +249,6 @@ pub struct StyleCodes {
pub red: &'static str, pub red: &'static str,
pub green: &'static str, pub green: &'static str,
pub yellow: &'static str, pub yellow: &'static str,
pub blue: &'static str,
pub magenta: &'static str,
pub cyan: &'static str, pub cyan: &'static str,
pub white: &'static str, pub white: &'static str,
pub bold: &'static str, pub bold: &'static str,
@ -260,12 +258,10 @@ pub struct StyleCodes {
} }
pub const ANSI_STYLE_CODES: StyleCodes = StyleCodes { pub const ANSI_STYLE_CODES: StyleCodes = StyleCodes {
red: "\u{001b}[31m", red: "\u{001b}[1;31m",
green: "\u{001b}[32m", green: "\u{001b}[1;32m",
yellow: "\u{001b}[33m", yellow: "\u{001b}[1;33m",
blue: "\u{001b}[34m", cyan: "\u{001b}[1;36m",
magenta: "\u{001b}[35m",
cyan: "\u{001b}[36m",
white: "\u{001b}[37m", white: "\u{001b}[37m",
bold: "\u{001b}[1m", bold: "\u{001b}[1m",
underline: "\u{001b}[4m", underline: "\u{001b}[4m",
@ -283,8 +279,6 @@ pub const HTML_STYLE_CODES: StyleCodes = StyleCodes {
red: html_color!("red"), red: html_color!("red"),
green: html_color!("green"), green: html_color!("green"),
yellow: html_color!("yellow"), yellow: html_color!("yellow"),
blue: html_color!("blue"),
magenta: html_color!("magenta"),
cyan: html_color!("cyan"), cyan: html_color!("cyan"),
white: html_color!("white"), white: html_color!("white"),
bold: "<span class='bold'>", bold: "<span class='bold'>",
@ -293,6 +287,19 @@ pub const HTML_STYLE_CODES: StyleCodes = StyleCodes {
color_reset: "</span>", color_reset: "</span>",
}; };
// useful for tests
pub fn strip_colors(str: &str) -> String {
str.replace(ANSI_STYLE_CODES.red, "")
.replace(ANSI_STYLE_CODES.green, "")
.replace(ANSI_STYLE_CODES.yellow, "")
.replace(ANSI_STYLE_CODES.cyan, "")
.replace(ANSI_STYLE_CODES.white, "")
.replace(ANSI_STYLE_CODES.bold, "")
.replace(ANSI_STYLE_CODES.underline, "")
.replace(ANSI_STYLE_CODES.reset, "")
.replace(ANSI_STYLE_CODES.color_reset, "")
}
// define custom allocator struct so we can `impl RocDocAllocator` custom helpers // define custom allocator struct so we can `impl RocDocAllocator` custom helpers
pub struct RocDocAllocator<'a> { pub struct RocDocAllocator<'a> {
upstream: BoxAllocator, upstream: BoxAllocator,