vkit 0.1.4

Fast Rust dev CLI: manage git worktrees, Node ports, run scripts, install & sync VS Code / Cursor extensions.
//! 全局配色主题:全屏统一的设计语言,避免各处散落字面色。
//!
//! Everforest 风格的低饱和调色板(真彩色 RGB),以柔和绿色为主强调(同时用于成功状态),
//! 黄色表示勾选 / 选中,橙色(前景)表示光标行高亮。
//! 启动时按终端明暗自动选择 dark / light 两套变体(见 `init`)。

use std::sync::OnceLock;

use ratatui::style::Color;

#[derive(Clone, Copy)]
pub struct Theme {
    /// 主强调(绿色):logo、面板标题、按键提示的 key、聚焦输入框边框、成功状态。
    pub accent: Color,
    /// 光标行高亮(橙色,前景色,与绿 / 黄形成对比)。
    pub highlight: Color,
    /// 边框、占位符、次要说明、表头。
    pub muted: Color,
    /// 勾选 / 多选选中(黄色)。
    pub selected: Color,
    /// 成功状态(绿色,与主强调一致,如状态 ✓)。
    pub success: Color,
    /// 危险 / 失败(红色,如需 pull 的 ↓)。
    pub danger: Color,
    /// 状态 / loading / 警示。
    pub warning: Color,
    /// 正文。
    pub text: Color,
    /// 表面块背景:按键提示 keycap 的底色。
    pub surface: Color,
}

/// 深色终端:Everforest dark(绿色强调 #a7c080,选中黄 #dbbc7f,光标橙 #e69875)。
const DARK: Theme = Theme {
    accent: Color::Rgb(167, 192, 128),
    highlight: Color::Rgb(230, 152, 117),
    muted: Color::Rgb(133, 146, 137),
    selected: Color::Rgb(219, 188, 127),
    success: Color::Rgb(167, 192, 128),
    danger: Color::Rgb(230, 126, 128),
    warning: Color::Rgb(219, 188, 127),
    text: Color::Rgb(211, 198, 170),
    surface: Color::Rgb(65, 75, 78),
};

/// 浅色终端:Everforest light(绿色强调 #5d793c,选中黄 #dfa000,光标橙 #f57d26)。
const LIGHT: Theme = Theme {
    accent: Color::Rgb(93, 121, 60),
    highlight: Color::Rgb(245, 125, 38),
    muted: Color::Rgb(124, 133, 120),
    selected: Color::Rgb(223, 160, 0),
    success: Color::Rgb(93, 121, 60),
    danger: Color::Rgb(248, 85, 82),
    warning: Color::Rgb(176, 133, 0),
    text: Color::Rgb(92, 106, 114),
    surface: Color::Rgb(228, 222, 203),
};

static THEME: OnceLock<Theme> = OnceLock::new();

/// 按终端明暗选定主题(仅第一次生效)。在进入 TUI 前调用。
pub fn init(is_light: bool) {
    let _ = THEME.set(if is_light { LIGHT } else { DARK });
}

fn current() -> Theme {
    *THEME.get_or_init(|| DARK)
}

pub fn accent() -> Color {
    current().accent
}
pub fn highlight() -> Color {
    current().highlight
}
pub fn muted() -> Color {
    current().muted
}
pub fn selected() -> Color {
    current().selected
}
pub fn success() -> Color {
    current().success
}
pub fn danger() -> Color {
    current().danger
}
pub fn warning() -> Color {
    current().warning
}
pub fn text() -> Color {
    current().text
}
pub fn surface() -> Color {
    current().surface
}