Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T04:42:54.720Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git
Browse files

schema.rs

1107 lines · 40.8 KB · rust
1#![allow(missing_docs)]
2
3use gpui::{HighlightStyle, Hsla};
4use palette::FromColor;
5use schemars::JsonSchema;
6use serde::{Deserialize, Serialize};
7use settings::IntoGpui;
8pub use settings::{
9    FontStyleContent, HighlightStyleContent, StatusColorsContent, ThemeColorsContent,
10    ThemeStyleContent,
11};
12pub use settings::{FontWeightContent, WindowBackgroundContent};
13
14use theme::{StatusColorsRefinement, ThemeColorsRefinement};
15
16const LIGHT_DIFF_HUNK_FILLED_OPACITY: f32 = 0.16;
17const LIGHT_DIFF_HUNK_HOLLOW_BACKGROUND_OPACITY: f32 = 0.08;
18const LIGHT_DIFF_HUNK_HOLLOW_BORDER_OPACITY: f32 = 0.48;
19const DARK_DIFF_HUNK_FILLED_OPACITY: f32 = 0.12;
20const DARK_DIFF_HUNK_HOLLOW_BACKGROUND_OPACITY: f32 = 0.06;
21const DARK_DIFF_HUNK_HOLLOW_BORDER_OPACITY: f32 = 0.36;
22
23/// The content of a serialized theme family.
24#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
25pub struct ThemeFamilyContent {
26    pub name: String,
27    pub author: String,
28    pub themes: Vec<ThemeContent>,
29}
30
31/// The content of a serialized theme.
32#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
33pub struct ThemeContent {
34    pub name: String,
35    pub appearance: theme::AppearanceContent,
36    pub style: settings::ThemeStyleContent,
37}
38
39/// Returns the syntax style overrides in the [`ThemeContent`].
40pub fn syntax_overrides(this: &settings::ThemeStyleContent) -> Vec<(String, HighlightStyle)> {
41    this.syntax
42        .iter()
43        .map(|(key, style)| {
44            (
45                key.clone(),
46                HighlightStyle {
47                    color: style
48                        .color
49                        .as_ref()
50                        .and_then(|color| theme::try_parse_color(color).ok()),
51                    background_color: style
52                        .background_color
53                        .as_ref()
54                        .and_then(|color| theme::try_parse_color(color).ok()),
55                    font_style: style.font_style.map(|s| s.into_gpui()),
56                    font_weight: style.font_weight.map(|w| w.into_gpui()),
57                    ..Default::default()
58                },
59            )
60        })
61        .collect()
62}
63
64pub fn status_colors_refinement(colors: &settings::StatusColorsContent) -> StatusColorsRefinement {
65    StatusColorsRefinement {
66        conflict: colors
67            .conflict
68            .as_ref()
69            .and_then(|color| try_parse_color(color).ok()),
70        conflict_background: colors
71            .conflict_background
72            .as_ref()
73            .and_then(|color| try_parse_color(color).ok()),
74        conflict_border: colors
75            .conflict_border
76            .as_ref()
77            .and_then(|color| try_parse_color(color).ok()),
78        created: colors
79            .created
80            .as_ref()
81            .and_then(|color| try_parse_color(color).ok()),
82        created_background: colors
83            .created_background
84            .as_ref()
85            .and_then(|color| try_parse_color(color).ok()),
86        created_border: colors
87            .created_border
88            .as_ref()
89            .and_then(|color| try_parse_color(color).ok()),
90        deleted: colors
91            .deleted
92            .as_ref()
93            .and_then(|color| try_parse_color(color).ok()),
94        deleted_background: colors
95            .deleted_background
96            .as_ref()
97            .and_then(|color| try_parse_color(color).ok()),
98        deleted_border: colors
99            .deleted_border
100            .as_ref()
101            .and_then(|color| try_parse_color(color).ok()),
102        error: colors
103            .error
104            .as_ref()
105            .and_then(|color| try_parse_color(color).ok()),
106        error_background: colors
107            .error_background
108            .as_ref()
109            .and_then(|color| try_parse_color(color).ok()),
110        error_border: colors
111            .error_border
112            .as_ref()
113            .and_then(|color| try_parse_color(color).ok()),
114        hidden: colors
115            .hidden
116            .as_ref()
117            .and_then(|color| try_parse_color(color).ok()),
118        hidden_background: colors
119            .hidden_background
120            .as_ref()
121            .and_then(|color| try_parse_color(color).ok()),
122        hidden_border: colors
123            .hidden_border
124            .as_ref()
125            .and_then(|color| try_parse_color(color).ok()),
126        hint: colors
127            .hint
128            .as_ref()
129            .and_then(|color| try_parse_color(color).ok()),
130        hint_background: colors
131            .hint_background
132            .as_ref()
133            .and_then(|color| try_parse_color(color).ok()),
134        hint_border: colors
135            .hint_border
136            .as_ref()
137            .and_then(|color| try_parse_color(color).ok()),
138        ignored: colors
139            .ignored
140            .as_ref()
141            .and_then(|color| try_parse_color(color).ok()),
142        ignored_background: colors
143            .ignored_background
144            .as_ref()
145            .and_then(|color| try_parse_color(color).ok()),
146        ignored_border: colors
147            .ignored_border
148            .as_ref()
149            .and_then(|color| try_parse_color(color).ok()),
150        info: colors
151            .info
152            .as_ref()
153            .and_then(|color| try_parse_color(color).ok()),
154        info_background: colors
155            .info_background
156            .as_ref()
157            .and_then(|color| try_parse_color(color).ok()),
158        info_border: colors
159            .info_border
160            .as_ref()
161            .and_then(|color| try_parse_color(color).ok()),
162        modified: colors
163            .modified
164            .as_ref()
165            .and_then(|color| try_parse_color(color).ok()),
166        modified_background: colors
167            .modified_background
168            .as_ref()
169            .and_then(|color| try_parse_color(color).ok()),
170        modified_border: colors
171            .modified_border
172            .as_ref()
173            .and_then(|color| try_parse_color(color).ok()),
174        predictive: colors
175            .predictive
176            .as_ref()
177            .and_then(|color| try_parse_color(color).ok()),
178        predictive_background: colors
179            .predictive_background
180            .as_ref()
181            .and_then(|color| try_parse_color(color).ok()),
182        predictive_border: colors
183            .predictive_border
184            .as_ref()
185            .and_then(|color| try_parse_color(color).ok()),
186        renamed: colors
187            .renamed
188            .as_ref()
189            .and_then(|color| try_parse_color(color).ok()),
190        renamed_background: colors
191            .renamed_background
192            .as_ref()
193            .and_then(|color| try_parse_color(color).ok()),
194        renamed_border: colors
195            .renamed_border
196            .as_ref()
197            .and_then(|color| try_parse_color(color).ok()),
198        success: colors
199            .success
200            .as_ref()
201            .and_then(|color| try_parse_color(color).ok()),
202        success_background: colors
203            .success_background
204            .as_ref()
205            .and_then(|color| try_parse_color(color).ok()),
206        success_border: colors
207            .success_border
208            .as_ref()
209            .and_then(|color| try_parse_color(color).ok()),
210        unreachable: colors
211            .unreachable
212            .as_ref()
213            .and_then(|color| try_parse_color(color).ok()),
214        unreachable_background: colors
215            .unreachable_background
216            .as_ref()
217            .and_then(|color| try_parse_color(color).ok()),
218        unreachable_border: colors
219            .unreachable_border
220            .as_ref()
221            .and_then(|color| try_parse_color(color).ok()),
222        warning: colors
223            .warning
224            .as_ref()
225            .and_then(|color| try_parse_color(color).ok()),
226        warning_background: colors
227            .warning_background
228            .as_ref()
229            .and_then(|color| try_parse_color(color).ok()),
230        warning_border: colors
231            .warning_border
232            .as_ref()
233            .and_then(|color| try_parse_color(color).ok()),
234    }
235}
236
237pub fn theme_colors_refinement(
238    this: &settings::ThemeColorsContent,
239    status_colors: &StatusColorsRefinement,
240    is_light: bool,
241) -> ThemeColorsRefinement {
242    let border = this
243        .border
244        .as_ref()
245        .and_then(|color| try_parse_color(color).ok());
246    let editor_document_highlight_read_background = this
247        .editor_document_highlight_read_background
248        .as_ref()
249        .and_then(|color| try_parse_color(color).ok());
250    let scrollbar_thumb_background = this
251        .scrollbar_thumb_background
252        .as_ref()
253        .and_then(|color| try_parse_color(color).ok())
254        .or_else(|| {
255            this.deprecated_scrollbar_thumb_background
256                .as_ref()
257                .and_then(|color| try_parse_color(color).ok())
258        });
259    let scrollbar_thumb_hover_background = this
260        .scrollbar_thumb_hover_background
261        .as_ref()
262        .and_then(|color| try_parse_color(color).ok());
263    let scrollbar_thumb_active_background = this
264        .scrollbar_thumb_active_background
265        .as_ref()
266        .and_then(|color| try_parse_color(color).ok())
267        .or(scrollbar_thumb_background);
268    let scrollbar_thumb_border = this
269        .scrollbar_thumb_border
270        .as_ref()
271        .and_then(|color| try_parse_color(color).ok());
272    let element_hover = this
273        .element_hover
274        .as_ref()
275        .and_then(|color| try_parse_color(color).ok());
276    let panel_background = this
277        .panel_background
278        .as_ref()
279        .and_then(|color| try_parse_color(color).ok());
280    let search_match_background = this
281        .search_match_background
282        .as_ref()
283        .and_then(|color| try_parse_color(color).ok());
284    let search_active_match_background = this
285        .search_active_match_background
286        .as_ref()
287        .and_then(|color| try_parse_color(color).ok())
288        .or(search_match_background);
289    let version_control_added = this
290        .version_control_added
291        .as_ref()
292        .and_then(|color| try_parse_color(color).ok())
293        .or(status_colors.created);
294    let version_control_deleted = this
295        .version_control_deleted
296        .as_ref()
297        .and_then(|color| try_parse_color(color).ok())
298        .or(status_colors.deleted);
299    let (hunk_fill, hunk_hollow_bg, hunk_hollow_border) = if is_light {
300        (
301            LIGHT_DIFF_HUNK_FILLED_OPACITY,
302            LIGHT_DIFF_HUNK_HOLLOW_BACKGROUND_OPACITY,
303            LIGHT_DIFF_HUNK_HOLLOW_BORDER_OPACITY,
304        )
305    } else {
306        (
307            DARK_DIFF_HUNK_FILLED_OPACITY,
308            DARK_DIFF_HUNK_HOLLOW_BACKGROUND_OPACITY,
309            DARK_DIFF_HUNK_HOLLOW_BORDER_OPACITY,
310        )
311    };
312    ThemeColorsRefinement {
313        border,
314        border_variant: this
315            .border_variant
316            .as_ref()
317            .and_then(|color| try_parse_color(color).ok()),
318        border_focused: this
319            .border_focused
320            .as_ref()
321            .and_then(|color| try_parse_color(color).ok()),
322        border_selected: this
323            .border_selected
324            .as_ref()
325            .and_then(|color| try_parse_color(color).ok()),
326        border_transparent: this
327            .border_transparent
328            .as_ref()
329            .and_then(|color| try_parse_color(color).ok()),
330        border_disabled: this
331            .border_disabled
332            .as_ref()
333            .and_then(|color| try_parse_color(color).ok()),
334        elevated_surface_background: this
335            .elevated_surface_background
336            .as_ref()
337            .and_then(|color| try_parse_color(color).ok()),
338        surface_background: this
339            .surface_background
340            .as_ref()
341            .and_then(|color| try_parse_color(color).ok()),
342        background: this
343            .background
344            .as_ref()
345            .and_then(|color| try_parse_color(color).ok()),
346        element_background: this
347            .element_background
348            .as_ref()
349            .and_then(|color| try_parse_color(color).ok()),
350        element_hover,
351        element_active: this
352            .element_active
353            .as_ref()
354            .and_then(|color| try_parse_color(color).ok()),
355        element_selected: this
356            .element_selected
357            .as_ref()
358            .and_then(|color| try_parse_color(color).ok()),
359        element_disabled: this
360            .element_disabled
361            .as_ref()
362            .and_then(|color| try_parse_color(color).ok()),
363        element_selection_background: this
364            .element_selection_background
365            .as_ref()
366            .and_then(|color| try_parse_color(color).ok()),
367        drop_target_background: this
368            .drop_target_background
369            .as_ref()
370            .and_then(|color| try_parse_color(color).ok()),
371        drop_target_border: this
372            .drop_target_border
373            .as_ref()
374            .and_then(|color| try_parse_color(color).ok()),
375        ghost_element_background: this
376            .ghost_element_background
377            .as_ref()
378            .and_then(|color| try_parse_color(color).ok()),
379        ghost_element_hover: this
380            .ghost_element_hover
381            .as_ref()
382            .and_then(|color| try_parse_color(color).ok()),
383        ghost_element_active: this
384            .ghost_element_active
385            .as_ref()
386            .and_then(|color| try_parse_color(color).ok()),
387        ghost_element_selected: this
388            .ghost_element_selected
389            .as_ref()
390            .and_then(|color| try_parse_color(color).ok()),
391        ghost_element_disabled: this
392            .ghost_element_disabled
393            .as_ref()
394            .and_then(|color| try_parse_color(color).ok()),
395        text: this
396            .text
397            .as_ref()
398            .and_then(|color| try_parse_color(color).ok()),
399        text_muted: this
400            .text_muted
401            .as_ref()
402            .and_then(|color| try_parse_color(color).ok()),
403        text_placeholder: this
404            .text_placeholder
405            .as_ref()
406            .and_then(|color| try_parse_color(color).ok()),
407        text_disabled: this
408            .text_disabled
409            .as_ref()
410            .and_then(|color| try_parse_color(color).ok()),
411        text_accent: this
412            .text_accent
413            .as_ref()
414            .and_then(|color| try_parse_color(color).ok()),
415        icon: this
416            .icon
417            .as_ref()
418            .and_then(|color| try_parse_color(color).ok()),
419        icon_muted: this
420            .icon_muted
421            .as_ref()
422            .and_then(|color| try_parse_color(color).ok()),
423        icon_disabled: this
424            .icon_disabled
425            .as_ref()
426            .and_then(|color| try_parse_color(color).ok()),
427        icon_placeholder: this
428            .icon_placeholder
429            .as_ref()
430            .and_then(|color| try_parse_color(color).ok()),
431        icon_accent: this
432            .icon_accent
433            .as_ref()
434            .and_then(|color| try_parse_color(color).ok()),
435        debugger_accent: this
436            .debugger_accent
437            .as_ref()
438            .and_then(|color| try_parse_color(color).ok()),
439        status_bar_background: this
440            .status_bar_background
441            .as_ref()
442            .and_then(|color| try_parse_color(color).ok()),
443        title_bar_background: this
444            .title_bar_background
445            .as_ref()
446            .and_then(|color| try_parse_color(color).ok()),
447        title_bar_inactive_background: this
448            .title_bar_inactive_background
449            .as_ref()
450            .and_then(|color| try_parse_color(color).ok()),
451        toolbar_background: this
452            .toolbar_background
453            .as_ref()
454            .and_then(|color| try_parse_color(color).ok()),
455        tab_bar_background: this
456            .tab_bar_background
457            .as_ref()
458            .and_then(|color| try_parse_color(color).ok()),
459        tab_inactive_background: this
460            .tab_inactive_background
461            .as_ref()
462            .and_then(|color| try_parse_color(color).ok()),
463        tab_active_background: this
464            .tab_active_background
465            .as_ref()
466            .and_then(|color| try_parse_color(color).ok()),
467        search_match_background,
468        search_active_match_background,
469        panel_background,
470        panel_focused_border: this
471            .panel_focused_border
472            .as_ref()
473            .and_then(|color| try_parse_color(color).ok()),
474        panel_indent_guide: this
475            .panel_indent_guide
476            .as_ref()
477            .and_then(|color| try_parse_color(color).ok()),
478        panel_indent_guide_hover: this
479            .panel_indent_guide_hover
480            .as_ref()
481            .and_then(|color| try_parse_color(color).ok()),
482        panel_indent_guide_active: this
483            .panel_indent_guide_active
484            .as_ref()
485            .and_then(|color| try_parse_color(color).ok()),
486        panel_overlay_background: this
487            .panel_overlay_background
488            .as_ref()
489            .and_then(|color| try_parse_color(color).ok())
490            .or(panel_background.map(ensure_opaque)),
491        panel_overlay_hover: this
492            .panel_overlay_hover
493            .as_ref()
494            .and_then(|color| try_parse_color(color).ok())
495            .or(panel_background
496                .zip(element_hover)
497                .map(|(panel_bg, hover_bg)| panel_bg.blend(hover_bg))
498                .map(ensure_opaque)),
499        pane_focused_border: this
500            .pane_focused_border
501            .as_ref()
502            .and_then(|color| try_parse_color(color).ok()),
503        pane_group_border: this
504            .pane_group_border
505            .as_ref()
506            .and_then(|color| try_parse_color(color).ok())
507            .or(border),
508        scrollbar_thumb_background,
509        scrollbar_thumb_hover_background,
510        scrollbar_thumb_active_background,
511        scrollbar_thumb_border,
512        scrollbar_track_background: this
513            .scrollbar_track_background
514            .as_ref()
515            .and_then(|color| try_parse_color(color).ok()),
516        scrollbar_track_border: this
517            .scrollbar_track_border
518            .as_ref()
519            .and_then(|color| try_parse_color(color).ok()),
520        minimap_thumb_background: this
521            .minimap_thumb_background
522            .as_ref()
523            .and_then(|color| try_parse_color(color).ok())
524            .or(scrollbar_thumb_background.map(ensure_non_opaque)),
525        minimap_thumb_hover_background: this
526            .minimap_thumb_hover_background
527            .as_ref()
528            .and_then(|color| try_parse_color(color).ok())
529            .or(scrollbar_thumb_hover_background.map(ensure_non_opaque)),
530        minimap_thumb_active_background: this
531            .minimap_thumb_active_background
532            .as_ref()
533            .and_then(|color| try_parse_color(color).ok())
534            .or(scrollbar_thumb_active_background.map(ensure_non_opaque)),
535        minimap_thumb_border: this
536            .minimap_thumb_border
537            .as_ref()
538            .and_then(|color| try_parse_color(color).ok())
539            .or(scrollbar_thumb_border),
540        editor_foreground: this
541            .editor_foreground
542            .as_ref()
543            .and_then(|color| try_parse_color(color).ok()),
544        editor_background: this
545            .editor_background
546            .as_ref()
547            .and_then(|color| try_parse_color(color).ok()),
548        editor_gutter_background: this
549            .editor_gutter_background
550            .as_ref()
551            .and_then(|color| try_parse_color(color).ok()),
552        editor_subheader_background: this
553            .editor_subheader_background
554            .as_ref()
555            .and_then(|color| try_parse_color(color).ok()),
556        editor_active_line_background: this
557            .editor_active_line_background
558            .as_ref()
559            .and_then(|color| try_parse_color(color).ok()),
560        editor_highlighted_line_background: this
561            .editor_highlighted_line_background
562            .as_ref()
563            .and_then(|color| try_parse_color(color).ok()),
564        editor_debugger_active_line_background: this
565            .editor_debugger_active_line_background
566            .as_ref()
567            .and_then(|color| try_parse_color(color).ok()),
568        editor_line_number: this
569            .editor_line_number
570            .as_ref()
571            .and_then(|color| try_parse_color(color).ok()),
572        editor_hover_line_number: this
573            .editor_hover_line_number
574            .as_ref()
575            .and_then(|color| try_parse_color(color).ok()),
576        editor_active_line_number: this
577            .editor_active_line_number
578            .as_ref()
579            .and_then(|color| try_parse_color(color).ok()),
580        editor_invisible: this
581            .editor_invisible
582            .as_ref()
583            .and_then(|color| try_parse_color(color).ok()),
584        editor_wrap_guide: this
585            .editor_wrap_guide
586            .as_ref()
587            .and_then(|color| try_parse_color(color).ok()),
588        editor_active_wrap_guide: this
589            .editor_active_wrap_guide
590            .as_ref()
591            .and_then(|color| try_parse_color(color).ok()),
592        editor_indent_guide: this
593            .editor_indent_guide
594            .as_ref()
595            .and_then(|color| try_parse_color(color).ok()),
596        editor_indent_guide_active: this
597            .editor_indent_guide_active
598            .as_ref()
599            .and_then(|color| try_parse_color(color).ok()),
600        editor_document_highlight_read_background,
601        editor_document_highlight_write_background: this
602            .editor_document_highlight_write_background
603            .as_ref()
604            .and_then(|color| try_parse_color(color).ok()),
605        editor_document_highlight_bracket_background: this
606            .editor_document_highlight_bracket_background
607            .as_ref()
608            .and_then(|color| try_parse_color(color).ok())
609            .or(editor_document_highlight_read_background),
610        editor_diff_hunk_added_background: this
611            .editor_diff_hunk_added_background
612            .as_ref()
613            .and_then(|color| try_parse_color(color).ok())
614            .or_else(|| version_control_added.map(|c| c.opacity(hunk_fill))),
615        editor_diff_hunk_added_hollow_background: this
616            .editor_diff_hunk_added_hollow_background
617            .as_ref()
618            .and_then(|color| try_parse_color(color).ok())
619            .or_else(|| version_control_added.map(|c| c.opacity(hunk_hollow_bg))),
620        editor_diff_hunk_added_hollow_border: this
621            .editor_diff_hunk_added_hollow_border
622            .as_ref()
623            .and_then(|color| try_parse_color(color).ok())
624            .or_else(|| version_control_added.map(|c| c.opacity(hunk_hollow_border))),
625        editor_diff_hunk_deleted_background: this
626            .editor_diff_hunk_deleted_background
627            .as_ref()
628            .and_then(|color| try_parse_color(color).ok())
629            .or_else(|| version_control_deleted.map(|c| c.opacity(hunk_fill))),
630        editor_diff_hunk_deleted_hollow_background: this
631            .editor_diff_hunk_deleted_hollow_background
632            .as_ref()
633            .and_then(|color| try_parse_color(color).ok())
634            .or_else(|| version_control_deleted.map(|c| c.opacity(hunk_hollow_bg))),
635        editor_diff_hunk_deleted_hollow_border: this
636            .editor_diff_hunk_deleted_hollow_border
637            .as_ref()
638            .and_then(|color| try_parse_color(color).ok())
639            .or_else(|| version_control_deleted.map(|c| c.opacity(hunk_hollow_border))),
640        terminal_background: this
641            .terminal_background
642            .as_ref()
643            .and_then(|color| try_parse_color(color).ok()),
644        terminal_ansi_background: this
645            .terminal_ansi_background
646            .as_ref()
647            .and_then(|color| try_parse_color(color).ok()),
648        terminal_foreground: this
649            .terminal_foreground
650            .as_ref()
651            .and_then(|color| try_parse_color(color).ok()),
652        terminal_bright_foreground: this
653            .terminal_bright_foreground
654            .as_ref()
655            .and_then(|color| try_parse_color(color).ok()),
656        terminal_dim_foreground: this
657            .terminal_dim_foreground
658            .as_ref()
659            .and_then(|color| try_parse_color(color).ok()),
660        terminal_ansi_black: this
661            .terminal_ansi_black
662            .as_ref()
663            .and_then(|color| try_parse_color(color).ok()),
664        terminal_ansi_bright_black: this
665            .terminal_ansi_bright_black
666            .as_ref()
667            .and_then(|color| try_parse_color(color).ok()),
668        terminal_ansi_dim_black: this
669            .terminal_ansi_dim_black
670            .as_ref()
671            .and_then(|color| try_parse_color(color).ok()),
672        terminal_ansi_red: this
673            .terminal_ansi_red
674            .as_ref()
675            .and_then(|color| try_parse_color(color).ok()),
676        terminal_ansi_bright_red: this
677            .terminal_ansi_bright_red
678            .as_ref()
679            .and_then(|color| try_parse_color(color).ok()),
680        terminal_ansi_dim_red: this
681            .terminal_ansi_dim_red
682            .as_ref()
683            .and_then(|color| try_parse_color(color).ok()),
684        terminal_ansi_green: this
685            .terminal_ansi_green
686            .as_ref()
687            .and_then(|color| try_parse_color(color).ok()),
688        terminal_ansi_bright_green: this
689            .terminal_ansi_bright_green
690            .as_ref()
691            .and_then(|color| try_parse_color(color).ok()),
692        terminal_ansi_dim_green: this
693            .terminal_ansi_dim_green
694            .as_ref()
695            .and_then(|color| try_parse_color(color).ok()),
696        terminal_ansi_yellow: this
697            .terminal_ansi_yellow
698            .as_ref()
699            .and_then(|color| try_parse_color(color).ok()),
700        terminal_ansi_bright_yellow: this
701            .terminal_ansi_bright_yellow
702            .as_ref()
703            .and_then(|color| try_parse_color(color).ok()),
704        terminal_ansi_dim_yellow: this
705            .terminal_ansi_dim_yellow
706            .as_ref()
707            .and_then(|color| try_parse_color(color).ok()),
708        terminal_ansi_blue: this
709            .terminal_ansi_blue
710            .as_ref()
711            .and_then(|color| try_parse_color(color).ok()),
712        terminal_ansi_bright_blue: this
713            .terminal_ansi_bright_blue
714            .as_ref()
715            .and_then(|color| try_parse_color(color).ok()),
716        terminal_ansi_dim_blue: this
717            .terminal_ansi_dim_blue
718            .as_ref()
719            .and_then(|color| try_parse_color(color).ok()),
720        terminal_ansi_magenta: this
721            .terminal_ansi_magenta
722            .as_ref()
723            .and_then(|color| try_parse_color(color).ok()),
724        terminal_ansi_bright_magenta: this
725            .terminal_ansi_bright_magenta
726            .as_ref()
727            .and_then(|color| try_parse_color(color).ok()),
728        terminal_ansi_dim_magenta: this
729            .terminal_ansi_dim_magenta
730            .as_ref()
731            .and_then(|color| try_parse_color(color).ok()),
732        terminal_ansi_cyan: this
733            .terminal_ansi_cyan
734            .as_ref()
735            .and_then(|color| try_parse_color(color).ok()),
736        terminal_ansi_bright_cyan: this
737            .terminal_ansi_bright_cyan
738            .as_ref()
739            .and_then(|color| try_parse_color(color).ok()),
740        terminal_ansi_dim_cyan: this
741            .terminal_ansi_dim_cyan
742            .as_ref()
743            .and_then(|color| try_parse_color(color).ok()),
744        terminal_ansi_white: this
745            .terminal_ansi_white
746            .as_ref()
747            .and_then(|color| try_parse_color(color).ok()),
748        terminal_ansi_bright_white: this
749            .terminal_ansi_bright_white
750            .as_ref()
751            .and_then(|color| try_parse_color(color).ok()),
752        terminal_ansi_dim_white: this
753            .terminal_ansi_dim_white
754            .as_ref()
755            .and_then(|color| try_parse_color(color).ok()),
756        link_text_hover: this
757            .link_text_hover
758            .as_ref()
759            .and_then(|color| try_parse_color(color).ok()),
760        version_control_added,
761        version_control_deleted,
762        version_control_modified: this
763            .version_control_modified
764            .as_ref()
765            .and_then(|color| try_parse_color(color).ok())
766            .or(status_colors.modified),
767        version_control_renamed: this
768            .version_control_renamed
769            .as_ref()
770            .and_then(|color| try_parse_color(color).ok())
771            .or(status_colors.modified),
772        version_control_conflict: this
773            .version_control_conflict
774            .as_ref()
775            .and_then(|color| try_parse_color(color).ok())
776            .or(status_colors.ignored),
777        version_control_ignored: this
778            .version_control_ignored
779            .as_ref()
780            .and_then(|color| try_parse_color(color).ok())
781            .or(status_colors.ignored),
782        version_control_word_added: this
783            .version_control_word_added
784            .as_ref()
785            .and_then(|color| try_parse_color(color).ok()),
786        version_control_word_deleted: this
787            .version_control_word_deleted
788            .as_ref()
789            .and_then(|color| try_parse_color(color).ok()),
790        #[allow(deprecated)]
791        version_control_conflict_marker_ours: this
792            .version_control_conflict_marker_ours
793            .as_ref()
794            .or(this.version_control_conflict_ours_background.as_ref())
795            .and_then(|color| try_parse_color(color).ok()),
796        #[allow(deprecated)]
797        version_control_conflict_marker_theirs: this
798            .version_control_conflict_marker_theirs
799            .as_ref()
800            .or(this.version_control_conflict_theirs_background.as_ref())
801            .and_then(|color| try_parse_color(color).ok()),
802        vim_normal_background: this
803            .vim_normal_background
804            .as_ref()
805            .and_then(|color| try_parse_color(color).ok()),
806        vim_insert_background: this
807            .vim_insert_background
808            .as_ref()
809            .and_then(|color| try_parse_color(color).ok()),
810        vim_replace_background: this
811            .vim_replace_background
812            .as_ref()
813            .and_then(|color| try_parse_color(color).ok()),
814        vim_visual_background: this
815            .vim_visual_background
816            .as_ref()
817            .and_then(|color| try_parse_color(color).ok()),
818        vim_visual_line_background: this
819            .vim_visual_line_background
820            .as_ref()
821            .and_then(|color| try_parse_color(color).ok()),
822        vim_visual_block_background: this
823            .vim_visual_block_background
824            .as_ref()
825            .and_then(|color| try_parse_color(color).ok()),
826        vim_yank_background: this
827            .vim_yank_background
828            .as_ref()
829            .and_then(|color| try_parse_color(color).ok())
830            .or(editor_document_highlight_read_background),
831        vim_helix_jump_label_foreground: this
832            .vim_helix_jump_label_foreground
833            .as_ref()
834            .and_then(|color| try_parse_color(color).ok())
835            .or(status_colors.error),
836        vim_helix_normal_background: this
837            .vim_helix_normal_background
838            .as_ref()
839            .and_then(|color| try_parse_color(color).ok()),
840        vim_helix_select_background: this
841            .vim_helix_select_background
842            .as_ref()
843            .and_then(|color| try_parse_color(color).ok()),
844        vim_normal_foreground: this
845            .vim_normal_foreground
846            .as_ref()
847            .and_then(|color| try_parse_color(color).ok()),
848        vim_insert_foreground: this
849            .vim_insert_foreground
850            .as_ref()
851            .and_then(|color| try_parse_color(color).ok()),
852        vim_replace_foreground: this
853            .vim_replace_foreground
854            .as_ref()
855            .and_then(|color| try_parse_color(color).ok()),
856        vim_visual_foreground: this
857            .vim_visual_foreground
858            .as_ref()
859            .and_then(|color| try_parse_color(color).ok()),
860        vim_visual_line_foreground: this
861            .vim_visual_line_foreground
862            .as_ref()
863            .and_then(|color| try_parse_color(color).ok()),
864        vim_visual_block_foreground: this
865            .vim_visual_block_foreground
866            .as_ref()
867            .and_then(|color| try_parse_color(color).ok()),
868        vim_helix_normal_foreground: this
869            .vim_helix_normal_foreground
870            .as_ref()
871            .and_then(|color| try_parse_color(color).ok()),
872        vim_helix_select_foreground: this
873            .vim_helix_select_foreground
874            .as_ref()
875            .and_then(|color| try_parse_color(color).ok()),
876    }
877}
878
879fn ensure_non_opaque(color: Hsla) -> Hsla {
880    const MAXIMUM_OPACITY: f32 = 0.7;
881    if color.a <= MAXIMUM_OPACITY {
882        color
883    } else {
884        Hsla {
885            a: MAXIMUM_OPACITY,
886            ..color
887        }
888    }
889}
890
891fn ensure_opaque(color: Hsla) -> Hsla {
892    Hsla { a: 1.0, ..color }
893}
894
895fn try_parse_color(color: &str) -> anyhow::Result<Hsla> {
896    let rgba = gpui::Rgba::try_from(color)?;
897    let rgba = palette::rgb::Srgba::from_components((rgba.r, rgba.g, rgba.b, rgba.a));
898    let hsla = palette::Hsla::from_color(rgba);
899
900    let hsla = gpui::hsla(
901        hsla.hue.into_positive_degrees() / 360.,
902        hsla.saturation,
903        hsla.lightness,
904        hsla.alpha,
905    );
906
907    Ok(hsla)
908}
909
910#[cfg(test)]
911mod tests {
912    use theme::StatusColorsRefinement;
913
914    use super::{
915        StatusColorsContent, ThemeColorsContent, status_colors_refinement, theme_colors_refinement,
916        try_parse_color,
917    };
918
919    #[test]
920    fn explicit_diff_hunk_colors_take_precedence_over_fallbacks() {
921        let mut colors = ThemeColorsContent::default();
922        colors.editor_diff_hunk_added_background = Some("#112233".to_string());
923        colors.editor_diff_hunk_added_hollow_background = Some("#223344".to_string());
924        colors.editor_diff_hunk_added_hollow_border = Some("#334455".to_string());
925        colors.editor_diff_hunk_deleted_background = Some("#445566".to_string());
926        colors.editor_diff_hunk_deleted_hollow_background = Some("#556677".to_string());
927        colors.editor_diff_hunk_deleted_hollow_border = Some("#667788".to_string());
928        colors.version_control_added = Some("#00ff00".to_string());
929        colors.version_control_deleted = Some("#ff0000".to_string());
930
931        let refinement = theme_colors_refinement(
932            &colors,
933            &status_colors_refinement(&StatusColorsContent::default()),
934            true,
935        );
936
937        assert_eq!(
938            refinement.editor_diff_hunk_added_background,
939            Some(parse_color("#112233"))
940        );
941        assert_eq!(
942            refinement.editor_diff_hunk_added_hollow_background,
943            Some(parse_color("#223344"))
944        );
945        assert_eq!(
946            refinement.editor_diff_hunk_added_hollow_border,
947            Some(parse_color("#334455"))
948        );
949        assert_eq!(
950            refinement.editor_diff_hunk_deleted_background,
951            Some(parse_color("#445566"))
952        );
953        assert_eq!(
954            refinement.editor_diff_hunk_deleted_hollow_background,
955            Some(parse_color("#556677"))
956        );
957        assert_eq!(
958            refinement.editor_diff_hunk_deleted_hollow_border,
959            Some(parse_color("#667788"))
960        );
961    }
962
963    #[test]
964    fn diff_hunk_colors_fallback_to_version_control_colors() {
965        let mut colors = ThemeColorsContent::default();
966        colors.version_control_added = Some("#00ff00".to_string());
967        colors.version_control_deleted = Some("#ff0000".to_string());
968
969        let refinement = theme_colors_refinement(
970            &colors,
971            &status_colors_refinement(&StatusColorsContent::default()),
972            true,
973        );
974
975        let added = parse_color("#00ff00");
976        let deleted = parse_color("#ff0000");
977
978        assert_eq!(
979            refinement.editor_diff_hunk_added_background,
980            Some(added.opacity(0.16))
981        );
982        assert_eq!(
983            refinement.editor_diff_hunk_added_hollow_background,
984            Some(added.opacity(0.08))
985        );
986        assert_eq!(
987            refinement.editor_diff_hunk_added_hollow_border,
988            Some(added.opacity(0.48))
989        );
990        assert_eq!(
991            refinement.editor_diff_hunk_deleted_background,
992            Some(deleted.opacity(0.16))
993        );
994        assert_eq!(
995            refinement.editor_diff_hunk_deleted_hollow_background,
996            Some(deleted.opacity(0.08))
997        );
998        assert_eq!(
999            refinement.editor_diff_hunk_deleted_hollow_border,
1000            Some(deleted.opacity(0.48))
1001        );
1002    }
1003
1004    #[test]
1005    fn diff_hunk_opacity_fallbacks_use_correct_values_for_light_and_dark_themes() {
1006        let mut colors = ThemeColorsContent::default();
1007        colors.version_control_added = Some("#00ff00".to_string());
1008
1009        let light_refinement = theme_colors_refinement(
1010            &colors,
1011            &status_colors_refinement(&StatusColorsContent::default()),
1012            true,
1013        );
1014        let dark_refinement = theme_colors_refinement(
1015            &colors,
1016            &status_colors_refinement(&StatusColorsContent::default()),
1017            false,
1018        );
1019
1020        let added = parse_color("#00ff00");
1021
1022        assert_eq!(
1023            light_refinement.editor_diff_hunk_added_background,
1024            Some(added.opacity(0.16))
1025        );
1026        assert_eq!(
1027            light_refinement.editor_diff_hunk_added_hollow_background,
1028            Some(added.opacity(0.08))
1029        );
1030        assert_eq!(
1031            light_refinement.editor_diff_hunk_added_hollow_border,
1032            Some(added.opacity(0.48))
1033        );
1034
1035        assert_eq!(
1036            dark_refinement.editor_diff_hunk_added_background,
1037            Some(added.opacity(0.12))
1038        );
1039        assert_eq!(
1040            dark_refinement.editor_diff_hunk_added_hollow_background,
1041            Some(added.opacity(0.06))
1042        );
1043        assert_eq!(
1044            dark_refinement.editor_diff_hunk_added_hollow_border,
1045            Some(added.opacity(0.36))
1046        );
1047    }
1048
1049    #[test]
1050    fn diff_hunk_fallbacks_are_absent_when_status_and_version_control_colors_are_missing() {
1051        let refinement = theme_colors_refinement(
1052            &ThemeColorsContent::default(),
1053            &status_colors_refinement(&StatusColorsContent::default()),
1054            true,
1055        );
1056
1057        assert_eq!(refinement.editor_diff_hunk_added_background, None);
1058        assert_eq!(refinement.editor_diff_hunk_added_hollow_background, None);
1059        assert_eq!(refinement.editor_diff_hunk_added_hollow_border, None);
1060        assert_eq!(refinement.editor_diff_hunk_deleted_background, None);
1061        assert_eq!(refinement.editor_diff_hunk_deleted_hollow_background, None);
1062        assert_eq!(refinement.editor_diff_hunk_deleted_hollow_border, None);
1063    }
1064
1065    fn parse_color(color: &str) -> gpui::Hsla {
1066        match try_parse_color(color) {
1067            Ok(color) => color,
1068            Err(error) => panic!("failed to parse color {color}: {error}"),
1069        }
1070    }
1071
1072    #[test]
1073    fn helix_jump_label_color_uses_theme_color_or_status_error() {
1074        let status_error = try_parse_color("#e63333").expect("valid color");
1075        let override_color = try_parse_color("#00ff00").expect("valid color");
1076        let status_colors = StatusColorsRefinement {
1077            error: Some(status_error),
1078            ..Default::default()
1079        };
1080
1081        let fallback_refinement = theme_colors_refinement(
1082            &ThemeColorsContent::default(),
1083            &status_colors,
1084            Default::default(),
1085        );
1086
1087        assert_eq!(
1088            fallback_refinement.vim_helix_jump_label_foreground,
1089            Some(status_error)
1090        );
1091
1092        let override_refinement = theme_colors_refinement(
1093            &ThemeColorsContent {
1094                vim_helix_jump_label_foreground: Some("#00ff00".to_string()),
1095                ..Default::default()
1096            },
1097            &status_colors,
1098            Default::default(),
1099        );
1100
1101        assert_eq!(
1102            override_refinement.vim_helix_jump_label_foreground,
1103            Some(override_color)
1104        );
1105    }
1106}
1107
Served at tenant.openagents/omega Member data and write actions are omitted.