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