1465 lines · 50.4 KB · Rust
RawDownload
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, 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        })    }} /// 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 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 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 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,    PartialEq,    JsonSchema,    MergeFrom,    Default,    strum::EnumDiscriminants,)]#[strum_discriminants(derive(strum::VariantArray, strum::VariantNames, strum::FromRepr))]#[serde(rename_all = "snake_case")]pub enum BufferLineHeight {    /// A less dense line height.    #[default]    Comfortable,    /// The default line height.    Standard,    /// A custom line height, where 1.0 is the font's height. Must be at least 1.0.    Custom(#[serde(deserialize_with = "deserialize_line_height")] f32),} fn deserialize_line_height<'de, D>(deserializer: D) -> Result<f32, D::Error>where    D: serde::Deserializer<'de>,{    let value = f32::deserialize(deserializer)?;    if value < 1.0 {        return Err(serde::de::Error::custom(            "buffer_line_height.custom must be at least 1.0",        ));    }     Ok(value)} /// The content of a serialized theme.#[with_fallible_options]#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq)]#[serde(default)]pub struct ThemeStyleContent {    #[serde(rename = "background.appearance")]    pub window_background_appearance: Option<WindowBackgroundContent>,     #[serde(default)]    pub accents: Vec<AccentContent>,     #[serde(flatten, default)]    pub colors: ThemeColorsContent,     #[serde(flatten, default)]    pub status: StatusColorsContent,     #[serde(default)]    pub players: Vec<PlayerColorContent>,     /// The styles for syntax nodes.    #[serde(default)]    pub syntax: IndexMap<String, HighlightStyleContent>,} #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq)]pub struct AccentContent(pub Option<String>); #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq)]pub struct PlayerColorContent {    pub cursor: Option<String>,    pub background: Option<String>,    pub selection: Option<String>,} 

Lines 1–500 of 1465.