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