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