blob: 638cbd7670dfa271d2c55caa6913748feeca31aa [file] [log] [blame]
use std::ops::{Index, IndexMut};
use std::fmt;
use crate::{Rgb, ansi};
use crate::config::Colors;
pub const COUNT: usize = 270;
/// List of indexed colors
///
/// The first 16 entries are the standard ansi named colors. Items 16..232 are
/// the color cube. Items 233..256 are the grayscale ramp. Item 256 is
/// the configured foreground color, item 257 is the configured background
/// color, item 258 is the cursor foreground color, item 259 is the cursor
/// background color. Following that are 8 positions for dim colors.
/// Item 268 is the bright foreground color, 269 the dim foreground.
#[derive(Copy, Clone)]
pub struct List([Rgb; COUNT]);
impl<'a> From<&'a Colors> for List {
fn from(colors: &Colors) -> List {
// Type inference fails without this annotation
let mut list: List = unsafe { ::std::mem::uninitialized() };
list.fill_named(colors);
list.fill_cube(colors);
list.fill_gray_ramp(colors);
list
}
}
impl List {
pub fn fill_named(&mut self, colors: &Colors) {
// Normals
self[ansi::NamedColor::Black] = colors.normal.black;
self[ansi::NamedColor::Red] = colors.normal.red;
self[ansi::NamedColor::Green] = colors.normal.green;
self[ansi::NamedColor::Yellow] = colors.normal.yellow;
self[ansi::NamedColor::Blue] = colors.normal.blue;
self[ansi::NamedColor::Magenta] = colors.normal.magenta;
self[ansi::NamedColor::Cyan] = colors.normal.cyan;
self[ansi::NamedColor::White] = colors.normal.white;
// Brights
self[ansi::NamedColor::BrightBlack] = colors.bright.black;
self[ansi::NamedColor::BrightRed] = colors.bright.red;
self[ansi::NamedColor::BrightGreen] = colors.bright.green;
self[ansi::NamedColor::BrightYellow] = colors.bright.yellow;
self[ansi::NamedColor::BrightBlue] = colors.bright.blue;
self[ansi::NamedColor::BrightMagenta] = colors.bright.magenta;
self[ansi::NamedColor::BrightCyan] = colors.bright.cyan;
self[ansi::NamedColor::BrightWhite] = colors.bright.white;
self[ansi::NamedColor::BrightForeground] = colors
.primary
.bright_foreground
.unwrap_or(colors.primary.foreground);
// Foreground and background
self[ansi::NamedColor::Foreground] = colors.primary.foreground;
self[ansi::NamedColor::Background] = colors.primary.background;
// Foreground and background for custom cursor colors
self[ansi::NamedColor::CursorText] = colors.cursor.text.unwrap_or_else(Rgb::default);
self[ansi::NamedColor::Cursor] = colors.cursor.cursor.unwrap_or_else(Rgb::default);
// Dims
self[ansi::NamedColor::DimForeground] = colors
.primary
.dim_foreground
.unwrap_or(colors.primary.foreground * 0.66);
match colors.dim {
Some(ref dim) => {
trace!("Using config-provided dim colors");
self[ansi::NamedColor::DimBlack] = dim.black;
self[ansi::NamedColor::DimRed] = dim.red;
self[ansi::NamedColor::DimGreen] = dim.green;
self[ansi::NamedColor::DimYellow] = dim.yellow;
self[ansi::NamedColor::DimBlue] = dim.blue;
self[ansi::NamedColor::DimMagenta] = dim.magenta;
self[ansi::NamedColor::DimCyan] = dim.cyan;
self[ansi::NamedColor::DimWhite] = dim.white;
}
None => {
trace!("Deriving dim colors from normal colors");
self[ansi::NamedColor::DimBlack] = colors.normal.black * 0.66;
self[ansi::NamedColor::DimRed] = colors.normal.red * 0.66;
self[ansi::NamedColor::DimGreen] = colors.normal.green * 0.66;
self[ansi::NamedColor::DimYellow] = colors.normal.yellow * 0.66;
self[ansi::NamedColor::DimBlue] = colors.normal.blue * 0.66;
self[ansi::NamedColor::DimMagenta] = colors.normal.magenta * 0.66;
self[ansi::NamedColor::DimCyan] = colors.normal.cyan * 0.66;
self[ansi::NamedColor::DimWhite] = colors.normal.white * 0.66;
}
}
}
pub fn fill_cube(&mut self, colors: &Colors) {
let mut index: usize = 16;
// Build colors
for r in 0..6 {
for g in 0..6 {
for b in 0..6 {
// Override colors 16..232 with the config (if present)
if let Some(indexed_color) = colors
.indexed_colors
.iter()
.find(|ic| ic.index == index as u8)
{
self[index] = indexed_color.color;
} else {
self[index] = Rgb { r: if r == 0 { 0 } else { r * 40 + 55 },
b: if b == 0 { 0 } else { b * 40 + 55 },
g: if g == 0 { 0 } else { g * 40 + 55 },
};
}
index += 1;
}
}
}
debug_assert!(index == 232);
}
pub fn fill_gray_ramp(&mut self, colors: &Colors) {
let mut index: usize = 232;
for i in 0..24 {
// Index of the color is number of named colors + number of cube colors + i
let color_index = 16 + 216 + i;
// Override colors 232..256 with the config (if present)
if let Some(indexed_color) = colors
.indexed_colors
.iter()
.find(|ic| ic.index == color_index)
{
self[index] = indexed_color.color;
index += 1;
continue;
}
let value = i * 10 + 8;
self[index] = Rgb {
r: value,
g: value,
b: value
};
index += 1;
}
debug_assert!(index == 256);
}
}
impl fmt::Debug for List {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("List[..]")
}
}
impl Index<ansi::NamedColor> for List {
type Output = Rgb;
#[inline]
fn index(&self, idx: ansi::NamedColor) -> &Self::Output {
&self.0[idx as usize]
}
}
impl IndexMut<ansi::NamedColor> for List {
#[inline]
fn index_mut(&mut self, idx: ansi::NamedColor) -> &mut Self::Output {
&mut self.0[idx as usize]
}
}
impl Index<usize> for List {
type Output = Rgb;
#[inline]
fn index(&self, idx: usize) -> &Self::Output {
&self.0[idx]
}
}
impl IndexMut<usize> for List {
#[inline]
fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
&mut self.0[idx]
}
}
impl Index<u8> for List {
type Output = Rgb;
#[inline]
fn index(&self, idx: u8) -> &Self::Output {
&self.0[idx as usize]
}
}
impl IndexMut<u8> for List {
#[inline]
fn index_mut(&mut self, idx: u8) -> &mut Self::Output {
&mut self.0[idx as usize]
}
}