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