use crate::color::{Color, ColorTriplet, ColorType, ANSI_BASE_PALETTE};
#[derive(Debug, Clone)]
pub struct TerminalTheme {
pub background: ColorTriplet,
pub foreground: ColorTriplet,
pub ansi: [ColorTriplet; 16],
}
impl TerminalTheme {
pub fn resolve(&self, color: &Color, foreground: bool) -> ColorTriplet {
match color.kind {
ColorType::Default => {
if foreground {
self.foreground
} else {
self.background
}
}
ColorType::Standard | ColorType::Windows => {
self.ansi[(color.number.unwrap_or(0) as usize) & 0x0f]
}
ColorType::EightBit | ColorType::Truecolor => {
color.get_truecolor().unwrap_or(self.foreground)
}
}
}
}
pub const DEFAULT_TERMINAL_THEME: TerminalTheme = TerminalTheme {
background: ColorTriplet::new(255, 255, 255),
foreground: ColorTriplet::new(0, 0, 0),
ansi: ANSI_BASE_PALETTE,
};
pub const SVG_EXPORT_THEME: TerminalTheme = TerminalTheme {
background: ColorTriplet::new(41, 41, 41),
foreground: ColorTriplet::new(197, 200, 198),
ansi: [
ColorTriplet::new(75, 78, 85),
ColorTriplet::new(204, 85, 90),
ColorTriplet::new(152, 168, 75),
ColorTriplet::new(208, 179, 68),
ColorTriplet::new(96, 138, 177),
ColorTriplet::new(152, 114, 159),
ColorTriplet::new(104, 160, 179),
ColorTriplet::new(197, 200, 198),
ColorTriplet::new(154, 155, 153),
ColorTriplet::new(255, 38, 39),
ColorTriplet::new(0, 130, 61),
ColorTriplet::new(208, 132, 66),
ColorTriplet::new(25, 132, 233),
ColorTriplet::new(255, 44, 122),
ColorTriplet::new(57, 130, 128),
ColorTriplet::new(253, 253, 197),
],
};
pub const MONOKAI: TerminalTheme = TerminalTheme {
background: ColorTriplet::new(12, 12, 12),
foreground: ColorTriplet::new(217, 217, 217),
ansi: [
ColorTriplet::new(26, 26, 26),
ColorTriplet::new(244, 0, 95),
ColorTriplet::new(152, 224, 36),
ColorTriplet::new(253, 151, 31),
ColorTriplet::new(157, 101, 255),
ColorTriplet::new(244, 0, 95),
ColorTriplet::new(88, 209, 235),
ColorTriplet::new(196, 197, 181),
ColorTriplet::new(98, 94, 76),
ColorTriplet::new(244, 0, 95),
ColorTriplet::new(152, 224, 36),
ColorTriplet::new(224, 213, 97),
ColorTriplet::new(157, 101, 255),
ColorTriplet::new(244, 0, 95),
ColorTriplet::new(88, 209, 235),
ColorTriplet::new(246, 246, 239),
],
};
pub const DIMMED_MONOKAI: TerminalTheme = TerminalTheme {
background: ColorTriplet::new(25, 25, 25),
foreground: ColorTriplet::new(185, 188, 186),
ansi: [
ColorTriplet::new(58, 61, 67),
ColorTriplet::new(190, 63, 72),
ColorTriplet::new(135, 154, 59),
ColorTriplet::new(197, 166, 53),
ColorTriplet::new(79, 118, 161),
ColorTriplet::new(133, 92, 141),
ColorTriplet::new(87, 143, 164),
ColorTriplet::new(185, 188, 186),
ColorTriplet::new(136, 137, 135),
ColorTriplet::new(251, 0, 31),
ColorTriplet::new(15, 114, 47),
ColorTriplet::new(196, 112, 51),
ColorTriplet::new(24, 109, 227),
ColorTriplet::new(251, 0, 103),
ColorTriplet::new(46, 112, 109),
ColorTriplet::new(253, 255, 185),
],
};
pub const NIGHT_OWLISH: TerminalTheme = TerminalTheme {
background: ColorTriplet::new(255, 255, 255),
foreground: ColorTriplet::new(64, 63, 83),
ansi: [
ColorTriplet::new(1, 22, 39),
ColorTriplet::new(211, 66, 62),
ColorTriplet::new(42, 162, 152),
ColorTriplet::new(218, 170, 1),
ColorTriplet::new(72, 118, 214),
ColorTriplet::new(64, 63, 83),
ColorTriplet::new(8, 145, 106),
ColorTriplet::new(122, 129, 129),
ColorTriplet::new(122, 129, 129),
ColorTriplet::new(247, 110, 110),
ColorTriplet::new(73, 208, 197),
ColorTriplet::new(218, 194, 107),
ColorTriplet::new(92, 167, 228),
ColorTriplet::new(105, 112, 152),
ColorTriplet::new(0, 201, 144),
ColorTriplet::new(152, 159, 177),
],
};
pub fn blend_rgb(color1: ColorTriplet, color2: ColorTriplet, cross_fade: f64) -> ColorTriplet {
let mix = |a: u8, b: u8| (a as f64 + (b as f64 - a as f64) * cross_fade) as u8;
ColorTriplet::new(
mix(color1.red, color2.red),
mix(color1.green, color2.green),
mix(color1.blue, color2.blue),
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn svg_export_theme_matches_upstream() {
assert_eq!(
(
SVG_EXPORT_THEME.background.red,
SVG_EXPORT_THEME.background.green,
SVG_EXPORT_THEME.background.blue
),
(41, 41, 41)
);
assert_eq!(
(
SVG_EXPORT_THEME.foreground.red,
SVG_EXPORT_THEME.foreground.green,
SVG_EXPORT_THEME.foreground.blue
),
(197, 200, 198)
);
let ansi: Vec<(u8, u8, u8)> = SVG_EXPORT_THEME
.ansi
.iter()
.map(|c| (c.red, c.green, c.blue))
.collect();
assert_eq!(
ansi,
vec![
(75, 78, 85),
(204, 85, 90),
(152, 168, 75),
(208, 179, 68),
(96, 138, 177),
(152, 114, 159),
(104, 160, 179),
(197, 200, 198),
(154, 155, 153),
(255, 38, 39),
(0, 130, 61),
(208, 132, 66),
(25, 132, 233),
(255, 44, 122),
(57, 130, 128),
(253, 253, 197),
]
);
}
#[test]
fn blend_rgb_truncates_like_upstream() {
let fg = ColorTriplet::new(197, 200, 198);
let bg = ColorTriplet::new(41, 41, 41);
let dim = blend_rgb(fg, bg, 0.4);
assert_eq!((dim.red, dim.green, dim.blue), (134, 136, 135));
}
}