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