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