use ratatui::style::{Color, Modifier, Style};
pub fn color(name: &str) -> Color {
Color::Indexed(match name {
"red" => 160,
"yellow" => 226,
"green" => 41,
"cyan" => 37,
"blue" => 39,
"purple" => 141,
"white" => 231,
"black" => 234,
"grey" => 244,
_ => 39,
})
}
pub const RED: Color = Color::Indexed(196);
pub const GREEN: Color = Color::Indexed(41);
pub const GREY: Color = Color::Indexed(244);
pub fn dimmed(c: Color) -> Color {
let Color::Indexed(code) = c else { return c };
let dim = match code {
0..=15 => {
if code >= 8 {
code - 8
} else {
code
}
}
232.. => code.saturating_sub(4).max(232),
_ => {
let base = code - 16;
let (r, g, b) = (base / 36, (base % 36) / 6, base % 6);
16 + 36 * r.saturating_sub(1) + 6 * g.saturating_sub(1) + b.saturating_sub(1)
}
};
Color::Indexed(dim)
}
pub fn tint(color: Color) -> Color {
let (r, g, b) = rgb_of(color);
let wash = |c: u8| (c / 4).saturating_add(8);
Color::Rgb(wash(r), wash(g), wash(b))
}
fn rgb_of(color: Color) -> (u8, u8, u8) {
let code = match color {
Color::Rgb(r, g, b) => return (r, g, b),
Color::Indexed(code) => code,
_ => return (0, 0, 0),
};
match code {
16..232 => {
let level = |c: u8| if c == 0 { 0 } else { 55 + c * 40 };
let base = code - 16;
(level(base / 36), level((base % 36) / 6), level(base % 6))
}
232.. => {
let v = 8 + (code - 232) * 10;
(v, v, v)
}
_ => (0, 0, 0),
}
}
pub struct Theme {
pub accent: Color,
}
impl Theme {
pub fn new(name: &str) -> Self {
Self {
accent: color(name),
}
}
pub fn selection(&self) -> Style {
Style::new()
.bg(tint(self.accent))
.add_modifier(Modifier::BOLD)
}
pub fn selection_unfocused(&self) -> Style {
Style::new().bg(tint(self.accent))
}
pub fn accent_text(&self) -> Style {
Style::new().fg(self.accent)
}
pub fn plain(&self) -> Style {
Style::new()
}
}