1use collections::{HashMap, IndexMap};
2use gpui::{FontFallbacks, FontFeatures, FontStyle, FontWeight};
3use schemars::{JsonSchema, JsonSchema_repr};
4use serde::{Deserialize, Deserializer, Serialize};
5use serde_json::Value;
6use serde_repr::{Deserialize_repr, Serialize_repr};
7use std::sync::Arc;
8
9/// Settings for rendering text in UI and text buffers.
10#[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize, JsonSchema)]
11pub struct ThemeSettingsContent {
12 /// The default font size for text in the UI.
13 #[serde(default)]
14 pub ui_font_size: Option<f32>,
15 /// The name of a font to use for rendering in the UI.
16 #[serde(default)]
17 pub ui_font_family: Option<FontFamilyName>,
18 /// The font fallbacks to use for rendering in the UI.
19 #[serde(default)]
20 #[schemars(default = "default_font_fallbacks")]
21 #[schemars(extend("uniqueItems" = true))]
22 pub ui_font_fallbacks: Option<Vec<FontFamilyName>>,
23 /// The OpenType features to enable for text in the UI.
24 #[serde(default)]
25 #[schemars(default = "default_font_features")]
26 pub ui_font_features: Option<FontFeatures>,
27 /// The weight of the UI font in CSS units from 100 to 900.
28 #[serde(default)]
29 pub ui_font_weight: Option<f32>,
30 /// The name of a font to use for rendering in text buffers.
31 #[serde(default)]
32 pub buffer_font_family: Option<FontFamilyName>,
33 /// The font fallbacks to use for rendering in text buffers.
34 #[serde(default)]
35 #[schemars(extend("uniqueItems" = true))]
36 pub buffer_font_fallbacks: Option<Vec<FontFamilyName>>,
37 /// The default font size for rendering in text buffers.
38 #[serde(default)]
39 pub buffer_font_size: Option<f32>,
40 /// The weight of the editor font in CSS units from 100 to 900.
41 #[serde(default)]
42 pub buffer_font_weight: Option<f32>,
43 /// The buffer's line height.
44 #[serde(default)]
45 pub buffer_line_height: Option<BufferLineHeight>,
46 /// The OpenType features to enable for rendering in text buffers.
47 #[serde(default)]
48 #[schemars(default = "default_font_features")]
49 pub buffer_font_features: Option<FontFeatures>,
50 /// The font size for the agent panel. Falls back to the UI font size if unset.
51 #[serde(default)]
52 pub agent_font_size: Option<Option<f32>>,
53 /// The name of the Zed theme to use.
54 #[serde(default)]
55 pub theme: Option<ThemeSelection>,
56 /// The name of the icon theme to use.
57 #[serde(default)]
58 pub icon_theme: Option<IconThemeSelection>,
59
60 /// UNSTABLE: Expect many elements to be broken.
61 ///
62 // Controls the density of the UI.
63 #[serde(rename = "unstable.ui_density", default)]
64 pub ui_density: Option<UiDensity>,
65
66 /// How much to fade out unused code.
67 #[serde(default)]
68 pub unnecessary_code_fade: Option<f32>,
69
70 /// EXPERIMENTAL: Overrides for the current theme.
71 ///
72 /// These values will override the ones on the current theme specified in `theme`.
73 #[serde(rename = "experimental.theme_overrides", default)]
74 pub experimental_theme_overrides: Option<ThemeStyleContent>,
75
76 /// Overrides per theme
77 ///
78 /// These values will override the ones on the specified theme
79 #[serde(default)]
80 pub theme_overrides: HashMap<String, ThemeStyleContent>,
81}
82
83fn default_font_features() -> Option<FontFeatures> {
84 Some(FontFeatures::default())
85}
86
87fn default_font_fallbacks() -> Option<FontFallbacks> {
88 Some(FontFallbacks::default())
89}
90
91/// Represents the selection of a theme, which can be either static or dynamic.
92#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
93#[serde(untagged)]
94pub enum ThemeSelection {
95 /// A static theme selection, represented by a single theme name.
96 Static(ThemeName),
97 /// A dynamic theme selection, which can change based the [ThemeMode].
98 Dynamic {
99 /// The mode used to determine which theme to use.
100 #[serde(default)]
101 mode: ThemeMode,
102 /// The theme to use for light mode.
103 light: ThemeName,
104 /// The theme to use for dark mode.
105 dark: ThemeName,
106 },
107}
108
109/// Represents the selection of an icon theme, which can be either static or dynamic.
110#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
111#[serde(untagged)]
112pub enum IconThemeSelection {
113 /// A static icon theme selection, represented by a single icon theme name.
114 Static(IconThemeName),
115 /// A dynamic icon theme selection, which can change based on the [`ThemeMode`].
116 Dynamic {
117 /// The mode used to determine which theme to use.
118 #[serde(default)]
119 mode: ThemeMode,
120 /// The icon theme to use for light mode.
121 light: IconThemeName,
122 /// The icon theme to use for dark mode.
123 dark: IconThemeName,
124 },
125}
126
127// TODO: Rename ThemeMode -> ThemeAppearanceMode
128/// The mode use to select a theme.
129///
130/// `Light` and `Dark` will select their respective themes.
131///
132/// `System` will select the theme based on the system's appearance.
133#[derive(Debug, PartialEq, Eq, Clone, Copy, Default, Serialize, Deserialize, JsonSchema)]
134#[serde(rename_all = "snake_case")]
135pub enum ThemeMode {
136 /// Use the specified `light` theme.
137 Light,
138
139 /// Use the specified `dark` theme.
140 Dark,
141
142 /// Use the theme based on the system's appearance.
143 #[default]
144 System,
145}
146
147/// Specifies the density of the UI.
148/// Note: This setting is still experimental. See [this tracking issue](https://github.com/zed-industries/zed/issues/18078)
149#[derive(
150 Debug,
151 Default,
152 PartialEq,
153 Eq,
154 PartialOrd,
155 Ord,
156 Hash,
157 Clone,
158 Copy,
159 Serialize,
160 Deserialize,
161 JsonSchema,
162)]
163#[serde(rename_all = "snake_case")]
164pub enum UiDensity {
165 /// A denser UI with tighter spacing and smaller elements.
166 #[serde(alias = "compact")]
167 Compact,
168 #[default]
169 #[serde(alias = "default")]
170 /// The default UI density.
171 Default,
172 #[serde(alias = "comfortable")]
173 /// A looser UI with more spacing and larger elements.
174 Comfortable,
175}
176
177impl UiDensity {
178 /// The spacing ratio of a given density.
179 /// TODO: Standardize usage throughout the app or remove
180 pub fn spacing_ratio(self) -> f32 {
181 match self {
182 UiDensity::Compact => 0.75,
183 UiDensity::Default => 1.0,
184 UiDensity::Comfortable => 1.25,
185 }
186 }
187}
188
189/// Newtype for font family name. Its `ParameterizedJsonSchema` lists the font families known at
190/// runtime.
191#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
192#[serde(transparent)]
193pub struct FontFamilyName(pub Arc<str>);
194
195/// The buffer's line height.
196#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, JsonSchema, Default)]
197#[serde(rename_all = "snake_case")]
198pub enum BufferLineHeight {
199 /// A less dense line height.
200 #[default]
201 Comfortable,
202 /// The default line height.
203 Standard,
204 /// A custom line height, where 1.0 is the font's height. Must be at least 1.0.
205 Custom(#[serde(deserialize_with = "deserialize_line_height")] f32),
206}
207
208fn deserialize_line_height<'de, D>(deserializer: D) -> Result<f32, D::Error>
209where
210 D: serde::Deserializer<'de>,
211{
212 let value = f32::deserialize(deserializer)?;
213 if value < 1.0 {
214 return Err(serde::de::Error::custom(
215 "buffer_line_height.custom must be at least 1.0",
216 ));
217 }
218
219 Ok(value)
220}
221
222/// The content of a serialized theme.
223#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema, PartialEq)]
224#[serde(default)]
225pub struct ThemeStyleContent {
226 #[serde(default, rename = "background.appearance")]
227 pub window_background_appearance: Option<WindowBackgroundContent>,
228
229 #[serde(default)]
230 pub accents: Vec<AccentContent>,
231
232 #[serde(flatten, default)]
233 pub colors: ThemeColorsContent,
234
235 #[serde(flatten, default)]
236 pub status: StatusColorsContent,
237
238 #[serde(default)]
239 pub players: Vec<PlayerColorContent>,
240
241 /// The styles for syntax nodes.
242 #[serde(default)]
243 pub syntax: IndexMap<String, HighlightStyleContent>,
244}
245
246#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
247pub struct AccentContent(pub Option<String>);
248
249#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
250pub struct PlayerColorContent {
251 pub cursor: Option<String>,
252 pub background: Option<String>,
253 pub selection: Option<String>,
254}
255
256/// Newtype for a theme name. Its `ParameterizedJsonSchema` lists the theme names known at runtime.
257#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
258#[serde(transparent)]
259pub struct ThemeName(pub Arc<str>);
260
261/// Newtype for a icon theme name. Its `ParameterizedJsonSchema` lists the icon theme names known at
262/// runtime.
263#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
264#[serde(transparent)]
265pub struct IconThemeName(pub Arc<str>);
266
267#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema, PartialEq)]
268#[serde(default)]
269pub struct ThemeColorsContent {
270 /// Border color. Used for most borders, is usually a high contrast color.
271 #[serde(rename = "border")]
272 pub border: Option<String>,
273
274 /// Border color. Used for deemphasized borders, like a visual divider between two sections
275 #[serde(rename = "border.variant")]
276 pub border_variant: Option<String>,
277
278 /// Border color. Used for focused elements, like keyboard focused list item.
279 #[serde(rename = "border.focused")]
280 pub border_focused: Option<String>,
281
282 /// Border color. Used for selected elements, like an active search filter or selected checkbox.
283 #[serde(rename = "border.selected")]
284 pub border_selected: Option<String>,
285
286 /// Border color. Used for transparent borders. Used for placeholder borders when an element gains a border on state change.
287 #[serde(rename = "border.transparent")]
288 pub border_transparent: Option<String>,
289
290 /// Border color. Used for disabled elements, like a disabled input or button.
291 #[serde(rename = "border.disabled")]
292 pub border_disabled: Option<String>,
293
294 /// Background color. Used for elevated surfaces, like a context menu, popup, or dialog.
295 #[serde(rename = "elevated_surface.background")]
296 pub elevated_surface_background: Option<String>,
297
298 /// Background Color. Used for grounded surfaces like a panel or tab.
299 #[serde(rename = "surface.background")]
300 pub surface_background: Option<String>,
301
302 /// Background Color. Used for the app background and blank panels or windows.
303 #[serde(rename = "background")]
304 pub background: Option<String>,
305
306 /// Background Color. Used for the background of an element that should have a different background than the surface it's on.
307 ///
308 /// Elements might include: Buttons, Inputs, Checkboxes, Radio Buttons...
309 ///
310 /// For an element that should have the same background as the surface it's on, use `ghost_element_background`.
311 #[serde(rename = "element.background")]
312 pub element_background: Option<String>,
313
314 /// Background Color. Used for the hover state of an element that should have a different background than the surface it's on.
315 ///
316 /// Hover states are triggered by the mouse entering an element, or a finger touching an element on a touch screen.
317 #[serde(rename = "element.hover")]
318 pub element_hover: Option<String>,
319
320 /// Background Color. Used for the active state of an element that should have a different background than the surface it's on.
321 ///
322 /// Active states are triggered by the mouse button being pressed down on an element, or the Return button or other activator being pressed.
323 #[serde(rename = "element.active")]
324 pub element_active: Option<String>,
325
326 /// Background Color. Used for the selected state of an element that should have a different background than the surface it's on.
327 ///
328 /// Selected states are triggered by the element being selected (or "activated") by the user.
329 ///
330 /// This could include a selected checkbox, a toggleable button that is toggled on, etc.
331 #[serde(rename = "element.selected")]
332 pub element_selected: Option<String>,
333
334 /// Background Color. Used for the disabled state of an element that should have a different background than the surface it's on.
335 ///
336 /// Disabled states are shown when a user cannot interact with an element, like a disabled button or input.
337 #[serde(rename = "element.disabled")]
338 pub element_disabled: Option<String>,
339
340 /// Background Color. Used for the background of selections in a UI element.
341 #[serde(rename = "element.selection_background")]
342 pub element_selection_background: Option<String>,
343
344 /// Background Color. Used for the area that shows where a dragged element will be dropped.
345 #[serde(rename = "drop_target.background")]
346 pub drop_target_background: Option<String>,
347
348 /// Border Color. Used for the border that shows where a dragged element will be dropped.
349 #[serde(rename = "drop_target.border")]
350 pub drop_target_border: Option<String>,
351
352 /// Used for the background of a ghost element that should have the same background as the surface it's on.
353 ///
354 /// Elements might include: Buttons, Inputs, Checkboxes, Radio Buttons...
355 ///
356 /// For an element that should have a different background than the surface it's on, use `element_background`.
357 #[serde(rename = "ghost_element.background")]
358 pub ghost_element_background: Option<String>,
359
360 /// Background Color. Used for the hover state of a ghost element that should have the same background as the surface it's on.
361 ///
362 /// Hover states are triggered by the mouse entering an element, or a finger touching an element on a touch screen.
363 #[serde(rename = "ghost_element.hover")]
364 pub ghost_element_hover: Option<String>,
365
366 /// Background Color. Used for the active state of a ghost element that should have the same background as the surface it's on.
367 ///
368 /// Active states are triggered by the mouse button being pressed down on an element, or the Return button or other activator being pressed.
369 #[serde(rename = "ghost_element.active")]
370 pub ghost_element_active: Option<String>,
371
372 /// Background Color. Used for the selected state of a ghost element that should have the same background as the surface it's on.
373 ///
374 /// Selected states are triggered by the element being selected (or "activated") by the user.
375 ///
376 /// This could include a selected checkbox, a toggleable button that is toggled on, etc.
377 #[serde(rename = "ghost_element.selected")]
378 pub ghost_element_selected: Option<String>,
379
380 /// Background Color. Used for the disabled state of a ghost element that should have the same background as the surface it's on.
381 ///
382 /// Disabled states are shown when a user cannot interact with an element, like a disabled button or input.
383 #[serde(rename = "ghost_element.disabled")]
384 pub ghost_element_disabled: Option<String>,
385
386 /// Text Color. Default text color used for most text.
387 #[serde(rename = "text")]
388 pub text: Option<String>,
389
390 /// Text Color. Color of muted or deemphasized text. It is a subdued version of the standard text color.
391 #[serde(rename = "text.muted")]
392 pub text_muted: Option<String>,
393
394 /// Text Color. Color of the placeholder text typically shown in input fields to guide the user to enter valid data.
395 #[serde(rename = "text.placeholder")]
396 pub text_placeholder: Option<String>,
397
398 /// Text Color. Color used for text denoting disabled elements. Typically, the color is faded or grayed out to emphasize the disabled state.
399 #[serde(rename = "text.disabled")]
400 pub text_disabled: Option<String>,
401
402 /// Text Color. Color used for emphasis or highlighting certain text, like an active filter or a matched character in a search.
403 #[serde(rename = "text.accent")]
404 pub text_accent: Option<String>,
405
406 /// Fill Color. Used for the default fill color of an icon.
407 #[serde(rename = "icon")]
408 pub icon: Option<String>,
409
410 /// Fill Color. Used for the muted or deemphasized fill color of an icon.
411 ///
412 /// 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.
413 #[serde(rename = "icon.muted")]
414 pub icon_muted: Option<String>,
415
416 /// Fill Color. Used for the disabled fill color of an icon.
417 ///
418 /// Disabled states are shown when a user cannot interact with an element, like a icon button.
419 #[serde(rename = "icon.disabled")]
420 pub icon_disabled: Option<String>,
421
422 /// Fill Color. Used for the placeholder fill color of an icon.
423 ///
424 /// This might be used to show an icon in an input that disappears when the user enters text.
425 #[serde(rename = "icon.placeholder")]
426 pub icon_placeholder: Option<String>,
427
428 /// Fill Color. Used for the accent fill color of an icon.
429 ///
430 /// This might be used to show when a toggleable icon button is selected.
431 #[serde(rename = "icon.accent")]
432 pub icon_accent: Option<String>,
433
434 /// Color used to accent some of the debuggers elements
435 /// Only accent breakpoint & breakpoint related symbols right now
436 #[serde(rename = "debugger.accent")]
437 pub debugger_accent: Option<String>,
438
439 #[serde(rename = "status_bar.background")]
440 pub status_bar_background: Option<String>,
441
442 #[serde(rename = "title_bar.background")]
443 pub title_bar_background: Option<String>,
444
445 #[serde(rename = "title_bar.inactive_background")]
446 pub title_bar_inactive_background: Option<String>,
447
448 #[serde(rename = "toolbar.background")]
449 pub toolbar_background: Option<String>,
450
451 #[serde(rename = "tab_bar.background")]
452 pub tab_bar_background: Option<String>,
453
454 #[serde(rename = "tab.inactive_background")]
455 pub tab_inactive_background: Option<String>,
456
457 #[serde(rename = "tab.active_background")]
458 pub tab_active_background: Option<String>,
459
460 #[serde(rename = "search.match_background")]
461 pub search_match_background: Option<String>,
462
463 #[serde(rename = "panel.background")]
464 pub panel_background: Option<String>,
465
466 #[serde(rename = "panel.focused_border")]
467 pub panel_focused_border: Option<String>,
468
469 #[serde(rename = "panel.indent_guide")]
470 pub panel_indent_guide: Option<String>,
471
472 #[serde(rename = "panel.indent_guide_hover")]
473 pub panel_indent_guide_hover: Option<String>,
474
475 #[serde(rename = "panel.indent_guide_active")]
476 pub panel_indent_guide_active: Option<String>,
477
478 #[serde(rename = "panel.overlay_background")]
479 pub panel_overlay_background: Option<String>,
480
481 #[serde(rename = "panel.overlay_hover")]
482 pub panel_overlay_hover: Option<String>,
483
484 #[serde(rename = "pane.focused_border")]
485 pub pane_focused_border: Option<String>,
486
487 #[serde(rename = "pane_group.border")]
488 pub pane_group_border: Option<String>,
489
490 /// The deprecated version of `scrollbar.thumb.background`.
491 ///
492 /// Don't use this field.
493 #[serde(rename = "scrollbar_thumb.background", skip_serializing)]
494 #[schemars(skip)]
495 pub deprecated_scrollbar_thumb_background: Option<String>,
496
497 /// The color of the scrollbar thumb.
498 #[serde(rename = "scrollbar.thumb.background")]
499 pub scrollbar_thumb_background: Option<String>,
500
501 /// The color of the scrollbar thumb when hovered over.
502 #[serde(rename = "scrollbar.thumb.hover_background")]
503 pub scrollbar_thumb_hover_background: Option<String>,
504
505 /// The color of the scrollbar thumb whilst being actively dragged.
506 #[serde(rename = "scrollbar.thumb.active_background")]
507 pub scrollbar_thumb_active_background: Option<String>,
508
509 /// The border color of the scrollbar thumb.
510 #[serde(rename = "scrollbar.thumb.border")]
511 pub scrollbar_thumb_border: Option<String>,
512
513 /// The background color of the scrollbar track.
514 #[serde(rename = "scrollbar.track.background")]
515 pub scrollbar_track_background: Option<String>,
516
517 /// The border color of the scrollbar track.
518 #[serde(rename = "scrollbar.track.border")]
519 pub scrollbar_track_border: Option<String>,
520
521 /// The color of the minimap thumb.
522 #[serde(rename = "minimap.thumb.background")]
523 pub minimap_thumb_background: Option<String>,
524
525 /// The color of the minimap thumb when hovered over.
526 #[serde(rename = "minimap.thumb.hover_background")]
527 pub minimap_thumb_hover_background: Option<String>,
528
529 /// The color of the minimap thumb whilst being actively dragged.
530 #[serde(rename = "minimap.thumb.active_background")]
531 pub minimap_thumb_active_background: Option<String>,
532
533 /// The border color of the minimap thumb.
534 #[serde(rename = "minimap.thumb.border")]
535 pub minimap_thumb_border: Option<String>,
536
537 #[serde(rename = "editor.foreground")]
538 pub editor_foreground: Option<String>,
539
540 #[serde(rename = "editor.background")]
541 pub editor_background: Option<String>,
542
543 #[serde(rename = "editor.gutter.background")]
544 pub editor_gutter_background: Option<String>,
545
546 #[serde(rename = "editor.subheader.background")]
547 pub editor_subheader_background: Option<String>,
548
549 #[serde(rename = "editor.active_line.background")]
550 pub editor_active_line_background: Option<String>,
551
552 #[serde(rename = "editor.highlighted_line.background")]
553 pub editor_highlighted_line_background: Option<String>,
554
555 /// Background of active line of debugger
556 #[serde(rename = "editor.debugger_active_line.background")]
557 pub editor_debugger_active_line_background: Option<String>,
558
559 /// Text Color. Used for the text of the line number in the editor gutter.
560 #[serde(rename = "editor.line_number")]
561 pub editor_line_number: Option<String>,
562
563 /// Text Color. Used for the text of the line number in the editor gutter when the line is highlighted.
564 #[serde(rename = "editor.active_line_number")]
565 pub editor_active_line_number: Option<String>,
566
567 /// Text Color. Used for the text of the line number in the editor gutter when the line is hovered over.
568 #[serde(rename = "editor.hover_line_number")]
569 pub editor_hover_line_number: Option<String>,
570
571 /// Text Color. Used to mark invisible characters in the editor.
572 ///
573 /// Example: spaces, tabs, carriage returns, etc.
574 #[serde(rename = "editor.invisible")]
575 pub editor_invisible: Option<String>,
576
577 #[serde(rename = "editor.wrap_guide")]
578 pub editor_wrap_guide: Option<String>,
579
580 #[serde(rename = "editor.active_wrap_guide")]
581 pub editor_active_wrap_guide: Option<String>,
582
583 #[serde(rename = "editor.indent_guide")]
584 pub editor_indent_guide: Option<String>,
585
586 #[serde(rename = "editor.indent_guide_active")]
587 pub editor_indent_guide_active: Option<String>,
588
589 /// Read-access of a symbol, like reading a variable.
590 ///
591 /// A document highlight is a range inside a text document which deserves
592 /// special attention. Usually a document highlight is visualized by changing
593 /// the background color of its range.
594 #[serde(rename = "editor.document_highlight.read_background")]
595 pub editor_document_highlight_read_background: Option<String>,
596
597 /// Read-access of a symbol, like reading a variable.
598 ///
599 /// A document highlight is a range inside a text document which deserves
600 /// special attention. Usually a document highlight is visualized by changing
601 /// the background color of its range.
602 #[serde(rename = "editor.document_highlight.write_background")]
603 pub editor_document_highlight_write_background: Option<String>,
604
605 /// Highlighted brackets background color.
606 ///
607 /// Matching brackets in the cursor scope are highlighted with this background color.
608 #[serde(rename = "editor.document_highlight.bracket_background")]
609 pub editor_document_highlight_bracket_background: Option<String>,
610
611 /// Terminal background color.
612 #[serde(rename = "terminal.background")]
613 pub terminal_background: Option<String>,
614
615 /// Terminal foreground color.
616 #[serde(rename = "terminal.foreground")]
617 pub terminal_foreground: Option<String>,
618
619 /// Terminal ANSI background color.
620 #[serde(rename = "terminal.ansi.background")]
621 pub terminal_ansi_background: Option<String>,
622
623 /// Bright terminal foreground color.
624 #[serde(rename = "terminal.bright_foreground")]
625 pub terminal_bright_foreground: Option<String>,
626
627 /// Dim terminal foreground color.
628 #[serde(rename = "terminal.dim_foreground")]
629 pub terminal_dim_foreground: Option<String>,
630
631 /// Black ANSI terminal color.
632 #[serde(rename = "terminal.ansi.black")]
633 pub terminal_ansi_black: Option<String>,
634
635 /// Bright black ANSI terminal color.
636 #[serde(rename = "terminal.ansi.bright_black")]
637 pub terminal_ansi_bright_black: Option<String>,
638
639 /// Dim black ANSI terminal color.
640 #[serde(rename = "terminal.ansi.dim_black")]
641 pub terminal_ansi_dim_black: Option<String>,
642
643 /// Red ANSI terminal color.
644 #[serde(rename = "terminal.ansi.red")]
645 pub terminal_ansi_red: Option<String>,
646
647 /// Bright red ANSI terminal color.
648 #[serde(rename = "terminal.ansi.bright_red")]
649 pub terminal_ansi_bright_red: Option<String>,
650
651 /// Dim red ANSI terminal color.
652 #[serde(rename = "terminal.ansi.dim_red")]
653 pub terminal_ansi_dim_red: Option<String>,
654
655 /// Green ANSI terminal color.
656 #[serde(rename = "terminal.ansi.green")]
657 pub terminal_ansi_green: Option<String>,
658
659 /// Bright green ANSI terminal color.
660 #[serde(rename = "terminal.ansi.bright_green")]
661 pub terminal_ansi_bright_green: Option<String>,
662
663 /// Dim green ANSI terminal color.
664 #[serde(rename = "terminal.ansi.dim_green")]
665 pub terminal_ansi_dim_green: Option<String>,
666
667 /// Yellow ANSI terminal color.
668 #[serde(rename = "terminal.ansi.yellow")]
669 pub terminal_ansi_yellow: Option<String>,
670
671 /// Bright yellow ANSI terminal color.
672 #[serde(rename = "terminal.ansi.bright_yellow")]
673 pub terminal_ansi_bright_yellow: Option<String>,
674
675 /// Dim yellow ANSI terminal color.
676 #[serde(rename = "terminal.ansi.dim_yellow")]
677 pub terminal_ansi_dim_yellow: Option<String>,
678
679 /// Blue ANSI terminal color.
680 #[serde(rename = "terminal.ansi.blue")]
681 pub terminal_ansi_blue: Option<String>,
682
683 /// Bright blue ANSI terminal color.
684 #[serde(rename = "terminal.ansi.bright_blue")]
685 pub terminal_ansi_bright_blue: Option<String>,
686
687 /// Dim blue ANSI terminal color.
688 #[serde(rename = "terminal.ansi.dim_blue")]
689 pub terminal_ansi_dim_blue: Option<String>,
690
691 /// Magenta ANSI terminal color.
692 #[serde(rename = "terminal.ansi.magenta")]
693 pub terminal_ansi_magenta: Option<String>,
694
695 /// Bright magenta ANSI terminal color.
696 #[serde(rename = "terminal.ansi.bright_magenta")]
697 pub terminal_ansi_bright_magenta: Option<String>,
698
699 /// Dim magenta ANSI terminal color.
700 #[serde(rename = "terminal.ansi.dim_magenta")]
701 pub terminal_ansi_dim_magenta: Option<String>,
702
703 /// Cyan ANSI terminal color.
704 #[serde(rename = "terminal.ansi.cyan")]
705 pub terminal_ansi_cyan: Option<String>,
706
707 /// Bright cyan ANSI terminal color.
708 #[serde(rename = "terminal.ansi.bright_cyan")]
709 pub terminal_ansi_bright_cyan: Option<String>,
710
711 /// Dim cyan ANSI terminal color.
712 #[serde(rename = "terminal.ansi.dim_cyan")]
713 pub terminal_ansi_dim_cyan: Option<String>,
714
715 /// White ANSI terminal color.
716 #[serde(rename = "terminal.ansi.white")]
717 pub terminal_ansi_white: Option<String>,
718
719 /// Bright white ANSI terminal color.
720 #[serde(rename = "terminal.ansi.bright_white")]
721 pub terminal_ansi_bright_white: Option<String>,
722
723 /// Dim white ANSI terminal color.
724 #[serde(rename = "terminal.ansi.dim_white")]
725 pub terminal_ansi_dim_white: Option<String>,
726
727 #[serde(rename = "link_text.hover")]
728 pub link_text_hover: Option<String>,
729
730 /// Added version control color.
731 #[serde(rename = "version_control.added")]
732 pub version_control_added: Option<String>,
733
734 /// Deleted version control color.
735 #[serde(rename = "version_control.deleted")]
736 pub version_control_deleted: Option<String>,
737
738 /// Modified version control color.
739 #[serde(rename = "version_control.modified")]
740 pub version_control_modified: Option<String>,
741
742 /// Renamed version control color.
743 #[serde(rename = "version_control.renamed")]
744 pub version_control_renamed: Option<String>,
745
746 /// Conflict version control color.
747 #[serde(rename = "version_control.conflict")]
748 pub version_control_conflict: Option<String>,
749
750 /// Ignored version control color.
751 #[serde(rename = "version_control.ignored")]
752 pub version_control_ignored: Option<String>,
753
754 /// Background color for row highlights of "ours" regions in merge conflicts.
755 #[serde(rename = "version_control.conflict_marker.ours")]
756 pub version_control_conflict_marker_ours: Option<String>,
757
758 /// Background color for row highlights of "theirs" regions in merge conflicts.
759 #[serde(rename = "version_control.conflict_marker.theirs")]
760 pub version_control_conflict_marker_theirs: Option<String>,
761
762 /// Deprecated in favor of `version_control_conflict_marker_ours`.
763 #[deprecated]
764 pub version_control_conflict_ours_background: Option<String>,
765
766 /// Deprecated in favor of `version_control_conflict_marker_theirs`.
767 #[deprecated]
768 pub version_control_conflict_theirs_background: Option<String>,
769}
770
771#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema, PartialEq)]
772#[serde(default)]
773pub struct HighlightStyleContent {
774 pub color: Option<String>,
775
776 #[serde(deserialize_with = "treat_error_as_none")]
777 pub background_color: Option<String>,
778
779 #[serde(deserialize_with = "treat_error_as_none")]
780 pub font_style: Option<FontStyleContent>,
781
782 #[serde(deserialize_with = "treat_error_as_none")]
783 pub font_weight: Option<FontWeightContent>,
784}
785
786impl HighlightStyleContent {
787 pub fn is_empty(&self) -> bool {
788 self.color.is_none()
789 && self.background_color.is_none()
790 && self.font_style.is_none()
791 && self.font_weight.is_none()
792 }
793}
794
795fn treat_error_as_none<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
796where
797 T: Deserialize<'de>,
798 D: Deserializer<'de>,
799{
800 let value: Value = Deserialize::deserialize(deserializer)?;
801 Ok(T::deserialize(value).ok())
802}
803
804#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema, PartialEq)]
805#[serde(default)]
806pub struct StatusColorsContent {
807 /// Indicates some kind of conflict, like a file changed on disk while it was open, or
808 /// merge conflicts in a Git repository.
809 #[serde(rename = "conflict")]
810 pub conflict: Option<String>,
811
812 #[serde(rename = "conflict.background")]
813 pub conflict_background: Option<String>,
814
815 #[serde(rename = "conflict.border")]
816 pub conflict_border: Option<String>,
817
818 /// Indicates something new, like a new file added to a Git repository.
819 #[serde(rename = "created")]
820 pub created: Option<String>,
821
822 #[serde(rename = "created.background")]
823 pub created_background: Option<String>,
824
825 #[serde(rename = "created.border")]
826 pub created_border: Option<String>,
827
828 /// Indicates that something no longer exists, like a deleted file.
829 #[serde(rename = "deleted")]
830 pub deleted: Option<String>,
831
832 #[serde(rename = "deleted.background")]
833 pub deleted_background: Option<String>,
834
835 #[serde(rename = "deleted.border")]
836 pub deleted_border: Option<String>,
837
838 /// Indicates a system error, a failed operation or a diagnostic error.
839 #[serde(rename = "error")]
840 pub error: Option<String>,
841
842 #[serde(rename = "error.background")]
843 pub error_background: Option<String>,
844
845 #[serde(rename = "error.border")]
846 pub error_border: Option<String>,
847
848 /// Represents a hidden status, such as a file being hidden in a file tree.
849 #[serde(rename = "hidden")]
850 pub hidden: Option<String>,
851
852 #[serde(rename = "hidden.background")]
853 pub hidden_background: Option<String>,
854
855 #[serde(rename = "hidden.border")]
856 pub hidden_border: Option<String>,
857
858 /// Indicates a hint or some kind of additional information.
859 #[serde(rename = "hint")]
860 pub hint: Option<String>,
861
862 #[serde(rename = "hint.background")]
863 pub hint_background: Option<String>,
864
865 #[serde(rename = "hint.border")]
866 pub hint_border: Option<String>,
867
868 /// Indicates that something is deliberately ignored, such as a file or operation ignored by Git.
869 #[serde(rename = "ignored")]
870 pub ignored: Option<String>,
871
872 #[serde(rename = "ignored.background")]
873 pub ignored_background: Option<String>,
874
875 #[serde(rename = "ignored.border")]
876 pub ignored_border: Option<String>,
877
878 /// Represents informational status updates or messages.
879 #[serde(rename = "info")]
880 pub info: Option<String>,
881
882 #[serde(rename = "info.background")]
883 pub info_background: Option<String>,
884
885 #[serde(rename = "info.border")]
886 pub info_border: Option<String>,
887
888 /// Indicates a changed or altered status, like a file that has been edited.
889 #[serde(rename = "modified")]
890 pub modified: Option<String>,
891
892 #[serde(rename = "modified.background")]
893 pub modified_background: Option<String>,
894
895 #[serde(rename = "modified.border")]
896 pub modified_border: Option<String>,
897
898 /// Indicates something that is predicted, like automatic code completion, or generated code.
899 #[serde(rename = "predictive")]
900 pub predictive: Option<String>,
901
902 #[serde(rename = "predictive.background")]
903 pub predictive_background: Option<String>,
904
905 #[serde(rename = "predictive.border")]
906 pub predictive_border: Option<String>,
907
908 /// Represents a renamed status, such as a file that has been renamed.
909 #[serde(rename = "renamed")]
910 pub renamed: Option<String>,
911
912 #[serde(rename = "renamed.background")]
913 pub renamed_background: Option<String>,
914
915 #[serde(rename = "renamed.border")]
916 pub renamed_border: Option<String>,
917
918 /// Indicates a successful operation or task completion.
919 #[serde(rename = "success")]
920 pub success: Option<String>,
921
922 #[serde(rename = "success.background")]
923 pub success_background: Option<String>,
924
925 #[serde(rename = "success.border")]
926 pub success_border: Option<String>,
927
928 /// Indicates some kind of unreachable status, like a block of code that can never be reached.
929 #[serde(rename = "unreachable")]
930 pub unreachable: Option<String>,
931
932 #[serde(rename = "unreachable.background")]
933 pub unreachable_background: Option<String>,
934
935 #[serde(rename = "unreachable.border")]
936 pub unreachable_border: Option<String>,
937
938 /// Represents a warning status, like an operation that is about to fail.
939 #[serde(rename = "warning")]
940 pub warning: Option<String>,
941
942 #[serde(rename = "warning.background")]
943 pub warning_background: Option<String>,
944
945 #[serde(rename = "warning.border")]
946 pub warning_border: Option<String>,
947}
948
949/// The background appearance of the window.
950#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize, JsonSchema)]
951#[serde(rename_all = "snake_case")]
952pub enum WindowBackgroundContent {
953 Opaque,
954 Transparent,
955 Blurred,
956}
957
958impl Into<gpui::WindowBackgroundAppearance> for WindowBackgroundContent {
959 fn into(self) -> gpui::WindowBackgroundAppearance {
960 match self {
961 WindowBackgroundContent::Opaque => gpui::WindowBackgroundAppearance::Opaque,
962 WindowBackgroundContent::Transparent => gpui::WindowBackgroundAppearance::Transparent,
963 WindowBackgroundContent::Blurred => gpui::WindowBackgroundAppearance::Blurred,
964 }
965 }
966}
967
968#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq)]
969#[serde(rename_all = "snake_case")]
970pub enum FontStyleContent {
971 Normal,
972 Italic,
973 Oblique,
974}
975
976impl From<FontStyleContent> for FontStyle {
977 fn from(value: FontStyleContent) -> Self {
978 match value {
979 FontStyleContent::Normal => FontStyle::Normal,
980 FontStyleContent::Italic => FontStyle::Italic,
981 FontStyleContent::Oblique => FontStyle::Oblique,
982 }
983 }
984}
985
986#[derive(Debug, Clone, Copy, Serialize_repr, Deserialize_repr, JsonSchema_repr, PartialEq)]
987#[repr(u16)]
988pub enum FontWeightContent {
989 Thin = 100,
990 ExtraLight = 200,
991 Light = 300,
992 Normal = 400,
993 Medium = 500,
994 Semibold = 600,
995 Bold = 700,
996 ExtraBold = 800,
997 Black = 900,
998}
999
1000impl From<FontWeightContent> for FontWeight {
1001 fn from(value: FontWeightContent) -> Self {
1002 match value {
1003 FontWeightContent::Thin => FontWeight::THIN,
1004 FontWeightContent::ExtraLight => FontWeight::EXTRA_LIGHT,
1005 FontWeightContent::Light => FontWeight::LIGHT,
1006 FontWeightContent::Normal => FontWeight::NORMAL,
1007 FontWeightContent::Medium => FontWeight::MEDIUM,
1008 FontWeightContent::Semibold => FontWeight::SEMIBOLD,
1009 FontWeightContent::Bold => FontWeight::BOLD,
1010 FontWeightContent::ExtraBold => FontWeight::EXTRA_BOLD,
1011 FontWeightContent::Black => FontWeight::BLACK,
1012 }
1013 }
1014}
1015
1016#[cfg(test)]
1017mod tests {
1018 use super::*;
1019 use serde_json::json;
1020
1021 #[test]
1022 fn test_buffer_line_height_deserialize_valid() {
1023 assert_eq!(
1024 serde_json::from_value::<BufferLineHeight>(json!("comfortable")).unwrap(),
1025 BufferLineHeight::Comfortable
1026 );
1027 assert_eq!(
1028 serde_json::from_value::<BufferLineHeight>(json!("standard")).unwrap(),
1029 BufferLineHeight::Standard
1030 );
1031 assert_eq!(
1032 serde_json::from_value::<BufferLineHeight>(json!({"custom": 1.0})).unwrap(),
1033 BufferLineHeight::Custom(1.0)
1034 );
1035 assert_eq!(
1036 serde_json::from_value::<BufferLineHeight>(json!({"custom": 1.5})).unwrap(),
1037 BufferLineHeight::Custom(1.5)
1038 );
1039 }
1040
1041 #[test]
1042 fn test_buffer_line_height_deserialize_invalid() {
1043 assert!(
1044 serde_json::from_value::<BufferLineHeight>(json!({"custom": 0.99}))
1045 .err()
1046 .unwrap()
1047 .to_string()
1048 .contains("buffer_line_height.custom must be at least 1.0")
1049 );
1050 assert!(
1051 serde_json::from_value::<BufferLineHeight>(json!({"custom": 0.0}))
1052 .err()
1053 .unwrap()
1054 .to_string()
1055 .contains("buffer_line_height.custom must be at least 1.0")
1056 );
1057 assert!(
1058 serde_json::from_value::<BufferLineHeight>(json!({"custom": -1.0}))
1059 .err()
1060 .unwrap()
1061 .to_string()
1062 .contains("buffer_line_height.custom must be at least 1.0")
1063 );
1064 }
1065}