1#![allow(missing_docs)]
2
3use anyhow::Result;
4use gpui::{FontStyle, FontWeight, HighlightStyle, Hsla, WindowBackgroundAppearance};
5use indexmap::IndexMap;
6use palette::FromColor;
7use schemars::{JsonSchema, JsonSchema_repr};
8use serde::{Deserialize, Deserializer, Serialize};
9use serde_json::Value;
10use serde_repr::{Deserialize_repr, Serialize_repr};
11
12use crate::{StatusColorsRefinement, ThemeColorsRefinement};
13
14fn ensure_non_opaque(color: Hsla) -> Hsla {
15 const MAXIMUM_OPACITY: f32 = 0.7;
16 if color.a <= MAXIMUM_OPACITY {
17 color
18 } else {
19 Hsla {
20 a: MAXIMUM_OPACITY,
21 ..color
22 }
23 }
24}
25
26fn ensure_opaque(color: Hsla) -> Hsla {
27 Hsla { a: 1.0, ..color }
28}
29
30#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize, JsonSchema)]
31#[serde(rename_all = "snake_case")]
32pub enum AppearanceContent {
33 Light,
34 Dark,
35}
36
37/// The background appearance of the window.
38#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize, JsonSchema)]
39#[serde(rename_all = "snake_case")]
40pub enum WindowBackgroundContent {
41 Opaque,
42 Transparent,
43 Blurred,
44}
45
46impl From<WindowBackgroundContent> for WindowBackgroundAppearance {
47 fn from(value: WindowBackgroundContent) -> Self {
48 match value {
49 WindowBackgroundContent::Opaque => WindowBackgroundAppearance::Opaque,
50 WindowBackgroundContent::Transparent => WindowBackgroundAppearance::Transparent,
51 WindowBackgroundContent::Blurred => WindowBackgroundAppearance::Blurred,
52 }
53 }
54}
55
56/// The content of a serialized theme family.
57#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
58pub struct ThemeFamilyContent {
59 pub name: String,
60 pub author: String,
61 pub themes: Vec<ThemeContent>,
62}
63
64/// The content of a serialized theme.
65#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
66pub struct ThemeContent {
67 pub name: String,
68 pub appearance: AppearanceContent,
69 pub style: settings::ThemeStyleContent,
70}
71
72/// The content of a serialized theme.
73#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema, PartialEq)]
74#[serde(default)]
75pub struct ThemeStyleContent {
76 #[serde(default, rename = "background.appearance")]
77 pub window_background_appearance: Option<WindowBackgroundContent>,
78
79 #[serde(default)]
80 pub accents: Vec<AccentContent>,
81
82 #[serde(flatten, default)]
83 pub colors: settings::ThemeColorsContent,
84
85 #[serde(flatten, default)]
86 pub status: settings::StatusColorsContent,
87
88 #[serde(default)]
89 pub players: Vec<PlayerColorContent>,
90
91 /// The styles for syntax nodes.
92 #[serde(default)]
93 pub syntax: IndexMap<String, settings::HighlightStyleContent>,
94}
95
96/// Returns the syntax style overrides in the [`ThemeContent`].
97pub fn syntax_overrides(this: &settings::ThemeStyleContent) -> Vec<(String, HighlightStyle)> {
98 this.syntax
99 .iter()
100 .map(|(key, style)| {
101 (
102 key.clone(),
103 HighlightStyle {
104 color: style
105 .color
106 .as_ref()
107 .and_then(|color| try_parse_color(color).ok()),
108 background_color: style
109 .background_color
110 .as_ref()
111 .and_then(|color| try_parse_color(color).ok()),
112 font_style: style.font_style.map(FontStyle::from),
113 font_weight: style.font_weight.map(FontWeight::from),
114 ..Default::default()
115 },
116 )
117 })
118 .collect()
119}
120
121pub fn status_colors_refinement(colors: &settings::StatusColorsContent) -> StatusColorsRefinement {
122 StatusColorsRefinement {
123 conflict: colors
124 .conflict
125 .as_ref()
126 .and_then(|color| try_parse_color(color).ok()),
127 conflict_background: colors
128 .conflict_background
129 .as_ref()
130 .and_then(|color| try_parse_color(color).ok()),
131 conflict_border: colors
132 .conflict_border
133 .as_ref()
134 .and_then(|color| try_parse_color(color).ok()),
135 created: colors
136 .created
137 .as_ref()
138 .and_then(|color| try_parse_color(color).ok()),
139 created_background: colors
140 .created_background
141 .as_ref()
142 .and_then(|color| try_parse_color(color).ok()),
143 created_border: colors
144 .created_border
145 .as_ref()
146 .and_then(|color| try_parse_color(color).ok()),
147 deleted: colors
148 .deleted
149 .as_ref()
150 .and_then(|color| try_parse_color(color).ok()),
151 deleted_background: colors
152 .deleted_background
153 .as_ref()
154 .and_then(|color| try_parse_color(color).ok()),
155 deleted_border: colors
156 .deleted_border
157 .as_ref()
158 .and_then(|color| try_parse_color(color).ok()),
159 error: colors
160 .error
161 .as_ref()
162 .and_then(|color| try_parse_color(color).ok()),
163 error_background: colors
164 .error_background
165 .as_ref()
166 .and_then(|color| try_parse_color(color).ok()),
167 error_border: colors
168 .error_border
169 .as_ref()
170 .and_then(|color| try_parse_color(color).ok()),
171 hidden: colors
172 .hidden
173 .as_ref()
174 .and_then(|color| try_parse_color(color).ok()),
175 hidden_background: colors
176 .hidden_background
177 .as_ref()
178 .and_then(|color| try_parse_color(color).ok()),
179 hidden_border: colors
180 .hidden_border
181 .as_ref()
182 .and_then(|color| try_parse_color(color).ok()),
183 hint: colors
184 .hint
185 .as_ref()
186 .and_then(|color| try_parse_color(color).ok()),
187 hint_background: colors
188 .hint_background
189 .as_ref()
190 .and_then(|color| try_parse_color(color).ok()),
191 hint_border: colors
192 .hint_border
193 .as_ref()
194 .and_then(|color| try_parse_color(color).ok()),
195 ignored: colors
196 .ignored
197 .as_ref()
198 .and_then(|color| try_parse_color(color).ok()),
199 ignored_background: colors
200 .ignored_background
201 .as_ref()
202 .and_then(|color| try_parse_color(color).ok()),
203 ignored_border: colors
204 .ignored_border
205 .as_ref()
206 .and_then(|color| try_parse_color(color).ok()),
207 info: colors
208 .info
209 .as_ref()
210 .and_then(|color| try_parse_color(color).ok()),
211 info_background: colors
212 .info_background
213 .as_ref()
214 .and_then(|color| try_parse_color(color).ok()),
215 info_border: colors
216 .info_border
217 .as_ref()
218 .and_then(|color| try_parse_color(color).ok()),
219 modified: colors
220 .modified
221 .as_ref()
222 .and_then(|color| try_parse_color(color).ok()),
223 modified_background: colors
224 .modified_background
225 .as_ref()
226 .and_then(|color| try_parse_color(color).ok()),
227 modified_border: colors
228 .modified_border
229 .as_ref()
230 .and_then(|color| try_parse_color(color).ok()),
231 predictive: colors
232 .predictive
233 .as_ref()
234 .and_then(|color| try_parse_color(color).ok()),
235 predictive_background: colors
236 .predictive_background
237 .as_ref()
238 .and_then(|color| try_parse_color(color).ok()),
239 predictive_border: colors
240 .predictive_border
241 .as_ref()
242 .and_then(|color| try_parse_color(color).ok()),
243 renamed: colors
244 .renamed
245 .as_ref()
246 .and_then(|color| try_parse_color(color).ok()),
247 renamed_background: colors
248 .renamed_background
249 .as_ref()
250 .and_then(|color| try_parse_color(color).ok()),
251 renamed_border: colors
252 .renamed_border
253 .as_ref()
254 .and_then(|color| try_parse_color(color).ok()),
255 success: colors
256 .success
257 .as_ref()
258 .and_then(|color| try_parse_color(color).ok()),
259 success_background: colors
260 .success_background
261 .as_ref()
262 .and_then(|color| try_parse_color(color).ok()),
263 success_border: colors
264 .success_border
265 .as_ref()
266 .and_then(|color| try_parse_color(color).ok()),
267 unreachable: colors
268 .unreachable
269 .as_ref()
270 .and_then(|color| try_parse_color(color).ok()),
271 unreachable_background: colors
272 .unreachable_background
273 .as_ref()
274 .and_then(|color| try_parse_color(color).ok()),
275 unreachable_border: colors
276 .unreachable_border
277 .as_ref()
278 .and_then(|color| try_parse_color(color).ok()),
279 warning: colors
280 .warning
281 .as_ref()
282 .and_then(|color| try_parse_color(color).ok()),
283 warning_background: colors
284 .warning_background
285 .as_ref()
286 .and_then(|color| try_parse_color(color).ok()),
287 warning_border: colors
288 .warning_border
289 .as_ref()
290 .and_then(|color| try_parse_color(color).ok()),
291 }
292}
293
294#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
295pub struct AccentContent(pub Option<String>);
296
297#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
298pub struct PlayerColorContent {
299 pub cursor: Option<String>,
300 pub background: Option<String>,
301 pub selection: Option<String>,
302}
303
304#[derive(Debug, Clone, Copy, Serialize_repr, Deserialize_repr, JsonSchema_repr, PartialEq)]
305#[repr(u16)]
306pub enum FontWeightContent {
307 Thin = 100,
308 ExtraLight = 200,
309 Light = 300,
310 Normal = 400,
311 Medium = 500,
312 Semibold = 600,
313 Bold = 700,
314 ExtraBold = 800,
315 Black = 900,
316}
317
318pub fn theme_colors_refinement(
319 this: &settings::ThemeColorsContent,
320 status_colors: &StatusColorsRefinement,
321) -> ThemeColorsRefinement {
322 let border = this
323 .border
324 .as_ref()
325 .and_then(|color| try_parse_color(color).ok());
326 let editor_document_highlight_read_background = this
327 .editor_document_highlight_read_background
328 .as_ref()
329 .and_then(|color| try_parse_color(color).ok());
330 let scrollbar_thumb_background = this
331 .scrollbar_thumb_background
332 .as_ref()
333 .and_then(|color| try_parse_color(color).ok())
334 .or_else(|| {
335 this.deprecated_scrollbar_thumb_background
336 .as_ref()
337 .and_then(|color| try_parse_color(color).ok())
338 });
339 let scrollbar_thumb_hover_background = this
340 .scrollbar_thumb_hover_background
341 .as_ref()
342 .and_then(|color| try_parse_color(color).ok());
343 let scrollbar_thumb_active_background = this
344 .scrollbar_thumb_active_background
345 .as_ref()
346 .and_then(|color| try_parse_color(color).ok())
347 .or(scrollbar_thumb_background);
348 let scrollbar_thumb_border = this
349 .scrollbar_thumb_border
350 .as_ref()
351 .and_then(|color| try_parse_color(color).ok());
352 let element_hover = this
353 .element_hover
354 .as_ref()
355 .and_then(|color| try_parse_color(color).ok());
356 let panel_background = this
357 .panel_background
358 .as_ref()
359 .and_then(|color| try_parse_color(color).ok());
360 ThemeColorsRefinement {
361 border,
362 border_variant: this
363 .border_variant
364 .as_ref()
365 .and_then(|color| try_parse_color(color).ok()),
366 border_focused: this
367 .border_focused
368 .as_ref()
369 .and_then(|color| try_parse_color(color).ok()),
370 border_selected: this
371 .border_selected
372 .as_ref()
373 .and_then(|color| try_parse_color(color).ok()),
374 border_transparent: this
375 .border_transparent
376 .as_ref()
377 .and_then(|color| try_parse_color(color).ok()),
378 border_disabled: this
379 .border_disabled
380 .as_ref()
381 .and_then(|color| try_parse_color(color).ok()),
382 elevated_surface_background: this
383 .elevated_surface_background
384 .as_ref()
385 .and_then(|color| try_parse_color(color).ok()),
386 surface_background: this
387 .surface_background
388 .as_ref()
389 .and_then(|color| try_parse_color(color).ok()),
390 background: this
391 .background
392 .as_ref()
393 .and_then(|color| try_parse_color(color).ok()),
394 element_background: this
395 .element_background
396 .as_ref()
397 .and_then(|color| try_parse_color(color).ok()),
398 element_hover,
399 element_active: this
400 .element_active
401 .as_ref()
402 .and_then(|color| try_parse_color(color).ok()),
403 element_selected: this
404 .element_selected
405 .as_ref()
406 .and_then(|color| try_parse_color(color).ok()),
407 element_disabled: this
408 .element_disabled
409 .as_ref()
410 .and_then(|color| try_parse_color(color).ok()),
411 element_selection_background: this
412 .element_selection_background
413 .as_ref()
414 .and_then(|color| try_parse_color(color).ok()),
415 drop_target_background: this
416 .drop_target_background
417 .as_ref()
418 .and_then(|color| try_parse_color(color).ok()),
419 drop_target_border: this
420 .drop_target_border
421 .as_ref()
422 .and_then(|color| try_parse_color(color).ok()),
423 ghost_element_background: this
424 .ghost_element_background
425 .as_ref()
426 .and_then(|color| try_parse_color(color).ok()),
427 ghost_element_hover: this
428 .ghost_element_hover
429 .as_ref()
430 .and_then(|color| try_parse_color(color).ok()),
431 ghost_element_active: this
432 .ghost_element_active
433 .as_ref()
434 .and_then(|color| try_parse_color(color).ok()),
435 ghost_element_selected: this
436 .ghost_element_selected
437 .as_ref()
438 .and_then(|color| try_parse_color(color).ok()),
439 ghost_element_disabled: this
440 .ghost_element_disabled
441 .as_ref()
442 .and_then(|color| try_parse_color(color).ok()),
443 text: this
444 .text
445 .as_ref()
446 .and_then(|color| try_parse_color(color).ok()),
447 text_muted: this
448 .text_muted
449 .as_ref()
450 .and_then(|color| try_parse_color(color).ok()),
451 text_placeholder: this
452 .text_placeholder
453 .as_ref()
454 .and_then(|color| try_parse_color(color).ok()),
455 text_disabled: this
456 .text_disabled
457 .as_ref()
458 .and_then(|color| try_parse_color(color).ok()),
459 text_accent: this
460 .text_accent
461 .as_ref()
462 .and_then(|color| try_parse_color(color).ok()),
463 icon: this
464 .icon
465 .as_ref()
466 .and_then(|color| try_parse_color(color).ok()),
467 icon_muted: this
468 .icon_muted
469 .as_ref()
470 .and_then(|color| try_parse_color(color).ok()),
471 icon_disabled: this
472 .icon_disabled
473 .as_ref()
474 .and_then(|color| try_parse_color(color).ok()),
475 icon_placeholder: this
476 .icon_placeholder
477 .as_ref()
478 .and_then(|color| try_parse_color(color).ok()),
479 icon_accent: this
480 .icon_accent
481 .as_ref()
482 .and_then(|color| try_parse_color(color).ok()),
483 debugger_accent: this
484 .debugger_accent
485 .as_ref()
486 .and_then(|color| try_parse_color(color).ok()),
487 status_bar_background: this
488 .status_bar_background
489 .as_ref()
490 .and_then(|color| try_parse_color(color).ok()),
491 title_bar_background: this
492 .title_bar_background
493 .as_ref()
494 .and_then(|color| try_parse_color(color).ok()),
495 title_bar_inactive_background: this
496 .title_bar_inactive_background
497 .as_ref()
498 .and_then(|color| try_parse_color(color).ok()),
499 toolbar_background: this
500 .toolbar_background
501 .as_ref()
502 .and_then(|color| try_parse_color(color).ok()),
503 tab_bar_background: this
504 .tab_bar_background
505 .as_ref()
506 .and_then(|color| try_parse_color(color).ok()),
507 tab_inactive_background: this
508 .tab_inactive_background
509 .as_ref()
510 .and_then(|color| try_parse_color(color).ok()),
511 tab_active_background: this
512 .tab_active_background
513 .as_ref()
514 .and_then(|color| try_parse_color(color).ok()),
515 search_match_background: this
516 .search_match_background
517 .as_ref()
518 .and_then(|color| try_parse_color(color).ok()),
519 panel_background,
520 panel_focused_border: this
521 .panel_focused_border
522 .as_ref()
523 .and_then(|color| try_parse_color(color).ok()),
524 panel_indent_guide: this
525 .panel_indent_guide
526 .as_ref()
527 .and_then(|color| try_parse_color(color).ok()),
528 panel_indent_guide_hover: this
529 .panel_indent_guide_hover
530 .as_ref()
531 .and_then(|color| try_parse_color(color).ok()),
532 panel_indent_guide_active: this
533 .panel_indent_guide_active
534 .as_ref()
535 .and_then(|color| try_parse_color(color).ok()),
536 panel_overlay_background: this
537 .panel_overlay_background
538 .as_ref()
539 .and_then(|color| try_parse_color(color).ok())
540 .or(panel_background.map(ensure_opaque)),
541 panel_overlay_hover: this
542 .panel_overlay_hover
543 .as_ref()
544 .and_then(|color| try_parse_color(color).ok())
545 .or(panel_background
546 .zip(element_hover)
547 .map(|(panel_bg, hover_bg)| panel_bg.blend(hover_bg))
548 .map(ensure_opaque)),
549 pane_focused_border: this
550 .pane_focused_border
551 .as_ref()
552 .and_then(|color| try_parse_color(color).ok()),
553 pane_group_border: this
554 .pane_group_border
555 .as_ref()
556 .and_then(|color| try_parse_color(color).ok())
557 .or(border),
558 scrollbar_thumb_background,
559 scrollbar_thumb_hover_background,
560 scrollbar_thumb_active_background,
561 scrollbar_thumb_border,
562 scrollbar_track_background: this
563 .scrollbar_track_background
564 .as_ref()
565 .and_then(|color| try_parse_color(color).ok()),
566 scrollbar_track_border: this
567 .scrollbar_track_border
568 .as_ref()
569 .and_then(|color| try_parse_color(color).ok()),
570 minimap_thumb_background: this
571 .minimap_thumb_background
572 .as_ref()
573 .and_then(|color| try_parse_color(color).ok())
574 .or(scrollbar_thumb_background.map(ensure_non_opaque)),
575 minimap_thumb_hover_background: this
576 .minimap_thumb_hover_background
577 .as_ref()
578 .and_then(|color| try_parse_color(color).ok())
579 .or(scrollbar_thumb_hover_background.map(ensure_non_opaque)),
580 minimap_thumb_active_background: this
581 .minimap_thumb_active_background
582 .as_ref()
583 .and_then(|color| try_parse_color(color).ok())
584 .or(scrollbar_thumb_active_background.map(ensure_non_opaque)),
585 minimap_thumb_border: this
586 .minimap_thumb_border
587 .as_ref()
588 .and_then(|color| try_parse_color(color).ok())
589 .or(scrollbar_thumb_border),
590 editor_foreground: this
591 .editor_foreground
592 .as_ref()
593 .and_then(|color| try_parse_color(color).ok()),
594 editor_background: this
595 .editor_background
596 .as_ref()
597 .and_then(|color| try_parse_color(color).ok()),
598 editor_gutter_background: this
599 .editor_gutter_background
600 .as_ref()
601 .and_then(|color| try_parse_color(color).ok()),
602 editor_subheader_background: this
603 .editor_subheader_background
604 .as_ref()
605 .and_then(|color| try_parse_color(color).ok()),
606 editor_active_line_background: this
607 .editor_active_line_background
608 .as_ref()
609 .and_then(|color| try_parse_color(color).ok()),
610 editor_highlighted_line_background: this
611 .editor_highlighted_line_background
612 .as_ref()
613 .and_then(|color| try_parse_color(color).ok()),
614 editor_debugger_active_line_background: this
615 .editor_debugger_active_line_background
616 .as_ref()
617 .and_then(|color| try_parse_color(color).ok()),
618 editor_line_number: this
619 .editor_line_number
620 .as_ref()
621 .and_then(|color| try_parse_color(color).ok()),
622 editor_hover_line_number: this
623 .editor_hover_line_number
624 .as_ref()
625 .and_then(|color| try_parse_color(color).ok()),
626 editor_active_line_number: this
627 .editor_active_line_number
628 .as_ref()
629 .and_then(|color| try_parse_color(color).ok()),
630 editor_invisible: this
631 .editor_invisible
632 .as_ref()
633 .and_then(|color| try_parse_color(color).ok()),
634 editor_wrap_guide: this
635 .editor_wrap_guide
636 .as_ref()
637 .and_then(|color| try_parse_color(color).ok()),
638 editor_active_wrap_guide: this
639 .editor_active_wrap_guide
640 .as_ref()
641 .and_then(|color| try_parse_color(color).ok()),
642 editor_indent_guide: this
643 .editor_indent_guide
644 .as_ref()
645 .and_then(|color| try_parse_color(color).ok()),
646 editor_indent_guide_active: this
647 .editor_indent_guide_active
648 .as_ref()
649 .and_then(|color| try_parse_color(color).ok()),
650 editor_document_highlight_read_background,
651 editor_document_highlight_write_background: this
652 .editor_document_highlight_write_background
653 .as_ref()
654 .and_then(|color| try_parse_color(color).ok()),
655 editor_document_highlight_bracket_background: this
656 .editor_document_highlight_bracket_background
657 .as_ref()
658 .and_then(|color| try_parse_color(color).ok())
659 // Fall back to `editor.document_highlight.read_background`, for backwards compatibility.
660 .or(editor_document_highlight_read_background),
661 terminal_background: this
662 .terminal_background
663 .as_ref()
664 .and_then(|color| try_parse_color(color).ok()),
665 terminal_ansi_background: this
666 .terminal_ansi_background
667 .as_ref()
668 .and_then(|color| try_parse_color(color).ok()),
669 terminal_foreground: this
670 .terminal_foreground
671 .as_ref()
672 .and_then(|color| try_parse_color(color).ok()),
673 terminal_bright_foreground: this
674 .terminal_bright_foreground
675 .as_ref()
676 .and_then(|color| try_parse_color(color).ok()),
677 terminal_dim_foreground: this
678 .terminal_dim_foreground
679 .as_ref()
680 .and_then(|color| try_parse_color(color).ok()),
681 terminal_ansi_black: this
682 .terminal_ansi_black
683 .as_ref()
684 .and_then(|color| try_parse_color(color).ok()),
685 terminal_ansi_bright_black: this
686 .terminal_ansi_bright_black
687 .as_ref()
688 .and_then(|color| try_parse_color(color).ok()),
689 terminal_ansi_dim_black: this
690 .terminal_ansi_dim_black
691 .as_ref()
692 .and_then(|color| try_parse_color(color).ok()),
693 terminal_ansi_red: this
694 .terminal_ansi_red
695 .as_ref()
696 .and_then(|color| try_parse_color(color).ok()),
697 terminal_ansi_bright_red: this
698 .terminal_ansi_bright_red
699 .as_ref()
700 .and_then(|color| try_parse_color(color).ok()),
701 terminal_ansi_dim_red: this
702 .terminal_ansi_dim_red
703 .as_ref()
704 .and_then(|color| try_parse_color(color).ok()),
705 terminal_ansi_green: this
706 .terminal_ansi_green
707 .as_ref()
708 .and_then(|color| try_parse_color(color).ok()),
709 terminal_ansi_bright_green: this
710 .terminal_ansi_bright_green
711 .as_ref()
712 .and_then(|color| try_parse_color(color).ok()),
713 terminal_ansi_dim_green: this
714 .terminal_ansi_dim_green
715 .as_ref()
716 .and_then(|color| try_parse_color(color).ok()),
717 terminal_ansi_yellow: this
718 .terminal_ansi_yellow
719 .as_ref()
720 .and_then(|color| try_parse_color(color).ok()),
721 terminal_ansi_bright_yellow: this
722 .terminal_ansi_bright_yellow
723 .as_ref()
724 .and_then(|color| try_parse_color(color).ok()),
725 terminal_ansi_dim_yellow: this
726 .terminal_ansi_dim_yellow
727 .as_ref()
728 .and_then(|color| try_parse_color(color).ok()),
729 terminal_ansi_blue: this
730 .terminal_ansi_blue
731 .as_ref()
732 .and_then(|color| try_parse_color(color).ok()),
733 terminal_ansi_bright_blue: this
734 .terminal_ansi_bright_blue
735 .as_ref()
736 .and_then(|color| try_parse_color(color).ok()),
737 terminal_ansi_dim_blue: this
738 .terminal_ansi_dim_blue
739 .as_ref()
740 .and_then(|color| try_parse_color(color).ok()),
741 terminal_ansi_magenta: this
742 .terminal_ansi_magenta
743 .as_ref()
744 .and_then(|color| try_parse_color(color).ok()),
745 terminal_ansi_bright_magenta: this
746 .terminal_ansi_bright_magenta
747 .as_ref()
748 .and_then(|color| try_parse_color(color).ok()),
749 terminal_ansi_dim_magenta: this
750 .terminal_ansi_dim_magenta
751 .as_ref()
752 .and_then(|color| try_parse_color(color).ok()),
753 terminal_ansi_cyan: this
754 .terminal_ansi_cyan
755 .as_ref()
756 .and_then(|color| try_parse_color(color).ok()),
757 terminal_ansi_bright_cyan: this
758 .terminal_ansi_bright_cyan
759 .as_ref()
760 .and_then(|color| try_parse_color(color).ok()),
761 terminal_ansi_dim_cyan: this
762 .terminal_ansi_dim_cyan
763 .as_ref()
764 .and_then(|color| try_parse_color(color).ok()),
765 terminal_ansi_white: this
766 .terminal_ansi_white
767 .as_ref()
768 .and_then(|color| try_parse_color(color).ok()),
769 terminal_ansi_bright_white: this
770 .terminal_ansi_bright_white
771 .as_ref()
772 .and_then(|color| try_parse_color(color).ok()),
773 terminal_ansi_dim_white: this
774 .terminal_ansi_dim_white
775 .as_ref()
776 .and_then(|color| try_parse_color(color).ok()),
777 link_text_hover: this
778 .link_text_hover
779 .as_ref()
780 .and_then(|color| try_parse_color(color).ok()),
781 version_control_added: this
782 .version_control_added
783 .as_ref()
784 .and_then(|color| try_parse_color(color).ok())
785 // Fall back to `created`, for backwards compatibility.
786 .or(status_colors.created),
787 version_control_deleted: this
788 .version_control_deleted
789 .as_ref()
790 .and_then(|color| try_parse_color(color).ok())
791 // Fall back to `deleted`, for backwards compatibility.
792 .or(status_colors.deleted),
793 version_control_modified: this
794 .version_control_modified
795 .as_ref()
796 .and_then(|color| try_parse_color(color).ok())
797 // Fall back to `modified`, for backwards compatibility.
798 .or(status_colors.modified),
799 version_control_renamed: this
800 .version_control_renamed
801 .as_ref()
802 .and_then(|color| try_parse_color(color).ok())
803 // Fall back to `modified`, for backwards compatibility.
804 .or(status_colors.modified),
805 version_control_conflict: this
806 .version_control_conflict
807 .as_ref()
808 .and_then(|color| try_parse_color(color).ok())
809 // Fall back to `ignored`, for backwards compatibility.
810 .or(status_colors.ignored),
811 version_control_ignored: this
812 .version_control_ignored
813 .as_ref()
814 .and_then(|color| try_parse_color(color).ok())
815 // Fall back to `conflict`, for backwards compatibility.
816 .or(status_colors.ignored),
817 #[allow(deprecated)]
818 version_control_conflict_marker_ours: this
819 .version_control_conflict_marker_ours
820 .as_ref()
821 .or(this.version_control_conflict_ours_background.as_ref())
822 .and_then(|color| try_parse_color(color).ok()),
823 #[allow(deprecated)]
824 version_control_conflict_marker_theirs: this
825 .version_control_conflict_marker_theirs
826 .as_ref()
827 .or(this.version_control_conflict_theirs_background.as_ref())
828 .and_then(|color| try_parse_color(color).ok()),
829 }
830}
831
832pub(crate) fn try_parse_color(color: &str) -> anyhow::Result<Hsla> {
833 let rgba = gpui::Rgba::try_from(color)?;
834 let rgba = palette::rgb::Srgba::from_components((rgba.r, rgba.g, rgba.b, rgba.a));
835 let hsla = palette::Hsla::from_color(rgba);
836
837 let hsla = gpui::hsla(
838 hsla.hue.into_positive_degrees() / 360.,
839 hsla.saturation,
840 hsla.lightness,
841 hsla.alpha,
842 );
843
844 Ok(hsla)
845}