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