use collections::{HashMap, IndexMap};use schemars::JsonSchema;use serde::{Deserialize, Deserializer, Serialize};use serde_json::Value;use settings_macros::{MergeFrom, with_fallible_options};use std::{borrow::Cow, fmt::Display, ops::Deref, sync::Arc}; use crate::serialize_f32_with_two_decimal_places; /// OpenType font features as a map of feature tag to value./// This is a content type that mirrors `gpui::FontFeatures` but without the Arc wrapper./// Values can be specified as booleans (true=1, false=0) or integers.#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, MergeFrom)]#[serde(transparent)]pub struct FontFeaturesContent(pub IndexMap<String, u32>); impl FontFeaturesContent { pub fn new() -> Self { Self(IndexMap::default()) }} #[derive(Debug, serde::Deserialize)]#[serde(untagged)]enum FeatureValue { Bool(bool), Number(serde_json::Number),} fn is_valid_feature_tag(tag: &str) -> bool { tag.len() == 4 && tag.chars().all(|c| c.is_ascii_alphanumeric())} impl<'de> Deserialize<'de> for FontFeaturesContent { fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>, { use serde::de::{MapAccess, Visitor}; use std::fmt; struct FontFeaturesVisitor; impl<'de> Visitor<'de> for FontFeaturesVisitor { type Value = FontFeaturesContent; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a map of font features") } fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error> where M: MapAccess<'de>, { let mut feature_map = IndexMap::default(); while let Some((key, value)) = access.next_entry::<String, Option<FeatureValue>>()? { if !is_valid_feature_tag(&key) { log::error!("Incorrect font feature tag: {}", key); continue; } if let Some(value) = value { match value { FeatureValue::Bool(enable) => { feature_map.insert(key, if enable { 1 } else { 0 }); } FeatureValue::Number(value) => { if value.is_u64() { feature_map.insert(key, value.as_u64().unwrap() as u32); } else { log::error!( "Incorrect font feature value {} for feature tag {}", value, key ); continue; } } } } } Ok(FontFeaturesContent(feature_map)) } } deserializer.deserialize_map(FontFeaturesVisitor) }} impl JsonSchema for FontFeaturesContent { fn schema_name() -> Cow<'static, str> { "FontFeaturesContent".into() } fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema { use schemars::json_schema; json_schema!({ "type": "object", "patternProperties": { "[0-9a-zA-Z]{4}$": { "type": ["boolean", "integer"], "minimum": 0, "multipleOf": 1 } }, "additionalProperties": false }) }} #[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, MergeFrom)]#[serde(transparent)]pub struct ThemeColor(String); impl JsonSchema for ThemeColor { fn schema_name() -> Cow<'static, str> { "Color".into() } fn json_schema(_generator: &mut schemars::SchemaGenerator) -> schemars::Schema { use schemars::json_schema; json_schema!({ "type": "string", "pattern": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$", "format": "color" }) }} impl From<String> for ThemeColor { fn from(value: String) -> Self { ThemeColor(value) }} impl From<&str> for ThemeColor { fn from(value: &str) -> Self { ThemeColor(value.to_string()) }} impl Deref for ThemeColor { type Target = str; fn deref(&self) -> &Self::Target { &self.0 }} impl From<ThemeColor> for String { fn from(value: ThemeColor) -> Self { value.0 }} impl Display for ThemeColor { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0) }} impl TryFrom<&ThemeColor> for gpui::Rgba { type Error = anyhow::Error; fn try_from(value: &ThemeColor) -> anyhow::Result<Self> { let s: &str = &value.0; gpui::Rgba::try_from(s) }} /// Settings for rendering text in UI and text buffers. #[with_fallible_options]#[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]pub struct ThemeSettingsContent { /// The default font size for text in the UI. pub ui_font_size: Option<FontSize>, /// The name of a font to use for rendering in the UI. pub ui_font_family: Option<FontFamilyName>, /// The font fallbacks to use for rendering in the UI. #[schemars(default = "default_font_fallbacks")] #[schemars(extend("uniqueItems" = true))] pub ui_font_fallbacks: Option<Vec<FontFamilyName>>, /// The OpenType features to enable for text in the UI. #[schemars(default = "default_font_features")] pub ui_font_features: Option<FontFeaturesContent>, /// The weight of the UI font in CSS units from 100 to 900. #[schemars(default = "default_buffer_font_weight")] pub ui_font_weight: Option<FontWeightContent>, /// The name of a font to use for rendering in text buffers. pub buffer_font_family: Option<FontFamilyName>, /// The font fallbacks to use for rendering in text buffers. #[schemars(extend("uniqueItems" = true))] pub buffer_font_fallbacks: Option<Vec<FontFamilyName>>, /// The default font size for rendering in text buffers. pub buffer_font_size: Option<FontSize>, /// The weight of the editor font in CSS units from 100 to 900. #[schemars(default = "default_buffer_font_weight")] pub buffer_font_weight: Option<FontWeightContent>, /// The buffer's line height. pub buffer_line_height: Option<BufferLineHeight>, /// The OpenType features to enable for rendering in text buffers. #[schemars(default = "default_font_features")] pub buffer_font_features: Option<FontFeaturesContent>, /// The name of a font to use for agent responses in the agent panel. Falls back to the UI font if unset. pub agent_ui_font_family: Option<FontFamilyName>, /// The font size for agent responses in the agent panel. Falls back to the UI font size if unset. pub agent_ui_font_size: Option<FontSize>, /// The name of a font to use for user messages in the agent panel. Falls back to the buffer font if unset. pub agent_buffer_font_family: Option<FontFamilyName>, /// The font size for user messages in the agent panel. pub agent_buffer_font_size: Option<FontSize>, pub git_commit_buffer_font_size: Option<FontSize>, /// The name of a font to use for rendering in the markdown preview. /// Falls back to the UI font if unset. pub markdown_preview_font_family: Option<FontFamilyName>, /// The name of a font to use for code (code blocks and inline code) in the /// markdown preview. Falls back to the buffer font if unset. pub markdown_preview_code_font_family: Option<FontFamilyName>, /// The font size to use for rendering in the markdown preview. /// Falls back to the UI font size if unset. pub markdown_preview_font_size: Option<FontSize>, /// The theme to use for the markdown preview. /// Falls back to the main editor theme if unset. pub markdown_preview_theme: Option<ThemeSelection>, /// The name of the Zed theme to use. pub theme: Option<ThemeSelection>, /// The name of the icon theme to use. pub icon_theme: Option<IconThemeSelection>, /// UNSTABLE: Expect many elements to be broken. /// // Controls the density of the UI. #[serde(rename = "unstable.ui_density")] pub ui_density: Option<UiDensity>, /// How much to fade out unused code. #[schemars(range(min = 0.0, max = 0.9))] pub unnecessary_code_fade: Option<CodeFade>, /// EXPERIMENTAL: Overrides for the current theme. /// /// These values will override the ones on the current theme specified in `theme`. #[serde(rename = "experimental.theme_overrides")] pub experimental_theme_overrides: Option<ThemeStyleContent>, /// Overrides per theme /// /// These values will override the ones on the specified theme #[serde(default)] pub theme_overrides: HashMap<String, ThemeStyleContent>,} /// A font size value in pixels, wrapping around `f32` for custom settings UI rendering.#[derive( Clone, Copy, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, PartialOrd, derive_more::FromStr,)]#[serde(transparent)]pub struct FontSize(#[serde(serialize_with = "serialize_f32_with_two_decimal_places")] pub f32); impl Display for FontSize { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{:.2}", self.0) }} impl From<f32> for FontSize { fn from(value: f32) -> Self { Self(value) }} #[derive( Clone, Copy, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, PartialOrd, derive_more::FromStr,)]#[serde(transparent)]pub struct CodeFade(#[serde(serialize_with = "serialize_f32_with_two_decimal_places")] pub f32); impl Display for CodeFade { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{:.2}", self.0) }} impl From<f32> for CodeFade { fn from(x: f32) -> Self { Self(x) }} fn default_font_features() -> Option<FontFeaturesContent> { Some(FontFeaturesContent::default())} fn default_font_fallbacks() -> Option<Vec<FontFamilyName>> { Some(Vec::new())} fn default_buffer_font_weight() -> Option<FontWeightContent> { Some(FontWeightContent::NORMAL)} /// Represents the selection of a theme, which can be either static or dynamic.#[derive( Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq, strum::EnumDiscriminants,)]#[strum_discriminants(derive(strum::VariantArray, strum::VariantNames, strum::FromRepr))]#[serde(untagged)]pub enum ThemeSelection { /// A static theme selection, represented by a single theme name. Static(ThemeName), /// A dynamic theme selection, which can change based the [ThemeMode]. Dynamic { /// The mode used to determine which theme to use. #[serde(default)] mode: ThemeAppearanceMode, /// The theme to use for light mode. light: ThemeName, /// The theme to use for dark mode. dark: ThemeName, },} pub const DEFAULT_LIGHT_THEME: &'static str = "One Light";pub const DEFAULT_DARK_THEME: &'static str = "One Dark"; impl Default for ThemeSelection { fn default() -> Self { Self::Dynamic { mode: ThemeAppearanceMode::default(), light: ThemeName(DEFAULT_LIGHT_THEME.into()), dark: ThemeName(DEFAULT_DARK_THEME.into()), } }} /// Represents the selection of an icon theme, which can be either static or dynamic.#[derive( Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq, strum::EnumDiscriminants,)]#[strum_discriminants(derive(strum::VariantArray, strum::VariantNames, strum::FromRepr))]#[serde(untagged)]pub enum IconThemeSelection { /// A static icon theme selection, represented by a single icon theme name. Static(IconThemeName), /// A dynamic icon theme selection, which can change based on the [`ThemeMode`]. Dynamic { /// The mode used to determine which theme to use. #[serde(default)] mode: ThemeAppearanceMode, /// The icon theme to use for light mode. light: IconThemeName, /// The icon theme to use for dark mode. dark: IconThemeName, },} /// The mode use to select a theme.////// `Light` and `Dark` will select their respective themes.////// `System` will select the theme based on the system's appearance.#[derive( Debug, PartialEq, Eq, Clone, Copy, Default, Serialize, Deserialize, JsonSchema, MergeFrom, strum::VariantArray, strum::VariantNames,)]#[serde(rename_all = "snake_case")]pub enum ThemeAppearanceMode { /// Use the specified `light` theme. Light, /// Use the specified `dark` theme. Dark, /// Use the theme based on the system's appearance. #[default] System,} /// Specifies the density of the UI./// Note: This setting is still experimental. See [this tracking issue](https://github.com/zed-industries/zed/issues/18078)#[derive( Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Serialize, Deserialize, JsonSchema, MergeFrom,)]#[serde(rename_all = "snake_case")]pub enum UiDensity { /// A denser UI with tighter spacing and smaller elements. #[serde(alias = "compact")] Compact, #[default] #[serde(alias = "default")] /// The default UI density. Default, #[serde(alias = "comfortable")] /// A looser UI with more spacing and larger elements. Comfortable,} impl UiDensity { /// The spacing ratio of a given density. /// TODO: Standardize usage throughout the app or remove pub fn spacing_ratio(self) -> f32 { match self { UiDensity::Compact => 0.75, UiDensity::Default => 1.0, UiDensity::Comfortable => 1.25, } }} /// Font family name.#[with_fallible_options]#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq)]#[serde(transparent)]pub struct FontFamilyName(pub Arc<str>); impl AsRef<str> for FontFamilyName { fn as_ref(&self) -> &str { &self.0 }} impl From<String> for FontFamilyName { fn from(value: String) -> Self { Self(Arc::from(value)) }} impl From<FontFamilyName> for String { fn from(value: FontFamilyName) -> Self { value.0.to_string() }} /// The buffer's line height.#[derive( Clone, Copy, Debug, Serialize, Deserialize,Lines 1–500 of 1532. Load more
use collections::{HashMap, IndexMap}; use schemars::JsonSchema; use serde::{Deserialize, Deserializer, Serialize}; use serde_json::Value; use settings_macros::{MergeFrom, with_fallible_options}; use std::{borrow::Cow, fmt::Display, ops::Deref, sync::Arc}; use crate::serialize_f32_with_two_decimal_places; /// OpenType font features as a map of feature tag to value. /// This is a content type that mirrors `gpui::FontFeatures` but without the Arc wrapper. /// Values can be specified as booleans (true=1, false=0) or integers. #[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, MergeFrom)] #[serde(transparent)] pub struct FontFeaturesContent(pub IndexMap<String, u32>); impl FontFeaturesContent { pub fn new() -> Self { Self(IndexMap::default()) } } #[derive(Debug, serde::Deserialize)] #[serde(untagged)] enum FeatureValue { Bool(bool), Number(serde_json::Number), } fn is_valid_feature_tag(tag: &str) -> bool { tag.len() == 4 && tag.chars().all(|c| c.is_ascii_alphanumeric()) } impl<'de> Deserialize<'de> for FontFeaturesContent { fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>, { use serde::de::{MapAccess, Visitor}; use std::fmt; struct FontFeaturesVisitor; impl<'de> Visitor<'de> for FontFeaturesVisitor { type Value = FontFeaturesContent; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a map of font features") } fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error> where M: MapAccess<'de>, { let mut feature_map = IndexMap::default(); while let Some((key, value)) = access.next_entry::<String, Option<FeatureValue>>()? { if !is_valid_feature_tag(&key) { log::error!("Incorrect font feature tag: {}", key); continue; } if let Some(value) = value { match value { FeatureValue::Bool(enable) => { feature_map.insert(key, if enable { 1 } else { 0 }); } FeatureValue::Number(value) => { if value.is_u64() { feature_map.insert(key, value.as_u64().unwrap() as u32); } else { log::error!( "Incorrect font feature value {} for feature tag {}", value, key ); continue; } } } } } Ok(FontFeaturesContent(feature_map)) } } deserializer.deserialize_map(FontFeaturesVisitor) } } impl JsonSchema for FontFeaturesContent { fn schema_name() -> Cow<'static, str> { "FontFeaturesContent".into() } fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema { use schemars::json_schema; json_schema!({ "type": "object", "patternProperties": { "[0-9a-zA-Z]{4}$": { "type": ["boolean", "integer"], "minimum": 0, "multipleOf": 1 } }, "additionalProperties": false }) } } #[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, MergeFrom)] #[serde(transparent)] pub struct ThemeColor(String); impl JsonSchema for ThemeColor { fn schema_name() -> Cow<'static, str> { "Color".into() } fn json_schema(_generator: &mut schemars::SchemaGenerator) -> schemars::Schema { use schemars::json_schema; json_schema!({ "type": "string", "pattern": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$", "format": "color" }) } } impl From<String> for ThemeColor { fn from(value: String) -> Self { ThemeColor(value) } } impl From<&str> for ThemeColor { fn from(value: &str) -> Self { ThemeColor(value.to_string()) } } impl Deref for ThemeColor { type Target = str; fn deref(&self) -> &Self::Target { &self.0 } } impl From<ThemeColor> for String { fn from(value: ThemeColor) -> Self { value.0 } } impl Display for ThemeColor { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0) } } impl TryFrom<&ThemeColor> for gpui::Rgba { type Error = anyhow::Error; fn try_from(value: &ThemeColor) -> anyhow::Result<Self> { let s: &str = &value.0; gpui::Rgba::try_from(s) } } /// Settings for rendering text in UI and text buffers. #[with_fallible_options] #[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom)] pub struct ThemeSettingsContent { /// The default font size for text in the UI. pub ui_font_size: Option<FontSize>, /// The name of a font to use for rendering in the UI. pub ui_font_family: Option<FontFamilyName>, /// The font fallbacks to use for rendering in the UI. #[schemars(default = "default_font_fallbacks")] #[schemars(extend("uniqueItems" = true))] pub ui_font_fallbacks: Option<Vec<FontFamilyName>>, /// The OpenType features to enable for text in the UI. #[schemars(default = "default_font_features")] pub ui_font_features: Option<FontFeaturesContent>, /// The weight of the UI font in CSS units from 100 to 900. #[schemars(default = "default_buffer_font_weight")] pub ui_font_weight: Option<FontWeightContent>, /// The name of a font to use for rendering in text buffers. pub buffer_font_family: Option<FontFamilyName>, /// The font fallbacks to use for rendering in text buffers. #[schemars(extend("uniqueItems" = true))] pub buffer_font_fallbacks: Option<Vec<FontFamilyName>>, /// The default font size for rendering in text buffers. pub buffer_font_size: Option<FontSize>, /// The weight of the editor font in CSS units from 100 to 900. #[schemars(default = "default_buffer_font_weight")] pub buffer_font_weight: Option<FontWeightContent>, /// The buffer's line height. pub buffer_line_height: Option<BufferLineHeight>, /// The OpenType features to enable for rendering in text buffers. #[schemars(default = "default_font_features")] pub buffer_font_features: Option<FontFeaturesContent>, /// The name of a font to use for agent responses in the agent panel. Falls back to the UI font if unset. pub agent_ui_font_family: Option<FontFamilyName>, /// The font size for agent responses in the agent panel. Falls back to the UI font size if unset. pub agent_ui_font_size: Option<FontSize>, /// The name of a font to use for user messages in the agent panel. Falls back to the buffer font if unset. pub agent_buffer_font_family: Option<FontFamilyName>, /// The font size for user messages in the agent panel. pub agent_buffer_font_size: Option<FontSize>, pub git_commit_buffer_font_size: Option<FontSize>, /// The name of a font to use for rendering in the markdown preview. /// Falls back to the UI font if unset. pub markdown_preview_font_family: Option<FontFamilyName>, /// The name of a font to use for code (code blocks and inline code) in the /// markdown preview. Falls back to the buffer font if unset. pub markdown_preview_code_font_family: Option<FontFamilyName>, /// The font size to use for rendering in the markdown preview. /// Falls back to the UI font size if unset. pub markdown_preview_font_size: Option<FontSize>, /// The theme to use for the markdown preview. /// Falls back to the main editor theme if unset. pub markdown_preview_theme: Option<ThemeSelection>, /// The name of the Zed theme to use. pub theme: Option<ThemeSelection>, /// The name of the icon theme to use. pub icon_theme: Option<IconThemeSelection>, /// UNSTABLE: Expect many elements to be broken. /// // Controls the density of the UI. #[serde(rename = "unstable.ui_density")] pub ui_density: Option<UiDensity>, /// How much to fade out unused code. #[schemars(range(min = 0.0, max = 0.9))] pub unnecessary_code_fade: Option<CodeFade>, /// EXPERIMENTAL: Overrides for the current theme. /// /// These values will override the ones on the current theme specified in `theme`. #[serde(rename = "experimental.theme_overrides")] pub experimental_theme_overrides: Option<ThemeStyleContent>, /// Overrides per theme /// /// These values will override the ones on the specified theme #[serde(default)] pub theme_overrides: HashMap<String, ThemeStyleContent>, } /// A font size value in pixels, wrapping around `f32` for custom settings UI rendering. #[derive( Clone, Copy, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, PartialOrd, derive_more::FromStr, )] #[serde(transparent)] pub struct FontSize(#[serde(serialize_with = "serialize_f32_with_two_decimal_places")] pub f32); impl Display for FontSize { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{:.2}", self.0) } } impl From<f32> for FontSize { fn from(value: f32) -> Self { Self(value) } } #[derive( Clone, Copy, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, PartialOrd, derive_more::FromStr, )] #[serde(transparent)] pub struct CodeFade(#[serde(serialize_with = "serialize_f32_with_two_decimal_places")] pub f32); impl Display for CodeFade { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{:.2}", self.0) } } impl From<f32> for CodeFade { fn from(x: f32) -> Self { Self(x) } } fn default_font_features() -> Option<FontFeaturesContent> { Some(FontFeaturesContent::default()) } fn default_font_fallbacks() -> Option<Vec<FontFamilyName>> { Some(Vec::new()) } fn default_buffer_font_weight() -> Option<FontWeightContent> { Some(FontWeightContent::NORMAL) } /// Represents the selection of a theme, which can be either static or dynamic. #[derive( Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq, strum::EnumDiscriminants, )] #[strum_discriminants(derive(strum::VariantArray, strum::VariantNames, strum::FromRepr))] #[serde(untagged)] pub enum ThemeSelection { /// A static theme selection, represented by a single theme name. Static(ThemeName), /// A dynamic theme selection, which can change based the [ThemeMode]. Dynamic { /// The mode used to determine which theme to use. #[serde(default)] mode: ThemeAppearanceMode, /// The theme to use for light mode. light: ThemeName, /// The theme to use for dark mode. dark: ThemeName, }, } pub const DEFAULT_LIGHT_THEME: &'static str = "One Light"; pub const DEFAULT_DARK_THEME: &'static str = "One Dark"; impl Default for ThemeSelection { fn default() -> Self { Self::Dynamic { mode: ThemeAppearanceMode::default(), light: ThemeName(DEFAULT_LIGHT_THEME.into()), dark: ThemeName(DEFAULT_DARK_THEME.into()), } } } /// Represents the selection of an icon theme, which can be either static or dynamic. #[derive( Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq, strum::EnumDiscriminants, )] #[strum_discriminants(derive(strum::VariantArray, strum::VariantNames, strum::FromRepr))] #[serde(untagged)] pub enum IconThemeSelection { /// A static icon theme selection, represented by a single icon theme name. Static(IconThemeName), /// A dynamic icon theme selection, which can change based on the [`ThemeMode`]. Dynamic { /// The mode used to determine which theme to use. #[serde(default)] mode: ThemeAppearanceMode, /// The icon theme to use for light mode. light: IconThemeName, /// The icon theme to use for dark mode. dark: IconThemeName, }, } /// The mode use to select a theme. /// /// `Light` and `Dark` will select their respective themes. /// /// `System` will select the theme based on the system's appearance. #[derive( Debug, PartialEq, Eq, Clone, Copy, Default, Serialize, Deserialize, JsonSchema, MergeFrom, strum::VariantArray, strum::VariantNames, )] #[serde(rename_all = "snake_case")] pub enum ThemeAppearanceMode { /// Use the specified `light` theme. Light, /// Use the specified `dark` theme. Dark, /// Use the theme based on the system's appearance. #[default] System, } /// Specifies the density of the UI. /// Note: This setting is still experimental. See [this tracking issue](https://github.com/zed-industries/zed/issues/18078) #[derive( Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Serialize, Deserialize, JsonSchema, MergeFrom, )] #[serde(rename_all = "snake_case")] pub enum UiDensity { /// A denser UI with tighter spacing and smaller elements. #[serde(alias = "compact")] Compact, #[default] #[serde(alias = "default")] /// The default UI density. Default, #[serde(alias = "comfortable")] /// A looser UI with more spacing and larger elements. Comfortable, } impl UiDensity { /// The spacing ratio of a given density. /// TODO: Standardize usage throughout the app or remove pub fn spacing_ratio(self) -> f32 { match self { UiDensity::Compact => 0.75, UiDensity::Default => 1.0, UiDensity::Comfortable => 1.25, } } } /// Font family name. #[with_fallible_options] #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq)] #[serde(transparent)] pub struct FontFamilyName(pub Arc<str>); impl AsRef<str> for FontFamilyName { fn as_ref(&self) -> &str { &self.0 } } impl From<String> for FontFamilyName { fn from(value: String) -> Self { Self(Arc::from(value)) } } impl From<FontFamilyName> for String { fn from(value: FontFamilyName) -> Self { value.0.to_string() } } /// The buffer's line height. #[derive( Clone, Copy, Debug, Serialize, Deserialize,