From def09b7c79f0927a7c3a56de54075f4ee52dec97 Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Sun, 1 Mar 2020 13:13:18 -0600 Subject: [PATCH] Support 256-color terminal environments Fixes #110 With this commit, delta enters "24 bit color mode" iff either of the following are true: 1. The --24-bit-color command line option value is "always" 2. The --24-bit-color command line option value is "auto" and the COLORTERM environment variable is set to "truecolor" or "24bit". See https://gist.github.com/XVilka/8346728#true-color-detection https://github.com/sharkdp/bat/blob/7779d9f6221b3e98c43a43ceb5596ba285fdf4f8/src/bin/bat/app.rs#L29-L33 Otherwise, delta enters "8-bit color mode". In "24 bit color mode", delta will 1. Emit 24-bit RGB color shell escape sequences that will only be displayed correctly by a terminal application that supports 24 bit colors. 2. Select default background colors that will only be displayed correctly by a terminal application that supports 24 bit colors. In "8-bit color mode", delta will 1. Emit color shell escape sequences specifying the entry in the ANSI 256 color palette that is closest (according to the ansi_colours library) to the requested color. 2. Select default background colors that will work well in a terminal application that suports 8-bit color but not 24-bit color. --- Cargo.lock | 10 +++++ Cargo.toml | 1 + src/cli.rs | 29 ++++++++++++++ src/config.rs | 44 +++++++------------- src/delta.rs | 32 ++++++--------- src/draw.rs | 41 +++++++++++++------ src/main.rs | 25 ++++++++---- src/paint.rs | 36 +++++++++++++---- src/style.rs | 108 ++++++++++++++++++++++++++++++++++++++++++++++---- 9 files changed, 241 insertions(+), 85 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8654d5ae5..cf2c6348a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,6 +13,14 @@ dependencies = [ "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ansi_colours" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ansi_term" version = "0.11.0" @@ -273,6 +281,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "git-delta" version = "0.0.16" dependencies = [ + "ansi_colours 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "box_drawing 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -829,6 +838,7 @@ dependencies = [ [metadata] "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" +"checksum ansi_colours 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d0f302a81afc6a7f4350c04f0ba7cfab529cc009bca3324b3fb5764e6add8b6" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" diff --git a/Cargo.toml b/Cargo.toml index fb7d071a7..25ff717bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ name = "delta" path = "src/main.rs" [dependencies] +ansi_colours = "1.0.1" ansi_term = "0.11.0" atty = "0.2.13" box_drawing = "0.1.2" diff --git a/src/cli.rs b/src/cli.rs index f896c4920..3337f7742 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -8,6 +8,7 @@ use structopt::StructOpt; use crate::bat::assets::HighlightingAssets; use crate::bat::output::PagingMode; use crate::config; +use crate::env; use crate::style; #[derive(StructOpt, Clone, Debug)] @@ -155,6 +156,14 @@ pub struct Opt { #[structopt(long = "max-line-distance", default_value = "0.3")] pub max_line_distance: f64, + /// Whether to emit 24-bit ("true color") RGB color codes. Options are auto, always, and never. + /// "auto" means that delta will emit 24-bit color codes iff the environment variable COLORTERM + /// has the value "truecolor" or "24bit". If your terminal application (the application you use + /// to enter commands at a shell prompt) supports 24 bit colors, then it probably already sets + /// this environment variable, in which case you don't need to do anything. + #[structopt(long = "24-bit-color", default_value = "auto")] + pub true_color: String, + /// Whether to use a pager when displaying output. Options are: auto, always, and never. The /// default pager is `less`: this can be altered by setting the environment variables BAT_PAGER /// or PAGER (BAT_PAGER has priority). @@ -257,12 +266,32 @@ pub fn process_command_line_arguments<'a>( } }; + let true_color = match opt.true_color.as_ref() { + "always" => true, + "never" => false, + "auto" => is_truecolor_terminal(), + _ => { + eprintln!( + "Invalid value for --24-bit-color option: {} (valid values are \"always\", \"never\", and \"auto\")", + opt.true_color + ); + process::exit(1); + } + }; + config::get_config( opt, &assets.syntax_set, &assets.theme_set, + true_color, available_terminal_width, background_color_width, paging_mode, ) } + +fn is_truecolor_terminal() -> bool { + env::get_env_var("COLORTERM") + .map(|colorterm| colorterm == "truecolor" || colorterm == "24bit") + .unwrap_or(false) +} diff --git a/src/config.rs b/src/config.rs index 3c3f033b1..2a6590aac 100644 --- a/src/config.rs +++ b/src/config.rs @@ -4,11 +4,11 @@ use std::str::FromStr; use syntect::highlighting::{Color, Style, StyleModifier, Theme, ThemeSet}; use syntect::parsing::SyntaxSet; +use crate::bat::output::PagingMode; use crate::cli; use crate::env; use crate::paint; use crate::style; -use crate::bat::output::{PagingMode}; pub struct Config<'a> { pub theme: Option<&'a Theme>, @@ -22,6 +22,7 @@ pub struct Config<'a> { pub hunk_color: Color, pub syntax_set: &'a SyntaxSet, pub terminal_width: usize, + pub true_color: bool, pub width: Option, pub tab_width: usize, pub opt: &'a cli::Opt, @@ -34,6 +35,7 @@ pub fn get_config<'a>( opt: &'a cli::Opt, syntax_set: &'a SyntaxSet, theme_set: &'a ThemeSet, + true_color: bool, terminal_width: usize, width: Option, paging_mode: PagingMode, @@ -53,11 +55,9 @@ pub fn get_config<'a>( }; let minus_style_modifier = StyleModifier { - background: Some(color_from_arg_or_mode_default( + background: Some(color_from_arg( opt.minus_color.as_ref(), - is_light_mode, - style::LIGHT_THEME_MINUS_COLOR, - style::DARK_THEME_MINUS_COLOR, + style::get_minus_color_default(is_light_mode, true_color), )), foreground: if opt.highlight_removed { None @@ -68,11 +68,9 @@ pub fn get_config<'a>( }; let minus_emph_style_modifier = StyleModifier { - background: Some(color_from_arg_or_mode_default( + background: Some(color_from_arg( opt.minus_emph_color.as_ref(), - is_light_mode, - style::LIGHT_THEME_MINUS_EMPH_COLOR, - style::DARK_THEME_MINUS_EMPH_COLOR, + style::get_minus_emph_color_default(is_light_mode, true_color), )), foreground: if opt.highlight_removed { None @@ -83,22 +81,18 @@ pub fn get_config<'a>( }; let plus_style_modifier = StyleModifier { - background: Some(color_from_arg_or_mode_default( + background: Some(color_from_arg( opt.plus_color.as_ref(), - is_light_mode, - style::LIGHT_THEME_PLUS_COLOR, - style::DARK_THEME_PLUS_COLOR, + style::get_plus_color_default(is_light_mode, true_color), )), foreground: None, font_style: None, }; let plus_emph_style_modifier = StyleModifier { - background: Some(color_from_arg_or_mode_default( + background: Some(color_from_arg( opt.plus_emph_color.as_ref(), - is_light_mode, - style::LIGHT_THEME_PLUS_EMPH_COLOR, - style::DARK_THEME_PLUS_EMPH_COLOR, + style::get_plus_emph_color_default(is_light_mode, true_color), )), foreground: None, font_style: None, @@ -114,6 +108,7 @@ pub fn get_config<'a>( commit_color: color_from_rgb_or_ansi_code(&opt.commit_color), file_color: color_from_rgb_or_ansi_code(&opt.file_color), hunk_color: color_from_rgb_or_ansi_code(&opt.hunk_color), + true_color, terminal_width, width, tab_width: opt.tab_width, @@ -192,20 +187,9 @@ fn color_from_rgb_or_ansi_code(s: &str) -> Color { } } -fn color_from_arg_or_mode_default( - arg: Option<&String>, - is_light_mode: bool, - light_theme_default: Color, - dark_theme_default: Color, -) -> Color { +fn color_from_arg(arg: Option<&String>, default: Color) -> Color { match arg { Some(string) => color_from_rgb_or_ansi_code(&string), - None => { - if is_light_mode { - light_theme_default - } else { - dark_theme_default - } - } + None => default, } } diff --git a/src/delta.rs b/src/delta.rs index e68b8bd03..8d36db585 100644 --- a/src/delta.rs +++ b/src/delta.rs @@ -204,6 +204,7 @@ fn handle_commit_meta_header_line( config.terminal_width, config.commit_color, true, + config.true_color, )?; Ok(()) } @@ -234,10 +235,11 @@ fn handle_generic_file_meta_header_line( writeln!(painter.writer)?; draw_fn( painter.writer, - &paint::paint_text_foreground(line, config.file_color), + &paint::paint_text_foreground(line, config.file_color, config.true_color), config.terminal_width, config.file_color, false, + config.true_color, )?; Ok(()) } @@ -279,13 +281,14 @@ fn handle_hunk_meta_line( config.terminal_width, config.hunk_color, false, + config.true_color, )?; painter.output_buffer.clear(); } writeln!( painter.writer, "\n{}", - paint::paint_text_foreground(line_number, config.hunk_color) + paint::paint_text_foreground(line_number, config.hunk_color, config.true_color) )?; Ok(()) } @@ -431,6 +434,7 @@ mod tests { #[test] fn test_theme_selection() { + #[derive(PartialEq)] enum Mode { Light, Dark, @@ -496,6 +500,7 @@ mod tests { } else { env::set_var("BAT_THEME", bat_theme_env_var); } + let is_true_color = true; let mut options = get_command_line_options(); options.theme = theme_option; match mode_option { @@ -521,31 +526,19 @@ mod tests { } assert_eq!( config.minus_style_modifier.background.unwrap(), - match expected_mode { - Mode::Light => style::LIGHT_THEME_MINUS_COLOR, - Mode::Dark => style::DARK_THEME_MINUS_COLOR, - } + style::get_minus_color_default(expected_mode == Mode::Light, is_true_color) ); assert_eq!( config.minus_emph_style_modifier.background.unwrap(), - match expected_mode { - Mode::Light => style::LIGHT_THEME_MINUS_EMPH_COLOR, - Mode::Dark => style::DARK_THEME_MINUS_EMPH_COLOR, - } + style::get_minus_emph_color_default(expected_mode == Mode::Light, is_true_color) ); assert_eq!( config.plus_style_modifier.background.unwrap(), - match expected_mode { - Mode::Light => style::LIGHT_THEME_PLUS_COLOR, - Mode::Dark => style::DARK_THEME_PLUS_COLOR, - } + style::get_plus_color_default(expected_mode == Mode::Light, is_true_color) ); assert_eq!( config.plus_emph_style_modifier.background.unwrap(), - match expected_mode { - Mode::Light => style::LIGHT_THEME_PLUS_EMPH_COLOR, - Mode::Dark => style::DARK_THEME_PLUS_EMPH_COLOR, - } + style::get_plus_emph_color_default(expected_mode == Mode::Light, is_true_color) ); } } @@ -580,7 +573,7 @@ mod tests { fn paint_text(input: &str, style_modifier: StyleModifier, config: &Config) -> String { let mut output = String::new(); let style = config.no_style.apply(style_modifier); - paint::paint_text(&input, style, &mut output); + paint::paint_text(&input, style, &mut output, config.true_color); output } @@ -623,6 +616,7 @@ mod tests { file_color: "Blue".to_string(), hunk_style: cli::SectionStyle::Box, hunk_color: "blue".to_string(), + true_color: "always".to_string(), width: Some("variable".to_string()), paging_mode: "auto".to_string(), tab_width: 4, diff --git a/src/draw.rs b/src/draw.rs index 751f99f9a..03b93bdb7 100644 --- a/src/draw.rs +++ b/src/draw.rs @@ -15,6 +15,7 @@ pub fn write_boxed( _line_width: usize, // ignored color: Color, heavy: bool, + true_color: bool, ) -> std::io::Result<()> { let up_left = if heavy { box_drawing::heavy::UP_LEFT @@ -22,8 +23,12 @@ pub fn write_boxed( box_drawing::light::UP_LEFT }; let box_width = strip_ansi_codes(text).graphemes(true).count() + 1; - write_boxed_partial(writer, text, box_width, color, heavy)?; - write!(writer, "{}", paint::paint_text_foreground(up_left, color))?; + write_boxed_partial(writer, text, box_width, color, heavy, true_color)?; + write!( + writer, + "{}", + paint::paint_text_foreground(up_left, color, true_color) + )?; Ok(()) } @@ -35,9 +40,10 @@ pub fn write_boxed_with_line( line_width: usize, color: Color, heavy: bool, + true_color: bool, ) -> std::io::Result<()> { let box_width = strip_ansi_codes(text).graphemes(true).count() + 1; - write_boxed_with_horizontal_whisker(writer, text, box_width, color, heavy)?; + write_boxed_with_horizontal_whisker(writer, text, box_width, color, heavy, true_color)?; write_horizontal_line( writer, if line_width > box_width { @@ -47,6 +53,7 @@ pub fn write_boxed_with_line( }, color, heavy, + true_color, )?; write!(writer, "\n")?; Ok(()) @@ -58,9 +65,14 @@ pub fn write_underlined( line_width: usize, color: Color, heavy: bool, + true_color: bool, ) -> std::io::Result<()> { - writeln!(writer, "{}", paint::paint_text_foreground(text, color))?; - write_horizontal_line(writer, line_width - 1, color, heavy)?; + writeln!( + writer, + "{}", + paint::paint_text_foreground(text, color, true_color) + )?; + write_horizontal_line(writer, line_width - 1, color, heavy, true_color)?; write!(writer, "\n")?; Ok(()) } @@ -70,6 +82,7 @@ fn write_horizontal_line( line_width: usize, color: Color, heavy: bool, + true_color: bool, ) -> std::io::Result<()> { let horizontal = if heavy { box_drawing::heavy::HORIZONTAL @@ -79,7 +92,7 @@ fn write_horizontal_line( write!( writer, "{}", - paint::paint_text_foreground(&horizontal.repeat(line_width), color) + paint::paint_text_foreground(&horizontal.repeat(line_width), color, true_color) ) } @@ -89,17 +102,18 @@ pub fn write_boxed_with_horizontal_whisker( box_width: usize, color: Color, heavy: bool, + true_color: bool, ) -> std::io::Result<()> { let up_horizontal = if heavy { box_drawing::heavy::UP_HORIZONTAL } else { box_drawing::light::UP_HORIZONTAL }; - write_boxed_partial(writer, text, box_width, color, heavy)?; + write_boxed_partial(writer, text, box_width, color, heavy, true_color)?; write!( writer, "{}", - paint::paint_text_foreground(up_horizontal, color) + paint::paint_text_foreground(up_horizontal, color, true_color) )?; Ok(()) } @@ -110,6 +124,7 @@ fn write_boxed_partial( box_width: usize, color: Color, heavy: bool, + true_color: bool, ) -> std::io::Result<()> { let horizontal = if heavy { box_drawing::heavy::HORIZONTAL @@ -131,10 +146,10 @@ fn write_boxed_partial( write!( writer, "{}{}\n{} {}\n{}", - paint::paint_text_foreground(&horizontal_edge, color), - paint::paint_text_foreground(down_left, color), - paint::paint_text_foreground(text, color), - paint::paint_text_foreground(vertical, color), - paint::paint_text_foreground(&horizontal_edge, color), + paint::paint_text_foreground(&horizontal_edge, color, true_color), + paint::paint_text_foreground(down_left, color, true_color), + paint::paint_text_foreground(text, color, true_color), + paint::paint_text_foreground(vertical, color, true_color), + paint::paint_text_foreground(&horizontal_edge, color, true_color), ) } diff --git a/src/main.rs b/src/main.rs index fea301158..79f00ea51 100644 --- a/src/main.rs +++ b/src/main.rs @@ -82,16 +82,26 @@ fn show_background_colors(config: &config::Config) { --minus-emph-color=\"{minus_emph_color}\" \ --plus-color=\"{plus_color}\" \ --plus-emph-color=\"{plus_emph_color}\"", - minus_color = get_painted_rgb_string(config.minus_style_modifier.background.unwrap()), - minus_emph_color = - get_painted_rgb_string(config.minus_emph_style_modifier.background.unwrap()), - plus_color = get_painted_rgb_string(config.plus_style_modifier.background.unwrap()), - plus_emph_color = - get_painted_rgb_string(config.plus_emph_style_modifier.background.unwrap()), + minus_color = get_painted_rgb_string( + config.minus_style_modifier.background.unwrap(), + config.true_color + ), + minus_emph_color = get_painted_rgb_string( + config.minus_emph_style_modifier.background.unwrap(), + config.true_color + ), + plus_color = get_painted_rgb_string( + config.plus_style_modifier.background.unwrap(), + config.true_color + ), + plus_emph_color = get_painted_rgb_string( + config.plus_emph_style_modifier.background.unwrap(), + config.true_color + ), ) } -fn get_painted_rgb_string(color: Color) -> String { +fn get_painted_rgb_string(color: Color, true_color: bool) -> String { let mut string = String::new(); let style = Style { foreground: style::NO_COLOR, @@ -102,6 +112,7 @@ fn get_painted_rgb_string(color: Color) -> String { &format!("#{:02x?}{:02x?}{:02x?}", color.r, color.g, color.b), style, &mut string, + true_color, ); string.push_str("\x1b[0m"); // reset string diff --git a/src/paint.rs b/src/paint.rs index cf6968e1d..f85c64a12 100644 --- a/src/paint.rs +++ b/src/paint.rs @@ -1,6 +1,7 @@ use std::io::Write; use std::str::FromStr; +use ansi_colours; use syntect::easy::HighlightLines; use syntect::highlighting::{Color, Style, StyleModifier}; use syntect::parsing::{SyntaxReference, SyntaxSet}; @@ -109,7 +110,7 @@ impl<'a> Painter<'a> { { let mut text_width = 0; for (style, text) in superimpose_style_sections(syntax_sections, diff_sections) { - paint_text(&text, style, output_buffer); + paint_text(&text, style, output_buffer, config.true_color); if config.width.is_some() { text_width += text.graphemes(true).count(); } @@ -127,6 +128,7 @@ impl<'a> Painter<'a> { &" ".repeat(width - text_width), background_style, output_buffer, + config.true_color, ); } _ => (), @@ -206,22 +208,34 @@ impl<'a> Painter<'a> { } /// Write section text to buffer with shell escape codes specifying foreground and background color. -pub fn paint_text(text: &str, style: Style, output_buffer: &mut String) { +pub fn paint_text(text: &str, style: Style, output_buffer: &mut String, true_color: bool) { if text.is_empty() { return; } if style.background != style::NO_COLOR { - output_buffer.push_str(&get_color_escape_sequence(style.background, false)); + output_buffer.push_str(&get_color_escape_sequence( + style.background, + false, + true_color, + )); } if style.foreground != style::NO_COLOR { - output_buffer.push_str(&get_color_escape_sequence(style.foreground, true)); + output_buffer.push_str(&get_color_escape_sequence( + style.foreground, + true, + true_color, + )); } output_buffer.push_str(text); } /// Return text together with shell escape codes specifying the foreground color. -pub fn paint_text_foreground(text: &str, color: Color) -> String { - format!("{}{}", get_color_escape_sequence(color, true), text) +pub fn paint_text_foreground(text: &str, color: Color, true_color: bool) -> String { + format!( + "{}{}", + get_color_escape_sequence(color, true, true_color), + text, + ) } /// Return shell escape sequence specifying either an RGB color, or a user-customizable 8-bit ANSI @@ -229,11 +243,11 @@ pub fn paint_text_foreground(text: &str, color: Color) -> String { // See // https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit // https://github.com/ogham/rust-ansi-term/blob/ff7eba98d55ad609c7fcc8c7bb0859b37c7545cc/src/ansi.rs#L82-L112 -fn get_color_escape_sequence(color: Color, foreground: bool) -> String { +fn get_color_escape_sequence(color: Color, foreground: bool, true_color: bool) -> String { if color.a == 0 { // See https://github.com/sharkdp/bat/pull/543 format!("\x1b[{};5;{}m", if foreground { 38 } else { 48 }, color.r) - } else { + } else if true_color { format!( "\x1b[{};2;{};{};{}m", if foreground { 38 } else { 48 }, @@ -241,6 +255,12 @@ fn get_color_escape_sequence(color: Color, foreground: bool) -> String { color.g, color.b ) + } else { + format!( + "\x1b[{};5;{}m", + if foreground { 38 } else { 48 }, + ansi_colours::ansi256_from_rgb((color.r, color.g, color.b)) + ) } } diff --git a/src/style.rs b/src/style.rs index ae483c8f5..802568053 100644 --- a/src/style.rs +++ b/src/style.rs @@ -19,62 +19,154 @@ pub fn is_no_syntax_highlighting_theme_name(theme_name: &str) -> bool { theme_name.to_lowercase() == "none" } -pub const LIGHT_THEME_MINUS_COLOR: Color = Color { +pub fn get_minus_color_default(is_light_mode: bool, is_true_color: bool) -> Color { + match (is_light_mode, is_true_color) { + (true, true) => LIGHT_THEME_MINUS_COLOR, + (true, false) => LIGHT_THEME_MINUS_COLOR_256, + (false, true) => DARK_THEME_MINUS_COLOR, + (false, false) => DARK_THEME_MINUS_COLOR_256, + } +} + +pub fn get_minus_emph_color_default(is_light_mode: bool, is_true_color: bool) -> Color { + match (is_light_mode, is_true_color) { + (true, true) => LIGHT_THEME_MINUS_EMPH_COLOR, + (true, false) => LIGHT_THEME_MINUS_EMPH_COLOR_256, + (false, true) => DARK_THEME_MINUS_EMPH_COLOR, + (false, false) => DARK_THEME_MINUS_EMPH_COLOR_256, + } +} + +pub fn get_plus_color_default(is_light_mode: bool, is_true_color: bool) -> Color { + match (is_light_mode, is_true_color) { + (true, true) => LIGHT_THEME_PLUS_COLOR, + (true, false) => LIGHT_THEME_PLUS_COLOR_256, + (false, true) => DARK_THEME_PLUS_COLOR, + (false, false) => DARK_THEME_PLUS_COLOR_256, + } +} + +pub fn get_plus_emph_color_default(is_light_mode: bool, is_true_color: bool) -> Color { + match (is_light_mode, is_true_color) { + (true, true) => LIGHT_THEME_PLUS_EMPH_COLOR, + (true, false) => LIGHT_THEME_PLUS_EMPH_COLOR_256, + (false, true) => DARK_THEME_PLUS_EMPH_COLOR, + (false, false) => DARK_THEME_PLUS_EMPH_COLOR_256, + } +} + +const LIGHT_THEME_MINUS_COLOR: Color = Color { r: 0xff, g: 0xe0, b: 0xe0, a: 0xff, }; -pub const LIGHT_THEME_MINUS_EMPH_COLOR: Color = Color { +const LIGHT_THEME_MINUS_COLOR_256: Color = Color { + r: 224, + g: 0x00, + b: 0x00, + a: 0x00, +}; + +const LIGHT_THEME_MINUS_EMPH_COLOR: Color = Color { r: 0xff, g: 0xc0, b: 0xc0, a: 0xff, }; -pub const LIGHT_THEME_PLUS_COLOR: Color = Color { +const LIGHT_THEME_MINUS_EMPH_COLOR_256: Color = Color { + r: 217, + g: 0x00, + b: 0x00, + a: 0x00, +}; + +const LIGHT_THEME_PLUS_COLOR: Color = Color { r: 0xd0, g: 0xff, b: 0xd0, a: 0xff, }; -pub const LIGHT_THEME_PLUS_EMPH_COLOR: Color = Color { +const LIGHT_THEME_PLUS_COLOR_256: Color = Color { + r: 194, + g: 0x00, + b: 0x00, + a: 0x00, +}; + +const LIGHT_THEME_PLUS_EMPH_COLOR: Color = Color { r: 0xa0, g: 0xef, b: 0xa0, a: 0xff, }; -pub const DARK_THEME_MINUS_COLOR: Color = Color { +const LIGHT_THEME_PLUS_EMPH_COLOR_256: Color = Color { + r: 157, + g: 0x00, + b: 0x00, + a: 0x00, +}; + +const DARK_THEME_MINUS_COLOR: Color = Color { r: 0x3f, g: 0x00, b: 0x01, a: 0xff, }; -pub const DARK_THEME_MINUS_EMPH_COLOR: Color = Color { +const DARK_THEME_MINUS_COLOR_256: Color = Color { + r: 52, + g: 0x00, + b: 0x00, + a: 0x00, +}; + +const DARK_THEME_MINUS_EMPH_COLOR: Color = Color { r: 0x90, g: 0x10, b: 0x11, a: 0xff, }; -pub const DARK_THEME_PLUS_COLOR: Color = Color { +const DARK_THEME_MINUS_EMPH_COLOR_256: Color = Color { + r: 124, + g: 0x00, + b: 0x00, + a: 0x00, +}; + +const DARK_THEME_PLUS_COLOR: Color = Color { r: 0x00, g: 0x28, b: 0x00, a: 0xff, }; -pub const DARK_THEME_PLUS_EMPH_COLOR: Color = Color { +const DARK_THEME_PLUS_COLOR_256: Color = Color { + r: 22, + g: 0x00, + b: 0x00, + a: 0x00, +}; + +const DARK_THEME_PLUS_EMPH_COLOR: Color = Color { r: 0x00, g: 0x60, b: 0x00, a: 0xff, }; +const DARK_THEME_PLUS_EMPH_COLOR_256: Color = Color { + r: 28, + g: 0x00, + b: 0x00, + a: 0x00, +}; + /// A special color to specify that no color escape codes should be emitted. pub const NO_COLOR: Color = Color::BLACK;