diff options
-rw-r--r-- | src/cli.rs | 8 | ||||
-rw-r--r-- | src/config.rs | 121 | ||||
-rw-r--r-- | src/delta.rs | 29 | ||||
-rw-r--r-- | src/draw.rs | 53 | ||||
-rw-r--r-- | src/main.rs | 43 | ||||
-rw-r--r-- | src/paint.rs | 257 | ||||
-rw-r--r-- | src/style.rs | 171 | ||||
-rw-r--r-- | src/syntect_color.rs | 39 | ||||
-rw-r--r-- | src/tests/ansi_test_utils.rs | 30 | ||||
-rw-r--r-- | src/tests/test_hunk_highlighting.rs | 52 |
10 files changed, 317 insertions, 486 deletions
@@ -472,19 +472,19 @@ mod tests { assert_eq!(config.theme.unwrap().name.as_ref().unwrap(), expected_theme); } assert_eq!( - config.minus_style_modifier.background.unwrap(), + config.minus_style.background.unwrap(), style::get_minus_color_default(expected_mode == Mode::Light, is_true_color) ); assert_eq!( - config.minus_emph_style_modifier.background.unwrap(), + config.minus_emph_style.background.unwrap(), style::get_minus_emph_color_default(expected_mode == Mode::Light, is_true_color) ); assert_eq!( - config.plus_style_modifier.background.unwrap(), + config.plus_style.background.unwrap(), style::get_plus_color_default(expected_mode == Mode::Light, is_true_color) ); assert_eq!( - config.plus_emph_style_modifier.background.unwrap(), + config.plus_emph_style.background.unwrap(), style::get_plus_emph_color_default(expected_mode == Mode::Light, is_true_color) ); } diff --git a/src/config.rs b/src/config.rs index 773d9a61..7af41290 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,15 +1,19 @@ use std::process; use std::str::FromStr; -use syntect::highlighting::{Color, FontStyle, Style, StyleModifier, Theme, ThemeSet}; +use ansi_term::{Color, Style}; +use syntect::highlighting::Color as SyntectColor; +use syntect::highlighting::Style as SyntectStyle; +use syntect::highlighting::{Theme, ThemeSet}; use syntect::parsing::SyntaxSet; use crate::bat::output::PagingMode; +use crate::bat::terminal::to_ansi_color; use crate::cli; use crate::delta::State; use crate::env; -use crate::paint; use crate::style; +use crate::syntect_color; pub struct Config<'a> { pub theme: Option<Theme>, @@ -17,10 +21,10 @@ pub struct Config<'a> { pub dummy_theme: Theme, pub max_line_distance: f64, pub max_line_distance_for_naively_paired_lines: f64, - pub minus_style_modifier: StyleModifier, - pub minus_emph_style_modifier: StyleModifier, - pub plus_style_modifier: StyleModifier, - pub plus_emph_style_modifier: StyleModifier, + pub minus_style: Style, + pub minus_emph_style: Style, + pub plus_style: Style, + pub plus_emph_style: Style, pub minus_line_marker: &'a str, pub plus_line_marker: &'a str, pub commit_style: cli::SectionStyle, @@ -34,7 +38,8 @@ pub struct Config<'a> { pub true_color: bool, pub background_color_extends_to_terminal_width: bool, pub tab_width: usize, - pub no_style: Style, + pub null_style: Style, + pub null_syntect_style: SyntectStyle, pub max_buffered_lines: usize, pub paging_mode: PagingMode, } @@ -48,11 +53,11 @@ use ColorLayer::*; use State::*; impl<'a> Config<'a> { - pub fn get_style(&self, state: &State) -> Option<StyleModifier> { + pub fn get_style(&self, state: &State) -> Option<Style> { match state { - HunkMinus => Some(self.minus_style_modifier), + HunkMinus => Some(self.minus_style), HunkZero => None, - HunkPlus => Some(self.plus_style_modifier), + HunkPlus => Some(self.plus_style), _ => panic!("Invalid"), } } @@ -108,12 +113,8 @@ pub fn get_config<'a>( &theme_set, ); - let ( - minus_style_modifier, - minus_emph_style_modifier, - plus_style_modifier, - plus_emph_style_modifier, - ) = make_styles(&opt, is_light_mode, true_color); + let (minus_style, minus_emph_style, plus_style, plus_emph_style) = + make_styles(&opt, is_light_mode, true_color); let theme = if style::is_no_syntax_highlighting_theme_name(&theme_name) { None @@ -136,24 +137,25 @@ pub fn get_config<'a>( dummy_theme, max_line_distance: opt.max_line_distance, max_line_distance_for_naively_paired_lines, - minus_style_modifier, - minus_emph_style_modifier, - plus_style_modifier, - plus_emph_style_modifier, + minus_style, + minus_emph_style, + plus_style, + plus_emph_style, minus_line_marker, plus_line_marker, commit_style, - commit_color: color_from_rgb_or_ansi_code(&opt.commit_color), + commit_color: color_from_rgb_or_ansi_code(&opt.commit_color, true_color), file_style, - file_color: color_from_rgb_or_ansi_code(&opt.file_color), + file_color: color_from_rgb_or_ansi_code(&opt.file_color, true_color), hunk_style, - hunk_color: color_from_rgb_or_ansi_code(&opt.hunk_color), + hunk_color: color_from_rgb_or_ansi_code(&opt.hunk_color, true_color), true_color, terminal_width, background_color_extends_to_terminal_width, tab_width, syntax_set, - no_style: style::get_no_style(), + null_style: Style::new(), + null_syntect_style: SyntectStyle::default(), max_buffered_lines: 32, paging_mode, } @@ -218,11 +220,12 @@ fn make_styles<'a>( opt: &'a cli::Opt, is_light_mode: bool, true_color: bool, -) -> (StyleModifier, StyleModifier, StyleModifier, StyleModifier) { +) -> (Style, Style, Style, Style) { let minus_style = make_style( opt.minus_style.as_deref(), Some(style::get_minus_color_default(is_light_mode, true_color)), None, + true_color, ); let minus_emph_style = make_style( @@ -232,12 +235,14 @@ fn make_styles<'a>( true_color, )), minus_style.foreground, + true_color, ); let plus_style = make_style( opt.plus_style.as_deref(), Some(style::get_plus_color_default(is_light_mode, true_color)), None, + true_color, ); let plus_emph_style = make_style( @@ -247,26 +252,27 @@ fn make_styles<'a>( true_color, )), plus_style.foreground, + true_color, ); (minus_style, minus_emph_style, plus_style, plus_emph_style) } -/// Construct syntect StyleModifier from background and foreground strings, -/// together with their defaults. The background string is handled specially in -/// that it may be a single color, or it may be a space-separated "style string". +/// Construct ansi_term Style from style string supplied on command line, +/// together with defaults. fn make_style( style_string: Option<&str>, background_default: Option<Color>, foreground_default: Option<Color>, -) -> StyleModifier { + true_color: bool, +) -> Style { if let Some(s) = style_string { - parse_style_string(s, background_default, foreground_default) + parse_style_string(s, background_default, foreground_default, true_color) } else { - StyleModifier { - background: background_default, + Style { foreground: foreground_default, - font_style: None, + background: background_default, + ..Style::new() } } } @@ -275,24 +281,35 @@ fn parse_style_string( style_string: &str, background_default: Option<Color>, foreground_default: Option<Color>, -) -> StyleModifier { + true_color: bool, +) -> Style { let mut foreground = foreground_default; let mut background = background_default; - let mut font_style = FontStyle::empty(); + let mut style = Style::new(); let mut seen_foreground = false; let mut seen_background = false; for s in style_string.to_lowercase().split_whitespace() { - if s == "bold" { - font_style.set(FontStyle::BOLD, true) + if s == "blink" { + style.is_blink = true; + } else if s == "bold" { + style.is_bold = true; + } else if s == "dimmed" { + style.is_dimmed = true; + } else if s == "hidden" { + style.is_hidden = true; } else if s == "italic" { - font_style.set(FontStyle::ITALIC, true) + style.is_italic = true; + } else if s == "reverse" { + style.is_reverse = true; + } else if s == "strikethrough" { + style.is_strikethrough = true; } else if s == "underline" { - font_style.set(FontStyle::UNDERLINE, true) + style.is_underline = true; } else if !seen_foreground { - foreground = color_from_rgb_or_ansi_code_with_default(Some(s), None); + foreground = color_from_rgb_or_ansi_code_with_default(Some(s), None, true_color); seen_foreground = true; } else if !seen_background { - background = color_from_rgb_or_ansi_code_with_default(Some(s), None); + background = color_from_rgb_or_ansi_code_with_default(Some(s), None, true_color); seen_background = true; } else { eprintln!( @@ -308,37 +325,39 @@ fn parse_style_string( process::exit(1); } } - StyleModifier { - background, + Style { foreground, - font_style: Some(font_style), + background, + ..style } } -fn color_from_rgb_or_ansi_code(s: &str) -> Color { +fn color_from_rgb_or_ansi_code(s: &str, true_color: bool) -> Color { let die = || { eprintln!("Invalid color: {}", s); process::exit(1); }; - if s.starts_with("#") { - Color::from_str(s).unwrap_or_else(|_| die()) + let syntect_color = if s.starts_with("#") { + SyntectColor::from_str(s).unwrap_or_else(|_| die()) } else { s.parse::<u8>() .ok() - .and_then(paint::color_from_ansi_number) - .or_else(|| paint::color_from_ansi_name(s)) + .and_then(syntect_color::syntect_color_from_ansi_number) + .or_else(|| syntect_color::syntect_color_from_ansi_name(s)) .unwrap_or_else(die) - } + }; + to_ansi_color(syntect_color, true_color) } fn color_from_rgb_or_ansi_code_with_default( arg: Option<&str>, default: Option<Color>, + true_color: bool, ) -> Option<Color> { match arg.map(str::to_lowercase) { Some(s) if s == "none" => None, Some(s) if s == "syntax" => Some(style::SYNTAX_HIGHLIGHTING_COLOR), - Some(s) => Some(color_from_rgb_or_ansi_code(&s)), + Some(s) => Some(color_from_rgb_or_ansi_code(&s, true_color)), None => default, } } diff --git a/src/delta.rs b/src/delta.rs index fb52b131..3483259a 100644 --- a/src/delta.rs +++ b/src/delta.rs @@ -1,5 +1,6 @@ use std::io::Write; +use ansi_term::Style; use bytelines::ByteLines; use console::strip_ansi_codes; use std::io::BufRead; @@ -8,9 +9,8 @@ use unicode_segmentation::UnicodeSegmentation; use crate::cli; use crate::config::Config; use crate::draw; -use crate::paint::{self, Painter}; +use crate::paint::Painter; use crate::parse; -use crate::style; #[derive(Clone, Debug, PartialEq)] pub enum State { @@ -202,7 +202,6 @@ fn handle_commit_meta_header_line( config.terminal_width, config.commit_color, true, - config.true_color, )?; Ok(()) } @@ -234,11 +233,10 @@ fn handle_generic_file_meta_header_line( writeln!(painter.writer)?; draw_fn( painter.writer, - &paint::paint_text_foreground(line, config.file_color, config.true_color), + &config.file_color.paint(line), config.terminal_width, config.file_color, false, - config.true_color, )?; Ok(()) } @@ -265,14 +263,11 @@ fn handle_hunk_meta_line( ); Painter::paint_lines( vec![syntax_style_sections], - vec![vec![( - style::NO_BACKGROUND_COLOR_STYLE_MODIFIER, - &code_fragment, - )]], + vec![vec![(Style::new(), &code_fragment)]], &mut painter.output_buffer, config, "", - style::NO_BACKGROUND_COLOR_STYLE_MODIFIER, + config.null_style, Some(false), ); painter.output_buffer.pop(); // trim newline @@ -282,15 +277,10 @@ 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, config.true_color) - )?; + writeln!(painter.writer, "\n{}", config.hunk_color.paint(line_number))?; Ok(()) } @@ -340,10 +330,9 @@ fn handle_hunk_line( &painter.config, ) } else { - vec![(style::get_no_style(), line.as_str())] + vec![(config.null_syntect_style, line.as_str())] }; - let diff_style_sections = - vec![(style::NO_BACKGROUND_COLOR_STYLE_MODIFIER, line.as_str())]; + let diff_style_sections = vec![(Style::new(), line.as_str())]; Painter::paint_lines( vec![syntax_style_sections], @@ -351,7 +340,7 @@ fn handle_hunk_line( &mut painter.output_buffer, config, prefix, - style::NO_BACKGROUND_COLOR_STYLE_MODIFIER, + config.null_style, None, ); state diff --git a/src/draw.rs b/src/draw.rs index c6a6b84c..ee911f7a 100644 --- a/src/draw.rs +++ b/src/draw.rs @@ -1,12 +1,10 @@ use std::io::Write; +use ansi_term::Color; use box_drawing; use console::strip_ansi_codes; -use syntect::highlighting::Color; use unicode_width::UnicodeWidthStr; -use crate::paint; - /// Write text to stream, surrounded by a box, leaving the cursor just /// beyond the bottom right corner. pub fn write_boxed( @@ -15,7 +13,6 @@ 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 @@ -23,12 +20,8 @@ pub fn write_boxed( box_drawing::light::UP_LEFT }; let box_width = UnicodeWidthStr::width(strip_ansi_codes(text).as_ref()) + 1; - write_boxed_partial(writer, text, box_width, color, heavy, true_color)?; - write!( - writer, - "{}", - paint::paint_text_foreground(up_left, color, true_color) - )?; + write_boxed_partial(writer, text, box_width, color, heavy)?; + write!(writer, "{}", color.paint(up_left))?; Ok(()) } @@ -40,10 +33,9 @@ pub fn write_boxed_with_line( line_width: usize, color: Color, heavy: bool, - true_color: bool, ) -> std::io::Result<()> { let box_width = UnicodeWidthStr::width(strip_ansi_codes(text).as_ref()) + 1; - write_boxed_with_horizontal_whisker(writer, text, box_width, color, heavy, true_color)?; + write_boxed_with_horizontal_whisker(writer, text, box_width, color, heavy)?; write_horizontal_line( writer, if line_width > box_width { @@ -53,7 +45,6 @@ pub fn write_boxed_with_line( }, color, heavy, - true_color, )?; write!(writer, "\n")?; Ok(()) @@ -65,14 +56,9 @@ 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, true_color) - )?; - write_horizontal_line(writer, line_width - 1, color, heavy, true_color)?; + writeln!(writer, "{}", color.paint(text))?; + write_horizontal_line(writer, line_width - 1, color, heavy)?; write!(writer, "\n")?; Ok(()) } @@ -82,18 +68,13 @@ 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 } else { box_drawing::light::HORIZONTAL }; - write!( - writer, - "{}", - paint::paint_text_foreground(&horizontal.repeat(line_width), color, true_color) - ) + write!(writer, "{}", color.paint(horizontal.repeat(line_width))) } pub fn write_boxed_with_horizontal_whisker( @@ -102,19 +83,14 @@ 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, true_color)?; - write!( - writer, - "{}", - paint::paint_text_foreground(up_horizontal, color, true_color) - )?; + write_boxed_partial(writer, text, box_width, color, heavy)?; + write!(writer, "{}", color.paint(up_horizontal))?; Ok(()) } @@ -124,7 +100,6 @@ 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 @@ -146,10 +121,10 @@ fn write_boxed_partial( write!( writer, "{}{}\n{} {}\n{}", - 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), + color.paint(&horizontal_edge), + color.paint(down_left), + color.paint(text), + color.paint(vertical), + color.paint(&horizontal_edge), ) } diff --git a/src/main.rs b/src/main.rs index 00c77950..46885dae 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,16 +12,16 @@ mod env; mod paint; mod parse; mod style; +mod syntect_color; mod tests; use std::io::{self, ErrorKind, Read, Write}; use std::process; -use ansi_term; +use ansi_term::{Color, Style}; use atty; use bytelines::ByteLinesReader; use structopt::StructOpt; -use syntect::highlighting::{Color, FontStyle, Style}; use crate::bat::assets::{list_languages, HighlightingAssets}; use crate::bat::output::{OutputType, PagingMode}; @@ -79,40 +79,15 @@ 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(), - 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 - ), + minus_color = get_painted_rgb_string(config.minus_style.background.unwrap()), + minus_emph_color = get_painted_rgb_string(config.minus_emph_style.background.unwrap()), + plus_color = get_painted_rgb_string(config.plus_style.background.unwrap()), + plus_emph_color = get_painted_rgb_string(config.plus_emph_style.background.unwrap()), ) } -fn get_painted_rgb_string(color: Color, true_color: bool) -> String { - let mut string = String::new(); - let style = Style { - foreground: style::NO_COLOR, - background: color, - font_style: FontStyle::empty(), - }; - paint::paint_text( - &format!("#{:02x?}{:02x?}{:02x?}", color.r, color.g, color.b), - style, - &mut string, - true_color, - ); - string.push_str("\x1b[0m"); // reset - string +fn get_painted_rgb_string(color: Color) -> String { + color.paint(format!("{:?}", color)).to_string() } fn list_themes() -> std::io::Result<()> { @@ -144,7 +119,7 @@ index f38589a..0f1bb83 100644 let stdout = io::stdout(); let mut stdout = stdout.lock(); - let style = ansi_term::Style::new().bold(); + let style = Style::new().bold(); let assets = HighlightingAssets::new(); diff --git a/src/paint.rs b/src/paint.rs index f3ebf9de..9ef25eca 100644 --- a/src/paint.rs +++ b/src/paint.rs @@ -1,17 +1,14 @@ use std::io::Write; -use std::str::FromStr; -use ansi_term; +use ansi_term::{self, Style}; use syntect::easy::HighlightLines; -use syntect::highlighting::{Color, FontStyle, Style, StyleModifier}; +use syntect::highlighting::Style as SyntectStyle; use syntect::parsing::{SyntaxReference, SyntaxSet}; -use crate::bat::terminal::to_ansi_color; use crate::config; use crate::delta::State; use crate::edits; use crate::paint::superimpose_style_sections::superimpose_style_sections; -use crate::style; pub const ANSI_CSI_ERASE_IN_LINE: &str = "\x1b[K"; pub const ANSI_SGR_RESET: &str = "\x1b[0m"; @@ -81,7 +78,7 @@ impl<'a> Painter<'a> { &mut self.output_buffer, self.config, self.config.minus_line_marker, - self.config.minus_style_modifier, + self.config.minus_style, None, ); } @@ -92,7 +89,7 @@ impl<'a> Painter<'a> { &mut self.output_buffer, self.config, self.config.plus_line_marker, - self.config.plus_style_modifier, + self.config.plus_style, None, ); } @@ -103,34 +100,34 @@ impl<'a> Painter<'a> { /// Superimpose background styles and foreground syntax /// highlighting styles, and write colored lines to output buffer. pub fn paint_lines( - syntax_style_sections: Vec<Vec<(Style, &str)>>, - diff_style_sections: Vec<Vec<(StyleModifier, &str)>>, + syntax_style_sections: Vec<Vec<(SyntectStyle, &str)>>, + diff_style_sections: Vec<Vec<(Style, &str)>>, output_buffer: &mut String, config: &config::Config, prefix: &str, - background_style_modifier: StyleModifier, + background_style: Style, background_color_extends_to_terminal_width: Option<bool>, ) { - let background_style = config.no_style.apply(background_style_modifier); - let background_ansi_style = to_ansi_style(background_style, config.true_color); for (syntax_sections, diff_sections) in syntax_style_sections.iter().zip(diff_style_sections.iter()) { let mut ansi_strings = Vec::new(); if prefix != "" { - ansi_strings.push(background_ansi_style.paint(prefix)); + ansi_strings.push(background_style.paint(prefix)); } let mut dropped_prefix = prefix == ""; // TODO: Hack - for (style, mut text) in superimpose_style_sections(syntax_sections, diff_sections) { + for (style, mut text) in + superimpose_style_sections(syntax_sections, diff_sections, config.true_color) + { if !dropped_prefix { if text.len() > 0 { text.remove(0); } dropped_prefix = true; } - ansi_strings.push(to_ansi_style(style, config.true_color).paint(text)); + ansi_strings.push(style.paint(text)); } - ansi_strings.push(background_ansi_style.paint("")); + ansi_strings.push(background_style.paint("")); let line = &mut ansi_term::ANSIStrings(&ansi_strings).to_string(); let background_color_extends_to_terminal_width = match background_color_extends_to_terminal_width { @@ -167,7 +164,7 @@ impl<'a> Painter<'a> { should_syntax_highlight: bool, highlighter: &mut HighlightLines, config: &config::Config, - ) -> Vec<Vec<(Style, &'s str)>> { + ) -> Vec<Vec<(SyntectStyle, &'s str)>> { let mut line_sections = Vec::new(); for line in lines.iter() { line_sections.push(Painter::get_line_syntax_style_sections( @@ -185,11 +182,11 @@ impl<'a> Painter<'a> { should_syntax_highlight: bool, highlighter: &mut HighlightLines, config: &config::Config, - ) -> Vec<(Style, &'a str)> { + ) -> Vec<(SyntectStyle, &'a str)> { if should_syntax_highlight && config.theme.is_some() { highlighter.highlight(line, &config.syntax_set) } else { - vec![(config.no_style, line)] + vec![(config.null_syntect_style, line)] } } @@ -198,112 +195,40 @@ impl<'a> Painter<'a> { minus_lines: &'b [String], plus_lines: &'b [String], config: &config::Config, - ) -> ( - Vec<Vec<(StyleModifier, &'b str)>>, - Vec<Vec<(StyleModifier, &'b str)>>, - ) { + ) -> (Vec<Vec<(Style, &'b str)>>, Vec<Vec<(Style, &'b str)>>) { edits::infer_edits( minus_lines, plus_lines, - config.minus_style_modifier, - config.minus_emph_style_modifier, - config.plus_style_modifier, - config.plus_emph_style_modifier, + config.minus_style, + config.minus_emph_style, + config.plus_style, + config.plus_emph_style, config.max_line_distance, config.max_line_distance_for_naively_paired_lines, ) } } -pub fn to_ansi_style(style: Style, true_color: bool) -> ansi_term::Style { - let mut ansi_style = ansi_term::Style::new(); - if style.background != style::NO_COLOR { - ansi_style = ansi_style.on(to_ansi_color(style.background, true_color)); - } - if style.foreground != style::NO_COLOR { - ansi_style = ansi_style.fg(to_ansi_color(style.foreground, true_color)); - } - if style.font_style.contains(FontStyle::BOLD) { - ansi_style.is_bold = true; - } - if style.font_style.contains(FontStyle::ITALIC) { - ansi_style.is_italic = true; - } - if style.font_style.contains(FontStyle::UNDERLINE) { - ansi_style.is_underline = true; - } - ansi_style -} - -/// 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, true_color: bool) { - if text.is_empty() { - return; - } - let ansi_style = to_ansi_style(style, true_color); - output_buffer.push_str(&ansi_style.paint(text).to_string()); -} - -/// Return text together with shell escape codes specifying the foreground color. -pub fn paint_text_foreground(text: &str, color: Color, true_color: bool) -> String { - to_ansi_color(color, true_color).paint(text).to_string() -} - -#[allow(dead_code)] -pub fn paint_text_background(text: &str, color: Color, true_color: bool) -> String { - let style = ansi_term::Style::new().on(to_ansi_color(color, true_color)); - style.paint(text).to_string() -} - -// See -// https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit -pub fn ansi_color_name_to_number(name: &str) -> Option<u8> { - match name.to_lowercase().as_ref() { - "black" => Some(0), - "red" => Some(1), - "green" => Some(2), - "yellow" => Some(3), - "blue" => Some(4), - "magenta" => Some(5), - "purple" => Some(5), - "cyan" => Some(6), - "white" => Some(7), - "bright-black" => Some(8), - "bright-red" => Some(9), |