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