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