use colored::{ColoredString, Colorize};
pub fn colored_char(red: u8, green: u8, blue: u8, char: char, background_color: bool) -> String {
if *crate::SUPPORTS_TRUECOLOR {
if background_color {
char.to_string().on_truecolor(red, green, blue).to_string()
} else {
char.to_string().truecolor(red, green, blue).to_string()
}
} else {
rgb_to_ansi(&char.to_string(), red, green, blue).to_string()
}
}
#[cfg(test)]
mod test_colored_string {
use std::env;
use super::*;
#[test]
#[ignore = "Requires truecolor support"]
fn rust_color_no_background() {
env::set_var("COLORTERM", "truecolor");
env::set_var("CLICOLOR_FORCE", "1");
assert_eq!(
"x".truecolor(154, 85, 54).to_string(),
colored_char(154, 85, 54, 'x', false)
);
}
#[test]
#[ignore = "Requires truecolor support"]
fn rust_color_with_background() {
env::set_var("COLORTERM", "truecolor");
env::set_var("CLICOLOR_FORCE", "1");
assert_eq!(
"x".on_truecolor(154, 85, 54).to_string(),
colored_char(154, 85, 54, 'x', true)
);
}
#[test]
fn rust_color_ansi_no_background() {
env::set_var("COLORTERM", "false");
env::set_var("CLICOLOR_FORCE", "1");
assert_eq!(
"\u{1b}[33mx\u{1b}[0m",
colored_char(154, 85, 54, 'x', false)
);
}
#[test]
fn rust_color_ansi_with_background() {
env::set_var("COLORTERM", "false");
env::set_var("CLICOLOR_FORCE", "1");
assert_eq!("\u{1b}[33mx\u{1b}[0m", colored_char(154, 85, 54, 'x', true));
}
}
fn rgb_to_ansi(input: &str, r: u8, g: u8, b: u8) -> ColoredString {
let r = r as i32;
let g = g as i32;
let b = b as i32;
let vga_colors = [
[0, 0, 0], [170, 0, 0], [0, 170, 0], [170, 85, 0], [0, 0, 170], [170, 0, 170], [0, 170, 170], [170, 170, 170], [128, 128, 128], [255, 0, 0], [0, 255, 0], [255, 255, 0], [0, 0, 255], [255, 0, 255], [0, 255, 255], [255, 255, 255], ];
let mut smallest_distance = i32::MAX;
let mut smallest_distance_index: u8 = 7;
for (index, vga_color) in vga_colors.iter().enumerate() {
let distance =
(r - vga_color[0]).pow(2) + (g - vga_color[1]).pow(2) + (b - vga_color[2]).pow(2);
if distance < smallest_distance {
smallest_distance = distance;
smallest_distance_index = index as u8;
}
}
match smallest_distance_index {
0 => input.black(),
1 => input.red(),
2 => input.green(),
3 => input.yellow(),
4 => input.blue(),
5 => input.magenta(),
6 => input.cyan(),
7 => input.white(),
8 => input.bright_black(),
9 => input.bright_red(),
10 => input.bright_green(),
11 => input.bright_yellow(),
12 => input.bright_blue(),
13 => input.bright_magenta(),
14 => input.bright_cyan(),
15 => input.bright_white(),
_ => input.normal(),
}
}
#[cfg(test)]
mod test_convert_rgb_ansi {
use super::*;
#[test]
fn convert_vga_normal_values() {
assert_eq!("input".black(), rgb_to_ansi("input", 0, 0, 0));
assert_eq!("input".red(), rgb_to_ansi("input", 170, 0, 0));
assert_eq!("input".green(), rgb_to_ansi("input", 0, 170, 0));
assert_eq!("input".yellow(), rgb_to_ansi("input", 170, 85, 0));
assert_eq!("input".blue(), rgb_to_ansi("input", 0, 0, 170));
assert_eq!("input".magenta(), rgb_to_ansi("input", 170, 0, 170));
assert_eq!("input".cyan(), rgb_to_ansi("input", 0, 170, 170));
assert_eq!("input".white(), rgb_to_ansi("input", 170, 170, 170));
}
#[test]
fn convert_vga_bright_values() {
assert_eq!("input".bright_black(), rgb_to_ansi("input", 128, 128, 128));
assert_eq!("input".bright_red(), rgb_to_ansi("input", 255, 0, 0));
assert_eq!("input".bright_green(), rgb_to_ansi("input", 0, 255, 0));
assert_eq!("input".bright_yellow(), rgb_to_ansi("input", 255, 255, 0));
assert_eq!("input".bright_blue(), rgb_to_ansi("input", 0, 0, 255));
assert_eq!("input".bright_magenta(), rgb_to_ansi("input", 255, 0, 255));
assert_eq!("input".bright_cyan(), rgb_to_ansi("input", 0, 255, 255));
assert_eq!("input".bright_white(), rgb_to_ansi("input", 255, 255, 255));
}
#[test]
fn rgb_blue() {
assert_eq!("input".blue(), rgb_to_ansi("input", 0, 0, 88));
}
}