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