theme.rs

  1mod highlight_map;
  2mod theme_registry;
  3
  4use anyhow::Result;
  5use gpui::{
  6    color::Color,
  7    elements::{ContainerStyle, LabelStyle},
  8    fonts::TextStyle,
  9};
 10use serde::{Deserialize, Deserializer};
 11use std::collections::HashMap;
 12
 13pub use highlight_map::*;
 14pub use theme_registry::*;
 15
 16pub const DEFAULT_THEME_NAME: &'static str = "dark";
 17
 18#[derive(Debug, Default, Deserialize)]
 19pub struct Theme {
 20    #[serde(default)]
 21    pub name: String,
 22    pub workspace: Workspace,
 23    pub chat_panel: ChatPanel,
 24    pub selector: Selector,
 25    pub editor: Editor,
 26    #[serde(deserialize_with = "deserialize_syntax_theme")]
 27    pub syntax: Vec<(String, TextStyle)>,
 28}
 29
 30#[derive(Debug, Default, Deserialize)]
 31pub struct Workspace {
 32    pub background: Color,
 33    pub tab: Tab,
 34    pub active_tab: Tab,
 35    pub sidebar: ContainerStyle,
 36    pub sidebar_icon: SidebarIcon,
 37    pub active_sidebar_icon: SidebarIcon,
 38}
 39
 40#[derive(Debug, Default, Deserialize)]
 41pub struct Tab {
 42    #[serde(flatten)]
 43    pub container: ContainerStyle,
 44    #[serde(flatten)]
 45    pub label: LabelStyle,
 46    pub icon_close: Color,
 47    pub icon_dirty: Color,
 48    pub icon_conflict: Color,
 49}
 50
 51#[derive(Debug, Default, Deserialize)]
 52pub struct SidebarIcon {
 53    pub color: Color,
 54}
 55
 56#[derive(Debug, Default, Deserialize)]
 57pub struct ChatPanel {
 58    pub message: ChatMessage,
 59}
 60
 61#[derive(Debug, Default, Deserialize)]
 62pub struct ChatMessage {
 63    pub body: TextStyle,
 64}
 65
 66#[derive(Debug, Default, Deserialize)]
 67pub struct Selector {
 68    #[serde(flatten)]
 69    pub container: ContainerStyle,
 70    #[serde(flatten)]
 71    pub label: LabelStyle,
 72
 73    pub item: SelectorItem,
 74    pub active_item: SelectorItem,
 75}
 76
 77#[derive(Debug, Default, Deserialize)]
 78pub struct SelectorItem {
 79    #[serde(flatten)]
 80    pub container: ContainerStyle,
 81    #[serde(flatten)]
 82    pub label: LabelStyle,
 83}
 84
 85#[derive(Debug, Deserialize)]
 86pub struct Editor {
 87    pub background: Color,
 88    pub gutter_background: Color,
 89    pub active_line_background: Color,
 90    pub line_number: Color,
 91    pub line_number_active: Color,
 92    pub text: Color,
 93    pub replicas: Vec<Replica>,
 94}
 95
 96#[derive(Clone, Copy, Debug, Default, Deserialize)]
 97pub struct Replica {
 98    pub cursor: Color,
 99    pub selection: Color,
100}
101
102impl Theme {
103    pub fn highlight_style(&self, id: HighlightId) -> TextStyle {
104        self.syntax
105            .get(id.0 as usize)
106            .map(|entry| entry.1.clone())
107            .unwrap_or_else(|| TextStyle {
108                color: self.editor.text,
109                font_properties: Default::default(),
110            })
111    }
112
113    #[cfg(test)]
114    pub fn highlight_name(&self, id: HighlightId) -> Option<&str> {
115        self.syntax.get(id.0 as usize).map(|e| e.0.as_str())
116    }
117}
118
119impl Default for Editor {
120    fn default() -> Self {
121        Self {
122            background: Default::default(),
123            gutter_background: Default::default(),
124            active_line_background: Default::default(),
125            line_number: Default::default(),
126            line_number_active: Default::default(),
127            text: Default::default(),
128            replicas: vec![Replica::default()],
129        }
130    }
131}
132
133pub fn deserialize_syntax_theme<'de, D>(
134    deserializer: D,
135) -> Result<Vec<(String, TextStyle)>, D::Error>
136where
137    D: Deserializer<'de>,
138{
139    let mut result = Vec::<(String, TextStyle)>::new();
140
141    let syntax_data: HashMap<String, TextStyle> = Deserialize::deserialize(deserializer)?;
142    for (key, style) in syntax_data {
143        match result.binary_search_by(|(needle, _)| needle.cmp(&key)) {
144            Ok(i) | Err(i) => {
145                result.insert(i, (key, style));
146            }
147        }
148    }
149
150    Ok(result)
151}