schema.rs

   1#![allow(missing_docs)]
   2
   3use anyhow::Result;
   4use gpui::{FontStyle, FontWeight, HighlightStyle, Hsla, WindowBackgroundAppearance};
   5use indexmap::IndexMap;
   6use palette::FromColor;
   7use schemars::{JsonSchema, JsonSchema_repr};
   8use serde::{Deserialize, Deserializer, Serialize};
   9use serde_json::Value;
  10use serde_repr::{Deserialize_repr, Serialize_repr};
  11
  12use crate::{StatusColorsRefinement, ThemeColorsRefinement};
  13
  14pub(crate) fn try_parse_color(color: &str) -> Result<Hsla> {
  15    let rgba = gpui::Rgba::try_from(color)?;
  16    let rgba = palette::rgb::Srgba::from_components((rgba.r, rgba.g, rgba.b, rgba.a));
  17    let hsla = palette::Hsla::from_color(rgba);
  18
  19    let hsla = gpui::hsla(
  20        hsla.hue.into_positive_degrees() / 360.,
  21        hsla.saturation,
  22        hsla.lightness,
  23        hsla.alpha,
  24    );
  25
  26    Ok(hsla)
  27}
  28
  29fn ensure_non_opaque(color: Hsla) -> Hsla {
  30    const MAXIMUM_OPACITY: f32 = 0.7;
  31    if color.a <= MAXIMUM_OPACITY {
  32        color
  33    } else {
  34        Hsla {
  35            a: MAXIMUM_OPACITY,
  36            ..color
  37        }
  38    }
  39}
  40
  41#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize, JsonSchema)]
  42#[serde(rename_all = "snake_case")]
  43pub enum AppearanceContent {
  44    Light,
  45    Dark,
  46}
  47
  48/// The background appearance of the window.
  49#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize, JsonSchema)]
  50#[serde(rename_all = "snake_case")]
  51pub enum WindowBackgroundContent {
  52    Opaque,
  53    Transparent,
  54    Blurred,
  55}
  56
  57impl From<WindowBackgroundContent> for WindowBackgroundAppearance {
  58    fn from(value: WindowBackgroundContent) -> Self {
  59        match value {
  60            WindowBackgroundContent::Opaque => WindowBackgroundAppearance::Opaque,
  61            WindowBackgroundContent::Transparent => WindowBackgroundAppearance::Transparent,
  62            WindowBackgroundContent::Blurred => WindowBackgroundAppearance::Blurred,
  63        }
  64    }
  65}
  66
  67/// The content of a serialized theme family.
  68#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
  69pub struct ThemeFamilyContent {
  70    pub name: String,
  71    pub author: String,
  72    pub themes: Vec<ThemeContent>,
  73}
  74
  75/// The content of a serialized theme.
  76#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
  77pub struct ThemeContent {
  78    pub name: String,
  79    pub appearance: AppearanceContent,
  80    pub style: ThemeStyleContent,
  81}
  82
  83/// The content of a serialized theme.
  84#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema, PartialEq)]
  85#[serde(default)]
  86pub struct ThemeStyleContent {
  87    #[serde(default, rename = "background.appearance")]
  88    pub window_background_appearance: Option<WindowBackgroundContent>,
  89
  90    #[serde(default)]
  91    pub accents: Vec<AccentContent>,
  92
  93    #[serde(flatten, default)]
  94    pub colors: ThemeColorsContent,
  95
  96    #[serde(flatten, default)]
  97    pub status: StatusColorsContent,
  98
  99    #[serde(default)]
 100    pub players: Vec<PlayerColorContent>,
 101
 102    /// The styles for syntax nodes.
 103    #[serde(default)]
 104    pub syntax: IndexMap<String, HighlightStyleContent>,
 105}
 106
 107impl ThemeStyleContent {
 108    /// Returns a [`ThemeColorsRefinement`] based on the colors in the [`ThemeContent`].
 109    #[inline(always)]
 110    pub fn theme_colors_refinement(&self) -> ThemeColorsRefinement {
 111        self.colors
 112            .theme_colors_refinement(&self.status_colors_refinement())
 113    }
 114
 115    /// Returns a [`StatusColorsRefinement`] based on the colors in the [`ThemeContent`].
 116    #[inline(always)]
 117    pub fn status_colors_refinement(&self) -> StatusColorsRefinement {
 118        self.status.status_colors_refinement()
 119    }
 120
 121    /// Returns the syntax style overrides in the [`ThemeContent`].
 122    pub fn syntax_overrides(&self) -> Vec<(String, HighlightStyle)> {
 123        self.syntax
 124            .iter()
 125            .map(|(key, style)| {
 126                (
 127                    key.clone(),
 128                    HighlightStyle {
 129                        color: style
 130                            .color
 131                            .as_ref()
 132                            .and_then(|color| try_parse_color(color).ok()),
 133                        background_color: style
 134                            .background_color
 135                            .as_ref()
 136                            .and_then(|color| try_parse_color(color).ok()),
 137                        font_style: style.font_style.map(FontStyle::from),
 138                        font_weight: style.font_weight.map(FontWeight::from),
 139                        ..Default::default()
 140                    },
 141                )
 142            })
 143            .collect()
 144    }
 145}
 146
 147#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema, PartialEq)]
 148#[serde(default)]
 149pub struct ThemeColorsContent {
 150    /// Border color. Used for most borders, is usually a high contrast color.
 151    #[serde(rename = "border")]
 152    pub border: Option<String>,
 153
 154    /// Border color. Used for deemphasized borders, like a visual divider between two sections
 155    #[serde(rename = "border.variant")]
 156    pub border_variant: Option<String>,
 157
 158    /// Border color. Used for focused elements, like keyboard focused list item.
 159    #[serde(rename = "border.focused")]
 160    pub border_focused: Option<String>,
 161
 162    /// Border color. Used for selected elements, like an active search filter or selected checkbox.
 163    #[serde(rename = "border.selected")]
 164    pub border_selected: Option<String>,
 165
 166    /// Border color. Used for transparent borders. Used for placeholder borders when an element gains a border on state change.
 167    #[serde(rename = "border.transparent")]
 168    pub border_transparent: Option<String>,
 169
 170    /// Border color. Used for disabled elements, like a disabled input or button.
 171    #[serde(rename = "border.disabled")]
 172    pub border_disabled: Option<String>,
 173
 174    /// Background color. Used for elevated surfaces, like a context menu, popup, or dialog.
 175    #[serde(rename = "elevated_surface.background")]
 176    pub elevated_surface_background: Option<String>,
 177
 178    /// Background Color. Used for grounded surfaces like a panel or tab.
 179    #[serde(rename = "surface.background")]
 180    pub surface_background: Option<String>,
 181
 182    /// Background Color. Used for the app background and blank panels or windows.
 183    #[serde(rename = "background")]
 184    pub background: Option<String>,
 185
 186    /// Background Color. Used for the background of an element that should have a different background than the surface it's on.
 187    ///
 188    /// Elements might include: Buttons, Inputs, Checkboxes, Radio Buttons...
 189    ///
 190    /// For an element that should have the same background as the surface it's on, use `ghost_element_background`.
 191    #[serde(rename = "element.background")]
 192    pub element_background: Option<String>,
 193
 194    /// Background Color. Used for the hover state of an element that should have a different background than the surface it's on.
 195    ///
 196    /// Hover states are triggered by the mouse entering an element, or a finger touching an element on a touch screen.
 197    #[serde(rename = "element.hover")]
 198    pub element_hover: Option<String>,
 199
 200    /// Background Color. Used for the active state of an element that should have a different background than the surface it's on.
 201    ///
 202    /// Active states are triggered by the mouse button being pressed down on an element, or the Return button or other activator being pressed.
 203    #[serde(rename = "element.active")]
 204    pub element_active: Option<String>,
 205
 206    /// Background Color. Used for the selected state of an element that should have a different background than the surface it's on.
 207    ///
 208    /// Selected states are triggered by the element being selected (or "activated") by the user.
 209    ///
 210    /// This could include a selected checkbox, a toggleable button that is toggled on, etc.
 211    #[serde(rename = "element.selected")]
 212    pub element_selected: Option<String>,
 213
 214    /// Background Color. Used for the disabled state of an element that should have a different background than the surface it's on.
 215    ///
 216    /// Disabled states are shown when a user cannot interact with an element, like a disabled button or input.
 217    #[serde(rename = "element.disabled")]
 218    pub element_disabled: Option<String>,
 219
 220    /// Background Color. Used for the background of selections in a UI element.
 221    #[serde(rename = "element.selection_background")]
 222    pub element_selection_background: Option<String>,
 223
 224    /// Background Color. Used for the area that shows where a dragged element will be dropped.
 225    #[serde(rename = "drop_target.background")]
 226    pub drop_target_background: Option<String>,
 227
 228    /// Used for the background of a ghost element that should have the same background as the surface it's on.
 229    ///
 230    /// Elements might include: Buttons, Inputs, Checkboxes, Radio Buttons...
 231    ///
 232    /// For an element that should have a different background than the surface it's on, use `element_background`.
 233    #[serde(rename = "ghost_element.background")]
 234    pub ghost_element_background: Option<String>,
 235
 236    /// Background Color. Used for the hover state of a ghost element that should have the same background as the surface it's on.
 237    ///
 238    /// Hover states are triggered by the mouse entering an element, or a finger touching an element on a touch screen.
 239    #[serde(rename = "ghost_element.hover")]
 240    pub ghost_element_hover: Option<String>,
 241
 242    /// Background Color. Used for the active state of a ghost element that should have the same background as the surface it's on.
 243    ///
 244    /// Active states are triggered by the mouse button being pressed down on an element, or the Return button or other activator being pressed.
 245    #[serde(rename = "ghost_element.active")]
 246    pub ghost_element_active: Option<String>,
 247
 248    /// Background Color. Used for the selected state of a ghost element that should have the same background as the surface it's on.
 249    ///
 250    /// Selected states are triggered by the element being selected (or "activated") by the user.
 251    ///
 252    /// This could include a selected checkbox, a toggleable button that is toggled on, etc.
 253    #[serde(rename = "ghost_element.selected")]
 254    pub ghost_element_selected: Option<String>,
 255
 256    /// Background Color. Used for the disabled state of a ghost element that should have the same background as the surface it's on.
 257    ///
 258    /// Disabled states are shown when a user cannot interact with an element, like a disabled button or input.
 259    #[serde(rename = "ghost_element.disabled")]
 260    pub ghost_element_disabled: Option<String>,
 261
 262    /// Text Color. Default text color used for most text.
 263    #[serde(rename = "text")]
 264    pub text: Option<String>,
 265
 266    /// Text Color. Color of muted or deemphasized text. It is a subdued version of the standard text color.
 267    #[serde(rename = "text.muted")]
 268    pub text_muted: Option<String>,
 269
 270    /// Text Color. Color of the placeholder text typically shown in input fields to guide the user to enter valid data.
 271    #[serde(rename = "text.placeholder")]
 272    pub text_placeholder: Option<String>,
 273
 274    /// Text Color. Color used for text denoting disabled elements. Typically, the color is faded or grayed out to emphasize the disabled state.
 275    #[serde(rename = "text.disabled")]
 276    pub text_disabled: Option<String>,
 277
 278    /// Text Color. Color used for emphasis or highlighting certain text, like an active filter or a matched character in a search.
 279    #[serde(rename = "text.accent")]
 280    pub text_accent: Option<String>,
 281
 282    /// Fill Color. Used for the default fill color of an icon.
 283    #[serde(rename = "icon")]
 284    pub icon: Option<String>,
 285
 286    /// Fill Color. Used for the muted or deemphasized fill color of an icon.
 287    ///
 288    /// This might be used to show an icon in an inactive pane, or to deemphasize a series of icons to give them less visual weight.
 289    #[serde(rename = "icon.muted")]
 290    pub icon_muted: Option<String>,
 291
 292    /// Fill Color. Used for the disabled fill color of an icon.
 293    ///
 294    /// Disabled states are shown when a user cannot interact with an element, like a icon button.
 295    #[serde(rename = "icon.disabled")]
 296    pub icon_disabled: Option<String>,
 297
 298    /// Fill Color. Used for the placeholder fill color of an icon.
 299    ///
 300    /// This might be used to show an icon in an input that disappears when the user enters text.
 301    #[serde(rename = "icon.placeholder")]
 302    pub icon_placeholder: Option<String>,
 303
 304    /// Fill Color. Used for the accent fill color of an icon.
 305    ///
 306    /// This might be used to show when a toggleable icon button is selected.
 307    #[serde(rename = "icon.accent")]
 308    pub icon_accent: Option<String>,
 309
 310    /// Color used to accent some of the debuggers elements
 311    /// Only accent breakpoint & breakpoint related symbols right now
 312    #[serde(rename = "debugger.accent")]
 313    pub debugger_accent: Option<String>,
 314
 315    #[serde(rename = "status_bar.background")]
 316    pub status_bar_background: Option<String>,
 317
 318    #[serde(rename = "title_bar.background")]
 319    pub title_bar_background: Option<String>,
 320
 321    #[serde(rename = "title_bar.inactive_background")]
 322    pub title_bar_inactive_background: Option<String>,
 323
 324    #[serde(rename = "toolbar.background")]
 325    pub toolbar_background: Option<String>,
 326
 327    #[serde(rename = "tab_bar.background")]
 328    pub tab_bar_background: Option<String>,
 329
 330    #[serde(rename = "tab.inactive_background")]
 331    pub tab_inactive_background: Option<String>,
 332
 333    #[serde(rename = "tab.active_background")]
 334    pub tab_active_background: Option<String>,
 335
 336    #[serde(rename = "search.match_background")]
 337    pub search_match_background: Option<String>,
 338
 339    #[serde(rename = "panel.background")]
 340    pub panel_background: Option<String>,
 341
 342    #[serde(rename = "panel.focused_border")]
 343    pub panel_focused_border: Option<String>,
 344
 345    #[serde(rename = "panel.indent_guide")]
 346    pub panel_indent_guide: Option<String>,
 347
 348    #[serde(rename = "panel.indent_guide_hover")]
 349    pub panel_indent_guide_hover: Option<String>,
 350
 351    #[serde(rename = "panel.indent_guide_active")]
 352    pub panel_indent_guide_active: Option<String>,
 353
 354    #[serde(rename = "panel.overlay_background")]
 355    pub panel_overlay_background: Option<String>,
 356
 357    #[serde(rename = "panel.overlay_hover")]
 358    pub panel_overlay_hover: Option<String>,
 359
 360    #[serde(rename = "pane.focused_border")]
 361    pub pane_focused_border: Option<String>,
 362
 363    #[serde(rename = "pane_group.border")]
 364    pub pane_group_border: Option<String>,
 365
 366    /// The deprecated version of `scrollbar.thumb.background`.
 367    ///
 368    /// Don't use this field.
 369    #[serde(rename = "scrollbar_thumb.background", skip_serializing)]
 370    #[schemars(skip)]
 371    pub deprecated_scrollbar_thumb_background: Option<String>,
 372
 373    /// The color of the scrollbar thumb.
 374    #[serde(rename = "scrollbar.thumb.background")]
 375    pub scrollbar_thumb_background: Option<String>,
 376
 377    /// The color of the scrollbar thumb when hovered over.
 378    #[serde(rename = "scrollbar.thumb.hover_background")]
 379    pub scrollbar_thumb_hover_background: Option<String>,
 380
 381    /// The color of the scrollbar thumb whilst being actively dragged.
 382    #[serde(rename = "scrollbar.thumb.active_background")]
 383    pub scrollbar_thumb_active_background: Option<String>,
 384
 385    /// The border color of the scrollbar thumb.
 386    #[serde(rename = "scrollbar.thumb.border")]
 387    pub scrollbar_thumb_border: Option<String>,
 388
 389    /// The background color of the scrollbar track.
 390    #[serde(rename = "scrollbar.track.background")]
 391    pub scrollbar_track_background: Option<String>,
 392
 393    /// The border color of the scrollbar track.
 394    #[serde(rename = "scrollbar.track.border")]
 395    pub scrollbar_track_border: Option<String>,
 396
 397    /// The color of the minimap thumb.
 398    #[serde(rename = "minimap.thumb.background")]
 399    pub minimap_thumb_background: Option<String>,
 400
 401    /// The color of the minimap thumb when hovered over.
 402    #[serde(rename = "minimap.thumb.hover_background")]
 403    pub minimap_thumb_hover_background: Option<String>,
 404
 405    /// The color of the minimap thumb whilst being actively dragged.
 406    #[serde(rename = "minimap.thumb.active_background")]
 407    pub minimap_thumb_active_background: Option<String>,
 408
 409    /// The border color of the minimap thumb.
 410    #[serde(rename = "minimap.thumb.border")]
 411    pub minimap_thumb_border: Option<String>,
 412
 413    #[serde(rename = "editor.foreground")]
 414    pub editor_foreground: Option<String>,
 415
 416    #[serde(rename = "editor.background")]
 417    pub editor_background: Option<String>,
 418
 419    #[serde(rename = "editor.gutter.background")]
 420    pub editor_gutter_background: Option<String>,
 421
 422    #[serde(rename = "editor.subheader.background")]
 423    pub editor_subheader_background: Option<String>,
 424
 425    #[serde(rename = "editor.active_line.background")]
 426    pub editor_active_line_background: Option<String>,
 427
 428    #[serde(rename = "editor.highlighted_line.background")]
 429    pub editor_highlighted_line_background: Option<String>,
 430
 431    /// Background of active line of debugger
 432    #[serde(rename = "editor.debugger_active_line.background")]
 433    pub editor_debugger_active_line_background: Option<String>,
 434
 435    /// Text Color. Used for the text of the line number in the editor gutter.
 436    #[serde(rename = "editor.line_number")]
 437    pub editor_line_number: Option<String>,
 438
 439    /// Text Color. Used for the text of the line number in the editor gutter when the line is highlighted.
 440    #[serde(rename = "editor.active_line_number")]
 441    pub editor_active_line_number: Option<String>,
 442
 443    /// Text Color. Used for the text of the line number in the editor gutter when the line is hovered over.
 444    #[serde(rename = "editor.hover_line_number")]
 445    pub editor_hover_line_number: Option<String>,
 446
 447    /// Text Color. Used to mark invisible characters in the editor.
 448    ///
 449    /// Example: spaces, tabs, carriage returns, etc.
 450    #[serde(rename = "editor.invisible")]
 451    pub editor_invisible: Option<String>,
 452
 453    #[serde(rename = "editor.wrap_guide")]
 454    pub editor_wrap_guide: Option<String>,
 455
 456    #[serde(rename = "editor.active_wrap_guide")]
 457    pub editor_active_wrap_guide: Option<String>,
 458
 459    #[serde(rename = "editor.indent_guide")]
 460    pub editor_indent_guide: Option<String>,
 461
 462    #[serde(rename = "editor.indent_guide_active")]
 463    pub editor_indent_guide_active: Option<String>,
 464
 465    /// Read-access of a symbol, like reading a variable.
 466    ///
 467    /// A document highlight is a range inside a text document which deserves
 468    /// special attention. Usually a document highlight is visualized by changing
 469    /// the background color of its range.
 470    #[serde(rename = "editor.document_highlight.read_background")]
 471    pub editor_document_highlight_read_background: Option<String>,
 472
 473    /// Read-access of a symbol, like reading a variable.
 474    ///
 475    /// A document highlight is a range inside a text document which deserves
 476    /// special attention. Usually a document highlight is visualized by changing
 477    /// the background color of its range.
 478    #[serde(rename = "editor.document_highlight.write_background")]
 479    pub editor_document_highlight_write_background: Option<String>,
 480
 481    /// Highlighted brackets background color.
 482    ///
 483    /// Matching brackets in the cursor scope are highlighted with this background color.
 484    #[serde(rename = "editor.document_highlight.bracket_background")]
 485    pub editor_document_highlight_bracket_background: Option<String>,
 486
 487    /// Terminal background color.
 488    #[serde(rename = "terminal.background")]
 489    pub terminal_background: Option<String>,
 490
 491    /// Terminal foreground color.
 492    #[serde(rename = "terminal.foreground")]
 493    pub terminal_foreground: Option<String>,
 494
 495    /// Terminal ANSI background color.
 496    #[serde(rename = "terminal.ansi.background")]
 497    pub terminal_ansi_background: Option<String>,
 498
 499    /// Bright terminal foreground color.
 500    #[serde(rename = "terminal.bright_foreground")]
 501    pub terminal_bright_foreground: Option<String>,
 502
 503    /// Dim terminal foreground color.
 504    #[serde(rename = "terminal.dim_foreground")]
 505    pub terminal_dim_foreground: Option<String>,
 506
 507    /// Black ANSI terminal color.
 508    #[serde(rename = "terminal.ansi.black")]
 509    pub terminal_ansi_black: Option<String>,
 510
 511    /// Bright black ANSI terminal color.
 512    #[serde(rename = "terminal.ansi.bright_black")]
 513    pub terminal_ansi_bright_black: Option<String>,
 514
 515    /// Dim black ANSI terminal color.
 516    #[serde(rename = "terminal.ansi.dim_black")]
 517    pub terminal_ansi_dim_black: Option<String>,
 518
 519    /// Red ANSI terminal color.
 520    #[serde(rename = "terminal.ansi.red")]
 521    pub terminal_ansi_red: Option<String>,
 522
 523    /// Bright red ANSI terminal color.
 524    #[serde(rename = "terminal.ansi.bright_red")]
 525    pub terminal_ansi_bright_red: Option<String>,
 526
 527    /// Dim red ANSI terminal color.
 528    #[serde(rename = "terminal.ansi.dim_red")]
 529    pub terminal_ansi_dim_red: Option<String>,
 530
 531    /// Green ANSI terminal color.
 532    #[serde(rename = "terminal.ansi.green")]
 533    pub terminal_ansi_green: Option<String>,
 534
 535    /// Bright green ANSI terminal color.
 536    #[serde(rename = "terminal.ansi.bright_green")]
 537    pub terminal_ansi_bright_green: Option<String>,
 538
 539    /// Dim green ANSI terminal color.
 540    #[serde(rename = "terminal.ansi.dim_green")]
 541    pub terminal_ansi_dim_green: Option<String>,
 542
 543    /// Yellow ANSI terminal color.
 544    #[serde(rename = "terminal.ansi.yellow")]
 545    pub terminal_ansi_yellow: Option<String>,
 546
 547    /// Bright yellow ANSI terminal color.
 548    #[serde(rename = "terminal.ansi.bright_yellow")]
 549    pub terminal_ansi_bright_yellow: Option<String>,
 550
 551    /// Dim yellow ANSI terminal color.
 552    #[serde(rename = "terminal.ansi.dim_yellow")]
 553    pub terminal_ansi_dim_yellow: Option<String>,
 554
 555    /// Blue ANSI terminal color.
 556    #[serde(rename = "terminal.ansi.blue")]
 557    pub terminal_ansi_blue: Option<String>,
 558
 559    /// Bright blue ANSI terminal color.
 560    #[serde(rename = "terminal.ansi.bright_blue")]
 561    pub terminal_ansi_bright_blue: Option<String>,
 562
 563    /// Dim blue ANSI terminal color.
 564    #[serde(rename = "terminal.ansi.dim_blue")]
 565    pub terminal_ansi_dim_blue: Option<String>,
 566
 567    /// Magenta ANSI terminal color.
 568    #[serde(rename = "terminal.ansi.magenta")]
 569    pub terminal_ansi_magenta: Option<String>,
 570
 571    /// Bright magenta ANSI terminal color.
 572    #[serde(rename = "terminal.ansi.bright_magenta")]
 573    pub terminal_ansi_bright_magenta: Option<String>,
 574
 575    /// Dim magenta ANSI terminal color.
 576    #[serde(rename = "terminal.ansi.dim_magenta")]
 577    pub terminal_ansi_dim_magenta: Option<String>,
 578
 579    /// Cyan ANSI terminal color.
 580    #[serde(rename = "terminal.ansi.cyan")]
 581    pub terminal_ansi_cyan: Option<String>,
 582
 583    /// Bright cyan ANSI terminal color.
 584    #[serde(rename = "terminal.ansi.bright_cyan")]
 585    pub terminal_ansi_bright_cyan: Option<String>,
 586
 587    /// Dim cyan ANSI terminal color.
 588    #[serde(rename = "terminal.ansi.dim_cyan")]
 589    pub terminal_ansi_dim_cyan: Option<String>,
 590
 591    /// White ANSI terminal color.
 592    #[serde(rename = "terminal.ansi.white")]
 593    pub terminal_ansi_white: Option<String>,
 594
 595    /// Bright white ANSI terminal color.
 596    #[serde(rename = "terminal.ansi.bright_white")]
 597    pub terminal_ansi_bright_white: Option<String>,
 598
 599    /// Dim white ANSI terminal color.
 600    #[serde(rename = "terminal.ansi.dim_white")]
 601    pub terminal_ansi_dim_white: Option<String>,
 602
 603    #[serde(rename = "link_text.hover")]
 604    pub link_text_hover: Option<String>,
 605
 606    /// Added version control color.
 607    #[serde(rename = "version_control.added")]
 608    pub version_control_added: Option<String>,
 609
 610    /// Deleted version control color.
 611    #[serde(rename = "version_control.deleted")]
 612    pub version_control_deleted: Option<String>,
 613
 614    /// Modified version control color.
 615    #[serde(rename = "version_control.modified")]
 616    pub version_control_modified: Option<String>,
 617
 618    /// Renamed version control color.
 619    #[serde(rename = "version_control.renamed")]
 620    pub version_control_renamed: Option<String>,
 621
 622    /// Conflict version control color.
 623    #[serde(rename = "version_control.conflict")]
 624    pub version_control_conflict: Option<String>,
 625
 626    /// Ignored version control color.
 627    #[serde(rename = "version_control.ignored")]
 628    pub version_control_ignored: Option<String>,
 629
 630    /// Background color for row highlights of "ours" regions in merge conflicts.
 631    #[serde(rename = "version_control.conflict_marker.ours")]
 632    pub version_control_conflict_marker_ours: Option<String>,
 633
 634    /// Background color for row highlights of "theirs" regions in merge conflicts.
 635    #[serde(rename = "version_control.conflict_marker.theirs")]
 636    pub version_control_conflict_marker_theirs: Option<String>,
 637
 638    /// Deprecated in favor of `version_control_conflict_marker_ours`.
 639    #[deprecated]
 640    pub version_control_conflict_ours_background: Option<String>,
 641
 642    /// Deprecated in favor of `version_control_conflict_marker_theirs`.
 643    #[deprecated]
 644    pub version_control_conflict_theirs_background: Option<String>,
 645}
 646
 647impl ThemeColorsContent {
 648    /// Returns a [`ThemeColorsRefinement`] based on the colors in the [`ThemeColorsContent`].
 649    pub fn theme_colors_refinement(
 650        &self,
 651        status_colors: &StatusColorsRefinement,
 652    ) -> ThemeColorsRefinement {
 653        let border = self
 654            .border
 655            .as_ref()
 656            .and_then(|color| try_parse_color(color).ok());
 657        let editor_document_highlight_read_background = self
 658            .editor_document_highlight_read_background
 659            .as_ref()
 660            .and_then(|color| try_parse_color(color).ok());
 661        let scrollbar_thumb_background = self
 662            .scrollbar_thumb_background
 663            .as_ref()
 664            .and_then(|color| try_parse_color(color).ok())
 665            .or_else(|| {
 666                self.deprecated_scrollbar_thumb_background
 667                    .as_ref()
 668                    .and_then(|color| try_parse_color(color).ok())
 669            });
 670        let scrollbar_thumb_hover_background = self
 671            .scrollbar_thumb_hover_background
 672            .as_ref()
 673            .and_then(|color| try_parse_color(color).ok());
 674        let scrollbar_thumb_active_background = self
 675            .scrollbar_thumb_active_background
 676            .as_ref()
 677            .and_then(|color| try_parse_color(color).ok())
 678            .or(scrollbar_thumb_background);
 679        let scrollbar_thumb_border = self
 680            .scrollbar_thumb_border
 681            .as_ref()
 682            .and_then(|color| try_parse_color(color).ok());
 683        let element_hover = self
 684            .element_hover
 685            .as_ref()
 686            .and_then(|color| try_parse_color(color).ok());
 687        let panel_background = self
 688            .panel_background
 689            .as_ref()
 690            .and_then(|color| try_parse_color(color).ok());
 691        ThemeColorsRefinement {
 692            border,
 693            border_variant: self
 694                .border_variant
 695                .as_ref()
 696                .and_then(|color| try_parse_color(color).ok()),
 697            border_focused: self
 698                .border_focused
 699                .as_ref()
 700                .and_then(|color| try_parse_color(color).ok()),
 701            border_selected: self
 702                .border_selected
 703                .as_ref()
 704                .and_then(|color| try_parse_color(color).ok()),
 705            border_transparent: self
 706                .border_transparent
 707                .as_ref()
 708                .and_then(|color| try_parse_color(color).ok()),
 709            border_disabled: self
 710                .border_disabled
 711                .as_ref()
 712                .and_then(|color| try_parse_color(color).ok()),
 713            elevated_surface_background: self
 714                .elevated_surface_background
 715                .as_ref()
 716                .and_then(|color| try_parse_color(color).ok()),
 717            surface_background: self
 718                .surface_background
 719                .as_ref()
 720                .and_then(|color| try_parse_color(color).ok()),
 721            background: self
 722                .background
 723                .as_ref()
 724                .and_then(|color| try_parse_color(color).ok()),
 725            element_background: self
 726                .element_background
 727                .as_ref()
 728                .and_then(|color| try_parse_color(color).ok()),
 729            element_hover,
 730            element_active: self
 731                .element_active
 732                .as_ref()
 733                .and_then(|color| try_parse_color(color).ok()),
 734            element_selected: self
 735                .element_selected
 736                .as_ref()
 737                .and_then(|color| try_parse_color(color).ok()),
 738            element_disabled: self
 739                .element_disabled
 740                .as_ref()
 741                .and_then(|color| try_parse_color(color).ok()),
 742            element_selection_background: self
 743                .element_selection_background
 744                .as_ref()
 745                .and_then(|color| try_parse_color(color).ok()),
 746            drop_target_background: self
 747                .drop_target_background
 748                .as_ref()
 749                .and_then(|color| try_parse_color(color).ok()),
 750            ghost_element_background: self
 751                .ghost_element_background
 752                .as_ref()
 753                .and_then(|color| try_parse_color(color).ok()),
 754            ghost_element_hover: self
 755                .ghost_element_hover
 756                .as_ref()
 757                .and_then(|color| try_parse_color(color).ok()),
 758            ghost_element_active: self
 759                .ghost_element_active
 760                .as_ref()
 761                .and_then(|color| try_parse_color(color).ok()),
 762            ghost_element_selected: self
 763                .ghost_element_selected
 764                .as_ref()
 765                .and_then(|color| try_parse_color(color).ok()),
 766            ghost_element_disabled: self
 767                .ghost_element_disabled
 768                .as_ref()
 769                .and_then(|color| try_parse_color(color).ok()),
 770            text: self
 771                .text
 772                .as_ref()
 773                .and_then(|color| try_parse_color(color).ok()),
 774            text_muted: self
 775                .text_muted
 776                .as_ref()
 777                .and_then(|color| try_parse_color(color).ok()),
 778            text_placeholder: self
 779                .text_placeholder
 780                .as_ref()
 781                .and_then(|color| try_parse_color(color).ok()),
 782            text_disabled: self
 783                .text_disabled
 784                .as_ref()
 785                .and_then(|color| try_parse_color(color).ok()),
 786            text_accent: self
 787                .text_accent
 788                .as_ref()
 789                .and_then(|color| try_parse_color(color).ok()),
 790            icon: self
 791                .icon
 792                .as_ref()
 793                .and_then(|color| try_parse_color(color).ok()),
 794            icon_muted: self
 795                .icon_muted
 796                .as_ref()
 797                .and_then(|color| try_parse_color(color).ok()),
 798            icon_disabled: self
 799                .icon_disabled
 800                .as_ref()
 801                .and_then(|color| try_parse_color(color).ok()),
 802            icon_placeholder: self
 803                .icon_placeholder
 804                .as_ref()
 805                .and_then(|color| try_parse_color(color).ok()),
 806            icon_accent: self
 807                .icon_accent
 808                .as_ref()
 809                .and_then(|color| try_parse_color(color).ok()),
 810            debugger_accent: self
 811                .debugger_accent
 812                .as_ref()
 813                .and_then(|color| try_parse_color(color).ok()),
 814            status_bar_background: self
 815                .status_bar_background
 816                .as_ref()
 817                .and_then(|color| try_parse_color(color).ok()),
 818            title_bar_background: self
 819                .title_bar_background
 820                .as_ref()
 821                .and_then(|color| try_parse_color(color).ok()),
 822            title_bar_inactive_background: self
 823                .title_bar_inactive_background
 824                .as_ref()
 825                .and_then(|color| try_parse_color(color).ok()),
 826            toolbar_background: self
 827                .toolbar_background
 828                .as_ref()
 829                .and_then(|color| try_parse_color(color).ok()),
 830            tab_bar_background: self
 831                .tab_bar_background
 832                .as_ref()
 833                .and_then(|color| try_parse_color(color).ok()),
 834            tab_inactive_background: self
 835                .tab_inactive_background
 836                .as_ref()
 837                .and_then(|color| try_parse_color(color).ok()),
 838            tab_active_background: self
 839                .tab_active_background
 840                .as_ref()
 841                .and_then(|color| try_parse_color(color).ok()),
 842            search_match_background: self
 843                .search_match_background
 844                .as_ref()
 845                .and_then(|color| try_parse_color(color).ok()),
 846            panel_background,
 847            panel_focused_border: self
 848                .panel_focused_border
 849                .as_ref()
 850                .and_then(|color| try_parse_color(color).ok()),
 851            panel_indent_guide: self
 852                .panel_indent_guide
 853                .as_ref()
 854                .and_then(|color| try_parse_color(color).ok()),
 855            panel_indent_guide_hover: self
 856                .panel_indent_guide_hover
 857                .as_ref()
 858                .and_then(|color| try_parse_color(color).ok()),
 859            panel_indent_guide_active: self
 860                .panel_indent_guide_active
 861                .as_ref()
 862                .and_then(|color| try_parse_color(color).ok()),
 863            panel_overlay_background: self
 864                .panel_overlay_background
 865                .as_ref()
 866                .and_then(|color| try_parse_color(color).ok())
 867                .or(panel_background),
 868            panel_overlay_hover: self
 869                .panel_overlay_hover
 870                .as_ref()
 871                .and_then(|color| try_parse_color(color).ok())
 872                .or(element_hover),
 873            pane_focused_border: self
 874                .pane_focused_border
 875                .as_ref()
 876                .and_then(|color| try_parse_color(color).ok()),
 877            pane_group_border: self
 878                .pane_group_border
 879                .as_ref()
 880                .and_then(|color| try_parse_color(color).ok())
 881                .or(border),
 882            scrollbar_thumb_background,
 883            scrollbar_thumb_hover_background,
 884            scrollbar_thumb_active_background,
 885            scrollbar_thumb_border,
 886            scrollbar_track_background: self
 887                .scrollbar_track_background
 888                .as_ref()
 889                .and_then(|color| try_parse_color(color).ok()),
 890            scrollbar_track_border: self
 891                .scrollbar_track_border
 892                .as_ref()
 893                .and_then(|color| try_parse_color(color).ok()),
 894            minimap_thumb_background: self
 895                .minimap_thumb_background
 896                .as_ref()
 897                .and_then(|color| try_parse_color(color).ok())
 898                .or(scrollbar_thumb_background.map(ensure_non_opaque)),
 899            minimap_thumb_hover_background: self
 900                .minimap_thumb_hover_background
 901                .as_ref()
 902                .and_then(|color| try_parse_color(color).ok())
 903                .or(scrollbar_thumb_hover_background.map(ensure_non_opaque)),
 904            minimap_thumb_active_background: self
 905                .minimap_thumb_active_background
 906                .as_ref()
 907                .and_then(|color| try_parse_color(color).ok())
 908                .or(scrollbar_thumb_active_background.map(ensure_non_opaque)),
 909            minimap_thumb_border: self
 910                .minimap_thumb_border
 911                .as_ref()
 912                .and_then(|color| try_parse_color(color).ok())
 913                .or(scrollbar_thumb_border),
 914            editor_foreground: self
 915                .editor_foreground
 916                .as_ref()
 917                .and_then(|color| try_parse_color(color).ok()),
 918            editor_background: self
 919                .editor_background
 920                .as_ref()
 921                .and_then(|color| try_parse_color(color).ok()),
 922            editor_gutter_background: self
 923                .editor_gutter_background
 924                .as_ref()
 925                .and_then(|color| try_parse_color(color).ok()),
 926            editor_subheader_background: self
 927                .editor_subheader_background
 928                .as_ref()
 929                .and_then(|color| try_parse_color(color).ok()),
 930            editor_active_line_background: self
 931                .editor_active_line_background
 932                .as_ref()
 933                .and_then(|color| try_parse_color(color).ok()),
 934            editor_highlighted_line_background: self
 935                .editor_highlighted_line_background
 936                .as_ref()
 937                .and_then(|color| try_parse_color(color).ok()),
 938            editor_debugger_active_line_background: self
 939                .editor_debugger_active_line_background
 940                .as_ref()
 941                .and_then(|color| try_parse_color(color).ok()),
 942            editor_line_number: self
 943                .editor_line_number
 944                .as_ref()
 945                .and_then(|color| try_parse_color(color).ok()),
 946            editor_hover_line_number: self
 947                .editor_hover_line_number
 948                .as_ref()
 949                .and_then(|color| try_parse_color(color).ok()),
 950            editor_active_line_number: self
 951                .editor_active_line_number
 952                .as_ref()
 953                .and_then(|color| try_parse_color(color).ok()),
 954            editor_invisible: self
 955                .editor_invisible
 956                .as_ref()
 957                .and_then(|color| try_parse_color(color).ok()),
 958            editor_wrap_guide: self
 959                .editor_wrap_guide
 960                .as_ref()
 961                .and_then(|color| try_parse_color(color).ok()),
 962            editor_active_wrap_guide: self
 963                .editor_active_wrap_guide
 964                .as_ref()
 965                .and_then(|color| try_parse_color(color).ok()),
 966            editor_indent_guide: self
 967                .editor_indent_guide
 968                .as_ref()
 969                .and_then(|color| try_parse_color(color).ok()),
 970            editor_indent_guide_active: self
 971                .editor_indent_guide_active
 972                .as_ref()
 973                .and_then(|color| try_parse_color(color).ok()),
 974            editor_document_highlight_read_background,
 975            editor_document_highlight_write_background: self
 976                .editor_document_highlight_write_background
 977                .as_ref()
 978                .and_then(|color| try_parse_color(color).ok()),
 979            editor_document_highlight_bracket_background: self
 980                .editor_document_highlight_bracket_background
 981                .as_ref()
 982                .and_then(|color| try_parse_color(color).ok())
 983                // Fall back to `editor.document_highlight.read_background`, for backwards compatibility.
 984                .or(editor_document_highlight_read_background),
 985            terminal_background: self
 986                .terminal_background
 987                .as_ref()
 988                .and_then(|color| try_parse_color(color).ok()),
 989            terminal_ansi_background: self
 990                .terminal_ansi_background
 991                .as_ref()
 992                .and_then(|color| try_parse_color(color).ok()),
 993            terminal_foreground: self
 994                .terminal_foreground
 995                .as_ref()
 996                .and_then(|color| try_parse_color(color).ok()),
 997            terminal_bright_foreground: self
 998                .terminal_bright_foreground
 999                .as_ref()
1000                .and_then(|color| try_parse_color(color).ok()),
1001            terminal_dim_foreground: self
1002                .terminal_dim_foreground
1003                .as_ref()
1004                .and_then(|color| try_parse_color(color).ok()),
1005            terminal_ansi_black: self
1006                .terminal_ansi_black
1007                .as_ref()
1008                .and_then(|color| try_parse_color(color).ok()),
1009            terminal_ansi_bright_black: self
1010                .terminal_ansi_bright_black
1011                .as_ref()
1012                .and_then(|color| try_parse_color(color).ok()),
1013            terminal_ansi_dim_black: self
1014                .terminal_ansi_dim_black
1015                .as_ref()
1016                .and_then(|color| try_parse_color(color).ok()),
1017            terminal_ansi_red: self
1018                .terminal_ansi_red
1019                .as_ref()
1020                .and_then(|color| try_parse_color(color).ok()),
1021            terminal_ansi_bright_red: self
1022                .terminal_ansi_bright_red
1023                .as_ref()
1024                .and_then(|color| try_parse_color(color).ok()),
1025            terminal_ansi_dim_red: self
1026                .terminal_ansi_dim_red
1027                .as_ref()
1028                .and_then(|color| try_parse_color(color).ok()),
1029            terminal_ansi_green: self
1030                .terminal_ansi_green
1031                .as_ref()
1032                .and_then(|color| try_parse_color(color).ok()),
1033            terminal_ansi_bright_green: self
1034                .terminal_ansi_bright_green
1035                .as_ref()
1036                .and_then(|color| try_parse_color(color).ok()),
1037            terminal_ansi_dim_green: self
1038                .terminal_ansi_dim_green
1039                .as_ref()
1040                .and_then(|color| try_parse_color(color).ok()),
1041            terminal_ansi_yellow: self
1042                .terminal_ansi_yellow
1043                .as_ref()
1044                .and_then(|color| try_parse_color(color).ok()),
1045            terminal_ansi_bright_yellow: self
1046                .terminal_ansi_bright_yellow
1047                .as_ref()
1048                .and_then(|color| try_parse_color(color).ok()),
1049            terminal_ansi_dim_yellow: self
1050                .terminal_ansi_dim_yellow
1051                .as_ref()
1052                .and_then(|color| try_parse_color(color).ok()),
1053            terminal_ansi_blue: self
1054                .terminal_ansi_blue
1055                .as_ref()
1056                .and_then(|color| try_parse_color(color).ok()),
1057            terminal_ansi_bright_blue: self
1058                .terminal_ansi_bright_blue
1059                .as_ref()
1060                .and_then(|color| try_parse_color(color).ok()),
1061            terminal_ansi_dim_blue: self
1062                .terminal_ansi_dim_blue
1063                .as_ref()
1064                .and_then(|color| try_parse_color(color).ok()),
1065            terminal_ansi_magenta: self
1066                .terminal_ansi_magenta
1067                .as_ref()
1068                .and_then(|color| try_parse_color(color).ok()),
1069            terminal_ansi_bright_magenta: self
1070                .terminal_ansi_bright_magenta
1071                .as_ref()
1072                .and_then(|color| try_parse_color(color).ok()),
1073            terminal_ansi_dim_magenta: self
1074                .terminal_ansi_dim_magenta
1075                .as_ref()
1076                .and_then(|color| try_parse_color(color).ok()),
1077            terminal_ansi_cyan: self
1078                .terminal_ansi_cyan
1079                .as_ref()
1080                .and_then(|color| try_parse_color(color).ok()),
1081            terminal_ansi_bright_cyan: self
1082                .terminal_ansi_bright_cyan
1083                .as_ref()
1084                .and_then(|color| try_parse_color(color).ok()),
1085            terminal_ansi_dim_cyan: self
1086                .terminal_ansi_dim_cyan
1087                .as_ref()
1088                .and_then(|color| try_parse_color(color).ok()),
1089            terminal_ansi_white: self
1090                .terminal_ansi_white
1091                .as_ref()
1092                .and_then(|color| try_parse_color(color).ok()),
1093            terminal_ansi_bright_white: self
1094                .terminal_ansi_bright_white
1095                .as_ref()
1096                .and_then(|color| try_parse_color(color).ok()),
1097            terminal_ansi_dim_white: self
1098                .terminal_ansi_dim_white
1099                .as_ref()
1100                .and_then(|color| try_parse_color(color).ok()),
1101            link_text_hover: self
1102                .link_text_hover
1103                .as_ref()
1104                .and_then(|color| try_parse_color(color).ok()),
1105            version_control_added: self
1106                .version_control_added
1107                .as_ref()
1108                .and_then(|color| try_parse_color(color).ok())
1109                // Fall back to `created`, for backwards compatibility.
1110                .or(status_colors.created),
1111            version_control_deleted: self
1112                .version_control_deleted
1113                .as_ref()
1114                .and_then(|color| try_parse_color(color).ok())
1115                // Fall back to `deleted`, for backwards compatibility.
1116                .or(status_colors.deleted),
1117            version_control_modified: self
1118                .version_control_modified
1119                .as_ref()
1120                .and_then(|color| try_parse_color(color).ok())
1121                // Fall back to `modified`, for backwards compatibility.
1122                .or(status_colors.modified),
1123            version_control_renamed: self
1124                .version_control_renamed
1125                .as_ref()
1126                .and_then(|color| try_parse_color(color).ok())
1127                // Fall back to `modified`, for backwards compatibility.
1128                .or(status_colors.modified),
1129            version_control_conflict: self
1130                .version_control_conflict
1131                .as_ref()
1132                .and_then(|color| try_parse_color(color).ok())
1133                // Fall back to `ignored`, for backwards compatibility.
1134                .or(status_colors.ignored),
1135            version_control_ignored: self
1136                .version_control_ignored
1137                .as_ref()
1138                .and_then(|color| try_parse_color(color).ok())
1139                // Fall back to `conflict`, for backwards compatibility.
1140                .or(status_colors.ignored),
1141            #[allow(deprecated)]
1142            version_control_conflict_marker_ours: self
1143                .version_control_conflict_marker_ours
1144                .as_ref()
1145                .or(self.version_control_conflict_ours_background.as_ref())
1146                .and_then(|color| try_parse_color(color).ok()),
1147            #[allow(deprecated)]
1148            version_control_conflict_marker_theirs: self
1149                .version_control_conflict_marker_theirs
1150                .as_ref()
1151                .or(self.version_control_conflict_theirs_background.as_ref())
1152                .and_then(|color| try_parse_color(color).ok()),
1153        }
1154    }
1155}
1156
1157#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema, PartialEq)]
1158#[serde(default)]
1159pub struct StatusColorsContent {
1160    /// Indicates some kind of conflict, like a file changed on disk while it was open, or
1161    /// merge conflicts in a Git repository.
1162    #[serde(rename = "conflict")]
1163    pub conflict: Option<String>,
1164
1165    #[serde(rename = "conflict.background")]
1166    pub conflict_background: Option<String>,
1167
1168    #[serde(rename = "conflict.border")]
1169    pub conflict_border: Option<String>,
1170
1171    /// Indicates something new, like a new file added to a Git repository.
1172    #[serde(rename = "created")]
1173    pub created: Option<String>,
1174
1175    #[serde(rename = "created.background")]
1176    pub created_background: Option<String>,
1177
1178    #[serde(rename = "created.border")]
1179    pub created_border: Option<String>,
1180
1181    /// Indicates that something no longer exists, like a deleted file.
1182    #[serde(rename = "deleted")]
1183    pub deleted: Option<String>,
1184
1185    #[serde(rename = "deleted.background")]
1186    pub deleted_background: Option<String>,
1187
1188    #[serde(rename = "deleted.border")]
1189    pub deleted_border: Option<String>,
1190
1191    /// Indicates a system error, a failed operation or a diagnostic error.
1192    #[serde(rename = "error")]
1193    pub error: Option<String>,
1194
1195    #[serde(rename = "error.background")]
1196    pub error_background: Option<String>,
1197
1198    #[serde(rename = "error.border")]
1199    pub error_border: Option<String>,
1200
1201    /// Represents a hidden status, such as a file being hidden in a file tree.
1202    #[serde(rename = "hidden")]
1203    pub hidden: Option<String>,
1204
1205    #[serde(rename = "hidden.background")]
1206    pub hidden_background: Option<String>,
1207
1208    #[serde(rename = "hidden.border")]
1209    pub hidden_border: Option<String>,
1210
1211    /// Indicates a hint or some kind of additional information.
1212    #[serde(rename = "hint")]
1213    pub hint: Option<String>,
1214
1215    #[serde(rename = "hint.background")]
1216    pub hint_background: Option<String>,
1217
1218    #[serde(rename = "hint.border")]
1219    pub hint_border: Option<String>,
1220
1221    /// Indicates that something is deliberately ignored, such as a file or operation ignored by Git.
1222    #[serde(rename = "ignored")]
1223    pub ignored: Option<String>,
1224
1225    #[serde(rename = "ignored.background")]
1226    pub ignored_background: Option<String>,
1227
1228    #[serde(rename = "ignored.border")]
1229    pub ignored_border: Option<String>,
1230
1231    /// Represents informational status updates or messages.
1232    #[serde(rename = "info")]
1233    pub info: Option<String>,
1234
1235    #[serde(rename = "info.background")]
1236    pub info_background: Option<String>,
1237
1238    #[serde(rename = "info.border")]
1239    pub info_border: Option<String>,
1240
1241    /// Indicates a changed or altered status, like a file that has been edited.
1242    #[serde(rename = "modified")]
1243    pub modified: Option<String>,
1244
1245    #[serde(rename = "modified.background")]
1246    pub modified_background: Option<String>,
1247
1248    #[serde(rename = "modified.border")]
1249    pub modified_border: Option<String>,
1250
1251    /// Indicates something that is predicted, like automatic code completion, or generated code.
1252    #[serde(rename = "predictive")]
1253    pub predictive: Option<String>,
1254
1255    #[serde(rename = "predictive.background")]
1256    pub predictive_background: Option<String>,
1257
1258    #[serde(rename = "predictive.border")]
1259    pub predictive_border: Option<String>,
1260
1261    /// Represents a renamed status, such as a file that has been renamed.
1262    #[serde(rename = "renamed")]
1263    pub renamed: Option<String>,
1264
1265    #[serde(rename = "renamed.background")]
1266    pub renamed_background: Option<String>,
1267
1268    #[serde(rename = "renamed.border")]
1269    pub renamed_border: Option<String>,
1270
1271    /// Indicates a successful operation or task completion.
1272    #[serde(rename = "success")]
1273    pub success: Option<String>,
1274
1275    #[serde(rename = "success.background")]
1276    pub success_background: Option<String>,
1277
1278    #[serde(rename = "success.border")]
1279    pub success_border: Option<String>,
1280
1281    /// Indicates some kind of unreachable status, like a block of code that can never be reached.
1282    #[serde(rename = "unreachable")]
1283    pub unreachable: Option<String>,
1284
1285    #[serde(rename = "unreachable.background")]
1286    pub unreachable_background: Option<String>,
1287
1288    #[serde(rename = "unreachable.border")]
1289    pub unreachable_border: Option<String>,
1290
1291    /// Represents a warning status, like an operation that is about to fail.
1292    #[serde(rename = "warning")]
1293    pub warning: Option<String>,
1294
1295    #[serde(rename = "warning.background")]
1296    pub warning_background: Option<String>,
1297
1298    #[serde(rename = "warning.border")]
1299    pub warning_border: Option<String>,
1300}
1301
1302impl StatusColorsContent {
1303    /// Returns a [`StatusColorsRefinement`] based on the colors in the [`StatusColorsContent`].
1304    pub fn status_colors_refinement(&self) -> StatusColorsRefinement {
1305        StatusColorsRefinement {
1306            conflict: self
1307                .conflict
1308                .as_ref()
1309                .and_then(|color| try_parse_color(color).ok()),
1310            conflict_background: self
1311                .conflict_background
1312                .as_ref()
1313                .and_then(|color| try_parse_color(color).ok()),
1314            conflict_border: self
1315                .conflict_border
1316                .as_ref()
1317                .and_then(|color| try_parse_color(color).ok()),
1318            created: self
1319                .created
1320                .as_ref()
1321                .and_then(|color| try_parse_color(color).ok()),
1322            created_background: self
1323                .created_background
1324                .as_ref()
1325                .and_then(|color| try_parse_color(color).ok()),
1326            created_border: self
1327                .created_border
1328                .as_ref()
1329                .and_then(|color| try_parse_color(color).ok()),
1330            deleted: self
1331                .deleted
1332                .as_ref()
1333                .and_then(|color| try_parse_color(color).ok()),
1334            deleted_background: self
1335                .deleted_background
1336                .as_ref()
1337                .and_then(|color| try_parse_color(color).ok()),
1338            deleted_border: self
1339                .deleted_border
1340                .as_ref()
1341                .and_then(|color| try_parse_color(color).ok()),
1342            error: self
1343                .error
1344                .as_ref()
1345                .and_then(|color| try_parse_color(color).ok()),
1346            error_background: self
1347                .error_background
1348                .as_ref()
1349                .and_then(|color| try_parse_color(color).ok()),
1350            error_border: self
1351                .error_border
1352                .as_ref()
1353                .and_then(|color| try_parse_color(color).ok()),
1354            hidden: self
1355                .hidden
1356                .as_ref()
1357                .and_then(|color| try_parse_color(color).ok()),
1358            hidden_background: self
1359                .hidden_background
1360                .as_ref()
1361                .and_then(|color| try_parse_color(color).ok()),
1362            hidden_border: self
1363                .hidden_border
1364                .as_ref()
1365                .and_then(|color| try_parse_color(color).ok()),
1366            hint: self
1367                .hint
1368                .as_ref()
1369                .and_then(|color| try_parse_color(color).ok()),
1370            hint_background: self
1371                .hint_background
1372                .as_ref()
1373                .and_then(|color| try_parse_color(color).ok()),
1374            hint_border: self
1375                .hint_border
1376                .as_ref()
1377                .and_then(|color| try_parse_color(color).ok()),
1378            ignored: self
1379                .ignored
1380                .as_ref()
1381                .and_then(|color| try_parse_color(color).ok()),
1382            ignored_background: self
1383                .ignored_background
1384                .as_ref()
1385                .and_then(|color| try_parse_color(color).ok()),
1386            ignored_border: self
1387                .ignored_border
1388                .as_ref()
1389                .and_then(|color| try_parse_color(color).ok()),
1390            info: self
1391                .info
1392                .as_ref()
1393                .and_then(|color| try_parse_color(color).ok()),
1394            info_background: self
1395                .info_background
1396                .as_ref()
1397                .and_then(|color| try_parse_color(color).ok()),
1398            info_border: self
1399                .info_border
1400                .as_ref()
1401                .and_then(|color| try_parse_color(color).ok()),
1402            modified: self
1403                .modified
1404                .as_ref()
1405                .and_then(|color| try_parse_color(color).ok()),
1406            modified_background: self
1407                .modified_background
1408                .as_ref()
1409                .and_then(|color| try_parse_color(color).ok()),
1410            modified_border: self
1411                .modified_border
1412                .as_ref()
1413                .and_then(|color| try_parse_color(color).ok()),
1414            predictive: self
1415                .predictive
1416                .as_ref()
1417                .and_then(|color| try_parse_color(color).ok()),
1418            predictive_background: self
1419                .predictive_background
1420                .as_ref()
1421                .and_then(|color| try_parse_color(color).ok()),
1422            predictive_border: self
1423                .predictive_border
1424                .as_ref()
1425                .and_then(|color| try_parse_color(color).ok()),
1426            renamed: self
1427                .renamed
1428                .as_ref()
1429                .and_then(|color| try_parse_color(color).ok()),
1430            renamed_background: self
1431                .renamed_background
1432                .as_ref()
1433                .and_then(|color| try_parse_color(color).ok()),
1434            renamed_border: self
1435                .renamed_border
1436                .as_ref()
1437                .and_then(|color| try_parse_color(color).ok()),
1438            success: self
1439                .success
1440                .as_ref()
1441                .and_then(|color| try_parse_color(color).ok()),
1442            success_background: self
1443                .success_background
1444                .as_ref()
1445                .and_then(|color| try_parse_color(color).ok()),
1446            success_border: self
1447                .success_border
1448                .as_ref()
1449                .and_then(|color| try_parse_color(color).ok()),
1450            unreachable: self
1451                .unreachable
1452                .as_ref()
1453                .and_then(|color| try_parse_color(color).ok()),
1454            unreachable_background: self
1455                .unreachable_background
1456                .as_ref()
1457                .and_then(|color| try_parse_color(color).ok()),
1458            unreachable_border: self
1459                .unreachable_border
1460                .as_ref()
1461                .and_then(|color| try_parse_color(color).ok()),
1462            warning: self
1463                .warning
1464                .as_ref()
1465                .and_then(|color| try_parse_color(color).ok()),
1466            warning_background: self
1467                .warning_background
1468                .as_ref()
1469                .and_then(|color| try_parse_color(color).ok()),
1470            warning_border: self
1471                .warning_border
1472                .as_ref()
1473                .and_then(|color| try_parse_color(color).ok()),
1474        }
1475    }
1476}
1477
1478#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
1479pub struct AccentContent(pub Option<String>);
1480
1481#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
1482pub struct PlayerColorContent {
1483    pub cursor: Option<String>,
1484    pub background: Option<String>,
1485    pub selection: Option<String>,
1486}
1487
1488#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq)]
1489#[serde(rename_all = "snake_case")]
1490pub enum FontStyleContent {
1491    Normal,
1492    Italic,
1493    Oblique,
1494}
1495
1496impl From<FontStyleContent> for FontStyle {
1497    fn from(value: FontStyleContent) -> Self {
1498        match value {
1499            FontStyleContent::Normal => FontStyle::Normal,
1500            FontStyleContent::Italic => FontStyle::Italic,
1501            FontStyleContent::Oblique => FontStyle::Oblique,
1502        }
1503    }
1504}
1505
1506#[derive(Debug, Clone, Copy, Serialize_repr, Deserialize_repr, JsonSchema_repr, PartialEq)]
1507#[repr(u16)]
1508pub enum FontWeightContent {
1509    Thin = 100,
1510    ExtraLight = 200,
1511    Light = 300,
1512    Normal = 400,
1513    Medium = 500,
1514    Semibold = 600,
1515    Bold = 700,
1516    ExtraBold = 800,
1517    Black = 900,
1518}
1519
1520impl From<FontWeightContent> for FontWeight {
1521    fn from(value: FontWeightContent) -> Self {
1522        match value {
1523            FontWeightContent::Thin => FontWeight::THIN,
1524            FontWeightContent::ExtraLight => FontWeight::EXTRA_LIGHT,
1525            FontWeightContent::Light => FontWeight::LIGHT,
1526            FontWeightContent::Normal => FontWeight::NORMAL,
1527            FontWeightContent::Medium => FontWeight::MEDIUM,
1528            FontWeightContent::Semibold => FontWeight::SEMIBOLD,
1529            FontWeightContent::Bold => FontWeight::BOLD,
1530            FontWeightContent::ExtraBold => FontWeight::EXTRA_BOLD,
1531            FontWeightContent::Black => FontWeight::BLACK,
1532        }
1533    }
1534}
1535
1536#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema, PartialEq)]
1537#[serde(default)]
1538pub struct HighlightStyleContent {
1539    pub color: Option<String>,
1540
1541    #[serde(deserialize_with = "treat_error_as_none")]
1542    pub background_color: Option<String>,
1543
1544    #[serde(deserialize_with = "treat_error_as_none")]
1545    pub font_style: Option<FontStyleContent>,
1546
1547    #[serde(deserialize_with = "treat_error_as_none")]
1548    pub font_weight: Option<FontWeightContent>,
1549}
1550
1551impl HighlightStyleContent {
1552    pub fn is_empty(&self) -> bool {
1553        self.color.is_none()
1554            && self.background_color.is_none()
1555            && self.font_style.is_none()
1556            && self.font_weight.is_none()
1557    }
1558}
1559
1560fn treat_error_as_none<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
1561where
1562    T: Deserialize<'de>,
1563    D: Deserializer<'de>,
1564{
1565    let value: Value = Deserialize::deserialize(deserializer)?;
1566    Ok(T::deserialize(value).ok())
1567}