mod color_utils;
mod palettes;
pub mod syntect;
use ratatui::style::Color;
use std::cell::RefCell;
pub use color_utils::{
adjust_surface_rgb, color_rgb_to_hex6, color_to_osc11_hex8, color_to_osc11_rgba_payload,
darken_rgb, lighten_rgb, rgb_euclidean_sq, rgb_to_hex6, rgb_to_osc11_hex8,
rgb_to_osc11_rgba_payload,
};
pub use palettes::{DEFAULT_COLORS, OBLIVION_INK, theme_ordered_list, theme_selector_entries};
pub use syntect::{CodeThemeKeys, SYNTECT_THEME_KEYS};
#[derive(Clone, Copy)]
pub enum SelectorEntry {
Section(&'static str),
Item(&'static Palette),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum Appearance {
Dark,
Light,
}
pub const DEFAULT_THEME: &Palette = &OBLIVION_INK;
pub const TABLE_SECTION_TITLE_TAB_FG_BG_MAX_DIST_SQ: u32 = 2200;
#[must_use]
pub fn table_section_title_fg(palette: &Palette) -> Color {
match color_utils::rgb_euclidean_sq(palette.background, palette.tab_active_fg) {
Some(d) if d <= TABLE_SECTION_TITLE_TAB_FG_BG_MAX_DIST_SQ => palette.tab_active_bg,
_ => palette.text,
}
}
#[inline]
#[must_use]
pub fn default_theme_for_new_config_file() -> &'static str {
DEFAULT_THEME.name
}
#[derive(Clone, Debug)]
pub struct Palette {
pub name: &'static str,
pub appearance: Appearance,
pub background: Color,
pub text: Color,
pub focused_border: Color,
pub tab_active_fg: Color,
pub tab_active_bg: Color,
pub tab_inactive_bg: Color,
pub search_text: Color,
pub hint: Color,
pub popup_bg: Color,
pub node_bg: Color,
pub notification_bg: Color,
pub delta_added: Color,
pub delta_mod: Color,
pub delta_removed: Color,
pub title_brand: Color,
pub swatch: Color,
}
const LIGHT_THEME_NODE_PILL_PCT: f32 = 0.11;
#[must_use]
pub fn node_pill_background(theme: &Palette) -> Color {
match theme.appearance {
Appearance::Light => adjust_surface_rgb(
theme.background,
LIGHT_THEME_NODE_PILL_PCT,
theme.appearance,
),
Appearance::Dark => theme.node_bg,
}
}
thread_local! {
static CURRENT_THEME_NAME: RefCell<Option<String>> = const { RefCell::new(None) };
}
pub fn set_current(name: Option<&str>) {
CURRENT_THEME_NAME.with(|cell| {
*cell.borrow_mut() = name.map(String::from);
});
}
#[must_use]
pub fn current() -> &'static Palette {
let name = CURRENT_THEME_NAME.with(|cell| cell.borrow().clone());
get(name.as_deref())
}
#[must_use]
pub fn theme_name_from_config(config_theme: Option<&str>) -> &str {
match config_theme {
None => DEFAULT_THEME.name,
Some(s) => {
let t = s.trim();
if t.is_empty() || t == "default" {
DEFAULT_THEME.name
} else {
t
}
}
}
}
#[must_use]
pub fn get(name: Option<&str>) -> &'static Palette {
let n = theme_name_from_config(name);
if n == DEFAULT_THEME.name {
return DEFAULT_THEME;
}
theme_ordered_list()
.iter()
.copied()
.find(|t| t.name == n)
.unwrap_or(DEFAULT_THEME)
}