schema.rs

   1use anyhow::Result;
   2use gpui::{HighlightStyle, Hsla};
   3use indexmap::IndexMap;
   4use palette::FromColor;
   5use schemars::gen::SchemaGenerator;
   6use schemars::schema::{Schema, SchemaObject};
   7use schemars::JsonSchema;
   8use serde::{Deserialize, Deserializer, Serialize};
   9use serde_json::Value;
  10use serde_repr::{Deserialize_repr, Serialize_repr};
  11
  12use crate::{StatusColorsRefinement, ThemeColorsRefinement};
  13
  14fn try_parse_color(color: &str) -> Result<Hsla> {
  15    let rgba = gpui::Rgba::try_from(color)?;
  16    let rgba = palette::rgb::Srgba::from_components((rgba.r, rgba.g, rgba.b, rgba.a));
  17    let hsla = palette::Hsla::from_color(rgba);
  18
  19    let hsla = gpui::hsla(
  20        hsla.hue.into_positive_degrees() / 360.,
  21        hsla.saturation,
  22        hsla.lightness,
  23        hsla.alpha,
  24    );
  25
  26    Ok(hsla)
  27}
  28
  29/// The content of a serialized theme.
  30#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema)]
  31#[serde(default)]
  32pub struct ThemeContent {
  33    #[serde(flatten, default)]
  34    pub colors: ThemeColorsContent,
  35
  36    #[serde(flatten, default)]
  37    pub status: StatusColorsContent,
  38
  39    /// The styles for syntax nodes.
  40    #[serde(default)]
  41    pub syntax: IndexMap<String, HighlightStyleContent>,
  42}
  43
  44impl ThemeContent {
  45    /// Returns a [`ThemeColorsRefinement`] based on the colors in the [`ThemeContent`].
  46    #[inline(always)]
  47    pub fn theme_colors_refinement(&self) -> ThemeColorsRefinement {
  48        self.colors.theme_colors_refinement()
  49    }
  50
  51    /// Returns a [`StatusColorsRefinement`] based on the colors in the [`ThemeContent`].
  52    #[inline(always)]
  53    pub fn status_colors_refinement(&self) -> StatusColorsRefinement {
  54        self.status.status_colors_refinement()
  55    }
  56
  57    /// Returns the syntax style overrides in the [`ThemeContent`].
  58    pub fn syntax_overrides(&self) -> Vec<(String, HighlightStyle)> {
  59        self.syntax
  60            .iter()
  61            .map(|(key, style)| {
  62                (
  63                    key.clone(),
  64                    HighlightStyle {
  65                        color: style
  66                            .color
  67                            .as_ref()
  68                            .and_then(|color| try_parse_color(&color).ok()),
  69                        ..Default::default()
  70                    },
  71                )
  72            })
  73            .collect()
  74    }
  75}
  76
  77#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema)]
  78#[serde(default)]
  79pub struct ThemeColorsContent {
  80    /// Border color. Used for most borders, is usually a high contrast color.
  81    #[serde(rename = "border")]
  82    pub border: Option<String>,
  83
  84    /// Border color. Used for deemphasized borders, like a visual divider between two sections
  85    #[serde(rename = "border.variant")]
  86    pub border_variant: Option<String>,
  87
  88    /// Border color. Used for focused elements, like keyboard focused list item.
  89    #[serde(rename = "border.focused")]
  90    pub border_focused: Option<String>,
  91
  92    /// Border color. Used for selected elements, like an active search filter or selected checkbox.
  93    #[serde(rename = "border.selected")]
  94    pub border_selected: Option<String>,
  95
  96    /// Border color. Used for transparent borders. Used for placeholder borders when an element gains a border on state change.
  97    #[serde(rename = "border.transparent")]
  98    pub border_transparent: Option<String>,
  99
 100    /// Border color. Used for disabled elements, like a disabled input or button.
 101    #[serde(rename = "border.disabled")]
 102    pub border_disabled: Option<String>,
 103
 104    /// Border color. Used for elevated surfaces, like a context menu, popup, or dialog.
 105    #[serde(rename = "elevated_surface.background")]
 106    pub elevated_surface_background: Option<String>,
 107
 108    /// Background Color. Used for grounded surfaces like a panel or tab.
 109    #[serde(rename = "surface.background")]
 110    pub surface_background: Option<String>,
 111
 112    /// Background Color. Used for the app background and blank panels or windows.
 113    #[serde(rename = "background")]
 114    pub background: Option<String>,
 115
 116    /// Background Color. Used for the background of an element that should have a different background than the surface it's on.
 117    ///
 118    /// Elements might include: Buttons, Inputs, Checkboxes, Radio Buttons...
 119    ///
 120    /// For an element that should have the same background as the surface it's on, use `ghost_element_background`.
 121    #[serde(rename = "element.background")]
 122    pub element_background: Option<String>,
 123
 124    /// Background Color. Used for the hover state of an element that should have a different background than the surface it's on.
 125    ///
 126    /// Hover states are triggered by the mouse entering an element, or a finger touching an element on a touch screen.
 127    #[serde(rename = "element.hover")]
 128    pub element_hover: Option<String>,
 129
 130    /// Background Color. Used for the active state of an element that should have a different background than the surface it's on.
 131    ///
 132    /// Active states are triggered by the mouse button being pressed down on an element, or the Return button or other activator being pressd.
 133    #[serde(rename = "element.active")]
 134    pub element_active: Option<String>,
 135
 136    /// Background Color. Used for the selected state of an element that should have a different background than the surface it's on.
 137    ///
 138    /// Selected states are triggered by the element being selected (or "activated") by the user.
 139    ///
 140    /// This could include a selected checkbox, a toggleable button that is toggled on, etc.
 141    #[serde(rename = "element.selected")]
 142    pub element_selected: Option<String>,
 143
 144    /// Background Color. Used for the disabled state of an element that should have a different background than the surface it's on.
 145    ///
 146    /// Disabled states are shown when a user cannot interact with an element, like a disabled button or input.
 147    #[serde(rename = "element.disabled")]
 148    pub element_disabled: Option<String>,
 149
 150    /// Background Color. Used for the area that shows where a dragged element will be dropped.
 151    #[serde(rename = "drop_target.background")]
 152    pub drop_target_background: Option<String>,
 153
 154    /// Used for the background of a ghost element that should have the same background as the surface it's on.
 155    ///
 156    /// Elements might include: Buttons, Inputs, Checkboxes, Radio Buttons...
 157    ///
 158    /// For an element that should have a different background than the surface it's on, use `element_background`.
 159    #[serde(rename = "ghost_element.background")]
 160    pub ghost_element_background: Option<String>,
 161
 162    /// Background Color. Used for the hover state of a ghost element that should have the same background as the surface it's on.
 163    ///
 164    /// Hover states are triggered by the mouse entering an element, or a finger touching an element on a touch screen.
 165    #[serde(rename = "ghost_element.hover")]
 166    pub ghost_element_hover: Option<String>,
 167
 168    /// Background Color. Used for the active state of a ghost element that should have the same background as the surface it's on.
 169    ///
 170    /// Active states are triggered by the mouse button being pressed down on an element, or the Return button or other activator being pressd.
 171    #[serde(rename = "ghost_element.active")]
 172    pub ghost_element_active: Option<String>,
 173
 174    /// Background Color. Used for the selected state of a ghost element that should have the same background as the surface it's on.
 175    ///
 176    /// Selected states are triggered by the element being selected (or "activated") by the user.
 177    ///
 178    /// This could include a selected checkbox, a toggleable button that is toggled on, etc.
 179    #[serde(rename = "ghost_element.selected")]
 180    pub ghost_element_selected: Option<String>,
 181
 182    /// Background Color. Used for the disabled state of a ghost element that should have the same background as the surface it's on.
 183    ///
 184    /// Disabled states are shown when a user cannot interact with an element, like a disabled button or input.
 185    #[serde(rename = "ghost_element.disabled")]
 186    pub ghost_element_disabled: Option<String>,
 187
 188    /// Text Color. Default text color used for most text.
 189    #[serde(rename = "text")]
 190    pub text: Option<String>,
 191
 192    /// Text Color. Color of muted or deemphasized text. It is a subdued version of the standard text color.
 193    #[serde(rename = "text.muted")]
 194    pub text_muted: Option<String>,
 195
 196    /// Text Color. Color of the placeholder text typically shown in input fields to guide the user to enter valid data.
 197    #[serde(rename = "text.placeholder")]
 198    pub text_placeholder: Option<String>,
 199
 200    /// Text Color. Color used for text denoting disabled elements. Typically, the color is faded or grayed out to emphasize the disabled state.
 201    #[serde(rename = "text.disabled")]
 202    pub text_disabled: Option<String>,
 203
 204    /// Text Color. Color used for emphasis or highlighting certain text, like an active filter or a matched character in a search.
 205    #[serde(rename = "text.accent")]
 206    pub text_accent: Option<String>,
 207
 208    /// Fill Color. Used for the default fill color of an icon.
 209    #[serde(rename = "icon")]
 210    pub icon: Option<String>,
 211
 212    /// Fill Color. Used for the muted or deemphasized fill color of an icon.
 213    ///
 214    /// This might be used to show an icon in an inactive pane, or to demphasize a series of icons to give them less visual weight.
 215    #[serde(rename = "icon.muted")]
 216    pub icon_muted: Option<String>,
 217
 218    /// Fill Color. Used for the disabled fill color of an icon.
 219    ///
 220    /// Disabled states are shown when a user cannot interact with an element, like a icon button.
 221    #[serde(rename = "icon.disabled")]
 222    pub icon_disabled: Option<String>,
 223
 224    /// Fill Color. Used for the placeholder fill color of an icon.
 225    ///
 226    /// This might be used to show an icon in an input that disappears when the user enters text.
 227    #[serde(rename = "icon.placeholder")]
 228    pub icon_placeholder: Option<String>,
 229
 230    /// Fill Color. Used for the accent fill color of an icon.
 231    ///
 232    /// This might be used to show when a toggleable icon button is selected.
 233    #[serde(rename = "con.accent")]
 234    pub icon_accent: Option<String>,
 235
 236    #[serde(rename = "status_bar.background")]
 237    pub status_bar_background: Option<String>,
 238
 239    #[serde(rename = "title_bar.background")]
 240    pub title_bar_background: Option<String>,
 241
 242    #[serde(rename = "toolbar.background")]
 243    pub toolbar_background: Option<String>,
 244
 245    #[serde(rename = "tab_bar.background")]
 246    pub tab_bar_background: Option<String>,
 247
 248    #[serde(rename = "tab.inactive_background")]
 249    pub tab_inactive_background: Option<String>,
 250
 251    #[serde(rename = "tab.active_background")]
 252    pub tab_active_background: Option<String>,
 253
 254    #[serde(rename = "search.match_background")]
 255    pub search_match_background: Option<String>,
 256
 257    #[serde(rename = "panel.background")]
 258    pub panel_background: Option<String>,
 259
 260    #[serde(rename = "panel.focused_border")]
 261    pub panel_focused_border: Option<String>,
 262
 263    #[serde(rename = "pane.focused_border")]
 264    pub pane_focused_border: Option<String>,
 265
 266    /// The color of the scrollbar thumb.
 267    #[serde(rename = "scrollbar_thumb.background")]
 268    pub scrollbar_thumb_background: Option<String>,
 269
 270    /// The color of the scrollbar thumb when hovered over.
 271    #[serde(rename = "scrollbar.thumb.hover_background")]
 272    pub scrollbar_thumb_hover_background: Option<String>,
 273
 274    /// The border color of the scrollbar thumb.
 275    #[serde(rename = "scrollbar.thumb.border")]
 276    pub scrollbar_thumb_border: Option<String>,
 277
 278    /// The background color of the scrollbar track.
 279    #[serde(rename = "scrollbar.track.background")]
 280    pub scrollbar_track_background: Option<String>,
 281
 282    /// The border color of the scrollbar track.
 283    #[serde(rename = "scrollbar.track.border")]
 284    pub scrollbar_track_border: Option<String>,
 285
 286    #[serde(rename = "editor.foreground")]
 287    pub editor_foreground: Option<String>,
 288
 289    #[serde(rename = "editor.background")]
 290    pub editor_background: Option<String>,
 291
 292    #[serde(rename = "editor.gutter.background")]
 293    pub editor_gutter_background: Option<String>,
 294
 295    #[serde(rename = "editor.subheader.background")]
 296    pub editor_subheader_background: Option<String>,
 297
 298    #[serde(rename = "editor.active_line.background")]
 299    pub editor_active_line_background: Option<String>,
 300
 301    #[serde(rename = "editor.highlighted_line.background")]
 302    pub editor_highlighted_line_background: Option<String>,
 303
 304    /// Text Color. Used for the text of the line number in the editor gutter.
 305    #[serde(rename = "editor.line_number")]
 306    pub editor_line_number: Option<String>,
 307
 308    /// Text Color. Used for the text of the line number in the editor gutter when the line is highlighted.
 309    #[serde(rename = "editor.active_line_number")]
 310    pub editor_active_line_number: Option<String>,
 311
 312    /// Text Color. Used to mark invisible characters in the editor.
 313    ///
 314    /// Example: spaces, tabs, carriage returns, etc.
 315    #[serde(rename = "editor.invisible")]
 316    pub editor_invisible: Option<String>,
 317
 318    #[serde(rename = "editor.wrap_guide")]
 319    pub editor_wrap_guide: Option<String>,
 320
 321    #[serde(rename = "editor.active_wrap_guide")]
 322    pub editor_active_wrap_guide: Option<String>,
 323
 324    /// Read-access of a symbol, like reading a variable.
 325    ///
 326    /// A document highlight is a range inside a text document which deserves
 327    /// special attention. Usually a document highlight is visualized by changing
 328    /// the background color of its range.
 329    #[serde(rename = "editor.document_highlight.read_background")]
 330    pub editor_document_highlight_read_background: Option<String>,
 331
 332    /// Read-access of a symbol, like reading a variable.
 333    ///
 334    /// A document highlight is a range inside a text document which deserves
 335    /// special attention. Usually a document highlight is visualized by changing
 336    /// the background color of its range.
 337    #[serde(rename = "editor.document_highlight.write_background")]
 338    pub editor_document_highlight_write_background: Option<String>,
 339
 340    /// Terminal background color.
 341    #[serde(rename = "terminal.background")]
 342    pub terminal_background: Option<String>,
 343
 344    /// Terminal foreground color.
 345    #[serde(rename = "terminal.foreground")]
 346    pub terminal_foreground: Option<String>,
 347
 348    /// Bright terminal foreground color.
 349    #[serde(rename = "terminal.bright_foreground")]
 350    pub terminal_bright_foreground: Option<String>,
 351
 352    /// Dim terminal foreground color.
 353    #[serde(rename = "terminal.dim_foreground")]
 354    pub terminal_dim_foreground: Option<String>,
 355
 356    /// Black ANSI terminal color.
 357    #[serde(rename = "terminal.ansi.black")]
 358    pub terminal_ansi_black: Option<String>,
 359
 360    /// Bright black ANSI terminal color.
 361    #[serde(rename = "terminal.ansi.bright_black")]
 362    pub terminal_ansi_bright_black: Option<String>,
 363
 364    /// Dim black ANSI terminal color.
 365    #[serde(rename = "terminal.ansi.dim_black")]
 366    pub terminal_ansi_dim_black: Option<String>,
 367
 368    /// Red ANSI terminal color.
 369    #[serde(rename = "terminal.ansi.red")]
 370    pub terminal_ansi_red: Option<String>,
 371
 372    /// Bright red ANSI terminal color.
 373    #[serde(rename = "terminal.ansi.bright_red")]
 374    pub terminal_ansi_bright_red: Option<String>,
 375
 376    /// Dim red ANSI terminal color.
 377    #[serde(rename = "terminal.ansi.dim_red")]
 378    pub terminal_ansi_dim_red: Option<String>,
 379
 380    /// Green ANSI terminal color.
 381    #[serde(rename = "terminal.ansi.green")]
 382    pub terminal_ansi_green: Option<String>,
 383
 384    /// Bright green ANSI terminal color.
 385    #[serde(rename = "terminal.ansi.bright_green")]
 386    pub terminal_ansi_bright_green: Option<String>,
 387
 388    /// Dim green ANSI terminal color.
 389    #[serde(rename = "terminal.ansi.dim_green")]
 390    pub terminal_ansi_dim_green: Option<String>,
 391
 392    /// Yellow ANSI terminal color.
 393    #[serde(rename = "terminal.ansi.yellow")]
 394    pub terminal_ansi_yellow: Option<String>,
 395
 396    /// Bright yellow ANSI terminal color.
 397    #[serde(rename = "terminal.ansi.bright_yellow")]
 398    pub terminal_ansi_bright_yellow: Option<String>,
 399
 400    /// Dim yellow ANSI terminal color.
 401    #[serde(rename = "terminal.ansi.dim_yellow")]
 402    pub terminal_ansi_dim_yellow: Option<String>,
 403
 404    /// Blue ANSI terminal color.
 405    #[serde(rename = "terminal.ansi.blue")]
 406    pub terminal_ansi_blue: Option<String>,
 407
 408    /// Bright blue ANSI terminal color.
 409    #[serde(rename = "terminal.ansi.bright_blue")]
 410    pub terminal_ansi_bright_blue: Option<String>,
 411
 412    /// Dim blue ANSI terminal color.
 413    #[serde(rename = "terminal.ansi.dim_blue")]
 414    pub terminal_ansi_dim_blue: Option<String>,
 415
 416    /// Magenta ANSI terminal color.
 417    #[serde(rename = "terminal.ansi.magenta")]
 418    pub terminal_ansi_magenta: Option<String>,
 419
 420    /// Bright magenta ANSI terminal color.
 421    #[serde(rename = "terminal.ansi.bright_magenta")]
 422    pub terminal_ansi_bright_magenta: Option<String>,
 423
 424    /// Dim magenta ANSI terminal color.
 425    #[serde(rename = "terminal.ansi.dim_magenta")]
 426    pub terminal_ansi_dim_magenta: Option<String>,
 427
 428    /// Cyan ANSI terminal color.
 429    #[serde(rename = "terminal.ansi.cyan")]
 430    pub terminal_ansi_cyan: Option<String>,
 431
 432    /// Bright cyan ANSI terminal color.
 433    #[serde(rename = "terminal.ansi.bright_cyan")]
 434    pub terminal_ansi_bright_cyan: Option<String>,
 435
 436    /// Dim cyan ANSI terminal color.
 437    #[serde(rename = "terminal.ansi.dim_cyan")]
 438    pub terminal_ansi_dim_cyan: Option<String>,
 439
 440    /// White ANSI terminal color.
 441    #[serde(rename = "terminal.ansi.white")]
 442    pub terminal_ansi_white: Option<String>,
 443
 444    /// Bright white ANSI terminal color.
 445    #[serde(rename = "terminal.ansi.bright_white")]
 446    pub terminal_ansi_bright_white: Option<String>,
 447
 448    /// Dim white ANSI terminal color.
 449    #[serde(rename = "terminal.ansi.dim_white")]
 450    pub terminal_ansi_dim_white: Option<String>,
 451
 452    #[serde(rename = "link_text.hover")]
 453    pub link_text_hover: Option<String>,
 454}
 455
 456impl ThemeColorsContent {
 457    /// Returns a [`ThemeColorsRefinement`] based on the colors in the [`ThemeColorsContent`].
 458    pub fn theme_colors_refinement(&self) -> ThemeColorsRefinement {
 459        ThemeColorsRefinement {
 460            border: self
 461                .border
 462                .as_ref()
 463                .and_then(|color| try_parse_color(&color).ok()),
 464            border_variant: self
 465                .border_variant
 466                .as_ref()
 467                .and_then(|color| try_parse_color(&color).ok()),
 468            border_focused: self
 469                .border_focused
 470                .as_ref()
 471                .and_then(|color| try_parse_color(&color).ok()),
 472            border_selected: self
 473                .border_selected
 474                .as_ref()
 475                .and_then(|color| try_parse_color(&color).ok()),
 476            border_transparent: self
 477                .border_transparent
 478                .as_ref()
 479                .and_then(|color| try_parse_color(&color).ok()),
 480            border_disabled: self
 481                .border_disabled
 482                .as_ref()
 483                .and_then(|color| try_parse_color(&color).ok()),
 484            elevated_surface_background: self
 485                .elevated_surface_background
 486                .as_ref()
 487                .and_then(|color| try_parse_color(&color).ok()),
 488            surface_background: self
 489                .surface_background
 490                .as_ref()
 491                .and_then(|color| try_parse_color(&color).ok()),
 492            background: self
 493                .background
 494                .as_ref()
 495                .and_then(|color| try_parse_color(&color).ok()),
 496            element_background: self
 497                .element_background
 498                .as_ref()
 499                .and_then(|color| try_parse_color(&color).ok()),
 500            element_hover: self
 501                .element_hover
 502                .as_ref()
 503                .and_then(|color| try_parse_color(&color).ok()),
 504            element_active: self
 505                .element_active
 506                .as_ref()
 507                .and_then(|color| try_parse_color(&color).ok()),
 508            element_selected: self
 509                .element_selected
 510                .as_ref()
 511                .and_then(|color| try_parse_color(&color).ok()),
 512            element_disabled: self
 513                .element_disabled
 514                .as_ref()
 515                .and_then(|color| try_parse_color(&color).ok()),
 516            drop_target_background: self
 517                .drop_target_background
 518                .as_ref()
 519                .and_then(|color| try_parse_color(&color).ok()),
 520            ghost_element_background: self
 521                .ghost_element_background
 522                .as_ref()
 523                .and_then(|color| try_parse_color(&color).ok()),
 524            ghost_element_hover: self
 525                .ghost_element_hover
 526                .as_ref()
 527                .and_then(|color| try_parse_color(&color).ok()),
 528            ghost_element_active: self
 529                .ghost_element_active
 530                .as_ref()
 531                .and_then(|color| try_parse_color(&color).ok()),
 532            ghost_element_selected: self
 533                .ghost_element_selected
 534                .as_ref()
 535                .and_then(|color| try_parse_color(&color).ok()),
 536            ghost_element_disabled: self
 537                .ghost_element_disabled
 538                .as_ref()
 539                .and_then(|color| try_parse_color(&color).ok()),
 540            text: self
 541                .text
 542                .as_ref()
 543                .and_then(|color| try_parse_color(&color).ok()),
 544            text_muted: self
 545                .text_muted
 546                .as_ref()
 547                .and_then(|color| try_parse_color(&color).ok()),
 548            text_placeholder: self
 549                .text_placeholder
 550                .as_ref()
 551                .and_then(|color| try_parse_color(&color).ok()),
 552            text_disabled: self
 553                .text_disabled
 554                .as_ref()
 555                .and_then(|color| try_parse_color(&color).ok()),
 556            text_accent: self
 557                .text_accent
 558                .as_ref()
 559                .and_then(|color| try_parse_color(&color).ok()),
 560            icon: self
 561                .icon
 562                .as_ref()
 563                .and_then(|color| try_parse_color(&color).ok()),
 564            icon_muted: self
 565                .icon_muted
 566                .as_ref()
 567                .and_then(|color| try_parse_color(&color).ok()),
 568            icon_disabled: self
 569                .icon_disabled
 570                .as_ref()
 571                .and_then(|color| try_parse_color(&color).ok()),
 572            icon_placeholder: self
 573                .icon_placeholder
 574                .as_ref()
 575                .and_then(|color| try_parse_color(&color).ok()),
 576            icon_accent: self
 577                .icon_accent
 578                .as_ref()
 579                .and_then(|color| try_parse_color(&color).ok()),
 580            status_bar_background: self
 581                .status_bar_background
 582                .as_ref()
 583                .and_then(|color| try_parse_color(&color).ok()),
 584            title_bar_background: self
 585                .title_bar_background
 586                .as_ref()
 587                .and_then(|color| try_parse_color(&color).ok()),
 588            toolbar_background: self
 589                .toolbar_background
 590                .as_ref()
 591                .and_then(|color| try_parse_color(&color).ok()),
 592            tab_bar_background: self
 593                .tab_bar_background
 594                .as_ref()
 595                .and_then(|color| try_parse_color(&color).ok()),
 596            tab_inactive_background: self
 597                .tab_inactive_background
 598                .as_ref()
 599                .and_then(|color| try_parse_color(&color).ok()),
 600            tab_active_background: self
 601                .tab_active_background
 602                .as_ref()
 603                .and_then(|color| try_parse_color(&color).ok()),
 604            search_match_background: self
 605                .search_match_background
 606                .as_ref()
 607                .and_then(|color| try_parse_color(&color).ok()),
 608            panel_background: self
 609                .panel_background
 610                .as_ref()
 611                .and_then(|color| try_parse_color(&color).ok()),
 612            panel_focused_border: self
 613                .panel_focused_border
 614                .as_ref()
 615                .and_then(|color| try_parse_color(&color).ok()),
 616            pane_focused_border: self
 617                .pane_focused_border
 618                .as_ref()
 619                .and_then(|color| try_parse_color(&color).ok()),
 620            scrollbar_thumb_background: self
 621                .scrollbar_thumb_background
 622                .as_ref()
 623                .and_then(|color| try_parse_color(&color).ok()),
 624            scrollbar_thumb_hover_background: self
 625                .scrollbar_thumb_hover_background
 626                .as_ref()
 627                .and_then(|color| try_parse_color(&color).ok()),
 628            scrollbar_thumb_border: self
 629                .scrollbar_thumb_border
 630                .as_ref()
 631                .and_then(|color| try_parse_color(&color).ok()),
 632            scrollbar_track_background: self
 633                .scrollbar_track_background
 634                .as_ref()
 635                .and_then(|color| try_parse_color(&color).ok()),
 636            scrollbar_track_border: self
 637                .scrollbar_track_border
 638                .as_ref()
 639                .and_then(|color| try_parse_color(&color).ok()),
 640            editor_foreground: self
 641                .editor_foreground
 642                .as_ref()
 643                .and_then(|color| try_parse_color(&color).ok()),
 644            editor_background: self
 645                .editor_background
 646                .as_ref()
 647                .and_then(|color| try_parse_color(&color).ok()),
 648            editor_gutter_background: self
 649                .editor_gutter_background
 650                .as_ref()
 651                .and_then(|color| try_parse_color(&color).ok()),
 652            editor_subheader_background: self
 653                .editor_subheader_background
 654                .as_ref()
 655                .and_then(|color| try_parse_color(&color).ok()),
 656            editor_active_line_background: self
 657                .editor_active_line_background
 658                .as_ref()
 659                .and_then(|color| try_parse_color(&color).ok()),
 660            editor_highlighted_line_background: self
 661                .editor_highlighted_line_background
 662                .as_ref()
 663                .and_then(|color| try_parse_color(&color).ok()),
 664            editor_line_number: self
 665                .editor_line_number
 666                .as_ref()
 667                .and_then(|color| try_parse_color(&color).ok()),
 668            editor_active_line_number: self
 669                .editor_active_line_number
 670                .as_ref()
 671                .and_then(|color| try_parse_color(&color).ok()),
 672            editor_invisible: self
 673                .editor_invisible
 674                .as_ref()
 675                .and_then(|color| try_parse_color(&color).ok()),
 676            editor_wrap_guide: self
 677                .editor_wrap_guide
 678                .as_ref()
 679                .and_then(|color| try_parse_color(&color).ok()),
 680            editor_active_wrap_guide: self
 681                .editor_active_wrap_guide
 682                .as_ref()
 683                .and_then(|color| try_parse_color(&color).ok()),
 684            editor_document_highlight_read_background: self
 685                .editor_document_highlight_read_background
 686                .as_ref()
 687                .and_then(|color| try_parse_color(&color).ok()),
 688            editor_document_highlight_write_background: self
 689                .editor_document_highlight_write_background
 690                .as_ref()
 691                .and_then(|color| try_parse_color(&color).ok()),
 692            terminal_background: self
 693                .terminal_background
 694                .as_ref()
 695                .and_then(|color| try_parse_color(&color).ok()),
 696            terminal_foreground: self
 697                .terminal_foreground
 698                .as_ref()
 699                .and_then(|color| try_parse_color(&color).ok()),
 700            terminal_bright_foreground: self
 701                .terminal_bright_foreground
 702                .as_ref()
 703                .and_then(|color| try_parse_color(&color).ok()),
 704            terminal_dim_foreground: self
 705                .terminal_dim_foreground
 706                .as_ref()
 707                .and_then(|color| try_parse_color(&color).ok()),
 708            terminal_ansi_black: self
 709                .terminal_ansi_black
 710                .as_ref()
 711                .and_then(|color| try_parse_color(&color).ok()),
 712            terminal_ansi_bright_black: self
 713                .terminal_ansi_bright_black
 714                .as_ref()
 715                .and_then(|color| try_parse_color(&color).ok()),
 716            terminal_ansi_dim_black: self
 717                .terminal_ansi_dim_black
 718                .as_ref()
 719                .and_then(|color| try_parse_color(&color).ok()),
 720            terminal_ansi_red: self
 721                .terminal_ansi_red
 722                .as_ref()
 723                .and_then(|color| try_parse_color(&color).ok()),
 724            terminal_ansi_bright_red: self
 725                .terminal_ansi_bright_red
 726                .as_ref()
 727                .and_then(|color| try_parse_color(&color).ok()),
 728            terminal_ansi_dim_red: self
 729                .terminal_ansi_dim_red
 730                .as_ref()
 731                .and_then(|color| try_parse_color(&color).ok()),
 732            terminal_ansi_green: self
 733                .terminal_ansi_green
 734                .as_ref()
 735                .and_then(|color| try_parse_color(&color).ok()),
 736            terminal_ansi_bright_green: self
 737                .terminal_ansi_bright_green
 738                .as_ref()
 739                .and_then(|color| try_parse_color(&color).ok()),
 740            terminal_ansi_dim_green: self
 741                .terminal_ansi_dim_green
 742                .as_ref()
 743                .and_then(|color| try_parse_color(&color).ok()),
 744            terminal_ansi_yellow: self
 745                .terminal_ansi_yellow
 746                .as_ref()
 747                .and_then(|color| try_parse_color(&color).ok()),
 748            terminal_ansi_bright_yellow: self
 749                .terminal_ansi_bright_yellow
 750                .as_ref()
 751                .and_then(|color| try_parse_color(&color).ok()),
 752            terminal_ansi_dim_yellow: self
 753                .terminal_ansi_dim_yellow
 754                .as_ref()
 755                .and_then(|color| try_parse_color(&color).ok()),
 756            terminal_ansi_blue: self
 757                .terminal_ansi_blue
 758                .as_ref()
 759                .and_then(|color| try_parse_color(&color).ok()),
 760            terminal_ansi_bright_blue: self
 761                .terminal_ansi_bright_blue
 762                .as_ref()
 763                .and_then(|color| try_parse_color(&color).ok()),
 764            terminal_ansi_dim_blue: self
 765                .terminal_ansi_dim_blue
 766                .as_ref()
 767                .and_then(|color| try_parse_color(&color).ok()),
 768            terminal_ansi_magenta: self
 769                .terminal_ansi_magenta
 770                .as_ref()
 771                .and_then(|color| try_parse_color(&color).ok()),
 772            terminal_ansi_bright_magenta: self
 773                .terminal_ansi_bright_magenta
 774                .as_ref()
 775                .and_then(|color| try_parse_color(&color).ok()),
 776            terminal_ansi_dim_magenta: self
 777                .terminal_ansi_dim_magenta
 778                .as_ref()
 779                .and_then(|color| try_parse_color(&color).ok()),
 780            terminal_ansi_cyan: self
 781                .terminal_ansi_cyan
 782                .as_ref()
 783                .and_then(|color| try_parse_color(&color).ok()),
 784            terminal_ansi_bright_cyan: self
 785                .terminal_ansi_bright_cyan
 786                .as_ref()
 787                .and_then(|color| try_parse_color(&color).ok()),
 788            terminal_ansi_dim_cyan: self
 789                .terminal_ansi_dim_cyan
 790                .as_ref()
 791                .and_then(|color| try_parse_color(&color).ok()),
 792            terminal_ansi_white: self
 793                .terminal_ansi_white
 794                .as_ref()
 795                .and_then(|color| try_parse_color(&color).ok()),
 796            terminal_ansi_bright_white: self
 797                .terminal_ansi_bright_white
 798                .as_ref()
 799                .and_then(|color| try_parse_color(&color).ok()),
 800            terminal_ansi_dim_white: self
 801                .terminal_ansi_dim_white
 802                .as_ref()
 803                .and_then(|color| try_parse_color(&color).ok()),
 804            link_text_hover: self
 805                .link_text_hover
 806                .as_ref()
 807                .and_then(|color| try_parse_color(&color).ok()),
 808        }
 809    }
 810}
 811
 812#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema)]
 813#[serde(default)]
 814pub struct StatusColorsContent {
 815    /// Indicates some kind of conflict, like a file changed on disk while it was open, or
 816    /// merge conflicts in a Git repository.
 817    #[serde(rename = "conflict")]
 818    pub conflict: Option<String>,
 819
 820    #[serde(rename = "conflict.background")]
 821    pub conflict_background: Option<String>,
 822
 823    #[serde(rename = "conflict.border")]
 824    pub conflict_border: Option<String>,
 825
 826    /// Indicates something new, like a new file added to a Git repository.
 827    #[serde(rename = "created")]
 828    pub created: Option<String>,
 829
 830    #[serde(rename = "created.background")]
 831    pub created_background: Option<String>,
 832
 833    #[serde(rename = "created.border")]
 834    pub created_border: Option<String>,
 835
 836    /// Indicates that something no longer exists, like a deleted file.
 837    #[serde(rename = "deleted")]
 838    pub deleted: Option<String>,
 839
 840    #[serde(rename = "deleted.background")]
 841    pub deleted_background: Option<String>,
 842
 843    #[serde(rename = "deleted.border")]
 844    pub deleted_border: Option<String>,
 845
 846    /// Indicates a system error, a failed operation or a diagnostic error.
 847    #[serde(rename = "error")]
 848    pub error: Option<String>,
 849
 850    #[serde(rename = "error.background")]
 851    pub error_background: Option<String>,
 852
 853    #[serde(rename = "error.border")]
 854    pub error_border: Option<String>,
 855
 856    /// Represents a hidden status, such as a file being hidden in a file tree.
 857    #[serde(rename = "hidden")]
 858    pub hidden: Option<String>,
 859
 860    #[serde(rename = "hidden.background")]
 861    pub hidden_background: Option<String>,
 862
 863    #[serde(rename = "hidden.border")]
 864    pub hidden_border: Option<String>,
 865
 866    /// Indicates a hint or some kind of additional information.
 867    #[serde(rename = "hint")]
 868    pub hint: Option<String>,
 869
 870    #[serde(rename = "hint.background")]
 871    pub hint_background: Option<String>,
 872
 873    #[serde(rename = "hint.border")]
 874    pub hint_border: Option<String>,
 875
 876    /// Indicates that something is deliberately ignored, such as a file or operation ignored by Git.
 877    #[serde(rename = "ignored")]
 878    pub ignored: Option<String>,
 879
 880    #[serde(rename = "ignored.background")]
 881    pub ignored_background: Option<String>,
 882
 883    #[serde(rename = "ignored.border")]
 884    pub ignored_border: Option<String>,
 885
 886    /// Represents informational status updates or messages.
 887    #[serde(rename = "info")]
 888    pub info: Option<String>,
 889
 890    #[serde(rename = "info.background")]
 891    pub info_background: Option<String>,
 892
 893    #[serde(rename = "info.border")]
 894    pub info_border: Option<String>,
 895
 896    /// Indicates a changed or altered status, like a file that has been edited.
 897    #[serde(rename = "modified")]
 898    pub modified: Option<String>,
 899
 900    #[serde(rename = "modified.background")]
 901    pub modified_background: Option<String>,
 902
 903    #[serde(rename = "modified.border")]
 904    pub modified_border: Option<String>,
 905
 906    /// Indicates something that is predicted, like automatic code completion, or generated code.
 907    #[serde(rename = "predictive")]
 908    pub predictive: Option<String>,
 909
 910    #[serde(rename = "predictive.background")]
 911    pub predictive_background: Option<String>,
 912
 913    #[serde(rename = "predictive.border")]
 914    pub predictive_border: Option<String>,
 915
 916    /// Represents a renamed status, such as a file that has been renamed.
 917    #[serde(rename = "renamed")]
 918    pub renamed: Option<String>,
 919
 920    #[serde(rename = "renamed.background")]
 921    pub renamed_background: Option<String>,
 922
 923    #[serde(rename = "renamed.border")]
 924    pub renamed_border: Option<String>,
 925
 926    /// Indicates a successful operation or task completion.
 927    #[serde(rename = "success")]
 928    pub success: Option<String>,
 929
 930    #[serde(rename = "success.background")]
 931    pub success_background: Option<String>,
 932
 933    #[serde(rename = "success.border")]
 934    pub success_border: Option<String>,
 935
 936    /// Indicates some kind of unreachable status, like a block of code that can never be reached.
 937    #[serde(rename = "unreachable")]
 938    pub unreachable: Option<String>,
 939
 940    #[serde(rename = "unreachable.background")]
 941    pub unreachable_background: Option<String>,
 942
 943    #[serde(rename = "unreachable.border")]
 944    pub unreachable_border: Option<String>,
 945
 946    /// Represents a warning status, like an operation that is about to fail.
 947    #[serde(rename = "warning")]
 948    pub warning: Option<String>,
 949
 950    #[serde(rename = "warning.background")]
 951    pub warning_background: Option<String>,
 952
 953    #[serde(rename = "warning.border")]
 954    pub warning_border: Option<String>,
 955}
 956
 957impl StatusColorsContent {
 958    /// Returns a [`StatusColorsRefinement`] based on the colors in the [`StatusColorsContent`].
 959    pub fn status_colors_refinement(&self) -> StatusColorsRefinement {
 960        StatusColorsRefinement {
 961            conflict: self
 962                .conflict
 963                .as_ref()
 964                .and_then(|color| try_parse_color(&color).ok()),
 965            conflict_background: self
 966                .conflict_background
 967                .as_ref()
 968                .and_then(|color| try_parse_color(&color).ok()),
 969            conflict_border: self
 970                .conflict_border
 971                .as_ref()
 972                .and_then(|color| try_parse_color(&color).ok()),
 973            created: self
 974                .created
 975                .as_ref()
 976                .and_then(|color| try_parse_color(&color).ok()),
 977            created_background: self
 978                .created_background
 979                .as_ref()
 980                .and_then(|color| try_parse_color(&color).ok()),
 981            created_border: self
 982                .created_border
 983                .as_ref()
 984                .and_then(|color| try_parse_color(&color).ok()),
 985            deleted: self
 986                .deleted
 987                .as_ref()
 988                .and_then(|color| try_parse_color(&color).ok()),
 989            deleted_background: self
 990                .deleted_background
 991                .as_ref()
 992                .and_then(|color| try_parse_color(&color).ok()),
 993            deleted_border: self
 994                .deleted_border
 995                .as_ref()
 996                .and_then(|color| try_parse_color(&color).ok()),
 997            error: self
 998                .error
 999                .as_ref()
1000                .and_then(|color| try_parse_color(&color).ok()),
1001            error_background: self
1002                .error_background
1003                .as_ref()
1004                .and_then(|color| try_parse_color(&color).ok()),
1005            error_border: self
1006                .error_border
1007                .as_ref()
1008                .and_then(|color| try_parse_color(&color).ok()),
1009            hidden: self
1010                .hidden
1011                .as_ref()
1012                .and_then(|color| try_parse_color(&color).ok()),
1013            hidden_background: self
1014                .hidden_background
1015                .as_ref()
1016                .and_then(|color| try_parse_color(&color).ok()),
1017            hidden_border: self
1018                .hidden_border
1019                .as_ref()
1020                .and_then(|color| try_parse_color(&color).ok()),
1021            hint: self
1022                .hint
1023                .as_ref()
1024                .and_then(|color| try_parse_color(&color).ok()),
1025            hint_background: self
1026                .hint_background
1027                .as_ref()
1028                .and_then(|color| try_parse_color(&color).ok()),
1029            hint_border: self
1030                .hint_border
1031                .as_ref()
1032                .and_then(|color| try_parse_color(&color).ok()),
1033            ignored: self
1034                .ignored
1035                .as_ref()
1036                .and_then(|color| try_parse_color(&color).ok()),
1037            ignored_background: self
1038                .ignored_background
1039                .as_ref()
1040                .and_then(|color| try_parse_color(&color).ok()),
1041            ignored_border: self
1042                .ignored_border
1043                .as_ref()
1044                .and_then(|color| try_parse_color(&color).ok()),
1045            info: self
1046                .info
1047                .as_ref()
1048                .and_then(|color| try_parse_color(&color).ok()),
1049            info_background: self
1050                .info_background
1051                .as_ref()
1052                .and_then(|color| try_parse_color(&color).ok()),
1053            info_border: self
1054                .info_border
1055                .as_ref()
1056                .and_then(|color| try_parse_color(&color).ok()),
1057            modified: self
1058                .modified
1059                .as_ref()
1060                .and_then(|color| try_parse_color(&color).ok()),
1061            modified_background: self
1062                .modified_background
1063                .as_ref()
1064                .and_then(|color| try_parse_color(&color).ok()),
1065            modified_border: self
1066                .modified_border
1067                .as_ref()
1068                .and_then(|color| try_parse_color(&color).ok()),
1069            predictive: self
1070                .predictive
1071                .as_ref()
1072                .and_then(|color| try_parse_color(&color).ok()),
1073            predictive_background: self
1074                .predictive_background
1075                .as_ref()
1076                .and_then(|color| try_parse_color(&color).ok()),
1077            predictive_border: self
1078                .predictive_border
1079                .as_ref()
1080                .and_then(|color| try_parse_color(&color).ok()),
1081            renamed: self
1082                .renamed
1083                .as_ref()
1084                .and_then(|color| try_parse_color(&color).ok()),
1085            renamed_background: self
1086                .renamed_background
1087                .as_ref()
1088                .and_then(|color| try_parse_color(&color).ok()),
1089            renamed_border: self
1090                .renamed_border
1091                .as_ref()
1092                .and_then(|color| try_parse_color(&color).ok()),
1093            success: self
1094                .success
1095                .as_ref()
1096                .and_then(|color| try_parse_color(&color).ok()),
1097            success_background: self
1098                .success_background
1099                .as_ref()
1100                .and_then(|color| try_parse_color(&color).ok()),
1101            success_border: self
1102                .success_border
1103                .as_ref()
1104                .and_then(|color| try_parse_color(&color).ok()),
1105            unreachable: self
1106                .unreachable
1107                .as_ref()
1108                .and_then(|color| try_parse_color(&color).ok()),
1109            unreachable_background: self
1110                .unreachable_background
1111                .as_ref()
1112                .and_then(|color| try_parse_color(&color).ok()),
1113            unreachable_border: self
1114                .unreachable_border
1115                .as_ref()
1116                .and_then(|color| try_parse_color(&color).ok()),
1117            warning: self
1118                .warning
1119                .as_ref()
1120                .and_then(|color| try_parse_color(&color).ok()),
1121            warning_background: self
1122                .warning_background
1123                .as_ref()
1124                .and_then(|color| try_parse_color(&color).ok()),
1125            warning_border: self
1126                .warning_border
1127                .as_ref()
1128                .and_then(|color| try_parse_color(&color).ok()),
1129        }
1130    }
1131}
1132
1133#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema)]
1134#[serde(rename_all = "snake_case")]
1135pub enum FontStyleContent {
1136    Normal,
1137    Italic,
1138    Oblique,
1139}
1140
1141#[derive(Debug, Clone, Copy, Serialize_repr, Deserialize_repr)]
1142#[repr(u16)]
1143pub enum FontWeightContent {
1144    Thin = 100,
1145    ExtraLight = 200,
1146    Light = 300,
1147    Normal = 400,
1148    Medium = 500,
1149    Semibold = 600,
1150    Bold = 700,
1151    ExtraBold = 800,
1152    Black = 900,
1153}
1154
1155impl JsonSchema for FontWeightContent {
1156    fn schema_name() -> String {
1157        "FontWeightContent".to_owned()
1158    }
1159
1160    fn is_referenceable() -> bool {
1161        false
1162    }
1163
1164    fn json_schema(_: &mut SchemaGenerator) -> Schema {
1165        let mut schema_object = SchemaObject::default();
1166        schema_object.enum_values = Some(vec![
1167            100.into(),
1168            200.into(),
1169            300.into(),
1170            400.into(),
1171            500.into(),
1172            600.into(),
1173            700.into(),
1174            800.into(),
1175            900.into(),
1176        ]);
1177        schema_object.into()
1178    }
1179}
1180
1181#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema)]
1182#[serde(default)]
1183pub struct HighlightStyleContent {
1184    pub color: Option<String>,
1185
1186    #[serde(deserialize_with = "treat_error_as_none")]
1187    pub font_style: Option<FontStyleContent>,
1188
1189    #[serde(deserialize_with = "treat_error_as_none")]
1190    pub font_weight: Option<FontWeightContent>,
1191}
1192
1193fn treat_error_as_none<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
1194where
1195    T: Deserialize<'de>,
1196    D: Deserializer<'de>,
1197{
1198    let value: Value = Deserialize::deserialize(deserializer)?;
1199    Ok(T::deserialize(value).ok())
1200}