mod structs;
mod colors;
mod builtins;
pub mod loader;
pub use structs::{ThemeConfig, PartialThemeConfig};
use ratatui::style::Color;
impl ThemeConfig {
pub fn builtins() -> &'static [&'static str] {
builtins::get_builtins()
}
pub fn load_named(name: &str) -> Self {
builtins::load_named_theme(name)
}
pub fn load_external(path: &std::path::Path, name: &str) -> Option<Self> {
loader::load_external_theme(path, name)
}
pub fn merge_partial(&mut self, other: PartialThemeConfig) {
loader::merge_partial(self, other)
}
pub fn parse_color(s: &str) -> Color {
colors::parse_color(s)
}
pub fn is_valid_color_str(s: &str) -> bool {
colors::is_valid_color_str(s)
}
}
impl ThemeConfig {
pub fn border_color(&self) -> Color {
Self::parse_color(&self.border)
}
pub fn fg_color(&self) -> Color {
Self::parse_color(&self.fg)
}
pub fn bg_color(&self) -> Color {
if self.enable_transparency {
Color::Reset
} else {
Self::parse_color(&self.bg)
}
}
pub fn muted_color(&self) -> Color {
Self::parse_color(&self.muted)
}
pub fn accent_color(&self) -> Color {
Self::parse_color(&self.accent)
}
pub fn border_focused_color(&self) -> Color {
Self::parse_color(&self.border_focused)
}
pub fn selection_bg_color(&self) -> Color {
Self::parse_color(&self.selection_bg)
}
pub fn selection_fg_color(&self) -> Color {
Self::parse_color(&self.selection_fg)
}
pub fn diff_add_color(&self) -> Color {
Self::parse_color(&self.diff_add)
}
pub fn diff_remove_color(&self) -> Color {
Self::parse_color(&self.diff_remove)
}
pub fn diff_hunk_color(&self) -> Color {
Self::parse_color(&self.diff_hunk)
}
pub fn error_color(&self) -> Color {
Self::parse_color(&self.error)
}
pub fn success_color(&self) -> Color {
Self::parse_color(&self.success)
}
pub fn diff_context_color(&self) -> Color {
Self::parse_color(&self.diff_context)
}
pub fn warning_color(&self) -> Color {
Self::parse_color(&self.warning)
}
pub fn footer_color(&self) -> Color {
Self::parse_color(&self.footer)
}
pub fn header_color(&self) -> Color {
Self::parse_color(&self.header)
}
pub fn staged_color(&self) -> Color {
Self::parse_color(&self.staged)
}
pub fn unstaged_color(&self) -> Color {
Self::parse_color(&self.unstaged)
}
pub fn untracked_color(&self) -> Color {
Self::parse_color(&self.untracked)
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::path::Path;
use std::fs;
#[test]
fn loads_external_nord_theme() {
let path = Path::new("themes/nord.toml");
if path.exists() {
let theme = ThemeConfig::load_external(path, "nord").expect("load nord");
assert_eq!(theme.selection_bg, "#3B4252");
assert_eq!(theme.fg, "#ECEFF4");
assert_eq!(theme.bg, "#2E3440");
}
}
#[test]
fn skips_invalid_color_and_keeps_base() {
let tmp = std::env::temp_dir().join("eazygit_invalid_theme.toml");
let content = r##"
[extend]
base = "nord"
[palette]
selection_bg = "#GGGGGG" # invalid
header = "#123456"
"##;
fs::write(&tmp, content).expect("write temp theme");
let theme = ThemeConfig::load_external(&tmp, "temp").expect("load temp");
assert_eq!(theme.selection_bg, "#3B4252");
assert_eq!(theme.header, "#123456");
let _ = fs::remove_file(&tmp);
}
}