use std::sync::RwLock;
use ratatui::style::{Color, Modifier, Style};
static THEME: RwLock<Option<Theme>> = RwLock::new(None);
static THEME_NAME: RwLock<Option<String>> = RwLock::new(None);
pub fn init_theme(name: &str, theme: Theme) {
if let Ok(mut guard) = THEME.write() {
*guard = Some(theme);
}
if let Ok(mut guard) = THEME_NAME.write() {
*guard = Some(name.to_string());
}
}
pub fn set_theme(name: &str, theme: Theme) {
if let Ok(mut guard) = THEME.write() {
*guard = Some(theme);
}
if let Ok(mut guard) = THEME_NAME.write() {
*guard = Some(name.to_string());
}
}
pub fn current_theme_name() -> String {
THEME_NAME
.read()
.ok()
.and_then(|guard| guard.clone())
.unwrap_or_else(|| "default".to_string())
}
pub fn theme() -> Theme {
THEME
.read()
.ok()
.and_then(|guard| guard.clone())
.unwrap_or_default()
}
#[derive(Clone)]
pub struct Theme {
pub background: Style,
pub text: Style,
pub border: Style,
pub border_focused: Style,
pub title_separator: Style,
pub title_indicator_connected: Style,
pub title_indicator_disconnected: Style,
pub title_text: Style,
pub user_prefix: Style,
pub system_prefix: Style,
pub assistant_prefix: Style,
pub timestamp: Style,
pub cursor: Style,
pub bold: Modifier,
pub italic: Modifier,
pub strikethrough: Modifier,
pub inline_code: Style,
pub link_text: Style,
pub link_url: Style,
pub heading_1: Style,
pub heading_2: Style,
pub heading_3: Style,
pub heading_4: Style,
pub code_block: Style,
pub table_header: Style,
pub table_cell: Style,
pub table_border: Style,
pub tool_header: Style,
pub tool_executing: Style,
pub tool_completed: Style,
pub tool_failed: Style,
pub input_border: Style,
pub input_text: Style,
pub prompt: Style,
pub throbber_label: Style,
pub throbber_spinner: Style,
pub status_help: Style,
pub status_model: Style,
pub popup_border: Style,
pub popup_header: Style,
pub popup_item: Style,
pub popup_item_selected: Style,
pub popup_item_desc: Style,
pub popup_item_desc_selected: Style,
pub popup_selected_bg: Style,
pub popup_empty: Style,
pub help_text: Style,
pub muted_text: Style,
pub focused_text: Style,
pub focus_indicator: Style,
pub selected: Style,
pub unselected: Style,
pub button_confirm: Style,
pub button_confirm_focused: Style,
pub button_cancel: Style,
pub button_cancel_focused: Style,
pub warning: Style,
pub category: Style,
pub resource: Style,
}
impl Theme {
pub fn bold(&self) -> Modifier {
self.bold
}
pub fn italic(&self) -> Modifier {
self.italic
}
pub fn strikethrough(&self) -> Modifier {
self.strikethrough
}
pub fn inline_code(&self) -> Style {
self.inline_code
}
pub fn link_text(&self) -> Style {
self.link_text
}
pub fn link_url(&self) -> Style {
self.link_url
}
pub fn heading_1(&self) -> Style {
self.heading_1
}
pub fn heading_2(&self) -> Style {
self.heading_2
}
pub fn heading_3(&self) -> Style {
self.heading_3
}
pub fn heading_4(&self) -> Style {
self.heading_4
}
pub fn code_block(&self) -> Style {
self.code_block
}
pub fn assistant_prefix(&self) -> Style {
self.assistant_prefix
}
pub fn table_header(&self) -> Style {
self.table_header
}
pub fn table_cell(&self) -> Style {
self.table_cell
}
pub fn table_border(&self) -> Style {
self.table_border
}
pub fn border(&self) -> Style {
self.border
}
pub fn border_focused(&self) -> Style {
self.border_focused
}
pub fn popup_border(&self) -> Style {
self.popup_border
}
pub fn popup_header(&self) -> Style {
self.popup_header
}
pub fn popup_item(&self) -> Style {
self.popup_item
}
pub fn popup_item_selected(&self) -> Style {
self.popup_item_selected
}
pub fn popup_item_desc(&self) -> Style {
self.popup_item_desc
}
pub fn popup_item_desc_selected(&self) -> Style {
self.popup_item_desc_selected
}
pub fn popup_selected_bg(&self) -> Style {
self.popup_selected_bg
}
pub fn popup_empty(&self) -> Style {
self.popup_empty
}
pub fn status_help(&self) -> Style {
self.status_help
}
pub fn background(&self) -> Style {
self.background
}
pub fn text(&self) -> Style {
self.text
}
pub fn cursor(&self) -> Style {
self.cursor
}
pub fn help_text(&self) -> Style {
self.help_text
}
pub fn muted_text(&self) -> Style {
self.muted_text
}
pub fn focused_text(&self) -> Style {
self.focused_text
}
pub fn focus_indicator(&self) -> Style {
self.focus_indicator
}
pub fn selected(&self) -> Style {
self.selected
}
pub fn unselected(&self) -> Style {
self.unselected
}
pub fn button_confirm(&self) -> Style {
self.button_confirm
}
pub fn button_confirm_focused(&self) -> Style {
self.button_confirm_focused
}
pub fn button_cancel(&self) -> Style {
self.button_cancel
}
pub fn button_cancel_focused(&self) -> Style {
self.button_cancel_focused
}
pub fn warning(&self) -> Style {
self.warning
}
pub fn category(&self) -> Style {
self.category
}
pub fn resource(&self) -> Style {
self.resource
}
}
impl Default for Theme {
fn default() -> Self {
Self {
background: Style::default(),
text: Style::default(),
border: Style::default().fg(Color::DarkGray),
border_focused: Style::default().fg(Color::Cyan),
title_separator: Style::default().fg(Color::DarkGray),
title_indicator_connected: Style::default().fg(Color::Green),
title_indicator_disconnected: Style::default().fg(Color::Red),
title_text: Style::default(),
user_prefix: Style::default().fg(Color::Blue),
system_prefix: Style::default().fg(Color::Yellow),
assistant_prefix: Style::default().fg(Color::Magenta),
timestamp: Style::default().fg(Color::DarkGray),
cursor: Style::default().fg(Color::Green),
bold: Modifier::BOLD,
italic: Modifier::ITALIC,
strikethrough: Modifier::CROSSED_OUT,
inline_code: Style::default().fg(Color::Yellow),
link_text: Style::default().fg(Color::Cyan),
link_url: Style::default().fg(Color::DarkGray),
heading_1: Style::default()
.fg(Color::Cyan)
.add_modifier(Modifier::BOLD),
heading_2: Style::default()
.fg(Color::Green)
.add_modifier(Modifier::BOLD),
heading_3: Style::default()
.fg(Color::Yellow)
.add_modifier(Modifier::BOLD),
heading_4: Style::default()
.fg(Color::White)
.add_modifier(Modifier::BOLD),
code_block: Style::default().fg(Color::Rgb(180, 180, 180)),
table_header: Style::default()
.fg(Color::Cyan)
.add_modifier(Modifier::BOLD),
table_cell: Style::default().fg(Color::White),
table_border: Style::default().fg(Color::DarkGray),
tool_header: Style::default().fg(Color::Cyan),
tool_executing: Style::default()
.fg(Color::Gray)
.add_modifier(Modifier::ITALIC),
tool_completed: Style::default().fg(Color::Green),
tool_failed: Style::default().fg(Color::Red),
input_border: Style::default().fg(Color::DarkGray),
input_text: Style::default(),
prompt: Style::default(),
throbber_label: Style::default().fg(Color::DarkGray),
throbber_spinner: Style::default().fg(Color::Cyan),
status_help: Style::default().fg(Color::DarkGray),
status_model: Style::default().fg(Color::DarkGray),
popup_border: Style::default().fg(Color::DarkGray),
popup_header: Style::default().fg(Color::DarkGray),
popup_item: Style::default().fg(Color::White),
popup_item_selected: Style::default()
.fg(Color::Cyan)
.add_modifier(Modifier::BOLD),
popup_item_desc: Style::default().fg(Color::DarkGray),
popup_item_desc_selected: Style::default().fg(Color::Gray),
popup_selected_bg: Style::default().bg(Color::DarkGray),
popup_empty: Style::default()
.fg(Color::DarkGray)
.add_modifier(Modifier::ITALIC),
help_text: Style::default().fg(Color::DarkGray),
muted_text: Style::default().fg(Color::Gray),
focused_text: Style::default()
.fg(Color::Cyan)
.add_modifier(Modifier::BOLD),
focus_indicator: Style::default().fg(Color::Yellow),
selected: Style::default().fg(Color::Green),
unselected: Style::default().fg(Color::Gray),
button_confirm: Style::default().fg(Color::Rgb(60, 120, 60)),
button_confirm_focused: Style::default()
.fg(Color::LightGreen)
.add_modifier(Modifier::BOLD),
button_cancel: Style::default().fg(Color::Rgb(140, 70, 70)),
button_cancel_focused: Style::default()
.fg(Color::LightRed)
.add_modifier(Modifier::BOLD),
warning: Style::default().fg(Color::Yellow),
category: Style::default().fg(Color::Magenta),
resource: Style::default().fg(Color::Cyan),
}
}
}