1use gpui::App;
2use settings::{LanguageSettingsContent, SettingsContent};
3use std::sync::Arc;
4use strum::IntoDiscriminant as _;
5use ui::{IntoElement, SharedString};
6
7use crate::{
8 DynamicItem, PROJECT, SettingField, SettingItem, SettingsFieldMetadata, SettingsPage,
9 SettingsPageItem, SubPageLink, USER, all_language_names, sub_page_stack,
10};
11
12const DEFAULT_STRING: String = String::new();
13/// A default empty string reference. Useful in `pick` functions for cases either in dynamic item fields, or when dealing with `settings::Maybe`
14/// to avoid the "NO DEFAULT" case.
15const DEFAULT_EMPTY_STRING: Option<&String> = Some(&DEFAULT_STRING);
16
17const DEFAULT_SHARED_STRING: SharedString = SharedString::new_static("");
18/// A default empty string reference. Useful in `pick` functions for cases either in dynamic item fields, or when dealing with `settings::Maybe`
19/// to avoid the "NO DEFAULT" case.
20const DEFAULT_EMPTY_SHARED_STRING: Option<&SharedString> = Some(&DEFAULT_SHARED_STRING);
21
22pub(crate) fn settings_data(cx: &App) -> Vec<SettingsPage> {
23 vec![
24 SettingsPage {
25 title: "General",
26 items: vec![
27 SettingsPageItem::SectionHeader("General Settings"),
28 SettingsPageItem::SettingItem(SettingItem {
29 files: PROJECT,
30 title: "Project Name",
31 description: "The displayed name of this project. If left empty, the root directory name will be displayed.",
32 field: Box::new(
33 SettingField {
34 json_path: Some("project_name"),
35 pick: |settings_content| {
36 settings_content.project.worktree.project_name.as_ref().or(DEFAULT_EMPTY_STRING)
37 },
38 write: |settings_content, value| {
39 settings_content.project.worktree.project_name = value.filter(|name| !name.is_empty());
40 },
41 }
42 ),
43 metadata: Some(Box::new(SettingsFieldMetadata { placeholder: Some("Project Name"), ..Default::default() })),
44 }),
45 SettingsPageItem::SettingItem(SettingItem {
46 title: "When Closing With No Tabs",
47 description: "What to do when using the 'close active item' action with no tabs.",
48 field: Box::new(SettingField {
49 json_path: Some("when_closing_with_no_tabs"),
50 pick: |settings_content| {
51 settings_content
52 .workspace
53 .when_closing_with_no_tabs
54 .as_ref()
55 },
56 write: |settings_content, value| {
57 settings_content.workspace.when_closing_with_no_tabs = value;
58 },
59 }),
60 metadata: None,
61 files: USER,
62 }),
63 SettingsPageItem::SettingItem(SettingItem {
64 title: "On Last Window Closed",
65 description: "What to do when the last window is closed.",
66 field: Box::new(SettingField {
67 json_path: Some("on_last_window_closed"),
68 pick: |settings_content| {
69 settings_content.workspace.on_last_window_closed.as_ref()
70 },
71 write: |settings_content, value| {
72 settings_content.workspace.on_last_window_closed = value;
73 },
74 }),
75 metadata: None,
76 files: USER,
77 }),
78 SettingsPageItem::SettingItem(SettingItem {
79 title: "Use System Path Prompts",
80 description: "Use native OS dialogs for 'Open' and 'Save As'.",
81 field: Box::new(SettingField {
82 json_path: Some("use_system_path_prompts"),
83 pick: |settings_content| {
84 settings_content.workspace.use_system_path_prompts.as_ref()
85 },
86 write: |settings_content, value| {
87 settings_content.workspace.use_system_path_prompts = value;
88 },
89 }),
90 metadata: None,
91 files: USER,
92 }),
93 SettingsPageItem::SettingItem(SettingItem {
94 title: "Use System Prompts",
95 description: "Use native OS dialogs for confirmations.",
96 field: Box::new(SettingField {
97 json_path: Some("use_system_prompts"),
98 pick: |settings_content| {
99 settings_content.workspace.use_system_prompts.as_ref()
100 },
101 write: |settings_content, value| {
102 settings_content.workspace.use_system_prompts = value;
103 },
104 }),
105 metadata: None,
106 files: USER,
107 }),
108 SettingsPageItem::SettingItem(SettingItem {
109 title: "Redact Private Values",
110 description: "Hide the values of variables in private files.",
111 field: Box::new(SettingField {
112 json_path: Some("redact_private_values"),
113 pick: |settings_content| {
114 settings_content.editor.redact_private_values.as_ref()
115 },
116 write: |settings_content, value| {
117 settings_content.editor.redact_private_values = value;
118 },
119 }),
120 metadata: None,
121 files: USER,
122 }),
123 SettingsPageItem::SettingItem(SettingItem {
124 title: "Private Files",
125 description: "Globs to match against file paths to determine if a file is private.",
126 field: Box::new(
127 SettingField {
128 json_path: Some("worktree.private_files"),
129 pick: |settings_content| {
130 settings_content.project.worktree.private_files.as_ref()
131 },
132 write: |settings_content, value| {
133 settings_content.project.worktree.private_files = value;
134 },
135 }
136 .unimplemented(),
137 ),
138 metadata: None,
139 files: USER,
140 }),
141 SettingsPageItem::SectionHeader("Workspace Restoration"),
142 SettingsPageItem::SettingItem(SettingItem {
143 title: "Restore Unsaved Buffers",
144 description: "Whether or not to restore unsaved buffers on restart.",
145 field: Box::new(SettingField {
146 json_path: Some("session.restore_unsaved_buffers"),
147 pick: |settings_content| {
148 settings_content
149 .session
150 .as_ref()
151 .and_then(|session| session.restore_unsaved_buffers.as_ref())
152 },
153 write: |settings_content, value| {
154 settings_content
155 .session
156 .get_or_insert_default()
157 .restore_unsaved_buffers = value;
158 },
159 }),
160 metadata: None,
161 files: USER,
162 }),
163 SettingsPageItem::SettingItem(SettingItem {
164 title: "Restore On Startup",
165 description: "What to restore from the previous session when opening Zed.",
166 field: Box::new(SettingField {
167 json_path: Some("restore_on_startup"),
168 pick: |settings_content| {
169 settings_content.workspace.restore_on_startup.as_ref()
170 },
171 write: |settings_content, value| {
172 settings_content.workspace.restore_on_startup = value;
173 },
174 }),
175 metadata: None,
176 files: USER,
177 }),
178 SettingsPageItem::SectionHeader("Scoped Settings"),
179 SettingsPageItem::SettingItem(SettingItem {
180 files: USER,
181 title: "Preview Channel",
182 description: "Which settings should be activated only in Preview build of Zed.",
183 field: Box::new(
184 SettingField {
185 json_path: Some("preview_channel_settings"),
186 pick: |settings_content| {
187 Some(settings_content)
188 },
189 write: |_settings_content, _value| {
190
191 },
192 }
193 .unimplemented(),
194 ),
195 metadata: None,
196 }),
197 SettingsPageItem::SettingItem(SettingItem {
198 files: USER,
199 title: "Settings Profiles",
200 description: "Any number of settings profiles that are temporarily applied on top of your existing user settings.",
201 field: Box::new(
202 SettingField {
203 json_path: Some("settings_profiles"),
204 pick: |settings_content| {
205 Some(settings_content)
206 },
207 write: |_settings_content, _value| {
208 },
209 }
210 .unimplemented(),
211 ),
212 metadata: None,
213 }),
214 SettingsPageItem::SectionHeader("Privacy"),
215 SettingsPageItem::SettingItem(SettingItem {
216 title: "Telemetry Diagnostics",
217 description: "Send debug information like crash reports.",
218 field: Box::new(SettingField {
219 json_path: Some("telemetry.diagnostics"),
220 pick: |settings_content| {
221 settings_content
222 .telemetry
223 .as_ref()
224 .and_then(|telemetry| telemetry.diagnostics.as_ref())
225 },
226 write: |settings_content, value| {
227 settings_content
228 .telemetry
229 .get_or_insert_default()
230 .diagnostics = value;
231 },
232 }),
233 metadata: None,
234 files: USER,
235 }),
236 SettingsPageItem::SettingItem(SettingItem {
237 title: "Telemetry Metrics",
238 description: "Send anonymized usage data like what languages you're using Zed with.",
239 field: Box::new(SettingField {
240 json_path: Some("telemetry.metrics"),
241 pick: |settings_content| {
242 settings_content
243 .telemetry
244 .as_ref()
245 .and_then(|telemetry| telemetry.metrics.as_ref())
246 },
247 write: |settings_content, value| {
248 settings_content.telemetry.get_or_insert_default().metrics = value;
249 },
250 }),
251 metadata: None,
252 files: USER,
253 }),
254 SettingsPageItem::SectionHeader("Auto Update"),
255 SettingsPageItem::SettingItem(SettingItem {
256 title: "Auto Update",
257 description: "Whether or not to automatically check for updates.",
258 field: Box::new(SettingField {
259 json_path: Some("auto_update"),
260 pick: |settings_content| settings_content.auto_update.as_ref(),
261 write: |settings_content, value| {
262 settings_content.auto_update = value;
263 },
264 }),
265 metadata: None,
266 files: USER,
267 }),
268 ],
269 },
270 SettingsPage {
271 title: "Appearance",
272 items: vec![
273 SettingsPageItem::SectionHeader("Theme"),
274 SettingsPageItem::DynamicItem(DynamicItem {
275 discriminant: SettingItem {
276 files: USER,
277 title: "Theme Mode",
278 description: "Choose a static, fixed theme or dynamically select themes based on appearance and light/dark modes.",
279 field: Box::new(SettingField {
280 json_path: Some("theme$"),
281 pick: |settings_content| {
282 Some(&dynamic_variants::<settings::ThemeSelection>()[
283 settings_content
284 .theme
285 .theme
286 .as_ref()?
287 .discriminant() as usize])
288 },
289 write: |settings_content, value| {
290 let Some(value) = value else {
291 settings_content.theme.theme = None;
292 return;
293 };
294 let settings_value = settings_content.theme.theme.get_or_insert_with(|| {
295 settings::ThemeSelection::Static(theme::ThemeName(theme::default_theme(theme::SystemAppearance::default().0).into()))
296 });
297 *settings_value = match value {
298 settings::ThemeSelectionDiscriminants::Static => {
299 let name = match settings_value {
300 settings::ThemeSelection::Static(_) => return,
301 settings::ThemeSelection::Dynamic { mode, light, dark } => {
302 match mode {
303 theme::ThemeAppearanceMode::Light => light.clone(),
304 theme::ThemeAppearanceMode::Dark => dark.clone(),
305 theme::ThemeAppearanceMode::System => dark.clone(), // no cx, can't determine correct choice
306 }
307 },
308 };
309 settings::ThemeSelection::Static(name)
310 },
311 settings::ThemeSelectionDiscriminants::Dynamic => {
312 let static_name = match settings_value {
313 settings::ThemeSelection::Static(theme_name) => theme_name.clone(),
314 settings::ThemeSelection::Dynamic {..} => return,
315 };
316
317 settings::ThemeSelection::Dynamic {
318 mode: settings::ThemeAppearanceMode::System,
319 light: static_name.clone(),
320 dark: static_name,
321 }
322 },
323 };
324 },
325 }),
326 metadata: None,
327 },
328 pick_discriminant: |settings_content| {
329 Some(settings_content.theme.theme.as_ref()?.discriminant() as usize)
330 },
331 fields: dynamic_variants::<settings::ThemeSelection>().into_iter().map(|variant| {
332 match variant {
333 settings::ThemeSelectionDiscriminants::Static => vec![
334 SettingItem {
335 files: USER,
336 title: "Theme Name",
337 description: "The name of your selected theme.",
338 field: Box::new(SettingField {
339 json_path: Some("theme"),
340 pick: |settings_content| {
341 match settings_content.theme.theme.as_ref() {
342 Some(settings::ThemeSelection::Static(name)) => Some(name),
343 _ => None
344 }
345 },
346 write: |settings_content, value| {
347 let Some(value) = value else {
348 return;
349 };
350 match settings_content
351 .theme
352 .theme.as_mut() {
353 Some(settings::ThemeSelection::Static(theme_name)) => *theme_name = value,
354 _ => return
355 }
356 },
357 }),
358 metadata: None,
359 }
360 ],
361 settings::ThemeSelectionDiscriminants::Dynamic => vec![
362 SettingItem {
363 files: USER,
364 title: "Mode",
365 description: "Choose whether to use the selected light or dark theme or to follow your OS appearance configuration.",
366 field: Box::new(SettingField {
367 json_path: Some("theme.mode"),
368 pick: |settings_content| {
369 match settings_content.theme.theme.as_ref() {
370 Some(settings::ThemeSelection::Dynamic { mode, ..}) => Some(mode),
371 _ => None
372 }
373 },
374 write: |settings_content, value| {
375 let Some(value) = value else {
376 return;
377 };
378 match settings_content
379 .theme
380 .theme.as_mut() {
381 Some(settings::ThemeSelection::Dynamic{ mode, ..}) => *mode = value,
382 _ => return
383 }
384 },
385 }),
386 metadata: None,
387 },
388 SettingItem {
389 files: USER,
390 title: "Light Theme",
391 description: "The theme to use when mode is set to light, or when mode is set to system and it is in light mode.",
392 field: Box::new(SettingField {
393 json_path: Some("theme.light"),
394 pick: |settings_content| {
395 match settings_content.theme.theme.as_ref() {
396 Some(settings::ThemeSelection::Dynamic { light, ..}) => Some(light),
397 _ => None
398 }
399 },
400 write: |settings_content, value| {
401 let Some(value) = value else {
402 return;
403 };
404 match settings_content
405 .theme
406 .theme.as_mut() {
407 Some(settings::ThemeSelection::Dynamic{ light, ..}) => *light = value,
408 _ => return
409 }
410 },
411 }),
412 metadata: None,
413 },
414 SettingItem {
415 files: USER,
416 title: "Dark Theme",
417 description: "The theme to use when mode is set to dark, or when mode is set to system and it is in dark mode.",
418 field: Box::new(SettingField {
419 json_path: Some("theme.dark"),
420 pick: |settings_content| {
421 match settings_content.theme.theme.as_ref() {
422 Some(settings::ThemeSelection::Dynamic { dark, ..}) => Some(dark),
423 _ => None
424 }
425 },
426 write: |settings_content, value| {
427 let Some(value) = value else {
428 return;
429 };
430 match settings_content
431 .theme
432 .theme.as_mut() {
433 Some(settings::ThemeSelection::Dynamic{ dark, ..}) => *dark = value,
434 _ => return
435 }
436 },
437 }),
438 metadata: None,
439 }
440 ],
441 }
442 }).collect(),
443 }),
444 SettingsPageItem::DynamicItem(DynamicItem {
445 discriminant: SettingItem {
446 files: USER,
447 title: "Icon Theme",
448 description: "The custom set of icons Zed will associate with files and directories.",
449 field: Box::new(SettingField {
450 json_path: Some("icon_theme$"),
451 pick: |settings_content| {
452 Some(&dynamic_variants::<settings::IconThemeSelection>()[
453 settings_content
454 .theme
455 .icon_theme
456 .as_ref()?
457 .discriminant() as usize])
458 },
459 write: |settings_content, value| {
460 let Some(value) = value else {
461 settings_content.theme.icon_theme = None;
462 return;
463 };
464 let settings_value = settings_content.theme.icon_theme.get_or_insert_with(|| {
465 settings::IconThemeSelection::Static(settings::IconThemeName(theme::default_icon_theme().name.clone().into()))
466 });
467 *settings_value = match value {
468 settings::IconThemeSelectionDiscriminants::Static => {
469 let name = match settings_value {
470 settings::IconThemeSelection::Static(_) => return,
471 settings::IconThemeSelection::Dynamic { mode, light, dark } => {
472 match mode {
473 theme::ThemeAppearanceMode::Light => light.clone(),
474 theme::ThemeAppearanceMode::Dark => dark.clone(),
475 theme::ThemeAppearanceMode::System => dark.clone(), // no cx, can't determine correct choice
476 }
477 },
478 };
479 settings::IconThemeSelection::Static(name)
480 },
481 settings::IconThemeSelectionDiscriminants::Dynamic => {
482 let static_name = match settings_value {
483 settings::IconThemeSelection::Static(theme_name) => theme_name.clone(),
484 settings::IconThemeSelection::Dynamic {..} => return,
485 };
486
487 settings::IconThemeSelection::Dynamic {
488 mode: settings::ThemeAppearanceMode::System,
489 light: static_name.clone(),
490 dark: static_name,
491 }
492 },
493 };
494 },
495 }),
496 metadata: None,
497 },
498 pick_discriminant: |settings_content| {
499 Some(settings_content.theme.icon_theme.as_ref()?.discriminant() as usize)
500 },
501 fields: dynamic_variants::<settings::IconThemeSelection>().into_iter().map(|variant| {
502 match variant {
503 settings::IconThemeSelectionDiscriminants::Static => vec![
504 SettingItem {
505 files: USER,
506 title: "Icon Theme Name",
507 description: "The name of your selected icon theme.",
508 field: Box::new(SettingField {
509 json_path: Some("icon_theme$string"),
510 pick: |settings_content| {
511 match settings_content.theme.icon_theme.as_ref() {
512 Some(settings::IconThemeSelection::Static(name)) => Some(name),
513 _ => None
514 }
515 },
516 write: |settings_content, value| {
517 let Some(value) = value else {
518 return;
519 };
520 match settings_content
521 .theme
522 .icon_theme.as_mut() {
523 Some(settings::IconThemeSelection::Static(theme_name)) => *theme_name = value,
524 _ => return
525 }
526 },
527 }),
528 metadata: None,
529 }
530 ],
531 settings::IconThemeSelectionDiscriminants::Dynamic => vec![
532 SettingItem {
533 files: USER,
534 title: "Mode",
535 description: "Choose whether to use the selected light or dark icon theme or to follow your OS appearance configuration.",
536 field: Box::new(SettingField {
537 json_path: Some("icon_theme"),
538 pick: |settings_content| {
539 match settings_content.theme.icon_theme.as_ref() {
540 Some(settings::IconThemeSelection::Dynamic { mode, ..}) => Some(mode),
541 _ => None
542 }
543 },
544 write: |settings_content, value| {
545 let Some(value) = value else {
546 return;
547 };
548 match settings_content
549 .theme
550 .icon_theme.as_mut() {
551 Some(settings::IconThemeSelection::Dynamic{ mode, ..}) => *mode = value,
552 _ => return
553 }
554 },
555 }),
556 metadata: None,
557 },
558 SettingItem {
559 files: USER,
560 title: "Light Icon Theme",
561 description: "The icon theme to use when mode is set to light, or when mode is set to system and it is in light mode.",
562 field: Box::new(SettingField {
563 json_path: Some("icon_theme.light"),
564 pick: |settings_content| {
565 match settings_content.theme.icon_theme.as_ref() {
566 Some(settings::IconThemeSelection::Dynamic { light, ..}) => Some(light),
567 _ => None
568 }
569 },
570 write: |settings_content, value| {
571 let Some(value) = value else {
572 return;
573 };
574 match settings_content
575 .theme
576 .icon_theme.as_mut() {
577 Some(settings::IconThemeSelection::Dynamic{ light, ..}) => *light = value,
578 _ => return
579 }
580 },
581 }),
582 metadata: None,
583 },
584 SettingItem {
585 files: USER,
586 title: "Dark Icon Theme",
587 description: "The icon theme to use when mode is set to dark, or when mode is set to system and it is in dark mode.",
588 field: Box::new(SettingField {
589 json_path: Some("icon_theme.dark"),
590 pick: |settings_content| {
591 match settings_content.theme.icon_theme.as_ref() {
592 Some(settings::IconThemeSelection::Dynamic { dark, ..}) => Some(dark),
593 _ => None
594 }
595 },
596 write: |settings_content, value| {
597 let Some(value) = value else {
598 return;
599 };
600 match settings_content
601 .theme
602 .icon_theme.as_mut() {
603 Some(settings::IconThemeSelection::Dynamic{ dark, ..}) => *dark = value,
604 _ => return
605 }
606 },
607 }),
608 metadata: None,
609 }
610 ],
611 }
612 }).collect(),
613 }),
614 SettingsPageItem::SectionHeader("Buffer Font"),
615 SettingsPageItem::SettingItem(SettingItem {
616 title: "Font Family",
617 description: "Font family for editor text.",
618 field: Box::new(SettingField {
619 json_path: Some("buffer_font_family"),
620 pick: |settings_content| settings_content.theme.buffer_font_family.as_ref(),
621 write: |settings_content, value|{ settings_content.theme.buffer_font_family = value;},
622 }),
623 metadata: None,
624 files: USER,
625 }),
626 SettingsPageItem::SettingItem(SettingItem {
627 title: "Font Size",
628 description: "Font size for editor text.",
629 field: Box::new(SettingField {
630 json_path: Some("buffer_font_size"),
631 pick: |settings_content| settings_content.theme.buffer_font_size.as_ref(),
632 write: |settings_content, value|{ settings_content.theme.buffer_font_size = value;},
633 }),
634 metadata: None,
635 files: USER,
636 }),
637 SettingsPageItem::SettingItem(SettingItem {
638 title: "Font Weight",
639 description: "Font weight for editor text (100-900).",
640 field: Box::new(SettingField {
641 json_path: Some("buffer_font_weight"),
642 pick: |settings_content| settings_content.theme.buffer_font_weight.as_ref(),
643 write: |settings_content, value|{ settings_content.theme.buffer_font_weight = value;},
644 }),
645 metadata: None,
646 files: USER,
647 }),
648 SettingsPageItem::DynamicItem(DynamicItem {
649 discriminant: SettingItem {
650 files: USER,
651 title: "Line Height",
652 description: "Line height for editor text.",
653 field: Box::new(SettingField {
654 json_path: Some("buffer_line_height$"),
655 pick: |settings_content| {
656 Some(&dynamic_variants::<settings::BufferLineHeight>()[
657 settings_content
658 .theme
659 .buffer_line_height
660 .as_ref()?
661 .discriminant() as usize])
662 },
663 write: |settings_content, value| {
664 let Some(value) = value else {
665 settings_content.theme.buffer_line_height = None;
666 return;
667 };
668 let settings_value = settings_content.theme.buffer_line_height.get_or_insert_with(|| {
669 settings::BufferLineHeight::default()
670 });
671 *settings_value = match value {
672 settings::BufferLineHeightDiscriminants::Comfortable => {
673 settings::BufferLineHeight::Comfortable
674 },
675 settings::BufferLineHeightDiscriminants::Standard => {
676 settings::BufferLineHeight::Standard
677 },
678 settings::BufferLineHeightDiscriminants::Custom => {
679 let custom_value = theme::BufferLineHeight::from(*settings_value).value();
680 settings::BufferLineHeight::Custom(custom_value)
681 },
682 };
683 },
684 }),
685 metadata: None,
686 },
687 pick_discriminant: |settings_content| {
688 Some(settings_content.theme.buffer_line_height.as_ref()?.discriminant() as usize)
689 },
690 fields: dynamic_variants::<settings::BufferLineHeight>().into_iter().map(|variant| {
691 match variant {
692 settings::BufferLineHeightDiscriminants::Comfortable => vec![],
693 settings::BufferLineHeightDiscriminants::Standard => vec![],
694 settings::BufferLineHeightDiscriminants::Custom => vec![
695 SettingItem {
696 files: USER,
697 title: "Custom Line Height",
698 description: "Custom line height value (must be at least 1.0).",
699 field: Box::new(SettingField {
700 json_path: Some("buffer_line_height"),
701 pick: |settings_content| {
702 match settings_content.theme.buffer_line_height.as_ref() {
703 Some(settings::BufferLineHeight::Custom(value)) => Some(value),
704 _ => None
705 }
706 },
707 write: |settings_content, value| {
708 let Some(value) = value else {
709 return;
710 };
711 match settings_content
712 .theme
713 .buffer_line_height.as_mut() {
714 Some(settings::BufferLineHeight::Custom(line_height)) => *line_height = f32::max(value, 1.0),
715 _ => return
716 }
717 },
718 }),
719 metadata: None,
720 }
721 ],
722 }
723 }).collect(),
724 }),
725 SettingsPageItem::SettingItem(SettingItem {
726 files: USER,
727 title: "Font Features",
728 description: "The OpenType features to enable for rendering in text buffers.",
729 field: Box::new(
730 SettingField {
731 json_path: Some("buffer_font_features"),
732 pick: |settings_content| {
733 settings_content.theme.buffer_font_features.as_ref()
734 },
735 write: |settings_content, value| {
736 settings_content.theme.buffer_font_features = value;
737
738 },
739 }
740 .unimplemented(),
741 ),
742 metadata: None,
743 }),
744 SettingsPageItem::SettingItem(SettingItem {
745 files: USER,
746 title: "Font Fallbacks",
747 description: "The font fallbacks to use for rendering in text buffers.",
748 field: Box::new(
749 SettingField {
750 json_path: Some("buffer_font_fallbacks"),
751 pick: |settings_content| {
752 settings_content.theme.buffer_font_fallbacks.as_ref()
753 },
754 write: |settings_content, value| {
755 settings_content.theme.buffer_font_fallbacks = value;
756
757 },
758 }
759 .unimplemented(),
760 ),
761 metadata: None,
762 }),
763 SettingsPageItem::SectionHeader("UI Font"),
764 SettingsPageItem::SettingItem(SettingItem {
765 title: "Font Family",
766 description: "Font family for UI elements.",
767 field: Box::new(SettingField {
768 json_path: Some("ui_font_family"),
769 pick: |settings_content| settings_content.theme.ui_font_family.as_ref(),
770 write: |settings_content, value|{ settings_content.theme.ui_font_family = value;},
771 }),
772 metadata: None,
773 files: USER,
774 }),
775 SettingsPageItem::SettingItem(SettingItem {
776 title: "Font Size",
777 description: "Font size for UI elements.",
778 field: Box::new(SettingField {
779 json_path: Some("ui_font_size"),
780 pick: |settings_content| settings_content.theme.ui_font_size.as_ref(),
781 write: |settings_content, value|{ settings_content.theme.ui_font_size = value;},
782 }),
783 metadata: None,
784 files: USER,
785 }),
786 SettingsPageItem::SettingItem(SettingItem {
787 title: "Font Weight",
788 description: "Font weight for UI elements (100-900).",
789 field: Box::new(SettingField {
790 json_path: Some("ui_font_weight"),
791 pick: |settings_content| settings_content.theme.ui_font_weight.as_ref(),
792 write: |settings_content, value|{ settings_content.theme.ui_font_weight = value;},
793 }),
794 metadata: None,
795 files: USER,
796 }),
797 SettingsPageItem::SettingItem(SettingItem {
798 files: USER,
799 title: "Font Features",
800 description: "The OpenType features to enable for rendering in UI elements.",
801 field: Box::new(
802 SettingField {
803 json_path: Some("ui_font_features"),
804 pick: |settings_content| {
805 settings_content.theme.ui_font_features.as_ref()
806 },
807 write: |settings_content, value| {
808 settings_content.theme.ui_font_features = value;
809
810 },
811 }
812 .unimplemented(),
813 ),
814 metadata: None,
815 }),
816 SettingsPageItem::SettingItem(SettingItem {
817 files: USER,
818 title: "Font Fallbacks",
819 description: "The font fallbacks to use for rendering in the UI.",
820 field: Box::new(
821 SettingField {
822 json_path: Some("ui_font_fallbacks"),
823 pick: |settings_content| {
824 settings_content.theme.ui_font_fallbacks.as_ref()
825 },
826 write: |settings_content, value| {
827 settings_content.theme.ui_font_fallbacks = value;
828
829 },
830 }
831 .unimplemented(),
832 ),
833 metadata: None,
834 }),
835 SettingsPageItem::SectionHeader("Agent Panel Font"),
836 SettingsPageItem::SettingItem(SettingItem {
837 title: "UI Font Size",
838 description: "Font size for agent response text in the agent panel. Falls back to the regular UI font size.",
839 field: Box::new(SettingField {
840 json_path: Some("agent_ui_font_size"),
841 pick: |settings_content| {
842 settings_content
843 .theme
844 .agent_ui_font_size
845 .as_ref()
846 .or(settings_content.theme.ui_font_size.as_ref())
847 },
848 write: |settings_content, value|{ settings_content.theme.agent_ui_font_size = value;},
849 }),
850 metadata: None,
851 files: USER,
852 }),
853 SettingsPageItem::SettingItem(SettingItem {
854 title: "Buffer Font Size",
855 description: "Font size for user messages text in the agent panel.",
856 field: Box::new(SettingField {
857 json_path: Some("agent_buffer_font_size"),
858 pick: |settings_content| {
859 settings_content
860 .theme
861 .agent_buffer_font_size
862 .as_ref()
863 .or(settings_content.theme.buffer_font_size.as_ref())
864 },
865 write: |settings_content, value| {
866 settings_content.theme.agent_buffer_font_size = value;
867
868 },
869 }),
870 metadata: None,
871 files: USER,
872 }),
873 SettingsPageItem::SectionHeader("Cursor"),
874 SettingsPageItem::SettingItem(SettingItem {
875 title: "Multi Cursor Modifier",
876 description: "Modifier key for adding multiple cursors.",
877 field: Box::new(SettingField {
878 json_path: Some("multi_cursor_modifier"),
879 pick: |settings_content| {
880 settings_content.editor.multi_cursor_modifier.as_ref()
881 },
882 write: |settings_content, value| {
883 settings_content.editor.multi_cursor_modifier = value;
884
885 },
886 }),
887 metadata: None,
888 files: USER,
889 }),
890 SettingsPageItem::SettingItem(SettingItem {
891 title: "Cursor Blink",
892 description: "Whether the cursor blinks in the editor.",
893 field: Box::new(SettingField {
894 json_path: Some("cursor_blink"),
895 pick: |settings_content| settings_content.editor.cursor_blink.as_ref(),
896 write: |settings_content, value|{ settings_content.editor.cursor_blink = value;},
897 }),
898 metadata: None,
899 files: USER,
900 }),
901 SettingsPageItem::SettingItem(SettingItem {
902 title: "Cursor Shape",
903 description: "Cursor shape for the editor.",
904 field: Box::new(SettingField {
905 json_path: Some("cursor_shape"),
906 pick: |settings_content| settings_content.editor.cursor_shape.as_ref(),
907 write: |settings_content, value|{ settings_content.editor.cursor_shape = value;},
908 }),
909 metadata: None,
910 files: USER,
911 }),
912 SettingsPageItem::SettingItem(SettingItem {
913 title: "Hide Mouse",
914 description: "When to hide the mouse cursor.",
915 field: Box::new(SettingField {
916 json_path: Some("hide_mouse"),
917 pick: |settings_content| settings_content.editor.hide_mouse.as_ref(),
918 write: |settings_content, value|{ settings_content.editor.hide_mouse = value;},
919 }),
920 metadata: None,
921 files: USER,
922 }),
923 SettingsPageItem::SectionHeader("Highlighting"),
924 SettingsPageItem::SettingItem(SettingItem {
925 title: "Unnecessary Code Fade",
926 description: "How much to fade out unused code (0.0 - 0.9).",
927 field: Box::new(SettingField {
928 json_path: Some("unnecessary_code_fade"),
929 pick: |settings_content| {
930 settings_content.theme.unnecessary_code_fade.as_ref()
931 },
932 write: |settings_content, value| {
933 settings_content.theme.unnecessary_code_fade = value;
934
935 },
936 }),
937 metadata: None,
938 files: USER,
939 }),
940 SettingsPageItem::SettingItem(SettingItem {
941 title: "Current Line Highlight",
942 description: "How to highlight the current line.",
943 field: Box::new(SettingField {
944 json_path: Some("current_line_highlight"),
945 pick: |settings_content| {
946 settings_content.editor.current_line_highlight.as_ref()
947 },
948 write: |settings_content, value| {
949 settings_content.editor.current_line_highlight = value;
950
951 },
952 }),
953 metadata: None,
954 files: USER,
955 }),
956 SettingsPageItem::SettingItem(SettingItem {
957 title: "Selection Highlight",
958 description: "Highlight all occurrences of selected text.",
959 field: Box::new(SettingField {
960 json_path: Some("selection_highlight"),
961 pick: |settings_content| {
962 settings_content.editor.selection_highlight.as_ref()
963 },
964 write: |settings_content, value| {
965 settings_content.editor.selection_highlight = value;
966
967 },
968 }),
969 metadata: None,
970 files: USER,
971 }),
972 SettingsPageItem::SettingItem(SettingItem {
973 title: "Rounded Selection",
974 description: "Whether the text selection should have rounded corners.",
975 field: Box::new(SettingField {
976 json_path: Some("rounded_selection"),
977 pick: |settings_content| settings_content.editor.rounded_selection.as_ref(),
978 write: |settings_content, value|{ settings_content.editor.rounded_selection = value;},
979 }),
980 metadata: None,
981 files: USER,
982 }),
983 SettingsPageItem::SettingItem(SettingItem {
984 title: "Minimum Contrast For Highlights",
985 description: "The minimum APCA perceptual contrast to maintain when rendering text over highlight backgrounds.",
986 field: Box::new(SettingField {
987 json_path: Some("minimum_contrast_for_highlights"),
988 pick: |settings_content| {
989 settings_content
990 .editor
991 .minimum_contrast_for_highlights
992 .as_ref()
993 },
994 write: |settings_content, value| {
995 settings_content.editor.minimum_contrast_for_highlights = value;
996
997 },
998 }),
999 metadata: None,
1000 files: USER,
1001 }),
1002 SettingsPageItem::SectionHeader("Guides"),
1003 SettingsPageItem::SettingItem(SettingItem {
1004 title: "Show Wrap Guides",
1005 description: "Show wrap guides (vertical rulers).",
1006 field: Box::new(SettingField {
1007 json_path: Some("show_wrap_guides"),
1008 pick: |settings_content| {
1009 settings_content
1010 .project
1011 .all_languages
1012 .defaults
1013 .show_wrap_guides
1014 .as_ref()
1015 },
1016 write: |settings_content, value| {
1017 settings_content
1018
1019 .project
1020 .all_languages
1021 .defaults
1022 .show_wrap_guides = value;
1023 },
1024 }),
1025 metadata: None,
1026 files: USER | PROJECT,
1027 }),
1028 // todo(settings_ui): This needs a custom component
1029 SettingsPageItem::SettingItem(SettingItem {
1030 title: "Wrap Guides",
1031 description: "Character counts at which to show wrap guides.",
1032 field: Box::new(
1033 SettingField {
1034 json_path: Some("wrap_guides"),
1035 pick: |settings_content| {
1036 settings_content
1037 .project
1038 .all_languages
1039 .defaults
1040 .wrap_guides
1041 .as_ref()
1042 },
1043 write: |settings_content, value| {
1044 settings_content.project.all_languages.defaults.wrap_guides = value;
1045 },
1046 }
1047 .unimplemented(),
1048 ),
1049 metadata: None,
1050 files: USER | PROJECT,
1051 }),
1052 ],
1053 },
1054 SettingsPage {
1055 title: "Keymap",
1056 items: vec![
1057 SettingsPageItem::SectionHeader("Base Keymap"),
1058 SettingsPageItem::SettingItem(SettingItem {
1059 title: "Base Keymap",
1060 description: "The name of a base set of key bindings to use.",
1061 field: Box::new(SettingField {
1062 json_path: Some("base_keymap"),
1063 pick: |settings_content| settings_content.base_keymap.as_ref(),
1064 write: |settings_content, value| {
1065 settings_content.base_keymap = value;
1066 },
1067 }),
1068 metadata: Some(Box::new(SettingsFieldMetadata {
1069 should_do_titlecase: Some(false),
1070 ..Default::default()
1071 })),
1072 files: USER,
1073 }),
1074 SettingsPageItem::SectionHeader("Modal Editing"),
1075 // todo(settings_ui): Vim/Helix Mode should be apart of one type because it's undefined
1076 // behavior to have them both enabled at the same time
1077 SettingsPageItem::SettingItem(SettingItem {
1078 title: "Vim Mode",
1079 description: "Enable Vim mode and key bindings.",
1080 field: Box::new(SettingField {
1081 json_path: Some("vim_mode"),
1082 pick: |settings_content| settings_content.vim_mode.as_ref(),
1083 write: |settings_content, value| {
1084 settings_content.vim_mode = value;
1085 },
1086 }),
1087 metadata: None,
1088 files: USER,
1089 }),
1090 SettingsPageItem::SettingItem(SettingItem {
1091 title: "Helix Mode",
1092 description: "Enable Helix mode and key bindings.",
1093 field: Box::new(SettingField {
1094 json_path: Some("helix_mode"),
1095 pick: |settings_content| settings_content.helix_mode.as_ref(),
1096 write: |settings_content, value| {
1097 settings_content.helix_mode = value;
1098 },
1099 }),
1100 metadata: None,
1101 files: USER,
1102 }),
1103 ],
1104 },
1105 SettingsPage {
1106 title: "Editor",
1107 items: {
1108 let mut items = vec![
1109 SettingsPageItem::SectionHeader("Auto Save"),
1110 SettingsPageItem::DynamicItem(DynamicItem {
1111 discriminant: SettingItem {
1112 files: USER,
1113 title: "Auto Save Mode",
1114 description: "When to auto save buffer changes.",
1115 field: Box::new(SettingField {
1116 json_path: Some("autosave$"),
1117 pick: |settings_content| {
1118 Some(&dynamic_variants::<settings::AutosaveSetting>()[
1119 settings_content
1120 .workspace
1121 .autosave
1122 .as_ref()?
1123 .discriminant() as usize])
1124 },
1125 write: |settings_content, value| {
1126 let Some(value) = value else {
1127 settings_content.workspace.autosave = None;
1128 return;
1129 };
1130 let settings_value = settings_content.workspace.autosave.get_or_insert_with(|| {
1131 settings::AutosaveSetting::Off
1132 });
1133 *settings_value = match value {
1134 settings::AutosaveSettingDiscriminants::Off => {
1135 settings::AutosaveSetting::Off
1136 },
1137 settings::AutosaveSettingDiscriminants::AfterDelay => {
1138 let milliseconds = match settings_value {
1139 settings::AutosaveSetting::AfterDelay { milliseconds } => *milliseconds,
1140 _ => settings::DelayMs(1000),
1141 };
1142 settings::AutosaveSetting::AfterDelay { milliseconds }
1143 },
1144 settings::AutosaveSettingDiscriminants::OnFocusChange => {
1145 settings::AutosaveSetting::OnFocusChange
1146 },
1147 settings::AutosaveSettingDiscriminants::OnWindowChange => {
1148 settings::AutosaveSetting::OnWindowChange
1149 },
1150 };
1151 },
1152 }),
1153 metadata: None,
1154 },
1155 pick_discriminant: |settings_content| {
1156 Some(settings_content.workspace.autosave.as_ref()?.discriminant() as usize)
1157 },
1158 fields: dynamic_variants::<settings::AutosaveSetting>().into_iter().map(|variant| {
1159 match variant {
1160 settings::AutosaveSettingDiscriminants::Off => vec![],
1161 settings::AutosaveSettingDiscriminants::AfterDelay => vec![
1162 SettingItem {
1163 files: USER,
1164 title: "Delay (milliseconds)",
1165 description: "Save after inactivity period (in milliseconds).",
1166 field: Box::new(SettingField {
1167 json_path: Some("autosave.after_delay.milliseconds"),
1168 pick: |settings_content| {
1169 match settings_content.workspace.autosave.as_ref() {
1170 Some(settings::AutosaveSetting::AfterDelay { milliseconds }) => Some(milliseconds),
1171 _ => None
1172 }
1173 },
1174 write: |settings_content, value| {
1175 let Some(value) = value else {
1176 settings_content.workspace.autosave = None;
1177 return;
1178 };
1179 match settings_content
1180 .workspace
1181 .autosave.as_mut() {
1182 Some(settings::AutosaveSetting::AfterDelay { milliseconds }) => *milliseconds = value,
1183 _ => return
1184 }
1185 },
1186 }),
1187 metadata: None,
1188 }
1189 ],
1190 settings::AutosaveSettingDiscriminants::OnFocusChange => vec![],
1191 settings::AutosaveSettingDiscriminants::OnWindowChange => vec![],
1192 }
1193 }).collect(),
1194 }),
1195 SettingsPageItem::SectionHeader("Multibuffer"),
1196 SettingsPageItem::SettingItem(SettingItem {
1197 title: "Double Click In Multibuffer",
1198 description: "What to do when multibuffer is double-clicked in some of its excerpts.",
1199 field: Box::new(SettingField {
1200 json_path: Some("double_click_in_multibuffer"),
1201 pick: |settings_content| {
1202 settings_content.editor.double_click_in_multibuffer.as_ref()
1203 },
1204 write: |settings_content, value| {
1205 settings_content.editor.double_click_in_multibuffer = value;
1206 },
1207 }),
1208 metadata: None,
1209 files: USER,
1210 }),
1211 SettingsPageItem::SettingItem(SettingItem {
1212 title: "Expand Excerpt Lines",
1213 description: "How many lines to expand the multibuffer excerpts by default.",
1214 field: Box::new(SettingField {
1215 json_path: Some("expand_excerpt_lines"),
1216 pick: |settings_content| {
1217 settings_content.editor.expand_excerpt_lines.as_ref()
1218 },
1219 write: |settings_content, value| {
1220 settings_content.editor.expand_excerpt_lines = value;
1221 },
1222 }),
1223 metadata: None,
1224 files: USER,
1225 }),
1226 SettingsPageItem::SettingItem(SettingItem {
1227 title: "Excerpt Context Lines",
1228 description: "How many lines of context to provide in multibuffer excerpts by default.",
1229 field: Box::new(SettingField {
1230 json_path: Some("excerpt_context_lines"),
1231 pick: |settings_content| {
1232 settings_content.editor.excerpt_context_lines.as_ref()
1233 },
1234 write: |settings_content, value| {
1235 settings_content.editor.excerpt_context_lines = value;
1236 },
1237 }),
1238 metadata: None,
1239 files: USER,
1240 }),
1241 SettingsPageItem::SettingItem(SettingItem {
1242 title: "Expand Outlines With Depth",
1243 description: "Default depth to expand outline items in the current file.",
1244 field: Box::new(SettingField {
1245 json_path: Some("outline_panel.expand_outlines_with_depth"),
1246 pick: |settings_content| {
1247 settings_content
1248 .outline_panel
1249 .as_ref()
1250 .and_then(|outline_panel| {
1251 outline_panel.expand_outlines_with_depth.as_ref()
1252 })
1253 },
1254 write: |settings_content, value| {
1255 settings_content
1256 .outline_panel
1257 .get_or_insert_default()
1258 .expand_outlines_with_depth = value;
1259 },
1260 }),
1261 metadata: None,
1262 files: USER,
1263 }),
1264 SettingsPageItem::SectionHeader("Scrolling"),
1265 SettingsPageItem::SettingItem(SettingItem {
1266 title: "Scroll Beyond Last Line",
1267 description: "Whether the editor will scroll beyond the last line.",
1268 field: Box::new(SettingField {
1269 json_path: Some("scroll_beyond_last_line"),
1270 pick: |settings_content| {
1271 settings_content.editor.scroll_beyond_last_line.as_ref()
1272 },
1273 write: |settings_content, value| {
1274 settings_content.editor.scroll_beyond_last_line = value;
1275 },
1276 }),
1277 metadata: None,
1278 files: USER,
1279 }),
1280 SettingsPageItem::SettingItem(SettingItem {
1281 title: "Vertical Scroll Margin",
1282 description: "The number of lines to keep above/below the cursor when auto-scrolling.",
1283 field: Box::new(SettingField {
1284 json_path: Some("vertical_scroll_margin"),
1285 pick: |settings_content| {
1286 settings_content.editor.vertical_scroll_margin.as_ref()
1287 },
1288 write: |settings_content, value| {
1289 settings_content.editor.vertical_scroll_margin = value;
1290 },
1291 }),
1292 metadata: None,
1293 files: USER,
1294 }),
1295 SettingsPageItem::SettingItem(SettingItem {
1296 title: "Horizontal Scroll Margin",
1297 description: "The number of characters to keep on either side when scrolling with the mouse.",
1298 field: Box::new(SettingField {
1299 json_path: Some("horizontal_scroll_margin"),
1300 pick: |settings_content| {
1301 settings_content.editor.horizontal_scroll_margin.as_ref()
1302 },
1303 write: |settings_content, value| {
1304 settings_content.editor.horizontal_scroll_margin = value;
1305 },
1306 }),
1307 metadata: None,
1308 files: USER,
1309 }),
1310 SettingsPageItem::SettingItem(SettingItem {
1311 title: "Scroll Sensitivity",
1312 description: "Scroll sensitivity multiplier for both horizontal and vertical scrolling.",
1313 field: Box::new(SettingField {
1314 json_path: Some("scroll_sensitivity"),
1315 pick: |settings_content| {
1316 settings_content.editor.scroll_sensitivity.as_ref()
1317 },
1318 write: |settings_content, value| {
1319 settings_content.editor.scroll_sensitivity = value;
1320 },
1321 }),
1322 metadata: None,
1323 files: USER,
1324 }),
1325 SettingsPageItem::SettingItem(SettingItem {
1326 title: "Fast Scroll Sensitivity",
1327 description: "Fast scroll sensitivity multiplier for both horizontal and vertical scrolling.",
1328 field: Box::new(SettingField {
1329 json_path: Some("fast_scroll_sensitivity"),
1330 pick: |settings_content| {
1331 settings_content.editor.fast_scroll_sensitivity.as_ref()
1332 },
1333 write: |settings_content, value| {
1334 settings_content.editor.fast_scroll_sensitivity = value;
1335 },
1336 }),
1337 metadata: None,
1338 files: USER,
1339 }),
1340 SettingsPageItem::SettingItem(SettingItem {
1341 title: "Autoscroll On Clicks",
1342 description: "Whether to scroll when clicking near the edge of the visible text area.",
1343 field: Box::new(SettingField {
1344 json_path: Some("autoscroll_on_clicks"),
1345 pick: |settings_content| {
1346 settings_content.editor.autoscroll_on_clicks.as_ref()
1347 },
1348 write: |settings_content, value| {
1349 settings_content.editor.autoscroll_on_clicks = value;
1350 },
1351 }),
1352 metadata: None,
1353 files: USER,
1354 }),
1355 SettingsPageItem::SettingItem(SettingItem {
1356 title: "Sticky Scroll",
1357 description: "Whether to stick scopes to the top of the editor",
1358 field: Box::new(SettingField {
1359 json_path: Some("sticky_scroll.enabled"),
1360 pick: |settings_content| {
1361 settings_content.editor.sticky_scroll.as_ref().and_then(|sticky_scroll| sticky_scroll.enabled.as_ref())
1362 },
1363 write: |settings_content, value| {
1364 settings_content.editor.sticky_scroll.get_or_insert_default().enabled = value;
1365 },
1366 }),
1367 metadata: None,
1368 files: USER,
1369 }),
1370 SettingsPageItem::SectionHeader("Signature Help"),
1371 SettingsPageItem::SettingItem(SettingItem {
1372 title: "Auto Signature Help",
1373 description: "Automatically show a signature help pop-up.",
1374 field: Box::new(SettingField {
1375 json_path: Some("auto_signature_help"),
1376 pick: |settings_content| {
1377 settings_content.editor.auto_signature_help.as_ref()
1378 },
1379 write: |settings_content, value| {
1380 settings_content.editor.auto_signature_help = value;
1381 },
1382 }),
1383 metadata: None,
1384 files: USER,
1385 }),
1386 SettingsPageItem::SettingItem(SettingItem {
1387 title: "Show Signature Help After Edits",
1388 description: "Show the signature help pop-up after completions or bracket pairs are inserted.",
1389 field: Box::new(SettingField {
1390 json_path: Some("show_signature_help_after_edits"),
1391 pick: |settings_content| {
1392 settings_content
1393 .editor
1394 .show_signature_help_after_edits
1395 .as_ref()
1396 },
1397 write: |settings_content, value| {
1398 settings_content.editor.show_signature_help_after_edits = value;
1399 },
1400 }),
1401 metadata: None,
1402 files: USER,
1403 }),
1404 SettingsPageItem::SettingItem(SettingItem {
1405 title: "Snippet Sort Order",
1406 description: "Determines how snippets are sorted relative to other completion items.",
1407 field: Box::new(SettingField {
1408 json_path: Some("snippet_sort_order"),
1409 pick: |settings_content| {
1410 settings_content.editor.snippet_sort_order.as_ref()
1411 },
1412 write: |settings_content, value| {
1413 settings_content.editor.snippet_sort_order = value;
1414 },
1415 }),
1416 metadata: None,
1417 files: USER,
1418 }),
1419 SettingsPageItem::SectionHeader("Hover Popover"),
1420 SettingsPageItem::SettingItem(SettingItem {
1421 title: "Enabled",
1422 description: "Show the informational hover box when moving the mouse over symbols in the editor.",
1423 field: Box::new(SettingField {
1424 json_path: Some("hover_popover_enabled"),
1425 pick: |settings_content| {
1426 settings_content.editor.hover_popover_enabled.as_ref()
1427 },
1428 write: |settings_content, value| {
1429 settings_content.editor.hover_popover_enabled = value;
1430 },
1431 }),
1432 metadata: None,
1433 files: USER,
1434 }),
1435 // todo(settings ui): add units to this number input
1436 SettingsPageItem::SettingItem(SettingItem {
1437 title: "Delay",
1438 description: "Time to wait in milliseconds before showing the informational hover box.",
1439 field: Box::new(SettingField {
1440 json_path: Some("hover_popover_enabled"),
1441 pick: |settings_content| {
1442 settings_content.editor.hover_popover_delay.as_ref()
1443 },
1444 write: |settings_content, value| {
1445 settings_content.editor.hover_popover_delay = value;
1446 },
1447 }),
1448 metadata: None,
1449 files: USER,
1450 }),
1451 SettingsPageItem::SectionHeader("Drag And Drop Selection"),
1452 SettingsPageItem::SettingItem(SettingItem {
1453 title: "Enabled",
1454 description: "Enable drag and drop selection.",
1455 field: Box::new(SettingField {
1456 json_path: Some("drag_and_drop_selection.enabled"),
1457 pick: |settings_content| {
1458 settings_content
1459 .editor
1460 .drag_and_drop_selection
1461 .as_ref()
1462 .and_then(|drag_and_drop| drag_and_drop.enabled.as_ref())
1463 },
1464 write: |settings_content, value| {
1465 settings_content
1466 .editor
1467 .drag_and_drop_selection
1468 .get_or_insert_default()
1469 .enabled = value;
1470 },
1471 }),
1472 metadata: None,
1473 files: USER,
1474 }),
1475 SettingsPageItem::SettingItem(SettingItem {
1476 title: "Delay",
1477 description: "Delay in milliseconds before drag and drop selection starts.",
1478 field: Box::new(SettingField {
1479 json_path: Some("drag_and_drop_selection.delay"),
1480 pick: |settings_content| {
1481 settings_content
1482 .editor
1483 .drag_and_drop_selection
1484 .as_ref()
1485 .and_then(|drag_and_drop| drag_and_drop.delay.as_ref())
1486 },
1487 write: |settings_content, value| {
1488 settings_content
1489 .editor
1490 .drag_and_drop_selection
1491 .get_or_insert_default()
1492 .delay = value;
1493 },
1494 }),
1495 metadata: None,
1496 files: USER,
1497 }),
1498 SettingsPageItem::SectionHeader("Gutter"),
1499 SettingsPageItem::SettingItem(SettingItem {
1500 title: "Show Line Numbers",
1501 description: "Show line numbers in the gutter.",
1502 field: Box::new(SettingField {
1503 json_path: Some("gutter.line_numbers"),
1504 pick: |settings_content| {
1505 settings_content
1506 .editor
1507 .gutter
1508 .as_ref()
1509 .and_then(|gutter| gutter.line_numbers.as_ref())
1510 },
1511 write: |settings_content, value| {
1512 settings_content
1513 .editor
1514 .gutter
1515 .get_or_insert_default()
1516 .line_numbers = value;
1517 },
1518 }),
1519 metadata: None,
1520 files: USER,
1521 }),
1522 SettingsPageItem::SettingItem(SettingItem {
1523 title: "Relative Line Numbers",
1524 description: "Controls line number display in the editor's gutter. \"disabled\" shows absolute line numbers, \"enabled\" shows relative line numbers for each absolute line, and \"wrapped\" shows relative line numbers for every line, absolute or wrapped.",
1525 field: Box::new(SettingField {
1526 json_path: Some("relative_line_numbers"),
1527 pick: |settings_content| {
1528 settings_content.editor.relative_line_numbers.as_ref()
1529 },
1530 write: |settings_content, value| {
1531 settings_content.editor.relative_line_numbers = value;
1532 },
1533 }),
1534 metadata: None,
1535 files: USER,
1536 }),
1537 SettingsPageItem::SettingItem(SettingItem {
1538 title: "Show Runnables",
1539 description: "Show runnable buttons in the gutter.",
1540 field: Box::new(SettingField {
1541 json_path: Some("gutter.runnables"),
1542 pick: |settings_content| {
1543 settings_content
1544 .editor
1545 .gutter
1546 .as_ref()
1547 .and_then(|gutter| gutter.runnables.as_ref())
1548 },
1549 write: |settings_content, value| {
1550 settings_content
1551 .editor
1552 .gutter
1553 .get_or_insert_default()
1554 .runnables = value;
1555 },
1556 }),
1557 metadata: None,
1558 files: USER,
1559 }),
1560 SettingsPageItem::SettingItem(SettingItem {
1561 title: "Show Breakpoints",
1562 description: "Show breakpoints in the gutter.",
1563 field: Box::new(SettingField {
1564 json_path: Some("gutter.breakpoints"),
1565 pick: |settings_content| {
1566 settings_content
1567 .editor
1568 .gutter
1569 .as_ref()
1570 .and_then(|gutter| gutter.breakpoints.as_ref())
1571 },
1572 write: |settings_content, value| {
1573 settings_content
1574 .editor
1575 .gutter
1576 .get_or_insert_default()
1577 .breakpoints = value;
1578 },
1579 }),
1580 metadata: None,
1581 files: USER,
1582 }),
1583 SettingsPageItem::SettingItem(SettingItem {
1584 title: "Show Folds",
1585 description: "Show code folding controls in the gutter.",
1586 field: Box::new(SettingField {
1587 json_path: Some("gutter.folds"),
1588 pick: |settings_content| {
1589 settings_content
1590 .editor
1591 .gutter
1592 .as_ref()
1593 .and_then(|gutter| gutter.folds.as_ref())
1594 },
1595 write: |settings_content, value| {
1596 settings_content.editor.gutter.get_or_insert_default().folds =
1597 value;
1598 },
1599 }),
1600 metadata: None,
1601 files: USER,
1602 }),
1603 SettingsPageItem::SettingItem(SettingItem {
1604 title: "Min Line Number Digits",
1605 description: "Minimum number of characters to reserve space for in the gutter.",
1606 field: Box::new(SettingField {
1607 json_path: Some("gutter.min_line_number_digits"),
1608 pick: |settings_content| {
1609 settings_content
1610 .editor
1611 .gutter
1612 .as_ref()
1613 .and_then(|gutter| gutter.min_line_number_digits.as_ref())
1614 },
1615 write: |settings_content, value| {
1616 settings_content
1617 .editor
1618 .gutter
1619 .get_or_insert_default()
1620 .min_line_number_digits = value;
1621 },
1622 }),
1623 metadata: None,
1624 files: USER,
1625 }),
1626 SettingsPageItem::SettingItem(SettingItem {
1627 title: "Inline Code Actions",
1628 description: "Show code action button at start of buffer line.",
1629 field: Box::new(SettingField {
1630 json_path: Some("inline_code_actions"),
1631 pick: |settings_content| {
1632 settings_content.editor.inline_code_actions.as_ref()
1633 },
1634 write: |settings_content, value| {
1635 settings_content.editor.inline_code_actions = value;
1636 },
1637 }),
1638 metadata: None,
1639 files: USER,
1640 }),
1641 SettingsPageItem::SectionHeader("Scrollbar"),
1642 SettingsPageItem::SettingItem(SettingItem {
1643 title: "Show",
1644 description: "When to show the scrollbar in the editor.",
1645 field: Box::new(SettingField {
1646 json_path: Some("scrollbar"),
1647 pick: |settings_content| {
1648 settings_content.editor.scrollbar.as_ref()?.show.as_ref()
1649 },
1650 write: |settings_content, value| {
1651 settings_content
1652 .editor
1653 .scrollbar
1654 .get_or_insert_default()
1655 .show = value;
1656 },
1657 }),
1658 metadata: None,
1659 files: USER,
1660 }),
1661 SettingsPageItem::SettingItem(SettingItem {
1662 title: "Cursors",
1663 description: "Show cursor positions in the scrollbar.",
1664 field: Box::new(SettingField {
1665 json_path: Some("scrollbar.cursors"),
1666 pick: |settings_content| {
1667 settings_content.editor.scrollbar.as_ref()?.cursors.as_ref()
1668 },
1669 write: |settings_content, value| {
1670 settings_content
1671 .editor
1672 .scrollbar
1673 .get_or_insert_default()
1674 .cursors = value;
1675 },
1676 }),
1677 metadata: None,
1678 files: USER,
1679 }),
1680 SettingsPageItem::SettingItem(SettingItem {
1681 title: "Git Diff",
1682 description: "Show Git diff indicators in the scrollbar.",
1683 field: Box::new(SettingField {
1684 json_path: Some("scrollbar.git_diff"),
1685 pick: |settings_content| {
1686 settings_content
1687 .editor
1688 .scrollbar
1689 .as_ref()?
1690 .git_diff
1691 .as_ref()
1692 },
1693 write: |settings_content, value| {
1694 settings_content
1695 .editor
1696 .scrollbar
1697 .get_or_insert_default()
1698 .git_diff = value;
1699 },
1700 }),
1701 metadata: None,
1702 files: USER,
1703 }),
1704 SettingsPageItem::SettingItem(SettingItem {
1705 title: "Search Results",
1706 description: "Show buffer search result indicators in the scrollbar.",
1707 field: Box::new(SettingField {
1708 json_path: Some("scrollbar.search_results"),
1709 pick: |settings_content| {
1710 settings_content
1711 .editor
1712 .scrollbar
1713 .as_ref()?
1714 .search_results
1715 .as_ref()
1716 },
1717 write: |settings_content, value| {
1718 settings_content
1719 .editor
1720 .scrollbar
1721 .get_or_insert_default()
1722 .search_results = value;
1723 },
1724 }),
1725 metadata: None,
1726 files: USER,
1727 }),
1728 SettingsPageItem::SettingItem(SettingItem {
1729 title: "Selected Text",
1730 description: "Show selected text occurrences in the scrollbar.",
1731 field: Box::new(SettingField {
1732 json_path: Some("scrollbar.selected_text"),
1733 pick: |settings_content| {
1734 settings_content
1735 .editor
1736 .scrollbar
1737 .as_ref()?
1738 .selected_text
1739 .as_ref()
1740 },
1741 write: |settings_content, value| {
1742 settings_content
1743 .editor
1744 .scrollbar
1745 .get_or_insert_default()
1746 .selected_text = value;
1747 },
1748 }),
1749 metadata: None,
1750 files: USER,
1751 }),
1752 SettingsPageItem::SettingItem(SettingItem {
1753 title: "Selected Symbol",
1754 description: "Show selected symbol occurrences in the scrollbar.",
1755 field: Box::new(SettingField {
1756 json_path: Some("scrollbar.selected_symbol"),
1757 pick: |settings_content| {
1758 settings_content
1759 .editor
1760 .scrollbar
1761 .as_ref()?
1762 .selected_symbol
1763 .as_ref()
1764 },
1765 write: |settings_content, value| {
1766 settings_content
1767 .editor
1768 .scrollbar
1769 .get_or_insert_default()
1770 .selected_symbol = value;
1771 },
1772 }),
1773 metadata: None,
1774 files: USER,
1775 }),
1776 SettingsPageItem::SettingItem(SettingItem {
1777 title: "Diagnostics",
1778 description: "Which diagnostic indicators to show in the scrollbar.",
1779 field: Box::new(SettingField {
1780 json_path: Some("scrollbar.diagnostics"),
1781 pick: |settings_content| {
1782 settings_content
1783 .editor
1784 .scrollbar
1785 .as_ref()?
1786 .diagnostics
1787 .as_ref()
1788 },
1789 write: |settings_content, value| {
1790 settings_content
1791 .editor
1792 .scrollbar
1793 .get_or_insert_default()
1794 .diagnostics = value;
1795 },
1796 }),
1797 metadata: None,
1798 files: USER,
1799 }),
1800 SettingsPageItem::SettingItem(SettingItem {
1801 title: "Horizontal Scrollbar",
1802 description: "When false, forcefully disables the horizontal scrollbar.",
1803 field: Box::new(SettingField {
1804 json_path: Some("scrollbar.axes.horizontal"),
1805 pick: |settings_content| {
1806 settings_content
1807 .editor
1808 .scrollbar
1809 .as_ref()?
1810 .axes
1811 .as_ref()?
1812 .horizontal
1813 .as_ref()
1814 },
1815 write: |settings_content, value| {
1816 settings_content
1817 .editor
1818 .scrollbar
1819 .get_or_insert_default()
1820 .axes
1821 .get_or_insert_default()
1822 .horizontal = value;
1823 },
1824 }),
1825 metadata: None,
1826 files: USER,
1827 }),
1828 SettingsPageItem::SettingItem(SettingItem {
1829 title: "Vertical Scrollbar",
1830 description: "When false, forcefully disables the vertical scrollbar.",
1831 field: Box::new(SettingField {
1832 json_path: Some("scrollbar.axes.vertical"),
1833 pick: |settings_content| {
1834 settings_content
1835 .editor
1836 .scrollbar
1837 .as_ref()?
1838 .axes
1839 .as_ref()?
1840 .vertical
1841 .as_ref()
1842 },
1843 write: |settings_content, value| {
1844 settings_content
1845 .editor
1846 .scrollbar
1847 .get_or_insert_default()
1848 .axes
1849 .get_or_insert_default()
1850 .vertical = value;
1851 },
1852 }),
1853 metadata: None,
1854 files: USER,
1855 }),
1856 SettingsPageItem::SectionHeader("Minimap"),
1857 SettingsPageItem::SettingItem(SettingItem {
1858 title: "Show",
1859 description: "When to show the minimap in the editor.",
1860 field: Box::new(SettingField {
1861 json_path: Some("minimap.show"),
1862 pick: |settings_content| {
1863 settings_content.editor.minimap.as_ref()?.show.as_ref()
1864 },
1865 write: |settings_content, value| {
1866 settings_content.editor.minimap.get_or_insert_default().show =
1867 value;
1868 },
1869 }),
1870 metadata: None,
1871 files: USER,
1872 }),
1873 SettingsPageItem::SettingItem(SettingItem {
1874 title: "Display In",
1875 description: "Where to show the minimap in the editor.",
1876 field: Box::new(SettingField {
1877 json_path: Some("minimap.display_in"),
1878 pick: |settings_content| {
1879 settings_content
1880 .editor
1881 .minimap
1882 .as_ref()?
1883 .display_in
1884 .as_ref()
1885 },
1886 write: |settings_content, value| {
1887 settings_content
1888 .editor
1889 .minimap
1890 .get_or_insert_default()
1891 .display_in = value;
1892 },
1893 }),
1894 metadata: None,
1895 files: USER,
1896 }),
1897 SettingsPageItem::SettingItem(SettingItem {
1898 title: "Thumb",
1899 description: "When to show the minimap thumb.",
1900 field: Box::new(SettingField {
1901 json_path: Some("minimap.thumb"),
1902 pick: |settings_content| {
1903 settings_content.editor.minimap.as_ref()?.thumb.as_ref()
1904 },
1905 write: |settings_content, value| {
1906 settings_content
1907 .editor
1908 .minimap
1909 .get_or_insert_default()
1910 .thumb = value;
1911 },
1912 }),
1913 metadata: None,
1914 files: USER,
1915 }),
1916 SettingsPageItem::SettingItem(SettingItem {
1917 title: "Thumb Border",
1918 description: "Border style for the minimap's scrollbar thumb.",
1919 field: Box::new(SettingField {
1920 json_path: Some("minimap.thumb_border"),
1921 pick: |settings_content| {
1922 settings_content
1923 .editor
1924 .minimap
1925 .as_ref()?
1926 .thumb_border
1927 .as_ref()
1928 },
1929 write: |settings_content, value| {
1930 settings_content
1931 .editor
1932 .minimap
1933 .get_or_insert_default()
1934 .thumb_border = value;
1935 },
1936 }),
1937 metadata: None,
1938 files: USER,
1939 }),
1940 SettingsPageItem::SettingItem(SettingItem {
1941 title: "Current Line Highlight",
1942 description: "How to highlight the current line in the minimap.",
1943 field: Box::new(SettingField {
1944 json_path: Some("minimap.current_line_highlight"),
1945 pick: |settings_content| {
1946 settings_content
1947 .editor
1948 .minimap
1949 .as_ref()
1950 .and_then(|minimap| minimap.current_line_highlight.as_ref())
1951 .or(settings_content.editor.current_line_highlight.as_ref())
1952 },
1953 write: |settings_content, value| {
1954 settings_content
1955 .editor
1956 .minimap
1957 .get_or_insert_default()
1958 .current_line_highlight = value;
1959 },
1960 }),
1961 metadata: None,
1962 files: USER,
1963 }),
1964 SettingsPageItem::SettingItem(SettingItem {
1965 title: "Max Width Columns",
1966 description: "Maximum number of columns to display in the minimap.",
1967 field: Box::new(SettingField {
1968 json_path: Some("minimap.max_width_columns"),
1969 pick: |settings_content| {
1970 settings_content
1971 .editor
1972 .minimap
1973 .as_ref()?
1974 .max_width_columns
1975 .as_ref()
1976 },
1977 write: |settings_content, value| {
1978 settings_content
1979 .editor
1980 .minimap
1981 .get_or_insert_default()
1982 .max_width_columns = value;
1983 },
1984 }),
1985 metadata: None,
1986 files: USER,
1987 }),
1988 SettingsPageItem::SectionHeader("Toolbar"),
1989 SettingsPageItem::SettingItem(SettingItem {
1990 title: "Breadcrumbs",
1991 description: "Show breadcrumbs.",
1992 field: Box::new(SettingField {
1993 json_path: Some("toolbar.breadcrumbs"),
1994 pick: |settings_content| {
1995 settings_content
1996 .editor
1997 .toolbar
1998 .as_ref()?
1999 .breadcrumbs
2000 .as_ref()
2001 },
2002 write: |settings_content, value| {
2003 settings_content
2004 .editor
2005 .toolbar
2006 .get_or_insert_default()
2007 .breadcrumbs = value;
2008 },
2009 }),
2010 metadata: None,
2011 files: USER,
2012 }),
2013 SettingsPageItem::SettingItem(SettingItem {
2014 title: "Quick Actions",
2015 description: "Show quick action buttons (e.g., search, selection, editor controls, etc.).",
2016 field: Box::new(SettingField {
2017 json_path: Some("toolbar.quick_actions"),
2018 pick: |settings_content| {
2019 settings_content
2020 .editor
2021 .toolbar
2022 .as_ref()?
2023 .quick_actions
2024 .as_ref()
2025 },
2026 write: |settings_content, value| {
2027 settings_content
2028 .editor
2029 .toolbar
2030 .get_or_insert_default()
2031 .quick_actions = value;
2032 },
2033 }),
2034 metadata: None,
2035 files: USER,
2036 }),
2037 SettingsPageItem::SettingItem(SettingItem {
2038 title: "Selections Menu",
2039 description: "Show the selections menu in the editor toolbar.",
2040 field: Box::new(SettingField {
2041 json_path: Some("toolbar.selections_menu"),
2042 pick: |settings_content| {
2043 settings_content
2044 .editor
2045 .toolbar
2046 .as_ref()?
2047 .selections_menu
2048 .as_ref()
2049 },
2050 write: |settings_content, value| {
2051 settings_content
2052 .editor
2053 .toolbar
2054 .get_or_insert_default()
2055 .selections_menu = value;
2056 },
2057 }),
2058 metadata: None,
2059 files: USER,
2060 }),
2061 SettingsPageItem::SettingItem(SettingItem {
2062 title: "Agent Review",
2063 description: "Show agent review buttons in the editor toolbar.",
2064 field: Box::new(SettingField {
2065 json_path: Some("toolbar.agent_review"),
2066 pick: |settings_content| {
2067 settings_content
2068 .editor
2069 .toolbar
2070 .as_ref()?
2071 .agent_review
2072 .as_ref()
2073 },
2074 write: |settings_content, value| {
2075 settings_content
2076 .editor
2077 .toolbar
2078 .get_or_insert_default()
2079 .agent_review = value;
2080 },
2081 }),
2082 metadata: None,
2083 files: USER,
2084 }),
2085 SettingsPageItem::SettingItem(SettingItem {
2086 title: "Code Actions",
2087 description: "Show code action buttons in the editor toolbar.",
2088 field: Box::new(SettingField {
2089 json_path: Some("toolbar.code_actions"),
2090 pick: |settings_content| {
2091 settings_content
2092 .editor
2093 .toolbar
2094 .as_ref()?
2095 .code_actions
2096 .as_ref()
2097 },
2098 write: |settings_content, value| {
2099 settings_content
2100 .editor
2101 .toolbar
2102 .get_or_insert_default()
2103 .code_actions = value;
2104 },
2105 }),
2106 metadata: None,
2107 files: USER,
2108 }),
2109 ];
2110 items.extend(language_settings_data());
2111 items
2112 },
2113 },
2114 SettingsPage {
2115 title: "Languages & Tools",
2116 items: {
2117 let mut items = vec![];
2118 items.extend(non_editor_language_settings_data());
2119 items.extend([
2120 SettingsPageItem::SectionHeader("File Types"),
2121 SettingsPageItem::SettingItem(SettingItem {
2122 title: "File Type Associations",
2123 description: "A mapping from languages to files and file extensions that should be treated as that language.",
2124 field: Box::new(
2125 SettingField {
2126 json_path: Some("file_type_associations"),
2127 pick: |settings_content| {
2128 settings_content.project.all_languages.file_types.as_ref()
2129 },
2130 write: |settings_content, value| {
2131 settings_content.project.all_languages.file_types = value;
2132
2133 },
2134 }
2135 .unimplemented(),
2136 ),
2137 metadata: None,
2138 files: USER | PROJECT,
2139 }),
2140 ]);
2141
2142 items.extend([
2143 SettingsPageItem::SectionHeader("Diagnostics"),
2144 SettingsPageItem::SettingItem(SettingItem {
2145 title: "Max Severity",
2146 description: "Which level to use to filter out diagnostics displayed in the editor.",
2147 field: Box::new(SettingField {
2148 json_path: Some("diagnostics_max_severity"),
2149 pick: |settings_content| settings_content.editor.diagnostics_max_severity.as_ref(),
2150 write: |settings_content, value| {
2151 settings_content.editor.diagnostics_max_severity = value;
2152
2153 },
2154 }),
2155 metadata: None,
2156 files: USER,
2157 }),
2158 SettingsPageItem::SettingItem(SettingItem {
2159 title: "Include Warnings",
2160 description: "Whether to show warnings or not by default.",
2161 field: Box::new(SettingField {
2162 json_path: Some("diagnostics.include_warnings"),
2163 pick: |settings_content| {
2164 settings_content.diagnostics.as_ref()?.include_warnings.as_ref()
2165 },
2166 write: |settings_content, value| {
2167 settings_content
2168
2169 .diagnostics
2170 .get_or_insert_default()
2171 .include_warnings
2172 = value;
2173 },
2174 }),
2175 metadata: None,
2176 files: USER,
2177 }),
2178 SettingsPageItem::SectionHeader("Inline Diagnostics"),
2179 SettingsPageItem::SettingItem(SettingItem {
2180 title: "Enabled",
2181 description: "Whether to show diagnostics inline or not.",
2182 field: Box::new(SettingField {
2183 json_path: Some("diagnostics.inline.enabled"),
2184 pick: |settings_content| {
2185 settings_content.diagnostics.as_ref()?.inline.as_ref()?.enabled.as_ref()
2186 },
2187 write: |settings_content, value| {
2188 settings_content
2189
2190 .diagnostics
2191 .get_or_insert_default()
2192 .inline
2193 .get_or_insert_default()
2194 .enabled
2195 = value;
2196 },
2197 }),
2198 metadata: None,
2199 files: USER,
2200 }),
2201 SettingsPageItem::SettingItem(SettingItem {
2202 title: "Update Debounce",
2203 description: "The delay in milliseconds to show inline diagnostics after the last diagnostic update.",
2204 field: Box::new(SettingField {
2205 json_path: Some("diagnostics.inline.update_debounce_ms"),
2206 pick: |settings_content| {
2207 settings_content.diagnostics.as_ref()?.inline.as_ref()?.update_debounce_ms.as_ref()
2208 },
2209 write: |settings_content, value| {
2210 settings_content
2211
2212 .diagnostics
2213 .get_or_insert_default()
2214 .inline
2215 .get_or_insert_default()
2216 .update_debounce_ms
2217 = value;
2218 },
2219 }),
2220 metadata: None,
2221 files: USER,
2222 }),
2223 SettingsPageItem::SettingItem(SettingItem {
2224 title: "Padding",
2225 description: "The amount of padding between the end of the source line and the start of the inline diagnostic.",
2226 field: Box::new(SettingField {
2227 json_path: Some("diagnostics.inline.padding"),
2228 pick: |settings_content| {
2229 settings_content.diagnostics.as_ref()?.inline.as_ref()?.padding.as_ref()
2230 },
2231 write: |settings_content, value| {
2232 settings_content
2233
2234 .diagnostics
2235 .get_or_insert_default()
2236 .inline
2237 .get_or_insert_default()
2238 .padding
2239 = value;
2240 },
2241 }),
2242 metadata: None,
2243 files: USER,
2244 }),
2245 SettingsPageItem::SettingItem(SettingItem {
2246 title: "Minimum Column",
2247 description: "The minimum column at which to display inline diagnostics.",
2248 field: Box::new(SettingField {
2249 json_path: Some("diagnostics.inline.min_column"),
2250 pick: |settings_content| {
2251 settings_content.diagnostics.as_ref()?.inline.as_ref()?.min_column.as_ref()
2252 },
2253 write: |settings_content, value| {
2254 settings_content
2255
2256 .diagnostics
2257 .get_or_insert_default()
2258 .inline
2259 .get_or_insert_default()
2260 .min_column
2261 = value;
2262 },
2263 }),
2264 metadata: None,
2265 files: USER,
2266 }),
2267 SettingsPageItem::SectionHeader("LSP Pull Diagnostics"),
2268 SettingsPageItem::SettingItem(SettingItem {
2269 title: "Enabled",
2270 description: "Whether to pull for language server-powered diagnostics or not.",
2271 field: Box::new(SettingField {
2272 json_path: Some("diagnostics.lsp_pull_diagnostics.enabled"),
2273 pick: |settings_content| {
2274 settings_content.diagnostics.as_ref()?.lsp_pull_diagnostics.as_ref()?.enabled.as_ref()
2275 },
2276 write: |settings_content, value| {
2277 settings_content
2278
2279 .diagnostics
2280 .get_or_insert_default()
2281 .lsp_pull_diagnostics
2282 .get_or_insert_default()
2283 .enabled
2284 = value;
2285 },
2286 }),
2287 metadata: None,
2288 files: USER,
2289 }),
2290 // todo(settings_ui): Needs unit
2291 SettingsPageItem::SettingItem(SettingItem {
2292 title: "Debounce",
2293 description: "Minimum time to wait before pulling diagnostics from the language server(s).",
2294 field: Box::new(SettingField {
2295 json_path: Some("diagnostics.lsp_pull_diagnostics.debounce_ms"),
2296 pick: |settings_content| {
2297 settings_content.diagnostics.as_ref()?.lsp_pull_diagnostics.as_ref()?.debounce_ms.as_ref()
2298 },
2299 write: |settings_content, value| {
2300 settings_content
2301
2302 .diagnostics
2303 .get_or_insert_default()
2304 .lsp_pull_diagnostics
2305 .get_or_insert_default()
2306 .debounce_ms
2307 = value;
2308 },
2309 }),
2310 metadata: None,
2311 files: USER,
2312 }),
2313 SettingsPageItem::SectionHeader("LSP Highlights"),
2314 SettingsPageItem::SettingItem(SettingItem {
2315 title: "Debounce",
2316 description: "The debounce delay before querying highlights from the language.",
2317 field: Box::new(SettingField {
2318 json_path: Some("lsp_highlight_debounce"),
2319 pick: |settings_content| settings_content.editor.lsp_highlight_debounce.as_ref(),
2320 write: |settings_content, value| {
2321 settings_content.editor.lsp_highlight_debounce = value;
2322 },
2323 }),
2324 metadata: None,
2325 files: USER,
2326 }),
2327 ]);
2328
2329 // todo(settings_ui): Refresh on extension (un)/installed
2330 // Note that `crates/json_schema_store` solves the same problem, there is probably a way to unify the two
2331 items.push(SettingsPageItem::SectionHeader(LANGUAGES_SECTION_HEADER));
2332 items.extend(all_language_names(cx).into_iter().map(|language_name| {
2333 SettingsPageItem::SubPageLink(SubPageLink {
2334 title: language_name,
2335 files: USER | PROJECT,
2336 render: Arc::new(|this, window, cx| {
2337 this.render_sub_page_items(
2338 language_settings_data()
2339 .iter()
2340 .chain(non_editor_language_settings_data().iter())
2341 .chain(edit_prediction_language_settings_section().iter())
2342 .enumerate(),
2343 None,
2344 window,
2345 cx,
2346 )
2347 .into_any_element()
2348 }),
2349 })
2350 }));
2351 items
2352 },
2353 },
2354 SettingsPage {
2355 title: "Search & Files",
2356 items: vec![
2357 SettingsPageItem::SectionHeader("Search"),
2358 SettingsPageItem::SettingItem(SettingItem {
2359 title: "Whole Word",
2360 description: "Search for whole words by default.",
2361 field: Box::new(SettingField {
2362 json_path: Some("search.whole_word"),
2363 pick: |settings_content| {
2364 settings_content.editor.search.as_ref()?.whole_word.as_ref()
2365 },
2366 write: |settings_content, value| {
2367 settings_content
2368 .editor
2369 .search
2370 .get_or_insert_default()
2371 .whole_word = value;
2372 },
2373 }),
2374 metadata: None,
2375 files: USER,
2376 }),
2377 SettingsPageItem::SettingItem(SettingItem {
2378 title: "Case Sensitive",
2379 description: "Search case-sensitively by default.",
2380 field: Box::new(SettingField {
2381 json_path: Some("search.case_sensitive"),
2382 pick: |settings_content| {
2383 settings_content
2384 .editor
2385 .search
2386 .as_ref()?
2387 .case_sensitive
2388 .as_ref()
2389 },
2390 write: |settings_content, value| {
2391 settings_content
2392 .editor
2393 .search
2394 .get_or_insert_default()
2395 .case_sensitive = value;
2396 },
2397 }),
2398 metadata: None,
2399 files: USER,
2400 }),
2401 SettingsPageItem::SettingItem(SettingItem {
2402 title: "Use Smartcase Search",
2403 description: "Whether to automatically enable case-sensitive search based on the search query.",
2404 field: Box::new(SettingField {
2405 json_path: Some("use_smartcase_search"),
2406 pick: |settings_content| {
2407 settings_content.editor.use_smartcase_search.as_ref()
2408 },
2409 write: |settings_content, value| {
2410 settings_content.editor.use_smartcase_search = value;
2411 },
2412 }),
2413 metadata: None,
2414 files: USER,
2415 }),
2416 SettingsPageItem::SettingItem(SettingItem {
2417 title: "Include Ignored",
2418 description: "Include ignored files in search results by default.",
2419 field: Box::new(SettingField {
2420 json_path: Some("search.include_ignored"),
2421 pick: |settings_content| {
2422 settings_content
2423 .editor
2424 .search
2425 .as_ref()?
2426 .include_ignored
2427 .as_ref()
2428 },
2429 write: |settings_content, value| {
2430 settings_content
2431 .editor
2432 .search
2433 .get_or_insert_default()
2434 .include_ignored = value;
2435 },
2436 }),
2437 metadata: None,
2438 files: USER,
2439 }),
2440 SettingsPageItem::SettingItem(SettingItem {
2441 title: "Regex",
2442 description: "Use regex search by default.",
2443 field: Box::new(SettingField {
2444 json_path: Some("search.regex"),
2445 pick: |settings_content| {
2446 settings_content.editor.search.as_ref()?.regex.as_ref()
2447 },
2448 write: |settings_content, value| {
2449 settings_content.editor.search.get_or_insert_default().regex = value;
2450 },
2451 }),
2452 metadata: None,
2453 files: USER,
2454 }),
2455 SettingsPageItem::SettingItem(SettingItem {
2456 title: "Search Wrap",
2457 description: "Whether the editor search results will loop.",
2458 field: Box::new(SettingField {
2459 json_path: Some("search_wrap"),
2460 pick: |settings_content| settings_content.editor.search_wrap.as_ref(),
2461 write: |settings_content, value| {
2462 settings_content.editor.search_wrap = value;
2463 },
2464 }),
2465 metadata: None,
2466 files: USER,
2467 }),
2468 SettingsPageItem::SettingItem(SettingItem {
2469 title: "Center on Match",
2470 description: "Whether to center the current match in the editor",
2471 field: Box::new(SettingField {
2472 json_path: Some("editor.search.center_on_match"),
2473 pick: |settings_content| {
2474 settings_content
2475 .editor
2476 .search
2477 .as_ref()
2478 .and_then(|search| search.center_on_match.as_ref())
2479 },
2480 write: |settings_content, value| {
2481 settings_content
2482 .editor
2483 .search
2484 .get_or_insert_default()
2485 .center_on_match = value;
2486 },
2487 }),
2488 metadata: None,
2489 files: USER,
2490 }),
2491 SettingsPageItem::SettingItem(SettingItem {
2492 title: "Seed Search Query From Cursor",
2493 description: "When to populate a new search's query based on the text under the cursor.",
2494 field: Box::new(SettingField {
2495 json_path: Some("seed_search_query_from_cursor"),
2496 pick: |settings_content| {
2497 settings_content
2498 .editor
2499 .seed_search_query_from_cursor
2500 .as_ref()
2501 },
2502 write: |settings_content, value| {
2503 settings_content.editor.seed_search_query_from_cursor = value;
2504 },
2505 }),
2506 metadata: None,
2507 files: USER,
2508 }),
2509 SettingsPageItem::SectionHeader("File Finder"),
2510 // todo: null by default
2511 SettingsPageItem::SettingItem(SettingItem {
2512 title: "Include Ignored in Search",
2513 description: "Use gitignored files when searching.",
2514 field: Box::new(
2515 SettingField {
2516 json_path: Some("file_finder.include_ignored"),
2517 pick: |settings_content| {
2518 settings_content
2519 .file_finder
2520 .as_ref()?
2521 .include_ignored
2522 .as_ref()
2523 },
2524 write: |settings_content, value| {
2525 settings_content
2526 .file_finder
2527 .get_or_insert_default()
2528 .include_ignored = value;
2529 },
2530 }
2531 ),
2532 metadata: None,
2533 files: USER,
2534 }),
2535 SettingsPageItem::SettingItem(SettingItem {
2536 title: "File Icons",
2537 description: "Show file icons in the file finder.",
2538 field: Box::new(SettingField {
2539 json_path: Some("file_finder.file_icons"),
2540 pick: |settings_content| {
2541 settings_content.file_finder.as_ref()?.file_icons.as_ref()
2542 },
2543 write: |settings_content, value| {
2544 settings_content
2545 .file_finder
2546 .get_or_insert_default()
2547 .file_icons = value;
2548 },
2549 }),
2550 metadata: None,
2551 files: USER,
2552 }),
2553 SettingsPageItem::SettingItem(SettingItem {
2554 title: "Modal Max Width",
2555 description: "Determines how much space the file finder can take up in relation to the available window width.",
2556 field: Box::new(SettingField {
2557 json_path: Some("file_finder.modal_max_width"),
2558 pick: |settings_content| {
2559 settings_content
2560 .file_finder
2561 .as_ref()?
2562 .modal_max_width
2563 .as_ref()
2564 },
2565 write: |settings_content, value| {
2566 settings_content
2567 .file_finder
2568 .get_or_insert_default()
2569 .modal_max_width = value;
2570 },
2571 }),
2572 metadata: None,
2573 files: USER,
2574 }),
2575 SettingsPageItem::SettingItem(SettingItem {
2576 title: "Skip Focus For Active In Search",
2577 description: "Whether the file finder should skip focus for the active file in search results.",
2578 field: Box::new(SettingField {
2579 json_path: Some("file_finder.skip_focus_for_active_in_search"),
2580 pick: |settings_content| {
2581 settings_content
2582 .file_finder
2583 .as_ref()?
2584 .skip_focus_for_active_in_search
2585 .as_ref()
2586 },
2587 write: |settings_content, value| {
2588 settings_content
2589 .file_finder
2590 .get_or_insert_default()
2591 .skip_focus_for_active_in_search = value;
2592 },
2593 }),
2594 metadata: None,
2595 files: USER,
2596 }),
2597 SettingsPageItem::SettingItem(SettingItem {
2598 title: "Git Status",
2599 description: "Show the Git status in the file finder.",
2600 field: Box::new(SettingField {
2601 json_path: Some("file_finder.git_status"),
2602 pick: |settings_content| {
2603 settings_content.file_finder.as_ref()?.git_status.as_ref()
2604 },
2605 write: |settings_content, value| {
2606 settings_content
2607 .file_finder
2608 .get_or_insert_default()
2609 .git_status = value;
2610 },
2611 }),
2612 metadata: None,
2613 files: USER,
2614 }),
2615 SettingsPageItem::SectionHeader("File Scan"),
2616 SettingsPageItem::SettingItem(SettingItem {
2617 title: "File Scan Exclusions",
2618 description: "Files or globs of files that will be excluded by Zed entirely. They will be skipped during file scans, file searches, and not be displayed in the project file tree. Takes precedence over \"File Scan Inclusions\"",
2619 field: Box::new(
2620 SettingField {
2621 json_path: Some("file_scan_exclusions"),
2622 pick: |settings_content| {
2623 settings_content
2624 .project
2625 .worktree
2626 .file_scan_exclusions
2627 .as_ref()
2628 },
2629 write: |settings_content, value| {
2630 settings_content.project.worktree.file_scan_exclusions = value;
2631 },
2632 }
2633 .unimplemented(),
2634 ),
2635 metadata: None,
2636 files: USER,
2637 }),
2638 SettingsPageItem::SettingItem(SettingItem {
2639 title: "File Scan Inclusions",
2640 description: "Files or globs of files that will be included by Zed, even when ignored by git. This is useful for files that are not tracked by git, but are still important to your project. Note that globs that are overly broad can slow down Zed's file scanning. \"File Scan Exclusions\" takes precedence over these inclusions",
2641 field: Box::new(
2642 SettingField {
2643 json_path: Some("file_scan_inclusions"),
2644 pick: |settings_content| {
2645 settings_content
2646 .project
2647 .worktree
2648 .file_scan_inclusions
2649 .as_ref()
2650 },
2651 write: |settings_content, value| {
2652 settings_content.project.worktree.file_scan_inclusions = value;
2653 },
2654 }
2655 .unimplemented(),
2656 ),
2657 metadata: None,
2658 files: USER,
2659 }),
2660 SettingsPageItem::SettingItem(SettingItem {
2661 title: "Restore File State",
2662 description: "Restore previous file state when reopening.",
2663 field: Box::new(SettingField {
2664 json_path: Some("restore_on_file_reopen"),
2665 pick: |settings_content| {
2666 settings_content.workspace.restore_on_file_reopen.as_ref()
2667 },
2668 write: |settings_content, value| {
2669 settings_content.workspace.restore_on_file_reopen = value;
2670 },
2671 }),
2672 metadata: None,
2673 files: USER,
2674 }),
2675 SettingsPageItem::SettingItem(SettingItem {
2676 title: "Close on File Delete",
2677 description: "Automatically close files that have been deleted.",
2678 field: Box::new(SettingField {
2679 json_path: Some("close_on_file_delete"),
2680 pick: |settings_content| {
2681 settings_content.workspace.close_on_file_delete.as_ref()
2682 },
2683 write: |settings_content, value| {
2684 settings_content.workspace.close_on_file_delete = value;
2685 },
2686 }),
2687 metadata: None,
2688 files: USER,
2689 }),
2690 ],
2691 },
2692 SettingsPage {
2693 title: "Window & Layout",
2694 items: vec![
2695 SettingsPageItem::SectionHeader("Status Bar"),
2696 SettingsPageItem::SettingItem(SettingItem {
2697 title: "Project Panel Button",
2698 description: "Show the project panel button in the status bar.",
2699 field: Box::new(SettingField {
2700 json_path: Some("project_panel.button"),
2701 pick: |settings_content| {
2702 settings_content.project_panel.as_ref()?.button.as_ref()
2703 },
2704 write: |settings_content, value| {
2705 settings_content
2706 .project_panel
2707 .get_or_insert_default()
2708 .button = value;
2709 },
2710 }),
2711 metadata: None,
2712 files: USER,
2713 }),
2714 SettingsPageItem::SettingItem(SettingItem {
2715 title: "Active Language Button",
2716 description: "Show the active language button in the status bar.",
2717 field: Box::new(SettingField {
2718 json_path: Some("status_bar.active_language_button"),
2719 pick: |settings_content| {
2720 settings_content
2721 .status_bar
2722 .as_ref()?
2723 .active_language_button
2724 .as_ref()
2725 },
2726 write: |settings_content, value| {
2727 settings_content
2728 .status_bar
2729 .get_or_insert_default()
2730 .active_language_button = value;
2731 },
2732 }),
2733 metadata: None,
2734 files: USER,
2735 }),
2736 SettingsPageItem::SettingItem(SettingItem {
2737 title: "Cursor Position Button",
2738 description: "Show the cursor position button in the status bar.",
2739 field: Box::new(SettingField {
2740 json_path: Some("status_bar.cursor_position_button"),
2741 pick: |settings_content| {
2742 settings_content
2743 .status_bar
2744 .as_ref()?
2745 .cursor_position_button
2746 .as_ref()
2747 },
2748 write: |settings_content, value| {
2749 settings_content
2750 .status_bar
2751 .get_or_insert_default()
2752 .cursor_position_button = value;
2753 },
2754 }),
2755 metadata: None,
2756 files: USER,
2757 }),
2758 SettingsPageItem::SettingItem(SettingItem {
2759 title: "Terminal Button",
2760 description: "Show the terminal button in the status bar.",
2761 field: Box::new(SettingField {
2762 json_path: Some("terminal.button"),
2763 pick: |settings_content| {
2764 settings_content.terminal.as_ref()?.button.as_ref()
2765 },
2766 write: |settings_content, value| {
2767 settings_content.terminal.get_or_insert_default().button = value;
2768 },
2769 }),
2770 metadata: None,
2771 files: USER,
2772 }),
2773 SettingsPageItem::SettingItem(SettingItem {
2774 title: "Diagnostics Button",
2775 description: "Show the project diagnostics button in the status bar.",
2776 field: Box::new(SettingField {
2777 json_path: Some("diagnostics.button"),
2778 pick: |settings_content| {
2779 settings_content.diagnostics.as_ref()?.button.as_ref()
2780 },
2781 write: |settings_content, value| {
2782 settings_content.diagnostics.get_or_insert_default().button = value;
2783 },
2784 }),
2785 metadata: None,
2786 files: USER,
2787 }),
2788 SettingsPageItem::SettingItem(SettingItem {
2789 title: "Project Search Button",
2790 description: "Show the project search button in the status bar.",
2791 field: Box::new(SettingField {
2792 json_path: Some("search.button"),
2793 pick: |settings_content| {
2794 settings_content.editor.search.as_ref()?.button.as_ref()
2795 },
2796 write: |settings_content, value| {
2797 settings_content
2798 .editor
2799 .search
2800 .get_or_insert_default()
2801 .button = value;
2802 },
2803 }),
2804 metadata: None,
2805 files: USER,
2806 }),
2807 SettingsPageItem::SettingItem(SettingItem {
2808 title: "Debugger Button",
2809 description: "Show the debugger button in the status bar.",
2810 field: Box::new(SettingField {
2811 json_path: Some("debugger.button"),
2812 pick: |settings_content| {
2813 settings_content.debugger.as_ref()?.button.as_ref()
2814 },
2815 write: |settings_content, value| {
2816 settings_content.debugger.get_or_insert_default().button = value;
2817 },
2818 }),
2819 metadata: None,
2820 files: USER,
2821 }),
2822 SettingsPageItem::SectionHeader("Title Bar"),
2823 SettingsPageItem::SettingItem(SettingItem {
2824 title: "Show Branch Icon",
2825 description: "Show the branch icon beside branch switcher in the titlebar.",
2826 field: Box::new(SettingField {
2827 json_path: Some("title_bar.show_branch_icon"),
2828 pick: |settings_content| {
2829 settings_content
2830 .title_bar
2831 .as_ref()?
2832 .show_branch_icon
2833 .as_ref()
2834 },
2835 write: |settings_content, value| {
2836 settings_content
2837 .title_bar
2838 .get_or_insert_default()
2839 .show_branch_icon = value;
2840 },
2841 }),
2842 metadata: None,
2843 files: USER,
2844 }),
2845 SettingsPageItem::SettingItem(SettingItem {
2846 title: "Show Branch Name",
2847 description: "Show the branch name button in the titlebar.",
2848 field: Box::new(SettingField {
2849 json_path: Some("title_bar.show_branch_name"),
2850 pick: |settings_content| {
2851 settings_content
2852 .title_bar
2853 .as_ref()?
2854 .show_branch_name
2855 .as_ref()
2856 },
2857 write: |settings_content, value| {
2858 settings_content
2859 .title_bar
2860 .get_or_insert_default()
2861 .show_branch_name = value;
2862 },
2863 }),
2864 metadata: None,
2865 files: USER,
2866 }),
2867 SettingsPageItem::SettingItem(SettingItem {
2868 title: "Show Project Items",
2869 description: "Show the project host and name in the titlebar.",
2870 field: Box::new(SettingField {
2871 json_path: Some("title_bar.show_project_items"),
2872 pick: |settings_content| {
2873 settings_content
2874 .title_bar
2875 .as_ref()?
2876 .show_project_items
2877 .as_ref()
2878 },
2879 write: |settings_content, value| {
2880 settings_content
2881 .title_bar
2882 .get_or_insert_default()
2883 .show_project_items = value;
2884 },
2885 }),
2886 metadata: None,
2887 files: USER,
2888 }),
2889 SettingsPageItem::SettingItem(SettingItem {
2890 title: "Show Onboarding Banner",
2891 description: "Show banners announcing new features in the titlebar.",
2892 field: Box::new(SettingField {
2893 json_path: Some("title_bar.show_onboarding_banner"),
2894 pick: |settings_content| {
2895 settings_content
2896 .title_bar
2897 .as_ref()?
2898 .show_onboarding_banner
2899 .as_ref()
2900 },
2901 write: |settings_content, value| {
2902 settings_content
2903 .title_bar
2904 .get_or_insert_default()
2905 .show_onboarding_banner = value;
2906 },
2907 }),
2908 metadata: None,
2909 files: USER,
2910 }),
2911 SettingsPageItem::SettingItem(SettingItem {
2912 title: "Show User Picture",
2913 description: "Show user picture in the titlebar.",
2914 field: Box::new(SettingField {
2915 json_path: Some("title_bar.show_user_picture"),
2916 pick: |settings_content| {
2917 settings_content
2918 .title_bar
2919 .as_ref()?
2920 .show_user_picture
2921 .as_ref()
2922 },
2923 write: |settings_content, value| {
2924 settings_content
2925 .title_bar
2926 .get_or_insert_default()
2927 .show_user_picture = value;
2928 },
2929 }),
2930 metadata: None,
2931 files: USER,
2932 }),
2933 SettingsPageItem::SettingItem(SettingItem {
2934 title: "Show Sign In",
2935 description: "Show the sign in button in the titlebar.",
2936 field: Box::new(SettingField {
2937 json_path: Some("title_bar.show_sign_in"),
2938 pick: |settings_content| {
2939 settings_content.title_bar.as_ref()?.show_sign_in.as_ref()
2940 },
2941 write: |settings_content, value| {
2942 settings_content
2943 .title_bar
2944 .get_or_insert_default()
2945 .show_sign_in = value;
2946 },
2947 }),
2948 metadata: None,
2949 files: USER,
2950 }),
2951 SettingsPageItem::SettingItem(SettingItem {
2952 title: "Show Menus",
2953 description: "Show the menus in the titlebar.",
2954 field: Box::new(SettingField {
2955 json_path: Some("title_bar.show_menus"),
2956 pick: |settings_content| {
2957 settings_content.title_bar.as_ref()?.show_menus.as_ref()
2958 },
2959 write: |settings_content, value| {
2960 settings_content
2961 .title_bar
2962 .get_or_insert_default()
2963 .show_menus = value;
2964 },
2965 }),
2966 metadata: None,
2967 files: USER,
2968 }),
2969 SettingsPageItem::SectionHeader("Tab Bar"),
2970 SettingsPageItem::SettingItem(SettingItem {
2971 title: "Show Tab Bar",
2972 description: "Show the tab bar in the editor.",
2973 field: Box::new(SettingField {
2974 json_path: Some("tab_bar.show"),
2975 pick: |settings_content| settings_content.tab_bar.as_ref()?.show.as_ref(),
2976 write: |settings_content, value| {
2977 settings_content.tab_bar.get_or_insert_default().show = value;
2978 },
2979 }),
2980 metadata: None,
2981 files: USER,
2982 }),
2983 SettingsPageItem::SettingItem(SettingItem {
2984 title: "Show Git Status In Tabs",
2985 description: "Show the Git file status on a tab item.",
2986 field: Box::new(SettingField {
2987 json_path: Some("tabs.git_status"),
2988 pick: |settings_content| {
2989 settings_content.tabs.as_ref()?.git_status.as_ref()
2990 },
2991 write: |settings_content, value| {
2992 settings_content.tabs.get_or_insert_default().git_status = value;
2993 },
2994 }),
2995 metadata: None,
2996 files: USER,
2997 }),
2998 SettingsPageItem::SettingItem(SettingItem {
2999 title: "Show File Icons In Tabs",
3000 description: "Show the file icon for a tab.",
3001 field: Box::new(SettingField {
3002 json_path: Some("tabs.file_icons"),
3003 pick: |settings_content| {
3004 settings_content.tabs.as_ref()?.file_icons.as_ref()
3005 },
3006 write: |settings_content, value| {
3007 settings_content.tabs.get_or_insert_default().file_icons = value;
3008 },
3009 }),
3010 metadata: None,
3011 files: USER,
3012 }),
3013 SettingsPageItem::SettingItem(SettingItem {
3014 title: "Tab Close Position",
3015 description: "Position of the close button in a tab.",
3016 field: Box::new(SettingField {
3017 json_path: Some("tabs.close_position"),
3018 pick: |settings_content| {
3019 settings_content.tabs.as_ref()?.close_position.as_ref()
3020 },
3021 write: |settings_content, value| {
3022 settings_content.tabs.get_or_insert_default().close_position = value;
3023 },
3024 }),
3025 metadata: None,
3026 files: USER,
3027 }),
3028 SettingsPageItem::SettingItem(SettingItem {
3029 files: USER,
3030 title: "Maximum Tabs",
3031 description: "Maximum open tabs in a pane. Will not close an unsaved tab.",
3032 // todo(settings_ui): The default for this value is null and it's use in code
3033 // is complex, so I'm going to come back to this later
3034 field: Box::new(
3035 SettingField {
3036 json_path: Some("max_tabs"),
3037 pick: |settings_content| settings_content.workspace.max_tabs.as_ref(),
3038 write: |settings_content, value| {
3039 settings_content.workspace.max_tabs = value;
3040 },
3041 }
3042 .unimplemented(),
3043 ),
3044 metadata: None,
3045 }),
3046 SettingsPageItem::SettingItem(SettingItem {
3047 title: "Show Navigation History Buttons",
3048 description: "Show the navigation history buttons in the tab bar.",
3049 field: Box::new(SettingField {
3050 json_path: Some("tab_bar.show_nav_history_buttons"),
3051 pick: |settings_content| {
3052 settings_content
3053 .tab_bar
3054 .as_ref()?
3055 .show_nav_history_buttons
3056 .as_ref()
3057 },
3058 write: |settings_content, value| {
3059 settings_content
3060 .tab_bar
3061 .get_or_insert_default()
3062 .show_nav_history_buttons = value;
3063 },
3064 }),
3065 metadata: None,
3066 files: USER,
3067 }),
3068 SettingsPageItem::SectionHeader("Tab Settings"),
3069 SettingsPageItem::SettingItem(SettingItem {
3070 title: "Activate On Close",
3071 description: "What to do after closing the current tab.",
3072 field: Box::new(SettingField {
3073 json_path: Some("tabs.activate_on_close"),
3074 pick: |settings_content| {
3075 settings_content.tabs.as_ref()?.activate_on_close.as_ref()
3076 },
3077 write: |settings_content, value| {
3078 settings_content
3079 .tabs
3080 .get_or_insert_default()
3081 .activate_on_close = value;
3082 },
3083 }),
3084 metadata: None,
3085 files: USER,
3086 }),
3087 SettingsPageItem::SettingItem(SettingItem {
3088 title: "Tab Show Diagnostics",
3089 description: "Which files containing diagnostic errors/warnings to mark in the tabs.",
3090 field: Box::new(SettingField {
3091 json_path: Some("tabs.show_diagnostics"),
3092 pick: |settings_content| {
3093 settings_content.tabs.as_ref()?.show_diagnostics.as_ref()
3094 },
3095 write: |settings_content, value| {
3096 settings_content
3097 .tabs
3098 .get_or_insert_default()
3099 .show_diagnostics = value;
3100 },
3101 }),
3102 metadata: None,
3103 files: USER,
3104 }),
3105 SettingsPageItem::SettingItem(SettingItem {
3106 title: "Show Close Button",
3107 description: "Controls the appearance behavior of the tab's close button.",
3108 field: Box::new(SettingField {
3109 json_path: Some("tabs.show_close_button"),
3110 pick: |settings_content| {
3111 settings_content.tabs.as_ref()?.show_close_button.as_ref()
3112 },
3113 write: |settings_content, value| {
3114 settings_content
3115 .tabs
3116 .get_or_insert_default()
3117 .show_close_button = value;
3118 },
3119 }),
3120 metadata: None,
3121 files: USER,
3122 }),
3123 SettingsPageItem::SectionHeader("Preview Tabs"),
3124 SettingsPageItem::SettingItem(SettingItem {
3125 title: "Preview Tabs Enabled",
3126 description: "Show opened editors as Preview tabs.",
3127 field: Box::new(SettingField {
3128 json_path: Some("preview_tabs.enabled"),
3129 pick: |settings_content| {
3130 settings_content.preview_tabs.as_ref()?.enabled.as_ref()
3131 },
3132 write: |settings_content, value| {
3133 settings_content
3134 .preview_tabs
3135 .get_or_insert_default()
3136 .enabled = value;
3137 },
3138 }),
3139 metadata: None,
3140 files: USER,
3141 }),
3142 SettingsPageItem::SettingItem(SettingItem {
3143 title: "Enable Preview From File Finder",
3144 description: "Whether to open tabs in Preview mode when selected from the file finder.",
3145 field: Box::new(SettingField {
3146 json_path: Some("preview_tabs.enable_preview_from_file_finder"),
3147 pick: |settings_content| {
3148 settings_content
3149 .preview_tabs
3150 .as_ref()?
3151 .enable_preview_from_file_finder
3152 .as_ref()
3153 },
3154 write: |settings_content, value| {
3155 settings_content
3156 .preview_tabs
3157 .get_or_insert_default()
3158 .enable_preview_from_file_finder = value;
3159 },
3160 }),
3161 metadata: None,
3162 files: USER,
3163 }),
3164 SettingsPageItem::SettingItem(SettingItem {
3165 title: "Enable Preview From Code Navigation",
3166 description: "Whether a preview tab gets replaced when code navigation is used to navigate away from the tab.",
3167 field: Box::new(SettingField {
3168 json_path: Some("preview_tabs.enable_preview_from_code_navigation"),
3169 pick: |settings_content| {
3170 settings_content
3171 .preview_tabs
3172 .as_ref()?
3173 .enable_preview_from_code_navigation
3174 .as_ref()
3175 },
3176 write: |settings_content, value| {
3177 settings_content
3178 .preview_tabs
3179 .get_or_insert_default()
3180 .enable_preview_from_code_navigation = value;
3181 },
3182 }),
3183 metadata: None,
3184 files: USER,
3185 }),
3186 SettingsPageItem::SectionHeader("Layout"),
3187 SettingsPageItem::SettingItem(SettingItem {
3188 title: "Bottom Dock Layout",
3189 description: "Layout mode for the bottom dock.",
3190 field: Box::new(SettingField {
3191 json_path: Some("bottom_dock_layout"),
3192 pick: |settings_content| {
3193 settings_content.workspace.bottom_dock_layout.as_ref()
3194 },
3195 write: |settings_content, value| {
3196 settings_content.workspace.bottom_dock_layout = value;
3197 },
3198 }),
3199 metadata: None,
3200 files: USER,
3201 }),
3202 SettingsPageItem::SettingItem(SettingItem {
3203 files: USER,
3204 title: "Centered Layout Left Padding",
3205 description: "Left padding for centered layout.",
3206 field: Box::new(SettingField {
3207 json_path: Some("centered_layout.left_padding"),
3208 pick: |settings_content| {
3209 settings_content
3210 .workspace
3211 .centered_layout
3212 .as_ref()?
3213 .left_padding
3214 .as_ref()
3215 },
3216 write: |settings_content, value| {
3217 settings_content
3218 .workspace
3219 .centered_layout
3220 .get_or_insert_default()
3221 .left_padding = value;
3222 },
3223 }),
3224 metadata: None,
3225 }),
3226 SettingsPageItem::SettingItem(SettingItem {
3227 files: USER,
3228 title: "Centered Layout Right Padding",
3229 description: "Right padding for centered layout.",
3230 field: Box::new(SettingField {
3231 json_path: Some("centered_layout.right_padding"),
3232 pick: |settings_content| {
3233 settings_content
3234 .workspace
3235 .centered_layout
3236 .as_ref()?
3237 .right_padding
3238 .as_ref()
3239 },
3240 write: |settings_content, value| {
3241 settings_content
3242 .workspace
3243 .centered_layout
3244 .get_or_insert_default()
3245 .right_padding = value;
3246 },
3247 }),
3248 metadata: None,
3249 }),
3250 SettingsPageItem::SectionHeader("Window"),
3251 // todo(settings_ui): Should we filter by platform.as_ref()?
3252 SettingsPageItem::SettingItem(SettingItem {
3253 title: "Use System Window Tabs",
3254 description: "(macOS only) whether to allow Windows to tab together.",
3255 field: Box::new(SettingField {
3256 json_path: Some("use_system_window_tabs"),
3257 pick: |settings_content| {
3258 settings_content.workspace.use_system_window_tabs.as_ref()
3259 },
3260 write: |settings_content, value| {
3261 settings_content.workspace.use_system_window_tabs = value;
3262 },
3263 }),
3264 metadata: None,
3265 files: USER,
3266 }),
3267 SettingsPageItem::SettingItem(SettingItem {
3268 title: "Window Decorations",
3269 description: "(Linux only) whether Zed or your compositor should draw window decorations.",
3270 field: Box::new(SettingField {
3271 json_path: Some("window_decorations"),
3272 pick: |settings_content| {
3273 settings_content.workspace.window_decorations.as_ref()
3274 },
3275 write: |settings_content, value| {
3276 settings_content.workspace.window_decorations = value;
3277 },
3278 }),
3279 metadata: None,
3280 files: USER,
3281 }),
3282 SettingsPageItem::SectionHeader("Pane Modifiers"),
3283 SettingsPageItem::SettingItem(SettingItem {
3284 title: "Inactive Opacity",
3285 description: "Opacity of inactive panels (0.0 - 1.0).",
3286 field: Box::new(SettingField {
3287 json_path: Some("active_pane_modifiers.inactive_opacity"),
3288 pick: |settings_content| {
3289 settings_content
3290 .workspace
3291 .active_pane_modifiers
3292 .as_ref()?
3293 .inactive_opacity
3294 .as_ref()
3295 },
3296 write: |settings_content, value| {
3297 settings_content
3298 .workspace
3299 .active_pane_modifiers
3300 .get_or_insert_default()
3301 .inactive_opacity = value;
3302 },
3303 }),
3304 metadata: None,
3305 files: USER,
3306 }),
3307 SettingsPageItem::SettingItem(SettingItem {
3308 title: "Border Size",
3309 description: "Size of the border surrounding the active pane.",
3310 field: Box::new(SettingField {
3311 json_path: Some("active_pane_modifiers.border_size"),
3312 pick: |settings_content| {
3313 settings_content
3314 .workspace
3315 .active_pane_modifiers
3316 .as_ref()?
3317 .border_size
3318 .as_ref()
3319 },
3320 write: |settings_content, value| {
3321 settings_content
3322 .workspace
3323 .active_pane_modifiers
3324 .get_or_insert_default()
3325 .border_size = value;
3326 },
3327 }),
3328 metadata: None,
3329 files: USER,
3330 }),
3331 SettingsPageItem::SettingItem(SettingItem {
3332 title: "Zoomed Padding",
3333 description: "Show padding for zoomed panes.",
3334 field: Box::new(SettingField {
3335 json_path: Some("zoomed_padding"),
3336 pick: |settings_content| settings_content.workspace.zoomed_padding.as_ref(),
3337 write: |settings_content, value| {
3338 settings_content.workspace.zoomed_padding = value;
3339 },
3340 }),
3341 metadata: None,
3342 files: USER,
3343 }),
3344 SettingsPageItem::SectionHeader("Pane Split Direction"),
3345 SettingsPageItem::SettingItem(SettingItem {
3346 title: "Vertical Split Direction",
3347 description: "Direction to split vertically.",
3348 field: Box::new(SettingField {
3349 json_path: Some("pane_split_direction_vertical"),
3350 pick: |settings_content| {
3351 settings_content
3352 .workspace
3353 .pane_split_direction_vertical
3354 .as_ref()
3355 },
3356 write: |settings_content, value| {
3357 settings_content.workspace.pane_split_direction_vertical = value;
3358 },
3359 }),
3360 metadata: None,
3361 files: USER,
3362 }),
3363 SettingsPageItem::SettingItem(SettingItem {
3364 title: "Horizontal Split Direction",
3365 description: "Direction to split horizontally.",
3366 field: Box::new(SettingField {
3367 json_path: Some("pane_split_direction_horizontal"),
3368 pick: |settings_content| {
3369 settings_content
3370 .workspace
3371 .pane_split_direction_horizontal
3372 .as_ref()
3373 },
3374 write: |settings_content, value| {
3375 settings_content.workspace.pane_split_direction_horizontal = value;
3376 },
3377 }),
3378 metadata: None,
3379 files: USER,
3380 }),
3381 ],
3382 },
3383 SettingsPage {
3384 title: "Panels",
3385 items: vec![
3386 SettingsPageItem::SectionHeader("Project Panel"),
3387 SettingsPageItem::SettingItem(SettingItem {
3388 title: "Project Panel Dock",
3389 description: "Where to dock the project panel.",
3390 field: Box::new(SettingField {
3391 json_path: Some("project_panel.dock"),
3392 pick: |settings_content| {
3393 settings_content.project_panel.as_ref()?.dock.as_ref()
3394 },
3395 write: |settings_content, value| {
3396 settings_content.project_panel.get_or_insert_default().dock = value;
3397 },
3398 }),
3399 metadata: None,
3400 files: USER,
3401 }),
3402 SettingsPageItem::SettingItem(SettingItem {
3403 title: "Project Panel Default Width",
3404 description: "Default width of the project panel in pixels.",
3405 field: Box::new(SettingField {
3406 json_path: Some("project_panel.default_width"),
3407 pick: |settings_content| {
3408 settings_content
3409 .project_panel
3410 .as_ref()?
3411 .default_width
3412 .as_ref()
3413 },
3414 write: |settings_content, value| {
3415 settings_content
3416 .project_panel
3417 .get_or_insert_default()
3418 .default_width = value;
3419 },
3420 }),
3421 metadata: None,
3422 files: USER,
3423 }),
3424 SettingsPageItem::SettingItem(SettingItem {
3425 title: "Hide .gitignore",
3426 description: "Whether to hide the gitignore entries in the project panel.",
3427 field: Box::new(SettingField {
3428 json_path: Some("project_panel.hide_gitignore"),
3429 pick: |settings_content| {
3430 settings_content
3431 .project_panel
3432 .as_ref()?
3433 .hide_gitignore
3434 .as_ref()
3435 },
3436 write: |settings_content, value| {
3437 settings_content
3438 .project_panel
3439 .get_or_insert_default()
3440 .hide_gitignore = value;
3441 },
3442 }),
3443 metadata: None,
3444 files: USER,
3445 }),
3446 SettingsPageItem::SettingItem(SettingItem {
3447 title: "Entry Spacing",
3448 description: "Spacing between worktree entries in the project panel.",
3449 field: Box::new(SettingField {
3450 json_path: Some("project_panel.entry_spacing"),
3451 pick: |settings_content| {
3452 settings_content
3453 .project_panel
3454 .as_ref()?
3455 .entry_spacing
3456 .as_ref()
3457 },
3458 write: |settings_content, value| {
3459 settings_content
3460 .project_panel
3461 .get_or_insert_default()
3462 .entry_spacing = value;
3463 },
3464 }),
3465 metadata: None,
3466 files: USER,
3467 }),
3468 SettingsPageItem::SettingItem(SettingItem {
3469 title: "File Icons",
3470 description: "Show file icons in the project panel.",
3471 field: Box::new(SettingField {
3472 json_path: Some("project_panel.file_icons"),
3473 pick: |settings_content| {
3474 settings_content.project_panel.as_ref()?.file_icons.as_ref()
3475 },
3476 write: |settings_content, value| {
3477 settings_content
3478 .project_panel
3479 .get_or_insert_default()
3480 .file_icons = value;
3481 },
3482 }),
3483 metadata: None,
3484 files: USER,
3485 }),
3486 SettingsPageItem::SettingItem(SettingItem {
3487 title: "Folder Icons",
3488 description: "Whether to show folder icons or chevrons for directories in the project panel.",
3489 field: Box::new(SettingField {
3490 json_path: Some("project_panel.folder_icons"),
3491 pick: |settings_content| {
3492 settings_content
3493 .project_panel
3494 .as_ref()?
3495 .folder_icons
3496 .as_ref()
3497 },
3498 write: |settings_content, value| {
3499 settings_content
3500 .project_panel
3501 .get_or_insert_default()
3502 .folder_icons = value;
3503 },
3504 }),
3505 metadata: None,
3506 files: USER,
3507 }),
3508 SettingsPageItem::SettingItem(SettingItem {
3509 title: "Git Status",
3510 description: "Show the Git status in the project panel.",
3511 field: Box::new(SettingField {
3512 json_path: Some("project_panel.git_status"),
3513 pick: |settings_content| {
3514 settings_content.project_panel.as_ref()?.git_status.as_ref()
3515 },
3516 write: |settings_content, value| {
3517 settings_content
3518 .project_panel
3519 .get_or_insert_default()
3520 .git_status = value;
3521 },
3522 }),
3523 metadata: None,
3524 files: USER,
3525 }),
3526 SettingsPageItem::SettingItem(SettingItem {
3527 title: "Indent Size",
3528 description: "Amount of indentation for nested items.",
3529 field: Box::new(SettingField {
3530 json_path: Some("project_panel.indent_size"),
3531 pick: |settings_content| {
3532 settings_content
3533 .project_panel
3534 .as_ref()?
3535 .indent_size
3536 .as_ref()
3537 },
3538 write: |settings_content, value| {
3539 settings_content
3540 .project_panel
3541 .get_or_insert_default()
3542 .indent_size = value;
3543 },
3544 }),
3545 metadata: None,
3546 files: USER,
3547 }),
3548 SettingsPageItem::SettingItem(SettingItem {
3549 title: "Auto Reveal Entries",
3550 description: "Whether to reveal entries in the project panel automatically when a corresponding project entry becomes active.",
3551 field: Box::new(SettingField {
3552 json_path: Some("project_panel.auto_reveal_entries"),
3553 pick: |settings_content| {
3554 settings_content
3555 .project_panel
3556 .as_ref()?
3557 .auto_reveal_entries
3558 .as_ref()
3559 },
3560 write: |settings_content, value| {
3561 settings_content
3562 .project_panel
3563 .get_or_insert_default()
3564 .auto_reveal_entries = value;
3565 },
3566 }),
3567 metadata: None,
3568 files: USER,
3569 }),
3570 SettingsPageItem::SettingItem(SettingItem {
3571 title: "Starts Open",
3572 description: "Whether the project panel should open on startup.",
3573 field: Box::new(SettingField {
3574 json_path: Some("project_panel.starts_open"),
3575 pick: |settings_content| {
3576 settings_content
3577 .project_panel
3578 .as_ref()?
3579 .starts_open
3580 .as_ref()
3581 },
3582 write: |settings_content, value| {
3583 settings_content
3584 .project_panel
3585 .get_or_insert_default()
3586 .starts_open = value;
3587 },
3588 }),
3589 metadata: None,
3590 files: USER,
3591 }),
3592 SettingsPageItem::SettingItem(SettingItem {
3593 title: "Auto Fold Directories",
3594 description: "Whether to fold directories automatically and show compact folders when a directory has only one subdirectory inside.",
3595 field: Box::new(SettingField {
3596 json_path: Some("project_panel.auto_fold_dirs"),
3597 pick: |settings_content| {
3598 settings_content
3599 .project_panel
3600 .as_ref()?
3601 .auto_fold_dirs
3602 .as_ref()
3603 },
3604 write: |settings_content, value| {
3605 settings_content
3606 .project_panel
3607 .get_or_insert_default()
3608 .auto_fold_dirs = value;
3609 },
3610 }),
3611 metadata: None,
3612 files: USER,
3613 }),
3614 SettingsPageItem::SettingItem(SettingItem {
3615 title: "Show Scrollbar",
3616 description: "Show the scrollbar in the project panel.",
3617 field: Box::new(SettingField {
3618 json_path: Some("project_panel.scrollbar.show"),
3619 pick: |settings_content| {
3620 show_scrollbar_or_editor(settings_content, |settings_content| {
3621 settings_content
3622 .project_panel
3623 .as_ref()?
3624 .scrollbar
3625 .as_ref()?
3626 .show
3627 .as_ref()
3628 })
3629 },
3630 write: |settings_content, value| {
3631 settings_content
3632 .project_panel
3633 .get_or_insert_default()
3634 .scrollbar
3635 .get_or_insert_default()
3636 .show = value;
3637 },
3638 }),
3639 metadata: None,
3640 files: USER,
3641 }),
3642 SettingsPageItem::SettingItem(SettingItem {
3643 title: "Show Diagnostics",
3644 description: "Which files containing diagnostic errors/warnings to mark in the project panel.",
3645 field: Box::new(SettingField {
3646 json_path: Some("project_panel.show_diagnostics"),
3647 pick: |settings_content| {
3648 settings_content
3649 .project_panel
3650 .as_ref()?
3651 .show_diagnostics
3652 .as_ref()
3653 },
3654 write: |settings_content, value| {
3655 settings_content
3656 .project_panel
3657 .get_or_insert_default()
3658 .show_diagnostics = value;
3659 },
3660 }),
3661 metadata: None,
3662 files: USER,
3663 }),
3664 SettingsPageItem::SettingItem(SettingItem {
3665 title: "Sticky Scroll",
3666 description: "Whether to stick parent directories at top of the project panel.",
3667 field: Box::new(SettingField {
3668 json_path: Some("project_panel.sticky_scroll"),
3669 pick: |settings_content| {
3670 settings_content
3671 .project_panel
3672 .as_ref()?
3673 .sticky_scroll
3674 .as_ref()
3675 },
3676 write: |settings_content, value| {
3677 settings_content
3678 .project_panel
3679 .get_or_insert_default()
3680 .sticky_scroll = value;
3681 },
3682 }),
3683 metadata: None,
3684 files: USER,
3685 }),
3686 SettingsPageItem::SettingItem(SettingItem {
3687 files: USER,
3688 title: "Show Indent Guides",
3689 description: "Show indent guides in the project panel.",
3690 field: Box::new(
3691 SettingField {
3692 json_path: Some("project_panel.indent_guides.show"),
3693 pick: |settings_content| {
3694 settings_content
3695 .project_panel
3696 .as_ref()?
3697 .indent_guides
3698 .as_ref()?
3699 .show
3700 .as_ref()
3701 },
3702 write: |settings_content, value| {
3703 settings_content
3704 .project_panel
3705 .get_or_insert_default()
3706 .indent_guides
3707 .get_or_insert_default()
3708 .show = value;
3709 },
3710 }
3711 ),
3712 metadata: None,
3713 }),
3714 SettingsPageItem::SettingItem(SettingItem {
3715 title: "Drag and Drop",
3716 description: "Whether to enable drag-and-drop operations in the project panel.",
3717 field: Box::new(SettingField {
3718 json_path: Some("project_panel.drag_and_drop"),
3719 pick: |settings_content| {
3720 settings_content
3721 .project_panel
3722 .as_ref()?
3723 .drag_and_drop
3724 .as_ref()
3725 },
3726 write: |settings_content, value| {
3727 settings_content
3728 .project_panel
3729 .get_or_insert_default()
3730 .drag_and_drop = value;
3731 },
3732 }),
3733 metadata: None,
3734 files: USER,
3735 }),
3736 SettingsPageItem::SettingItem(SettingItem {
3737 title: "Hide Root",
3738 description: "Whether to hide the root entry when only one folder is open in the window.",
3739 field: Box::new(SettingField {
3740 json_path: Some("project_panel.drag_and_drop"),
3741 pick: |settings_content| {
3742 settings_content.project_panel.as_ref()?.hide_root.as_ref()
3743 },
3744 write: |settings_content, value| {
3745 settings_content
3746 .project_panel
3747 .get_or_insert_default()
3748 .hide_root = value;
3749 },
3750 }),
3751 metadata: None,
3752 files: USER,
3753 }),
3754 SettingsPageItem::SettingItem(SettingItem {
3755 title: "Hide Hidden",
3756 description: "Whether to hide the hidden entries in the project panel.",
3757 field: Box::new(SettingField {
3758 json_path: Some("project_panel.hide_hidden"),
3759 pick: |settings_content| {
3760 settings_content
3761 .project_panel
3762 .as_ref()?
3763 .hide_hidden
3764 .as_ref()
3765 },
3766 write: |settings_content, value| {
3767 settings_content
3768 .project_panel
3769 .get_or_insert_default()
3770 .hide_hidden = value;
3771 },
3772 }),
3773 metadata: None,
3774 files: USER,
3775 }),
3776 SettingsPageItem::SettingItem(SettingItem {
3777 title: "Hidden Files",
3778 description: "Globs to match files that will be considered \"hidden\" and can be hidden from the project panel.",
3779 field: Box::new(
3780 SettingField {
3781 json_path: Some("worktree.hidden_files"),
3782 pick: |settings_content| {
3783 settings_content.project.worktree.hidden_files.as_ref()
3784 },
3785 write: |settings_content, value| {
3786 settings_content.project.worktree.hidden_files = value;
3787 },
3788 }
3789 .unimplemented(),
3790 ),
3791 metadata: None,
3792 files: USER,
3793 }),
3794 SettingsPageItem::SectionHeader("Auto Open Files"),
3795 SettingsPageItem::SettingItem(SettingItem {
3796 title: "On Create",
3797 description: "Whether to automatically open newly created files in the editor.",
3798 field: Box::new(SettingField {
3799 json_path: Some("project_panel.auto_open.on_create"),
3800 pick: |settings_content| {
3801 settings_content.project_panel.as_ref()?.auto_open.as_ref()?.on_create.as_ref()
3802 },
3803 write: |settings_content, value| {
3804 settings_content.project_panel.get_or_insert_default().auto_open.get_or_insert_default().on_create = value;
3805 },
3806 }),
3807 metadata: None,
3808 files: USER,
3809 }),
3810 SettingsPageItem::SettingItem(SettingItem {
3811 title: "On Paste",
3812 description: "Whether to automatically open files after pasting or duplicating them.",
3813 field: Box::new(SettingField {
3814 json_path: Some("project_panel.auto_open.on_paste"),
3815 pick: |settings_content| {
3816 settings_content.project_panel.as_ref()?.auto_open.as_ref()?.on_paste.as_ref()
3817 },
3818 write: |settings_content, value| {
3819 settings_content.project_panel.get_or_insert_default().auto_open.get_or_insert_default().on_paste = value;
3820 },
3821 }),
3822 metadata: None,
3823 files: USER,
3824 }),
3825 SettingsPageItem::SettingItem(SettingItem {
3826 title: "On Drop",
3827 description: "Whether to automatically open files dropped from external sources.",
3828 field: Box::new(SettingField {
3829 json_path: Some("project_panel.auto_open.on_drop"),
3830 pick: |settings_content| {
3831 settings_content.project_panel.as_ref()?.auto_open.as_ref()?.on_drop.as_ref()
3832 },
3833 write: |settings_content, value| {
3834 settings_content.project_panel.get_or_insert_default().auto_open.get_or_insert_default().on_drop = value;
3835 },
3836 }),
3837 metadata: None,
3838 files: USER,
3839 }),
3840 SettingsPageItem::SettingItem(SettingItem {
3841 title: "Sort Mode",
3842 description: "Sort order for entries in the project panel.",
3843 field: Box::new(SettingField {
3844 pick: |settings_content| {
3845 settings_content.project_panel.as_ref()?.sort_mode.as_ref()
3846 },
3847 write: |settings_content, value| {
3848 settings_content
3849 .project_panel
3850 .get_or_insert_default()
3851 .sort_mode = value;
3852 },
3853 json_path: Some("project_panel.sort_mode"),
3854 }),
3855 metadata: None,
3856 files: USER,
3857 }),
3858 SettingsPageItem::SectionHeader("Terminal Panel"),
3859 SettingsPageItem::SettingItem(SettingItem {
3860 title: "Terminal Dock",
3861 description: "Where to dock the terminal panel.",
3862 field: Box::new(SettingField {
3863 json_path: Some("terminal.dock"),
3864 pick: |settings_content| settings_content.terminal.as_ref()?.dock.as_ref(),
3865 write: |settings_content, value| {
3866 settings_content.terminal.get_or_insert_default().dock = value;
3867 },
3868 }),
3869 metadata: None,
3870 files: USER,
3871 }),
3872 SettingsPageItem::SectionHeader("Outline Panel"),
3873 SettingsPageItem::SettingItem(SettingItem {
3874 title: "Outline Panel Button",
3875 description: "Show the outline panel button in the status bar.",
3876 field: Box::new(SettingField {
3877 json_path: Some("outline_panel.button"),
3878 pick: |settings_content| {
3879 settings_content.outline_panel.as_ref()?.button.as_ref()
3880 },
3881 write: |settings_content, value| {
3882 settings_content
3883 .outline_panel
3884 .get_or_insert_default()
3885 .button = value;
3886 },
3887 }),
3888 metadata: None,
3889 files: USER,
3890 }),
3891 SettingsPageItem::SettingItem(SettingItem {
3892 title: "Outline Panel Dock",
3893 description: "Where to dock the outline panel.",
3894 field: Box::new(SettingField {
3895 json_path: Some("outline_panel.dock"),
3896 pick: |settings_content| {
3897 settings_content.outline_panel.as_ref()?.dock.as_ref()
3898 },
3899 write: |settings_content, value| {
3900 settings_content.outline_panel.get_or_insert_default().dock = value;
3901 },
3902 }),
3903 metadata: None,
3904 files: USER,
3905 }),
3906 SettingsPageItem::SettingItem(SettingItem {
3907 title: "Outline Panel Default Width",
3908 description: "Default width of the outline panel in pixels.",
3909 field: Box::new(SettingField {
3910 json_path: Some("outline_panel.default_width"),
3911 pick: |settings_content| {
3912 settings_content
3913 .outline_panel
3914 .as_ref()?
3915 .default_width
3916 .as_ref()
3917 },
3918 write: |settings_content, value| {
3919 settings_content
3920 .outline_panel
3921 .get_or_insert_default()
3922 .default_width = value;
3923 },
3924 }),
3925 metadata: None,
3926 files: USER,
3927 }),
3928 SettingsPageItem::SettingItem(SettingItem {
3929 title: "File Icons",
3930 description: "Show file icons in the outline panel.",
3931 field: Box::new(SettingField {
3932 json_path: Some("outline_panel.file_icons"),
3933 pick: |settings_content| {
3934 settings_content.outline_panel.as_ref()?.file_icons.as_ref()
3935 },
3936 write: |settings_content, value| {
3937 settings_content
3938 .outline_panel
3939 .get_or_insert_default()
3940 .file_icons = value;
3941 },
3942 }),
3943 metadata: None,
3944 files: USER,
3945 }),
3946 SettingsPageItem::SettingItem(SettingItem {
3947 title: "Folder Icons",
3948 description: "Whether to show folder icons or chevrons for directories in the outline panel.",
3949 field: Box::new(SettingField {
3950 json_path: Some("outline_panel.folder_icons"),
3951 pick: |settings_content| {
3952 settings_content
3953 .outline_panel
3954 .as_ref()?
3955 .folder_icons
3956 .as_ref()
3957 },
3958 write: |settings_content, value| {
3959 settings_content
3960 .outline_panel
3961 .get_or_insert_default()
3962 .folder_icons = value;
3963 },
3964 }),
3965 metadata: None,
3966 files: USER,
3967 }),
3968 SettingsPageItem::SettingItem(SettingItem {
3969 title: "Git Status",
3970 description: "Show the Git status in the outline panel.",
3971 field: Box::new(SettingField {
3972 json_path: Some("outline_panel.git_status"),
3973 pick: |settings_content| {
3974 settings_content.outline_panel.as_ref()?.git_status.as_ref()
3975 },
3976 write: |settings_content, value| {
3977 settings_content
3978 .outline_panel
3979 .get_or_insert_default()
3980 .git_status = value;
3981 },
3982 }),
3983 metadata: None,
3984 files: USER,
3985 }),
3986 SettingsPageItem::SettingItem(SettingItem {
3987 title: "Indent Size",
3988 description: "Amount of indentation for nested items.",
3989 field: Box::new(SettingField {
3990 json_path: Some("outline_panel.indent_size"),
3991 pick: |settings_content| {
3992 settings_content
3993 .outline_panel
3994 .as_ref()?
3995 .indent_size
3996 .as_ref()
3997 },
3998 write: |settings_content, value| {
3999 settings_content
4000 .outline_panel
4001 .get_or_insert_default()
4002 .indent_size = value;
4003 },
4004 }),
4005 metadata: None,
4006 files: USER,
4007 }),
4008 SettingsPageItem::SettingItem(SettingItem {
4009 title: "Auto Reveal Entries",
4010 description: "Whether to reveal when a corresponding outline entry becomes active.",
4011 field: Box::new(SettingField {
4012 json_path: Some("outline_panel.auto_reveal_entries"),
4013 pick: |settings_content| {
4014 settings_content
4015 .outline_panel
4016 .as_ref()?
4017 .auto_reveal_entries
4018 .as_ref()
4019 },
4020 write: |settings_content, value| {
4021 settings_content
4022 .outline_panel
4023 .get_or_insert_default()
4024 .auto_reveal_entries = value;
4025 },
4026 }),
4027 metadata: None,
4028 files: USER,
4029 }),
4030 SettingsPageItem::SettingItem(SettingItem {
4031 title: "Auto Fold Directories",
4032 description: "Whether to fold directories automatically when a directory contains only one subdirectory.",
4033 field: Box::new(SettingField {
4034 json_path: Some("outline_panel.auto_fold_dirs"),
4035 pick: |settings_content| {
4036 settings_content
4037 .outline_panel
4038 .as_ref()?
4039 .auto_fold_dirs
4040 .as_ref()
4041 },
4042 write: |settings_content, value| {
4043 settings_content
4044 .outline_panel
4045 .get_or_insert_default()
4046 .auto_fold_dirs = value;
4047 },
4048 }),
4049 metadata: None,
4050 files: USER,
4051 }),
4052 SettingsPageItem::SettingItem(SettingItem {
4053 files: USER,
4054 title: "Show Indent Guides",
4055 description: "When to show indent guides in the outline panel.",
4056 field: Box::new(
4057 SettingField {
4058 json_path: Some("outline_panel.indent_guides.show"),
4059 pick: |settings_content| {
4060 settings_content
4061 .outline_panel
4062 .as_ref()?
4063 .indent_guides
4064 .as_ref()?
4065 .show
4066 .as_ref()
4067 },
4068 write: |settings_content, value| {
4069 settings_content
4070 .outline_panel
4071 .get_or_insert_default()
4072 .indent_guides
4073 .get_or_insert_default()
4074 .show = value;
4075 },
4076 }
4077 ),
4078 metadata: None,
4079 }),
4080 SettingsPageItem::SectionHeader("Git Panel"),
4081 SettingsPageItem::SettingItem(SettingItem {
4082 title: "Git Panel Button",
4083 description: "Show the Git panel button in the status bar.",
4084 field: Box::new(SettingField {
4085 json_path: Some("git_panel.button"),
4086 pick: |settings_content| {
4087 settings_content.git_panel.as_ref()?.button.as_ref()
4088 },
4089 write: |settings_content, value| {
4090 settings_content.git_panel.get_or_insert_default().button = value;
4091 },
4092 }),
4093 metadata: None,
4094 files: USER,
4095 }),
4096 SettingsPageItem::SettingItem(SettingItem {
4097 title: "Git Panel Dock",
4098 description: "Where to dock the Git panel.",
4099 field: Box::new(SettingField {
4100 json_path: Some("git_panel.dock"),
4101 pick: |settings_content| settings_content.git_panel.as_ref()?.dock.as_ref(),
4102 write: |settings_content, value| {
4103 settings_content.git_panel.get_or_insert_default().dock = value;
4104 },
4105 }),
4106 metadata: None,
4107 files: USER,
4108 }),
4109 SettingsPageItem::SettingItem(SettingItem {
4110 title: "Git Panel Default Width",
4111 description: "Default width of the Git panel in pixels.",
4112 field: Box::new(SettingField {
4113 json_path: Some("git_panel.default_width"),
4114 pick: |settings_content| {
4115 settings_content.git_panel.as_ref()?.default_width.as_ref()
4116 },
4117 write: |settings_content, value| {
4118 settings_content
4119 .git_panel
4120 .get_or_insert_default()
4121 .default_width = value;
4122 },
4123 }),
4124 metadata: None,
4125 files: USER,
4126 }),
4127 SettingsPageItem::SettingItem(SettingItem {
4128 title: "Git Panel Status Style",
4129 description: "How entry statuses are displayed.",
4130 field: Box::new(SettingField {
4131 json_path: Some("git_panel.status_style"),
4132 pick: |settings_content| {
4133 settings_content.git_panel.as_ref()?.status_style.as_ref()
4134 },
4135 write: |settings_content, value| {
4136 settings_content
4137 .git_panel
4138 .get_or_insert_default()
4139 .status_style = value;
4140 },
4141 }),
4142 metadata: None,
4143 files: USER,
4144 }),
4145 SettingsPageItem::SettingItem(SettingItem {
4146 title: "Fallback Branch Name",
4147 description: "Default branch name will be when init.defaultbranch is not set in Git.",
4148 field: Box::new(SettingField {
4149 json_path: Some("git_panel.fallback_branch_name"),
4150 pick: |settings_content| {
4151 settings_content
4152 .git_panel
4153 .as_ref()?
4154 .fallback_branch_name
4155 .as_ref()
4156 },
4157 write: |settings_content, value| {
4158 settings_content
4159 .git_panel
4160 .get_or_insert_default()
4161 .fallback_branch_name = value;
4162 },
4163 }),
4164 metadata: None,
4165 files: USER,
4166 }),
4167 SettingsPageItem::SettingItem(SettingItem {
4168 title: "Sort By Path",
4169 description: "Enable to sort entries in the panel by path, disable to sort by status.",
4170 field: Box::new(SettingField {
4171 json_path: Some("git_panel.sort_by_path"),
4172 pick: |settings_content| {
4173 settings_content.git_panel.as_ref()?.sort_by_path.as_ref()
4174 },
4175 write: |settings_content, value| {
4176 settings_content
4177 .git_panel
4178 .get_or_insert_default()
4179 .sort_by_path = value;
4180 },
4181 }),
4182 metadata: None,
4183 files: USER,
4184 }),
4185 SettingsPageItem::SettingItem(SettingItem {
4186 title: "Collapse Untracked Diff",
4187 description: "Whether to collapse untracked files in the diff panel.",
4188 field: Box::new(SettingField {
4189 json_path: Some("git_panel.collapse_untracked_diff"),
4190 pick: |settings_content| {
4191 settings_content
4192 .git_panel
4193 .as_ref()?
4194 .collapse_untracked_diff
4195 .as_ref()
4196 },
4197 write: |settings_content, value| {
4198 settings_content
4199 .git_panel
4200 .get_or_insert_default()
4201 .collapse_untracked_diff = value;
4202 },
4203 }),
4204 metadata: None,
4205 files: USER,
4206 }),
4207 SettingsPageItem::SettingItem(SettingItem {
4208 title: "Scroll Bar",
4209 description: "How and when the scrollbar should be displayed.",
4210 field: Box::new(SettingField {
4211 json_path: Some("git_panel.scrollbar.show"),
4212 pick: |settings_content| {
4213 show_scrollbar_or_editor(settings_content, |settings_content| {
4214 settings_content
4215 .git_panel
4216 .as_ref()?
4217 .scrollbar
4218 .as_ref()?
4219 .show
4220 .as_ref()
4221 })
4222 },
4223 write: |settings_content, value| {
4224 settings_content
4225 .git_panel
4226 .get_or_insert_default()
4227 .scrollbar
4228 .get_or_insert_default()
4229 .show = value;
4230 },
4231 }),
4232 metadata: None,
4233 files: USER,
4234 }),
4235 SettingsPageItem::SectionHeader("Debugger Panel"),
4236 SettingsPageItem::SettingItem(SettingItem {
4237 title: "Debugger Panel Dock",
4238 description: "The dock position of the debug panel.",
4239 field: Box::new(SettingField {
4240 json_path: Some("debugger.dock"),
4241 pick: |settings_content| settings_content.debugger.as_ref()?.dock.as_ref(),
4242 write: |settings_content, value| {
4243 settings_content.debugger.get_or_insert_default().dock = value;
4244 },
4245 }),
4246 metadata: None,
4247 files: USER,
4248 }),
4249 SettingsPageItem::SectionHeader("Notification Panel"),
4250 SettingsPageItem::SettingItem(SettingItem {
4251 title: "Notification Panel Button",
4252 description: "Show the notification panel button in the status bar.",
4253 field: Box::new(SettingField {
4254 json_path: Some("notification_panel.button"),
4255 pick: |settings_content| {
4256 settings_content
4257 .notification_panel
4258 .as_ref()?
4259 .button
4260 .as_ref()
4261 },
4262 write: |settings_content, value| {
4263 settings_content
4264 .notification_panel
4265 .get_or_insert_default()
4266 .button = value;
4267 },
4268 }),
4269 metadata: None,
4270 files: USER,
4271 }),
4272 SettingsPageItem::SettingItem(SettingItem {
4273 title: "Notification Panel Dock",
4274 description: "Where to dock the notification panel.",
4275 field: Box::new(SettingField {
4276 json_path: Some("notification_panel.dock"),
4277 pick: |settings_content| {
4278 settings_content.notification_panel.as_ref()?.dock.as_ref()
4279 },
4280 write: |settings_content, value| {
4281 settings_content
4282 .notification_panel
4283 .get_or_insert_default()
4284 .dock = value;
4285 },
4286 }),
4287 metadata: None,
4288 files: USER,
4289 }),
4290 SettingsPageItem::SettingItem(SettingItem {
4291 title: "Notification Panel Default Width",
4292 description: "Default width of the notification panel in pixels.",
4293 field: Box::new(SettingField {
4294 json_path: Some("notification_panel.default_width"),
4295 pick: |settings_content| {
4296 settings_content
4297 .notification_panel
4298 .as_ref()?
4299 .default_width
4300 .as_ref()
4301 },
4302 write: |settings_content, value| {
4303 settings_content
4304 .notification_panel
4305 .get_or_insert_default()
4306 .default_width = value;
4307 },
4308 }),
4309 metadata: None,
4310 files: USER,
4311 }),
4312 SettingsPageItem::SectionHeader("Collaboration Panel"),
4313 SettingsPageItem::SettingItem(SettingItem {
4314 title: "Collaboration Panel Button",
4315 description: "Show the collaboration panel button in the status bar.",
4316 field: Box::new(SettingField {
4317 json_path: Some("collaboration_panel.button"),
4318 pick: |settings_content| {
4319 settings_content
4320 .collaboration_panel
4321 .as_ref()?
4322 .button
4323 .as_ref()
4324 },
4325 write: |settings_content, value| {
4326 settings_content
4327 .collaboration_panel
4328 .get_or_insert_default()
4329 .button = value;
4330 },
4331 }),
4332 metadata: None,
4333 files: USER,
4334 }),
4335 SettingsPageItem::SettingItem(SettingItem {
4336 title: "Collaboration Panel Dock",
4337 description: "Where to dock the collaboration panel.",
4338 field: Box::new(SettingField {
4339 json_path: Some("collaboration_panel.dock"),
4340 pick: |settings_content| {
4341 settings_content.collaboration_panel.as_ref()?.dock.as_ref()
4342 },
4343 write: |settings_content, value| {
4344 settings_content
4345 .collaboration_panel
4346 .get_or_insert_default()
4347 .dock = value;
4348 },
4349 }),
4350 metadata: None,
4351 files: USER,
4352 }),
4353 SettingsPageItem::SettingItem(SettingItem {
4354 title: "Collaboration Panel Default Width",
4355 description: "Default width of the collaboration panel in pixels.",
4356 field: Box::new(SettingField {
4357 json_path: Some("collaboration_panel.dock"),
4358 pick: |settings_content| {
4359 settings_content
4360 .collaboration_panel
4361 .as_ref()?
4362 .default_width
4363 .as_ref()
4364 },
4365 write: |settings_content, value| {
4366 settings_content
4367 .collaboration_panel
4368 .get_or_insert_default()
4369 .default_width = value;
4370 },
4371 }),
4372 metadata: None,
4373 files: USER,
4374 }),
4375 SettingsPageItem::SectionHeader("Agent Panel"),
4376 SettingsPageItem::SettingItem(SettingItem {
4377 title: "Agent Panel Button",
4378 description: "Whether to show the agent panel button in the status bar.",
4379 field: Box::new(SettingField {
4380 json_path: Some("agent.button"),
4381 pick: |settings_content| settings_content.agent.as_ref()?.button.as_ref(),
4382 write: |settings_content, value| {
4383 settings_content.agent.get_or_insert_default().button = value;
4384 },
4385 }),
4386 metadata: None,
4387 files: USER,
4388 }),
4389 SettingsPageItem::SettingItem(SettingItem {
4390 title: "Agent Panel Dock",
4391 description: "Where to dock the agent panel.",
4392 field: Box::new(SettingField {
4393 json_path: Some("agent.dock"),
4394 pick: |settings_content| settings_content.agent.as_ref()?.dock.as_ref(),
4395 write: |settings_content, value| {
4396 settings_content.agent.get_or_insert_default().dock = value;
4397 },
4398 }),
4399 metadata: None,
4400 files: USER,
4401 }),
4402 SettingsPageItem::SettingItem(SettingItem {
4403 title: "Agent Panel Default Width",
4404 description: "Default width when the agent panel is docked to the left or right.",
4405 field: Box::new(SettingField {
4406 json_path: Some("agent.default_width"),
4407 pick: |settings_content| {
4408 settings_content.agent.as_ref()?.default_width.as_ref()
4409 },
4410 write: |settings_content, value| {
4411 settings_content.agent.get_or_insert_default().default_width = value;
4412 },
4413 }),
4414 metadata: None,
4415 files: USER,
4416 }),
4417 SettingsPageItem::SettingItem(SettingItem {
4418 title: "Agent Panel Default Height",
4419 description: "Default height when the agent panel is docked to the bottom.",
4420 field: Box::new(SettingField {
4421 json_path: Some("agent.default_height"),
4422 pick: |settings_content| {
4423 settings_content.agent.as_ref()?.default_height.as_ref()
4424 },
4425 write: |settings_content, value| {
4426 settings_content
4427 .agent
4428 .get_or_insert_default()
4429 .default_height = value;
4430 },
4431 }),
4432 metadata: None,
4433 files: USER,
4434 }),
4435 ],
4436 },
4437 SettingsPage {
4438 title: "Debugger",
4439 items: vec![
4440 SettingsPageItem::SectionHeader("General"),
4441 SettingsPageItem::SettingItem(SettingItem {
4442 title: "Stepping Granularity",
4443 description: "Determines the stepping granularity for debug operations.",
4444 field: Box::new(SettingField {
4445 json_path: Some("agent.default_height"),
4446 pick: |settings_content| {
4447 settings_content
4448 .debugger
4449 .as_ref()?
4450 .stepping_granularity
4451 .as_ref()
4452 },
4453 write: |settings_content, value| {
4454 settings_content
4455 .debugger
4456 .get_or_insert_default()
4457 .stepping_granularity = value;
4458 },
4459 }),
4460 metadata: None,
4461 files: USER,
4462 }),
4463 SettingsPageItem::SettingItem(SettingItem {
4464 title: "Save Breakpoints",
4465 description: "Whether breakpoints should be reused across Zed sessions.",
4466 field: Box::new(SettingField {
4467 json_path: Some("debugger.save_breakpoints"),
4468 pick: |settings_content| {
4469 settings_content
4470 .debugger
4471 .as_ref()?
4472 .save_breakpoints
4473 .as_ref()
4474 },
4475 write: |settings_content, value| {
4476 settings_content
4477 .debugger
4478 .get_or_insert_default()
4479 .save_breakpoints = value;
4480 },
4481 }),
4482 metadata: None,
4483 files: USER,
4484 }),
4485 SettingsPageItem::SettingItem(SettingItem {
4486 title: "Timeout",
4487 description: "Time in milliseconds until timeout error when connecting to a TCP debug adapter.",
4488 field: Box::new(SettingField {
4489 json_path: Some("debugger.timeout"),
4490 pick: |settings_content| {
4491 settings_content.debugger.as_ref()?.timeout.as_ref()
4492 },
4493 write: |settings_content, value| {
4494 settings_content.debugger.get_or_insert_default().timeout = value;
4495 },
4496 }),
4497 metadata: None,
4498 files: USER,
4499 }),
4500 SettingsPageItem::SettingItem(SettingItem {
4501 title: "Log DAP Communications",
4502 description: "Whether to log messages between active debug adapters and Zed.",
4503 field: Box::new(SettingField {
4504 json_path: Some("debugger.log_dap_communications"),
4505 pick: |settings_content| {
4506 settings_content
4507 .debugger
4508 .as_ref()?
4509 .log_dap_communications
4510 .as_ref()
4511 },
4512 write: |settings_content, value| {
4513 settings_content
4514 .debugger
4515 .get_or_insert_default()
4516 .log_dap_communications = value;
4517 },
4518 }),
4519 metadata: None,
4520 files: USER,
4521 }),
4522 SettingsPageItem::SettingItem(SettingItem {
4523 title: "Format DAP Log Messages",
4524 description: "Whether to format DAP messages when adding them to debug adapter logger.",
4525 field: Box::new(SettingField {
4526 json_path: Some("debugger.format_dap_log_messages"),
4527 pick: |settings_content| {
4528 settings_content
4529 .debugger
4530 .as_ref()?
4531 .format_dap_log_messages
4532 .as_ref()
4533 },
4534 write: |settings_content, value| {
4535 settings_content
4536 .debugger
4537 .get_or_insert_default()
4538 .format_dap_log_messages = value;
4539 },
4540 }),
4541 metadata: None,
4542 files: USER,
4543 }),
4544 ],
4545 },
4546 SettingsPage {
4547 title: "Terminal",
4548 items: vec![
4549 SettingsPageItem::SectionHeader("Environment"),
4550 SettingsPageItem::DynamicItem(DynamicItem {
4551 discriminant: SettingItem {
4552 files: USER | PROJECT,
4553 title: "Shell",
4554 description: "What shell to use when opening a terminal.",
4555 field: Box::new(SettingField {
4556 json_path: Some("terminal.shell$"),
4557 pick: |settings_content| {
4558 Some(&dynamic_variants::<settings::Shell>()[
4559 settings_content
4560 .terminal
4561 .as_ref()?
4562 .project
4563 .shell
4564 .as_ref()?
4565 .discriminant() as usize])
4566 },
4567 write: |settings_content, value| {
4568 let Some(value) = value else {
4569 if let Some(terminal) = settings_content.terminal.as_mut() {
4570 terminal.project.shell = None;
4571 }
4572 return;
4573 };
4574 let settings_value = settings_content
4575 .terminal
4576 .get_or_insert_default()
4577 .project
4578 .shell
4579 .get_or_insert_with(|| settings::Shell::default());
4580 *settings_value = match value {
4581 settings::ShellDiscriminants::System => {
4582 settings::Shell::System
4583 },
4584 settings::ShellDiscriminants::Program => {
4585 let program = match settings_value {
4586 settings::Shell::Program(p) => p.clone(),
4587 settings::Shell::WithArguments { program, .. } => program.clone(),
4588 _ => String::from("sh"),
4589 };
4590 settings::Shell::Program(program)
4591 },
4592 settings::ShellDiscriminants::WithArguments => {
4593 let (program, args, title_override) = match settings_value {
4594 settings::Shell::Program(p) => (p.clone(), vec![], None),
4595 settings::Shell::WithArguments { program, args, title_override } => {
4596 (program.clone(), args.clone(), title_override.clone())
4597 },
4598 _ => (String::from("sh"), vec![], None),
4599 };
4600 settings::Shell::WithArguments {
4601 program,
4602 args,
4603 title_override,
4604 }
4605 },
4606 };
4607 },
4608 }),
4609 metadata: None,
4610 },
4611 pick_discriminant: |settings_content| {
4612 Some(settings_content.terminal.as_ref()?.project.shell.as_ref()?.discriminant() as usize)
4613 },
4614 fields: dynamic_variants::<settings::Shell>().into_iter().map(|variant| {
4615 match variant {
4616 settings::ShellDiscriminants::System => vec![],
4617 settings::ShellDiscriminants::Program => vec![
4618 SettingItem {
4619 files: USER | PROJECT,
4620 title: "Program",
4621 description: "The shell program to use.",
4622 field: Box::new(SettingField {
4623 json_path: Some("terminal.shell"),
4624 pick: |settings_content| {
4625 match settings_content.terminal.as_ref()?.project.shell.as_ref() {
4626 Some(settings::Shell::Program(program)) => Some(program),
4627 _ => None
4628 }
4629 },
4630 write: |settings_content, value| {
4631 let Some(value) = value else {
4632 return;
4633 };
4634 match settings_content
4635 .terminal
4636 .get_or_insert_default()
4637 .project
4638 .shell.as_mut() {
4639 Some(settings::Shell::Program(program)) => *program = value,
4640 _ => return
4641 }
4642 },
4643 }),
4644 metadata: None,
4645 }
4646 ],
4647 settings::ShellDiscriminants::WithArguments => vec![
4648 SettingItem {
4649 files: USER | PROJECT,
4650 title: "Program",
4651 description: "The shell program to run.",
4652 field: Box::new(SettingField {
4653 json_path: Some("terminal.shell.program"),
4654 pick: |settings_content| {
4655 match settings_content.terminal.as_ref()?.project.shell.as_ref() {
4656 Some(settings::Shell::WithArguments { program, .. }) => Some(program),
4657 _ => None
4658 }
4659 },
4660 write: |settings_content, value| {
4661 let Some(value) = value else {
4662 return;
4663 };
4664 match settings_content
4665 .terminal
4666 .get_or_insert_default()
4667 .project
4668 .shell.as_mut() {
4669 Some(settings::Shell::WithArguments { program, .. }) => *program = value,
4670 _ => return
4671 }
4672 },
4673 }),
4674 metadata: None,
4675 },
4676 SettingItem {
4677 files: USER | PROJECT,
4678 title: "Arguments",
4679 description: "The arguments to pass to the shell program.",
4680 field: Box::new(
4681 SettingField {
4682 json_path: Some("terminal.shell.args"),
4683 pick: |settings_content| {
4684 match settings_content.terminal.as_ref()?.project.shell.as_ref() {
4685 Some(settings::Shell::WithArguments { args, .. }) => Some(args),
4686 _ => None
4687 }
4688 },
4689 write: |settings_content, value| {
4690 let Some(value) = value else {
4691 return;
4692 };
4693 match settings_content
4694 .terminal
4695 .get_or_insert_default()
4696 .project
4697 .shell.as_mut() {
4698 Some(settings::Shell::WithArguments { args, .. }) => *args = value,
4699 _ => return
4700 }
4701 },
4702 }
4703 .unimplemented(),
4704 ),
4705 metadata: None,
4706 },
4707 SettingItem {
4708 files: USER | PROJECT,
4709 title: "Title Override",
4710 description: "An optional string to override the title of the terminal tab.",
4711 field: Box::new(SettingField {
4712 json_path: Some("terminal.shell.title_override"),
4713 pick: |settings_content| {
4714 match settings_content.terminal.as_ref()?.project.shell.as_ref() {
4715 Some(settings::Shell::WithArguments { title_override, .. }) => title_override.as_ref().or(DEFAULT_EMPTY_SHARED_STRING),
4716 _ => None
4717 }
4718 },
4719 write: |settings_content, value| {
4720 match settings_content
4721 .terminal
4722 .get_or_insert_default()
4723 .project
4724 .shell.as_mut() {
4725 Some(settings::Shell::WithArguments { title_override, .. }) => *title_override = value.filter(|s| !s.is_empty()),
4726 _ => return
4727 }
4728 },
4729 }),
4730 metadata: None,
4731 }
4732 ],
4733 }
4734 }).collect(),
4735 }),
4736 SettingsPageItem::DynamicItem(DynamicItem {
4737 discriminant: SettingItem {
4738 files: USER | PROJECT,
4739 title: "Working Directory",
4740 description: "What working directory to use when launching the terminal.",
4741 field: Box::new(SettingField {
4742 json_path: Some("terminal.working_directory$"),
4743 pick: |settings_content| {
4744 Some(&dynamic_variants::<settings::WorkingDirectory>()[
4745 settings_content
4746 .terminal
4747 .as_ref()?
4748 .project
4749 .working_directory
4750 .as_ref()?
4751 .discriminant() as usize])
4752 },
4753 write: |settings_content, value| {
4754 let Some(value) = value else {
4755 if let Some(terminal) = settings_content.terminal.as_mut() {
4756 terminal.project.working_directory = None;
4757 }
4758 return;
4759 };
4760 let settings_value = settings_content
4761 .terminal
4762 .get_or_insert_default()
4763 .project
4764 .working_directory
4765 .get_or_insert_with(|| settings::WorkingDirectory::CurrentProjectDirectory);
4766 *settings_value = match value {
4767 settings::WorkingDirectoryDiscriminants::CurrentProjectDirectory => {
4768 settings::WorkingDirectory::CurrentProjectDirectory
4769 },
4770 settings::WorkingDirectoryDiscriminants::FirstProjectDirectory => {
4771 settings::WorkingDirectory::FirstProjectDirectory
4772 },
4773 settings::WorkingDirectoryDiscriminants::AlwaysHome => {
4774 settings::WorkingDirectory::AlwaysHome
4775 },
4776 settings::WorkingDirectoryDiscriminants::Always => {
4777 let directory = match settings_value {
4778 settings::WorkingDirectory::Always { .. } => return,
4779 _ => String::new(),
4780 };
4781 settings::WorkingDirectory::Always { directory }
4782 },
4783 };
4784 },
4785 }),
4786 metadata: None,
4787 },
4788 pick_discriminant: |settings_content| {
4789 Some(settings_content.terminal.as_ref()?.project.working_directory.as_ref()?.discriminant() as usize)
4790 },
4791 fields: dynamic_variants::<settings::WorkingDirectory>().into_iter().map(|variant| {
4792 match variant {
4793 settings::WorkingDirectoryDiscriminants::CurrentProjectDirectory => vec![],
4794 settings::WorkingDirectoryDiscriminants::FirstProjectDirectory => vec![],
4795 settings::WorkingDirectoryDiscriminants::AlwaysHome => vec![],
4796 settings::WorkingDirectoryDiscriminants::Always => vec![
4797 SettingItem {
4798 files: USER | PROJECT,
4799 title: "Directory",
4800 description: "The directory path to use (will be shell expanded).",
4801 field: Box::new(SettingField {
4802 json_path: Some("terminal.working_directory.always"),
4803 pick: |settings_content| {
4804 match settings_content.terminal.as_ref()?.project.working_directory.as_ref() {
4805 Some(settings::WorkingDirectory::Always { directory }) => Some(directory),
4806 _ => None
4807 }
4808 },
4809 write: |settings_content, value| {
4810 let value = value.unwrap_or_default();
4811 match settings_content
4812 .terminal
4813 .get_or_insert_default()
4814 .project
4815 .working_directory.as_mut() {
4816 Some(settings::WorkingDirectory::Always { directory }) => *directory = value,
4817 _ => return
4818 }
4819 },
4820 }),
4821 metadata: None,
4822 }
4823 ],
4824 }
4825 }).collect(),
4826 }),
4827 SettingsPageItem::SettingItem(SettingItem {
4828 title: "Environment Variables",
4829 description: "Key-value pairs to add to the terminal's environment.",
4830 field: Box::new(
4831 SettingField {
4832 json_path: Some("terminal.env"),
4833 pick: |settings_content| {
4834 settings_content.terminal.as_ref()?.project.env.as_ref()
4835 },
4836 write: |settings_content, value| {
4837 settings_content
4838 .terminal
4839 .get_or_insert_default()
4840 .project
4841 .env = value;
4842 },
4843 }
4844 .unimplemented(),
4845 ),
4846 metadata: None,
4847 files: USER | PROJECT,
4848 }),
4849 SettingsPageItem::SettingItem(SettingItem {
4850 title: "Detect Virtual Environment",
4851 description: "Activates the Python virtual environment, if one is found, in the terminal's working directory.",
4852 field: Box::new(
4853 SettingField {
4854 json_path: Some("terminal.detect_venv"),
4855 pick: |settings_content| {
4856 settings_content
4857 .terminal
4858 .as_ref()?
4859 .project
4860 .detect_venv
4861 .as_ref()
4862 },
4863 write: |settings_content, value| {
4864 settings_content
4865 .terminal
4866 .get_or_insert_default()
4867 .project
4868 .detect_venv = value;
4869 },
4870 }
4871 .unimplemented(),
4872 ),
4873 metadata: None,
4874 files: USER | PROJECT,
4875 }),
4876 SettingsPageItem::SectionHeader("Font"),
4877 SettingsPageItem::SettingItem(SettingItem {
4878 title: "Font Size",
4879 description: "Font size for terminal text. If not set, defaults to buffer font size.",
4880 field: Box::new(SettingField {
4881 json_path: Some("terminal.font_size"),
4882 pick: |settings_content| {
4883 settings_content
4884 .terminal
4885 .as_ref()
4886 .and_then(|terminal| terminal.font_size.as_ref())
4887 .or(settings_content.theme.buffer_font_size.as_ref())
4888 },
4889 write: |settings_content, value| {
4890 settings_content.terminal.get_or_insert_default().font_size = value;
4891 },
4892 }),
4893 metadata: None,
4894 files: USER,
4895 }),
4896 SettingsPageItem::SettingItem(SettingItem {
4897 title: "Font Family",
4898 description: "Font family for terminal text. If not set, defaults to buffer font family.",
4899 field: Box::new(SettingField {
4900 json_path: Some("terminal.font_family"),
4901 pick: |settings_content| {
4902 settings_content
4903 .terminal
4904 .as_ref()
4905 .and_then(|terminal| terminal.font_family.as_ref())
4906 .or(settings_content.theme.buffer_font_family.as_ref())
4907 },
4908 write: |settings_content, value| {
4909 settings_content
4910 .terminal
4911 .get_or_insert_default()
4912 .font_family = value;
4913 },
4914 }),
4915 metadata: None,
4916 files: USER,
4917 }),
4918 SettingsPageItem::SettingItem(SettingItem {
4919 title: "Font Fallbacks",
4920 description: "Font fallbacks for terminal text. If not set, defaults to buffer font fallbacks.",
4921 field: Box::new(
4922 SettingField {
4923 json_path: Some("terminal.font_fallbacks"),
4924 pick: |settings_content| {
4925 settings_content
4926 .terminal
4927 .as_ref()
4928 .and_then(|terminal| terminal.font_fallbacks.as_ref())
4929 .or(settings_content.theme.buffer_font_fallbacks.as_ref())
4930 },
4931 write: |settings_content, value| {
4932 settings_content
4933 .terminal
4934 .get_or_insert_default()
4935 .font_fallbacks = value;
4936 },
4937 }
4938 .unimplemented(),
4939 ),
4940 metadata: None,
4941 files: USER,
4942 }),
4943 SettingsPageItem::SettingItem(SettingItem {
4944 title: "Font Weight",
4945 description: "Font weight for terminal text in CSS weight units (100-900).",
4946 field: Box::new(SettingField {
4947 json_path: Some("terminal.font_weight"),
4948 pick: |settings_content| {
4949 settings_content.terminal.as_ref()?.font_weight.as_ref()
4950 },
4951 write: |settings_content, value| {
4952 settings_content
4953 .terminal
4954 .get_or_insert_default()
4955 .font_weight = value;
4956 },
4957 }),
4958 metadata: None,
4959 files: USER,
4960 }),
4961 SettingsPageItem::SettingItem(SettingItem {
4962 title: "Font Features",
4963 description: "Font features for terminal text.",
4964 field: Box::new(
4965 SettingField {
4966 json_path: Some("terminal.font_features"),
4967 pick: |settings_content| {
4968 settings_content
4969 .terminal
4970 .as_ref()
4971 .and_then(|terminal| terminal.font_features.as_ref())
4972 .or(settings_content.theme.buffer_font_features.as_ref())
4973 },
4974 write: |settings_content, value| {
4975 settings_content
4976 .terminal
4977 .get_or_insert_default()
4978 .font_features = value;
4979 },
4980 }
4981 .unimplemented(),
4982 ),
4983 metadata: None,
4984 files: USER,
4985 }),
4986 SettingsPageItem::SectionHeader("Display Settings"),
4987 SettingsPageItem::SettingItem(SettingItem {
4988 title: "Line Height",
4989 description: "Line height for terminal text.",
4990 field: Box::new(
4991 SettingField {
4992 json_path: Some("terminal.line_height"),
4993 pick: |settings_content| {
4994 settings_content.terminal.as_ref()?.line_height.as_ref()
4995 },
4996 write: |settings_content, value| {
4997 settings_content
4998 .terminal
4999 .get_or_insert_default()
5000 .line_height = value;
5001 },
5002 }
5003 .unimplemented(),
5004 ),
5005 metadata: None,
5006 files: USER,
5007 }),
5008 SettingsPageItem::SettingItem(SettingItem {
5009 title: "Cursor Shape",
5010 description: "Default cursor shape for the terminal (bar, block, underline, or hollow).",
5011 field: Box::new(SettingField {
5012 json_path: Some("terminal.cursor_shape"),
5013 pick: |settings_content| {
5014 settings_content.terminal.as_ref()?.cursor_shape.as_ref()
5015 },
5016 write: |settings_content, value| {
5017 settings_content
5018 .terminal
5019 .get_or_insert_default()
5020 .cursor_shape = value;
5021 },
5022 }),
5023 metadata: None,
5024 files: USER,
5025 }),
5026 SettingsPageItem::SettingItem(SettingItem {
5027 title: "Cursor Blinking",
5028 description: "Sets the cursor blinking behavior in the terminal.",
5029 field: Box::new(SettingField {
5030 json_path: Some("terminal.blinking"),
5031 pick: |settings_content| {
5032 settings_content.terminal.as_ref()?.blinking.as_ref()
5033 },
5034 write: |settings_content, value| {
5035 settings_content.terminal.get_or_insert_default().blinking = value;
5036 },
5037 }),
5038 metadata: None,
5039 files: USER,
5040 }),
5041 SettingsPageItem::SettingItem(SettingItem {
5042 title: "Alternate Scroll",
5043 description: "Whether alternate scroll mode is active by default (converts mouse scroll to arrow keys in apps like Vim).",
5044 field: Box::new(SettingField {
5045 json_path: Some("terminal.alternate_scroll"),
5046 pick: |settings_content| {
5047 settings_content
5048 .terminal
5049 .as_ref()?
5050 .alternate_scroll
5051 .as_ref()
5052 },
5053 write: |settings_content, value| {
5054 settings_content
5055 .terminal
5056 .get_or_insert_default()
5057 .alternate_scroll = value;
5058 },
5059 }),
5060 metadata: None,
5061 files: USER,
5062 }),
5063 SettingsPageItem::SettingItem(SettingItem {
5064 title: "Minimum Contrast",
5065 description: "The minimum APCA perceptual contrast between foreground and background colors (0-106).",
5066 field: Box::new(SettingField {
5067 json_path: Some("terminal.minimum_contrast"),
5068 pick: |settings_content| {
5069 settings_content
5070 .terminal
5071 .as_ref()?
5072 .minimum_contrast
5073 .as_ref()
5074 },
5075 write: |settings_content, value| {
5076 settings_content
5077 .terminal
5078 .get_or_insert_default()
5079 .minimum_contrast = value;
5080 },
5081 }),
5082 metadata: None,
5083 files: USER,
5084 }),
5085 SettingsPageItem::SectionHeader("Behavior Settings"),
5086 SettingsPageItem::SettingItem(SettingItem {
5087 title: "Option As Meta",
5088 description: "Whether the option key behaves as the meta key.",
5089 field: Box::new(SettingField {
5090 json_path: Some("terminal.option_as_meta"),
5091 pick: |settings_content| {
5092 settings_content.terminal.as_ref()?.option_as_meta.as_ref()
5093 },
5094 write: |settings_content, value| {
5095 settings_content
5096 .terminal
5097 .get_or_insert_default()
5098 .option_as_meta = value;
5099 },
5100 }),
5101 metadata: None,
5102 files: USER,
5103 }),
5104 SettingsPageItem::SettingItem(SettingItem {
5105 title: "Copy On Select",
5106 description: "Whether selecting text in the terminal automatically copies to the system clipboard.",
5107 field: Box::new(SettingField {
5108 json_path: Some("terminal.copy_on_select"),
5109 pick: |settings_content| {
5110 settings_content.terminal.as_ref()?.copy_on_select.as_ref()
5111 },
5112 write: |settings_content, value| {
5113 settings_content
5114 .terminal
5115 .get_or_insert_default()
5116 .copy_on_select = value;
5117 },
5118 }),
5119 metadata: None,
5120 files: USER,
5121 }),
5122 SettingsPageItem::SettingItem(SettingItem {
5123 title: "Keep Selection On Copy",
5124 description: "Whether to keep the text selection after copying it to the clipboard.",
5125 field: Box::new(SettingField {
5126 json_path: Some("terminal.keep_selection_on_copy"),
5127 pick: |settings_content| {
5128 settings_content
5129 .terminal
5130 .as_ref()?
5131 .keep_selection_on_copy
5132 .as_ref()
5133 },
5134 write: |settings_content, value| {
5135 settings_content
5136 .terminal
5137 .get_or_insert_default()
5138 .keep_selection_on_copy = value;
5139 },
5140 }),
5141 metadata: None,
5142 files: USER,
5143 }),
5144 SettingsPageItem::SectionHeader("Layout Settings"),
5145 SettingsPageItem::SettingItem(SettingItem {
5146 title: "Default Width",
5147 description: "Default width when the terminal is docked to the left or right (in pixels).",
5148 field: Box::new(SettingField {
5149 json_path: Some("terminal.default_width"),
5150 pick: |settings_content| {
5151 settings_content.terminal.as_ref()?.default_width.as_ref()
5152 },
5153 write: |settings_content, value| {
5154 settings_content
5155 .terminal
5156 .get_or_insert_default()
5157 .default_width = value;
5158 },
5159 }),
5160 metadata: None,
5161 files: USER,
5162 }),
5163 SettingsPageItem::SettingItem(SettingItem {
5164 title: "Default Height",
5165 description: "Default height when the terminal is docked to the bottom (in pixels).",
5166 field: Box::new(SettingField {
5167 json_path: Some("terminal.default_height"),
5168 pick: |settings_content| {
5169 settings_content.terminal.as_ref()?.default_height.as_ref()
5170 },
5171 write: |settings_content, value| {
5172 settings_content
5173 .terminal
5174 .get_or_insert_default()
5175 .default_height = value;
5176 },
5177 }),
5178 metadata: None,
5179 files: USER,
5180 }),
5181 SettingsPageItem::SectionHeader("Advanced Settings"),
5182 SettingsPageItem::SettingItem(SettingItem {
5183 title: "Max Scroll History Lines",
5184 description: "Maximum number of lines to keep in scrollback history (max: 100,000; 0 disables scrolling).",
5185 field: Box::new(SettingField {
5186 json_path: Some("terminal.max_scroll_history_lines"),
5187 pick: |settings_content| {
5188 settings_content
5189 .terminal
5190 .as_ref()?
5191 .max_scroll_history_lines
5192 .as_ref()
5193 },
5194 write: |settings_content, value| {
5195 settings_content
5196 .terminal
5197 .get_or_insert_default()
5198 .max_scroll_history_lines = value;
5199 },
5200 }),
5201 metadata: None,
5202 files: USER,
5203 }),
5204 SettingsPageItem::SettingItem(SettingItem {
5205 title: "Scroll Multiplier",
5206 description: "The multiplier for scrolling in the terminal with the mouse wheel",
5207 field: Box::new(SettingField {
5208 json_path: Some("terminal.scroll_multiplier"),
5209 pick: |settings_content| {
5210 settings_content.terminal.as_ref()?.scroll_multiplier.as_ref()
5211 },
5212 write: |settings_content, value| {
5213 settings_content
5214 .terminal
5215 .get_or_insert_default()
5216 .scroll_multiplier = value;
5217 },
5218 }),
5219 metadata: None,
5220 files: USER,
5221 }),
5222 SettingsPageItem::SectionHeader("Toolbar"),
5223 SettingsPageItem::SettingItem(SettingItem {
5224 title: "Breadcrumbs",
5225 description: "Display the terminal title in breadcrumbs inside the terminal pane.",
5226 field: Box::new(SettingField {
5227 json_path: Some("terminal.toolbar.breadcrumbs"),
5228 pick: |settings_content| {
5229 settings_content
5230 .terminal
5231 .as_ref()?
5232 .toolbar
5233 .as_ref()?
5234 .breadcrumbs
5235 .as_ref()
5236 },
5237 write: |settings_content, value| {
5238 settings_content
5239 .terminal
5240 .get_or_insert_default()
5241 .toolbar
5242 .get_or_insert_default()
5243 .breadcrumbs = value;
5244 },
5245 }),
5246 metadata: None,
5247 files: USER,
5248 }),
5249 SettingsPageItem::SectionHeader("Scrollbar"),
5250 SettingsPageItem::SettingItem(SettingItem {
5251 title: "Show Scrollbar",
5252 description: "When to show the scrollbar in the terminal.",
5253 field: Box::new(SettingField {
5254 json_path: Some("terminal.scrollbar.show"),
5255 pick: |settings_content| {
5256 show_scrollbar_or_editor(settings_content, |settings_content| {
5257 settings_content
5258 .terminal
5259 .as_ref()?
5260 .scrollbar
5261 .as_ref()?
5262 .show
5263 .as_ref()
5264 })
5265 },
5266 write: |settings_content, value| {
5267 settings_content
5268 .terminal
5269 .get_or_insert_default()
5270 .scrollbar
5271 .get_or_insert_default()
5272 .show = value;
5273 },
5274 }),
5275 metadata: None,
5276 files: USER,
5277 }),
5278 ],
5279 },
5280 SettingsPage {
5281 title: "Version Control",
5282 items: vec![
5283 SettingsPageItem::SectionHeader("Git Gutter"),
5284 SettingsPageItem::SettingItem(SettingItem {
5285 title: "Visibility",
5286 description: "Control whether Git status is shown in the editor's gutter.",
5287 field: Box::new(SettingField {
5288 json_path: Some("git.git_gutter"),
5289 pick: |settings_content| settings_content.git.as_ref()?.git_gutter.as_ref(),
5290 write: |settings_content, value| {
5291 settings_content.git.get_or_insert_default().git_gutter = value;
5292 },
5293 }),
5294 metadata: None,
5295 files: USER,
5296 }),
5297 // todo(settings_ui): Figure out the right default for this value in default.json
5298 SettingsPageItem::SettingItem(SettingItem {
5299 title: "Debounce",
5300 description: "Debounce threshold in milliseconds after which changes are reflected in the Git gutter.",
5301 field: Box::new(SettingField {
5302 json_path: Some("git.gutter_debounce"),
5303 pick: |settings_content| {
5304 settings_content.git.as_ref()?.gutter_debounce.as_ref()
5305 },
5306 write: |settings_content, value| {
5307 settings_content.git.get_or_insert_default().gutter_debounce = value;
5308 },
5309 }),
5310 metadata: None,
5311 files: USER,
5312 }),
5313 SettingsPageItem::SectionHeader("Inline Git Blame"),
5314 SettingsPageItem::SettingItem(SettingItem {
5315 title: "Enabled",
5316 description: "Whether or not to show Git blame data inline in the currently focused line.",
5317 field: Box::new(SettingField {
5318 json_path: Some("git.inline_blame.enabled"),
5319 pick: |settings_content| {
5320 settings_content
5321 .git
5322 .as_ref()?
5323 .inline_blame
5324 .as_ref()?
5325 .enabled
5326 .as_ref()
5327 },
5328 write: |settings_content, value| {
5329 settings_content
5330 .git
5331 .get_or_insert_default()
5332 .inline_blame
5333 .get_or_insert_default()
5334 .enabled = value;
5335 },
5336 }),
5337 metadata: None,
5338 files: USER,
5339 }),
5340 SettingsPageItem::SettingItem(SettingItem {
5341 title: "Delay",
5342 description: "The delay after which the inline blame information is shown.",
5343 field: Box::new(SettingField {
5344 json_path: Some("git.inline_blame.delay_ms"),
5345 pick: |settings_content| {
5346 settings_content
5347 .git
5348 .as_ref()?
5349 .inline_blame
5350 .as_ref()?
5351 .delay_ms
5352 .as_ref()
5353 },
5354 write: |settings_content, value| {
5355 settings_content
5356 .git
5357 .get_or_insert_default()
5358 .inline_blame
5359 .get_or_insert_default()
5360 .delay_ms = value;
5361 },
5362 }),
5363 metadata: None,
5364 files: USER,
5365 }),
5366 SettingsPageItem::SettingItem(SettingItem {
5367 title: "Padding",
5368 description: "Padding between the end of the source line and the start of the inline blame in columns.",
5369 field: Box::new(SettingField {
5370 json_path: Some("git.inline_blame.padding"),
5371 pick: |settings_content| {
5372 settings_content
5373 .git
5374 .as_ref()?
5375 .inline_blame
5376 .as_ref()?
5377 .padding
5378 .as_ref()
5379 },
5380 write: |settings_content, value| {
5381 settings_content
5382 .git
5383 .get_or_insert_default()
5384 .inline_blame
5385 .get_or_insert_default()
5386 .padding = value;
5387 },
5388 }),
5389 metadata: None,
5390 files: USER,
5391 }),
5392 SettingsPageItem::SettingItem(SettingItem {
5393 title: "Minimum Column",
5394 description: "The minimum column number at which to show the inline blame information.",
5395 field: Box::new(SettingField {
5396 json_path: Some("git.inline_blame.min_column"),
5397 pick: |settings_content| {
5398 settings_content
5399 .git
5400 .as_ref()?
5401 .inline_blame
5402 .as_ref()?
5403 .min_column
5404 .as_ref()
5405 },
5406 write: |settings_content, value| {
5407 settings_content
5408 .git
5409 .get_or_insert_default()
5410 .inline_blame
5411 .get_or_insert_default()
5412 .min_column = value;
5413 },
5414 }),
5415 metadata: None,
5416 files: USER,
5417 }),
5418 SettingsPageItem::SettingItem(SettingItem {
5419 title: "Show Commit Summary",
5420 description: "Show commit summary as part of the inline blame.",
5421 field: Box::new(SettingField {
5422 json_path: Some("git.inline_blame.show_commit_summary"),
5423 pick: |settings_content| {
5424 settings_content
5425 .git
5426 .as_ref()?
5427 .inline_blame
5428 .as_ref()?
5429 .show_commit_summary
5430 .as_ref()
5431 },
5432 write: |settings_content, value| {
5433 settings_content
5434 .git
5435 .get_or_insert_default()
5436 .inline_blame
5437 .get_or_insert_default()
5438 .show_commit_summary = value;
5439 },
5440 }),
5441 metadata: None,
5442 files: USER,
5443 }),
5444 SettingsPageItem::SectionHeader("Git Blame View"),
5445 SettingsPageItem::SettingItem(SettingItem {
5446 title: "Show Avatar",
5447 description: "Show the avatar of the author of the commit.",
5448 field: Box::new(SettingField {
5449 json_path: Some("git.blame.show_avatar"),
5450 pick: |settings_content| {
5451 settings_content
5452 .git
5453 .as_ref()?
5454 .blame
5455 .as_ref()?
5456 .show_avatar
5457 .as_ref()
5458 },
5459 write: |settings_content, value| {
5460 settings_content
5461 .git
5462 .get_or_insert_default()
5463 .blame
5464 .get_or_insert_default()
5465 .show_avatar = value;
5466 },
5467 }),
5468 metadata: None,
5469 files: USER,
5470 }),
5471 SettingsPageItem::SectionHeader("Branch Picker"),
5472 SettingsPageItem::SettingItem(SettingItem {
5473 title: "Show Author Name",
5474 description: "Show author name as part of the commit information in branch picker.",
5475 field: Box::new(SettingField {
5476 json_path: Some("git.branch_picker.show_author_name"),
5477 pick: |settings_content| {
5478 settings_content
5479 .git
5480 .as_ref()?
5481 .branch_picker
5482 .as_ref()?
5483 .show_author_name
5484 .as_ref()
5485 },
5486 write: |settings_content, value| {
5487 settings_content
5488 .git
5489 .get_or_insert_default()
5490 .branch_picker
5491 .get_or_insert_default()
5492 .show_author_name = value;
5493 },
5494 }),
5495 metadata: None,
5496 files: USER,
5497 }),
5498 SettingsPageItem::SectionHeader("Git Hunks"),
5499 SettingsPageItem::SettingItem(SettingItem {
5500 title: "Hunk Style",
5501 description: "How Git hunks are displayed visually in the editor.",
5502 field: Box::new(SettingField {
5503 json_path: Some("git.hunk_style"),
5504 pick: |settings_content| settings_content.git.as_ref()?.hunk_style.as_ref(),
5505 write: |settings_content, value| {
5506 settings_content.git.get_or_insert_default().hunk_style = value;
5507 },
5508 }),
5509 metadata: None,
5510 files: USER,
5511 }),
5512 SettingsPageItem::SettingItem(SettingItem {
5513 title: "Path Style",
5514 description: "Should the name or path be displayed first in the git view.",
5515 field: Box::new(SettingField {
5516 json_path: Some("git.path_style"),
5517 pick: |settings_content| settings_content.git.as_ref()?.path_style.as_ref(),
5518 write: |settings_content, value| {
5519 settings_content.git.get_or_insert_default().path_style = value;
5520 },
5521 }),
5522 metadata: None,
5523 files: USER,
5524 }),
5525 ],
5526 },
5527 SettingsPage {
5528 title: "Collaboration",
5529 items: vec![
5530 SettingsPageItem::SectionHeader("Calls"),
5531 SettingsPageItem::SettingItem(SettingItem {
5532 title: "Mute On Join",
5533 description: "Whether the microphone should be muted when joining a channel or a call.",
5534 field: Box::new(SettingField {
5535 json_path: Some("calls.mute_on_join"),
5536 pick: |settings_content| {
5537 settings_content.calls.as_ref()?.mute_on_join.as_ref()
5538 },
5539 write: |settings_content, value| {
5540 settings_content.calls.get_or_insert_default().mute_on_join = value;
5541 },
5542 }),
5543 metadata: None,
5544 files: USER,
5545 }),
5546 SettingsPageItem::SettingItem(SettingItem {
5547 title: "Share On Join",
5548 description: "Whether your current project should be shared when joining an empty channel.",
5549 field: Box::new(SettingField {
5550 json_path: Some("calls.share_on_join"),
5551 pick: |settings_content| {
5552 settings_content.calls.as_ref()?.share_on_join.as_ref()
5553 },
5554 write: |settings_content, value| {
5555 settings_content.calls.get_or_insert_default().share_on_join = value;
5556 },
5557 }),
5558 metadata: None,
5559 files: USER,
5560 }),
5561 SettingsPageItem::SectionHeader("Experimental"),
5562 SettingsPageItem::SettingItem(SettingItem {
5563 title: "Rodio Audio",
5564 description: "Opt into the new audio system.",
5565 field: Box::new(SettingField {
5566 json_path: Some("audio.experimental.rodio_audio"),
5567 pick: |settings_content| {
5568 settings_content.audio.as_ref()?.rodio_audio.as_ref()
5569 },
5570 write: |settings_content, value| {
5571 settings_content.audio.get_or_insert_default().rodio_audio = value;
5572 },
5573 }),
5574 metadata: None,
5575 files: USER,
5576 }),
5577 SettingsPageItem::SettingItem(SettingItem {
5578 title: "Auto Microphone Volume",
5579 description: "Automatically adjust microphone volume (requires rodio audio).",
5580 field: Box::new(SettingField {
5581 json_path: Some("audio.experimental.auto_microphone_volume"),
5582 pick: |settings_content| {
5583 settings_content
5584 .audio
5585 .as_ref()?
5586 .auto_microphone_volume
5587 .as_ref()
5588 },
5589 write: |settings_content, value| {
5590 settings_content
5591 .audio
5592 .get_or_insert_default()
5593 .auto_microphone_volume = value;
5594 },
5595 }),
5596 metadata: None,
5597 files: USER,
5598 }),
5599 SettingsPageItem::SettingItem(SettingItem {
5600 title: "Auto Speaker Volume",
5601 description: "Automatically adjust volume of other call members (requires rodio audio).",
5602 field: Box::new(SettingField {
5603 json_path: Some("audio.experimental.auto_speaker_volume"),
5604 pick: |settings_content| {
5605 settings_content
5606 .audio
5607 .as_ref()?
5608 .auto_speaker_volume
5609 .as_ref()
5610 },
5611 write: |settings_content, value| {
5612 settings_content
5613 .audio
5614 .get_or_insert_default()
5615 .auto_speaker_volume = value;
5616 },
5617 }),
5618 metadata: None,
5619 files: USER,
5620 }),
5621 SettingsPageItem::SettingItem(SettingItem {
5622 title: "Denoise",
5623 description: "Remove background noises (requires rodio audio).",
5624 field: Box::new(SettingField {
5625 json_path: Some("audio.experimental.denoise"),
5626 pick: |settings_content| settings_content.audio.as_ref()?.denoise.as_ref(),
5627 write: |settings_content, value| {
5628 settings_content.audio.get_or_insert_default().denoise = value;
5629 },
5630 }),
5631 metadata: None,
5632 files: USER,
5633 }),
5634 SettingsPageItem::SettingItem(SettingItem {
5635 title: "Legacy Audio Compatible",
5636 description: "Use audio parameters compatible with previous versions (requires rodio audio).",
5637 field: Box::new(SettingField {
5638 json_path: Some("audio.experimental.legacy_audio_compatible"),
5639 pick: |settings_content| {
5640 settings_content
5641 .audio
5642 .as_ref()?
5643 .legacy_audio_compatible
5644 .as_ref()
5645 },
5646 write: |settings_content, value| {
5647 settings_content
5648 .audio
5649 .get_or_insert_default()
5650 .legacy_audio_compatible = value;
5651 },
5652 }),
5653 metadata: None,
5654 files: USER,
5655 }),
5656 ],
5657 },
5658 SettingsPage {
5659 title: "AI",
5660 items: {
5661 let mut items = vec![
5662 SettingsPageItem::SectionHeader("General"),
5663 SettingsPageItem::SettingItem(SettingItem {
5664 title: "Disable AI",
5665 description: "Whether to disable all AI features in Zed.",
5666 field: Box::new(SettingField {
5667 json_path: Some("disable_ai"),
5668 pick: |settings_content| settings_content.disable_ai.as_ref(),
5669 write: |settings_content, value| {
5670 settings_content.disable_ai = value;
5671 },
5672 }),
5673 metadata: None,
5674 files: USER,
5675 }),
5676 SettingsPageItem::SectionHeader("Agent Configuration"),
5677 SettingsPageItem::SettingItem(SettingItem {
5678 title: "Always Allow Tool Actions",
5679 description: "When enabled, the agent can run potentially destructive actions without asking for your confirmation. This setting has no effect on external agents.",
5680 field: Box::new(SettingField {
5681 json_path: Some("agent.always_allow_tool_actions"),
5682 pick: |settings_content| {
5683 settings_content
5684 .agent
5685 .as_ref()?
5686 .always_allow_tool_actions
5687 .as_ref()
5688 },
5689 write: |settings_content, value| {
5690 settings_content
5691 .agent
5692 .get_or_insert_default()
5693 .always_allow_tool_actions = value;
5694 },
5695 }),
5696 metadata: None,
5697 files: USER,
5698 }),
5699 SettingsPageItem::SettingItem(SettingItem {
5700 title: "Single File Review",
5701 description: "When enabled, agent edits will also be displayed in single-file buffers for review.",
5702 field: Box::new(SettingField {
5703 json_path: Some("agent.single_file_review"),
5704 pick: |settings_content| {
5705 settings_content.agent.as_ref()?.single_file_review.as_ref()
5706 },
5707 write: |settings_content, value| {
5708 settings_content
5709 .agent
5710 .get_or_insert_default()
5711 .single_file_review = value;
5712 },
5713 }),
5714 metadata: None,
5715 files: USER,
5716 }),
5717 SettingsPageItem::SettingItem(SettingItem {
5718 title: "Enable Feedback",
5719 description: "Show voting thumbs up/down icon buttons for feedback on agent edits.",
5720 field: Box::new(SettingField {
5721 json_path: Some("agent.enable_feedback"),
5722 pick: |settings_content| {
5723 settings_content.agent.as_ref()?.enable_feedback.as_ref()
5724 },
5725 write: |settings_content, value| {
5726 settings_content
5727 .agent
5728 .get_or_insert_default()
5729 .enable_feedback = value;
5730 },
5731 }),
5732 metadata: None,
5733 files: USER,
5734 }),
5735 SettingsPageItem::SettingItem(SettingItem {
5736 title: "Notify When Agent Waiting",
5737 description: "Where to show notifications when the agent has completed its response or needs confirmation before running a tool action.",
5738 field: Box::new(SettingField {
5739 json_path: Some("agent.notify_when_agent_waiting"),
5740 pick: |settings_content| {
5741 settings_content
5742 .agent
5743 .as_ref()?
5744 .notify_when_agent_waiting
5745 .as_ref()
5746 },
5747 write: |settings_content, value| {
5748 settings_content
5749 .agent
5750 .get_or_insert_default()
5751 .notify_when_agent_waiting = value;
5752 },
5753 }),
5754 metadata: None,
5755 files: USER,
5756 }),
5757 SettingsPageItem::SettingItem(SettingItem {
5758 title: "Play Sound When Agent Done",
5759 description: "Whether to play a sound when the agent has either completed its response, or needs user input.",
5760 field: Box::new(SettingField {
5761 json_path: Some("agent.play_sound_when_agent_done"),
5762 pick: |settings_content| {
5763 settings_content
5764 .agent
5765 .as_ref()?
5766 .play_sound_when_agent_done
5767 .as_ref()
5768 },
5769 write: |settings_content, value| {
5770 settings_content
5771 .agent
5772 .get_or_insert_default()
5773 .play_sound_when_agent_done = value;
5774 },
5775 }),
5776 metadata: None,
5777 files: USER,
5778 }),
5779 SettingsPageItem::SettingItem(SettingItem {
5780 title: "Expand Edit Card",
5781 description: "Whether to have edit cards in the agent panel expanded, showing a Preview of the diff.",
5782 field: Box::new(SettingField {
5783 json_path: Some("agent.expand_edit_card"),
5784 pick: |settings_content| {
5785 settings_content.agent.as_ref()?.expand_edit_card.as_ref()
5786 },
5787 write: |settings_content, value| {
5788 settings_content
5789 .agent
5790 .get_or_insert_default()
5791 .expand_edit_card = value;
5792 },
5793 }),
5794 metadata: None,
5795 files: USER,
5796 }),
5797 SettingsPageItem::SettingItem(SettingItem {
5798 title: "Expand Terminal Card",
5799 description: "Whether to have terminal cards in the agent panel expanded, showing the whole command output.",
5800 field: Box::new(SettingField {
5801 json_path: Some("agent.expand_terminal_card"),
5802 pick: |settings_content| {
5803 settings_content
5804 .agent
5805 .as_ref()?
5806 .expand_terminal_card
5807 .as_ref()
5808 },
5809 write: |settings_content, value| {
5810 settings_content
5811 .agent
5812 .get_or_insert_default()
5813 .expand_terminal_card = value;
5814 },
5815 }),
5816 metadata: None,
5817 files: USER,
5818 }),
5819 SettingsPageItem::SettingItem(SettingItem {
5820 title: "Use Modifier To Send",
5821 description: "Whether to always use cmd-enter (or ctrl-enter on Linux or Windows) to send messages.",
5822 field: Box::new(SettingField {
5823 json_path: Some("agent.use_modifier_to_send"),
5824 pick: |settings_content| {
5825 settings_content
5826 .agent
5827 .as_ref()?
5828 .use_modifier_to_send
5829 .as_ref()
5830 },
5831 write: |settings_content, value| {
5832 settings_content
5833 .agent
5834 .get_or_insert_default()
5835 .use_modifier_to_send = value;
5836 },
5837 }),
5838 metadata: None,
5839 files: USER,
5840 }),
5841 SettingsPageItem::SettingItem(SettingItem {
5842 title: "Message Editor Min Lines",
5843 description: "Minimum number of lines to display in the agent message editor.",
5844 field: Box::new(SettingField {
5845 json_path: Some("agent.message_editor_min_lines"),
5846 pick: |settings_content| {
5847 settings_content
5848 .agent
5849 .as_ref()?
5850 .message_editor_min_lines
5851 .as_ref()
5852 },
5853 write: |settings_content, value| {
5854 settings_content
5855 .agent
5856 .get_or_insert_default()
5857 .message_editor_min_lines = value;
5858 },
5859 }),
5860 metadata: None,
5861 files: USER,
5862 }),
5863 ];
5864 items.extend(edit_prediction_language_settings_section());
5865 items.extend(
5866 [
5867 SettingsPageItem::SettingItem(SettingItem {
5868 title: "Display Mode",
5869 description: "When to show edit predictions previews in buffer. The eager mode displays them inline, while the subtle mode displays them only when holding a modifier key.",
5870 field: Box::new(SettingField {
5871 json_path: Some("edit_prediction.display_mode"),
5872 pick: |settings_content| {
5873 settings_content.project.all_languages.edit_predictions.as_ref()?.mode.as_ref()
5874 },
5875 write: |settings_content, value| {
5876 settings_content.project.all_languages.edit_predictions.get_or_insert_default().mode = value;
5877 },
5878 }),
5879 metadata: None,
5880 files: USER,
5881 }),
5882 SettingsPageItem::SettingItem(SettingItem {
5883 title: "In Text Threads",
5884 description: "Whether edit predictions are enabled when editing text threads in the agent panel.",
5885 field: Box::new(SettingField {
5886 json_path: Some("edit_prediction.in_text_threads"),
5887 pick: |settings_content| {
5888 settings_content.project.all_languages.edit_predictions.as_ref()?.enabled_in_text_threads.as_ref()
5889 },
5890 write: |settings_content, value| {
5891 settings_content.project.all_languages.edit_predictions.get_or_insert_default().enabled_in_text_threads = value;
5892 },
5893 }),
5894 metadata: None,
5895 files: USER,
5896 }),
5897 SettingsPageItem::SettingItem(SettingItem {
5898 title: "Copilot Provider",
5899 description: "Use GitHub Copilot as your edit prediction provider.",
5900 field: Box::new(
5901 SettingField {
5902 json_path: Some("edit_prediction.copilot_provider"),
5903 pick: |settings_content| {
5904 settings_content.project.all_languages.edit_predictions.as_ref()?.copilot.as_ref()
5905 },
5906 write: |settings_content, value| {
5907 settings_content.project.all_languages.edit_predictions.get_or_insert_default().copilot = value;
5908 },
5909 }
5910 .unimplemented(),
5911 ),
5912 metadata: None,
5913 files: USER | PROJECT,
5914 }),
5915 SettingsPageItem::SettingItem(SettingItem {
5916 title: "Codestral Provider",
5917 description: "Use Mistral's Codestral as your edit prediction provider.",
5918 field: Box::new(
5919 SettingField {
5920 json_path: Some("edit_prediction.codestral_provider"),
5921 pick: |settings_content| {
5922 settings_content.project.all_languages.edit_predictions.as_ref()?.codestral.as_ref()
5923 },
5924 write: |settings_content, value| {
5925 settings_content.project.all_languages.edit_predictions.get_or_insert_default().codestral = value;
5926 },
5927 }
5928 .unimplemented(),
5929 ),
5930 metadata: None,
5931 files: USER | PROJECT,
5932 }),
5933 ]
5934 );
5935 items
5936 },
5937 },
5938 SettingsPage {
5939 title: "Network",
5940 items: vec![
5941 SettingsPageItem::SectionHeader("Network"),
5942 // todo(settings_ui): Proxy needs a default
5943 SettingsPageItem::SettingItem(SettingItem {
5944 title: "Proxy",
5945 description: "The proxy to use for network requests.",
5946 field: Box::new(
5947 SettingField {
5948 json_path: Some("proxy"),
5949 pick: |settings_content| settings_content.proxy.as_ref(),
5950 write: |settings_content, value| {
5951 settings_content.proxy = value;
5952 },
5953 }
5954 .unimplemented(),
5955 ),
5956 metadata: Some(Box::new(SettingsFieldMetadata {
5957 placeholder: Some("socks5h://localhost:10808"),
5958 ..Default::default()
5959 })),
5960 files: USER,
5961 }),
5962 SettingsPageItem::SettingItem(SettingItem {
5963 title: "Server URL",
5964 description: "The URL of the Zed server to connect to.",
5965 field: Box::new(SettingField {
5966 json_path: Some("server_url"),
5967 pick: |settings_content| settings_content.server_url.as_ref(),
5968 write: |settings_content, value| {
5969 settings_content.server_url = value;
5970 },
5971 }),
5972 metadata: Some(Box::new(SettingsFieldMetadata {
5973 placeholder: Some("https://zed.dev"),
5974 ..Default::default()
5975 })),
5976 files: USER,
5977 }),
5978 ],
5979 },
5980 ]
5981}
5982
5983const LANGUAGES_SECTION_HEADER: &'static str = "Languages";
5984
5985fn current_language() -> Option<SharedString> {
5986 sub_page_stack().iter().find_map(|page| {
5987 (page.section_header == LANGUAGES_SECTION_HEADER).then(|| page.link.title.clone())
5988 })
5989}
5990
5991fn language_settings_field<T>(
5992 settings_content: &SettingsContent,
5993 get: fn(&LanguageSettingsContent) -> Option<&T>,
5994) -> Option<&T> {
5995 let all_languages = &settings_content.project.all_languages;
5996 if let Some(current_language_name) = current_language() {
5997 if let Some(current_language) = all_languages.languages.0.get(¤t_language_name) {
5998 let value = get(current_language);
5999 if value.is_some() {
6000 return value;
6001 }
6002 }
6003 }
6004 let default_value = get(&all_languages.defaults);
6005 return default_value;
6006}
6007
6008fn language_settings_field_mut<T>(
6009 settings_content: &mut SettingsContent,
6010 value: Option<T>,
6011 write: fn(&mut LanguageSettingsContent, Option<T>),
6012) {
6013 let all_languages = &mut settings_content.project.all_languages;
6014 let language_content = if let Some(current_language) = current_language() {
6015 all_languages
6016 .languages
6017 .0
6018 .entry(current_language)
6019 .or_default()
6020 } else {
6021 &mut all_languages.defaults
6022 };
6023 write(language_content, value);
6024}
6025
6026fn language_settings_data() -> Vec<SettingsPageItem> {
6027 let mut items = vec![
6028 SettingsPageItem::SectionHeader("Indentation"),
6029 SettingsPageItem::SettingItem(SettingItem {
6030 title: "Tab Size",
6031 description: "How many columns a tab should occupy.",
6032 field: Box::new(SettingField {
6033 json_path: Some("languages.$(language).tab_size"), // TODO(cameron): not JQ syntax because not URL-safe
6034 pick: |settings_content| {
6035 language_settings_field(settings_content, |language| language.tab_size.as_ref())
6036 },
6037 write: |settings_content, value| {
6038 language_settings_field_mut(settings_content, value, |language, value| {
6039 language.tab_size = value;
6040 })
6041 },
6042 }),
6043 metadata: None,
6044 files: USER | PROJECT,
6045 }),
6046 SettingsPageItem::SettingItem(SettingItem {
6047 title: "Hard Tabs",
6048 description: "Whether to indent lines using tab characters, as opposed to multiple spaces.",
6049 field: Box::new(SettingField {
6050 json_path: Some("languages.$(language).hard_tabs"),
6051 pick: |settings_content| {
6052 language_settings_field(settings_content, |language| {
6053 language.hard_tabs.as_ref()
6054 })
6055 },
6056 write: |settings_content, value| {
6057 language_settings_field_mut(settings_content, value, |language, value| {
6058 language.hard_tabs = value;
6059 })
6060 },
6061 }),
6062 metadata: None,
6063 files: USER | PROJECT,
6064 }),
6065 SettingsPageItem::SettingItem(SettingItem {
6066 title: "Auto Indent",
6067 description: "Whether indentation should be adjusted based on the context whilst typing.",
6068 field: Box::new(SettingField {
6069 json_path: Some("languages.$(language).auto_indent"),
6070 pick: |settings_content| {
6071 language_settings_field(settings_content, |language| {
6072 language.auto_indent.as_ref()
6073 })
6074 },
6075 write: |settings_content, value| {
6076 language_settings_field_mut(settings_content, value, |language, value| {
6077 language.auto_indent = value;
6078 })
6079 },
6080 }),
6081 metadata: None,
6082 files: USER | PROJECT,
6083 }),
6084 SettingsPageItem::SettingItem(SettingItem {
6085 title: "Auto Indent On Paste",
6086 description: "Whether indentation of pasted content should be adjusted based on the context.",
6087 field: Box::new(SettingField {
6088 json_path: Some("languages.$(language).auto_indent_on_paste"),
6089 pick: |settings_content| {
6090 language_settings_field(settings_content, |language| {
6091 language.auto_indent_on_paste.as_ref()
6092 })
6093 },
6094 write: |settings_content, value| {
6095 language_settings_field_mut(settings_content, value, |language, value| {
6096 language.auto_indent_on_paste = value;
6097 })
6098 },
6099 }),
6100 metadata: None,
6101 files: USER | PROJECT,
6102 }),
6103 SettingsPageItem::SectionHeader("Wrapping"),
6104 SettingsPageItem::SettingItem(SettingItem {
6105 title: "Soft Wrap",
6106 description: "How to soft-wrap long lines of text.",
6107 field: Box::new(SettingField {
6108 json_path: Some("languages.$(language).soft_wrap"),
6109 pick: |settings_content| {
6110 language_settings_field(settings_content, |language| {
6111 language.soft_wrap.as_ref()
6112 })
6113 },
6114 write: |settings_content, value| {
6115 language_settings_field_mut(settings_content, value, |language, value| {
6116 language.soft_wrap = value;
6117 })
6118 },
6119 }),
6120 metadata: None,
6121 files: USER | PROJECT,
6122 }),
6123 SettingsPageItem::SettingItem(SettingItem {
6124 title: "Show Wrap Guides",
6125 description: "Show wrap guides in the editor.",
6126 field: Box::new(SettingField {
6127 json_path: Some("languages.$(language).show_wrap_guides"),
6128 pick: |settings_content| {
6129 language_settings_field(settings_content, |language| {
6130 language.show_wrap_guides.as_ref()
6131 })
6132 },
6133 write: |settings_content, value| {
6134 language_settings_field_mut(settings_content, value, |language, value| {
6135 language.show_wrap_guides = value;
6136 })
6137 },
6138 }),
6139 metadata: None,
6140 files: USER | PROJECT,
6141 }),
6142 SettingsPageItem::SettingItem(SettingItem {
6143 title: "Preferred Line Length",
6144 description: "The column at which to soft-wrap lines, for buffers where soft-wrap is enabled.",
6145 field: Box::new(SettingField {
6146 json_path: Some("languages.$(language).preferred_line_length"),
6147 pick: |settings_content| {
6148 language_settings_field(settings_content, |language| {
6149 language.preferred_line_length.as_ref()
6150 })
6151 },
6152 write: |settings_content, value| {
6153 language_settings_field_mut(settings_content, value, |language, value| {
6154 language.preferred_line_length = value;
6155 })
6156 },
6157 }),
6158 metadata: None,
6159 files: USER | PROJECT,
6160 }),
6161 SettingsPageItem::SettingItem(SettingItem {
6162 title: "Wrap Guides",
6163 description: "Character counts at which to show wrap guides in the editor.",
6164 field: Box::new(
6165 SettingField {
6166 json_path: Some("languages.$(language).wrap_guides"),
6167 pick: |settings_content| {
6168 language_settings_field(settings_content, |language| {
6169 language.wrap_guides.as_ref()
6170 })
6171 },
6172 write: |settings_content, value| {
6173 language_settings_field_mut(settings_content, value, |language, value| {
6174 language.wrap_guides = value;
6175 })
6176 },
6177 }
6178 .unimplemented(),
6179 ),
6180 metadata: None,
6181 files: USER | PROJECT,
6182 }),
6183 SettingsPageItem::SettingItem(SettingItem {
6184 title: "Allow Rewrap",
6185 description: "Controls where the `editor::rewrap` action is allowed for this language.",
6186 field: Box::new(SettingField {
6187 json_path: Some("languages.$(language).allow_rewrap"),
6188 pick: |settings_content| {
6189 language_settings_field(settings_content, |language| {
6190 language.allow_rewrap.as_ref()
6191 })
6192 },
6193 write: |settings_content, value| {
6194 language_settings_field_mut(settings_content, value, |language, value| {
6195 language.allow_rewrap = value;
6196 })
6197 },
6198 }),
6199 metadata: None,
6200 files: USER | PROJECT,
6201 }),
6202 SettingsPageItem::SectionHeader("Indent Guides"),
6203 SettingsPageItem::SettingItem(SettingItem {
6204 title: "Enabled",
6205 description: "Display indent guides in the editor.",
6206 field: Box::new(SettingField {
6207 json_path: Some("languages.$(language).indent_guides.enabled"),
6208 pick: |settings_content| {
6209 language_settings_field(settings_content, |language| {
6210 language
6211 .indent_guides
6212 .as_ref()
6213 .and_then(|indent_guides| indent_guides.enabled.as_ref())
6214 })
6215 },
6216 write: |settings_content, value| {
6217 language_settings_field_mut(settings_content, value, |language, value| {
6218 language.indent_guides.get_or_insert_default().enabled = value;
6219 })
6220 },
6221 }),
6222 metadata: None,
6223 files: USER | PROJECT,
6224 }),
6225 SettingsPageItem::SettingItem(SettingItem {
6226 title: "Line Width",
6227 description: "The width of the indent guides in pixels, between 1 and 10.",
6228 field: Box::new(SettingField {
6229 json_path: Some("languages.$(language).indent_guides.line_width"),
6230 pick: |settings_content| {
6231 language_settings_field(settings_content, |language| {
6232 language
6233 .indent_guides
6234 .as_ref()
6235 .and_then(|indent_guides| indent_guides.line_width.as_ref())
6236 })
6237 },
6238 write: |settings_content, value| {
6239 language_settings_field_mut(settings_content, value, |language, value| {
6240 language.indent_guides.get_or_insert_default().line_width = value;
6241 })
6242 },
6243 }),
6244 metadata: None,
6245 files: USER | PROJECT,
6246 }),
6247 SettingsPageItem::SettingItem(SettingItem {
6248 title: "Active Line Width",
6249 description: "The width of the active indent guide in pixels, between 1 and 10.",
6250 field: Box::new(SettingField {
6251 json_path: Some("languages.$(language).indent_guides.active_line_width"),
6252 pick: |settings_content| {
6253 language_settings_field(settings_content, |language| {
6254 language
6255 .indent_guides
6256 .as_ref()
6257 .and_then(|indent_guides| indent_guides.active_line_width.as_ref())
6258 })
6259 },
6260 write: |settings_content, value| {
6261 language_settings_field_mut(settings_content, value, |language, value| {
6262 language
6263 .indent_guides
6264 .get_or_insert_default()
6265 .active_line_width = value;
6266 })
6267 },
6268 }),
6269 metadata: None,
6270 files: USER | PROJECT,
6271 }),
6272 SettingsPageItem::SettingItem(SettingItem {
6273 title: "Coloring",
6274 description: "Determines how indent guides are colored.",
6275 field: Box::new(SettingField {
6276 json_path: Some("languages.$(language).indent_guides.coloring"),
6277 pick: |settings_content| {
6278 language_settings_field(settings_content, |language| {
6279 language
6280 .indent_guides
6281 .as_ref()
6282 .and_then(|indent_guides| indent_guides.coloring.as_ref())
6283 })
6284 },
6285 write: |settings_content, value| {
6286 language_settings_field_mut(settings_content, value, |language, value| {
6287 language.indent_guides.get_or_insert_default().coloring = value;
6288 })
6289 },
6290 }),
6291 metadata: None,
6292 files: USER | PROJECT,
6293 }),
6294 SettingsPageItem::SettingItem(SettingItem {
6295 title: "Background Coloring",
6296 description: "Determines how indent guide backgrounds are colored.",
6297 field: Box::new(SettingField {
6298 json_path: Some("languages.$(language).indent_guides.background_coloring"),
6299 pick: |settings_content| {
6300 language_settings_field(settings_content, |language| {
6301 language
6302 .indent_guides
6303 .as_ref()
6304 .and_then(|indent_guides| indent_guides.background_coloring.as_ref())
6305 })
6306 },
6307 write: |settings_content, value| {
6308 language_settings_field_mut(settings_content, value, |language, value| {
6309 language
6310 .indent_guides
6311 .get_or_insert_default()
6312 .background_coloring = value;
6313 })
6314 },
6315 }),
6316 metadata: None,
6317 files: USER | PROJECT,
6318 }),
6319 SettingsPageItem::SectionHeader("Formatting"),
6320 SettingsPageItem::SettingItem(SettingItem {
6321 title: "Format On Save",
6322 description: "Whether or not to perform a buffer format before saving.",
6323 field: Box::new(
6324 // TODO(settings_ui): this setting should just be a bool
6325 SettingField {
6326 json_path: Some("languages.$(language).format_on_save"),
6327 pick: |settings_content| {
6328 language_settings_field(settings_content, |language| {
6329 language.format_on_save.as_ref()
6330 })
6331 },
6332 write: |settings_content, value| {
6333 language_settings_field_mut(settings_content, value, |language, value| {
6334 language.format_on_save = value;
6335 })
6336 },
6337 },
6338 ),
6339 metadata: None,
6340 files: USER | PROJECT,
6341 }),
6342 SettingsPageItem::SettingItem(SettingItem {
6343 title: "Remove Trailing Whitespace On Save",
6344 description: "Whether or not to remove any trailing whitespace from lines of a buffer before saving it.",
6345 field: Box::new(SettingField {
6346 json_path: Some("languages.$(language).remove_trailing_whitespace_on_save"),
6347 pick: |settings_content| {
6348 language_settings_field(settings_content, |language| {
6349 language.remove_trailing_whitespace_on_save.as_ref()
6350 })
6351 },
6352 write: |settings_content, value| {
6353 language_settings_field_mut(settings_content, value, |language, value| {
6354 language.remove_trailing_whitespace_on_save = value;
6355 })
6356 },
6357 }),
6358 metadata: None,
6359 files: USER | PROJECT,
6360 }),
6361 SettingsPageItem::SettingItem(SettingItem {
6362 title: "Ensure Final Newline On Save",
6363 description: "Whether or not to ensure there's a single newline at the end of a buffer when saving it.",
6364 field: Box::new(SettingField {
6365 json_path: Some("languages.$(language).ensure_final_newline_on_save"),
6366 pick: |settings_content| {
6367 language_settings_field(settings_content, |language| {
6368 language.ensure_final_newline_on_save.as_ref()
6369 })
6370 },
6371 write: |settings_content, value| {
6372 language_settings_field_mut(settings_content, value, |language, value| {
6373 language.ensure_final_newline_on_save = value;
6374 })
6375 },
6376 }),
6377 metadata: None,
6378 files: USER | PROJECT,
6379 }),
6380 SettingsPageItem::SettingItem(SettingItem {
6381 title: "Formatter",
6382 description: "How to perform a buffer format.",
6383 field: Box::new(
6384 SettingField {
6385 json_path: Some("languages.$(language).formatter"),
6386 pick: |settings_content| {
6387 language_settings_field(settings_content, |language| {
6388 language.formatter.as_ref()
6389 })
6390 },
6391 write: |settings_content, value| {
6392 language_settings_field_mut(settings_content, value, |language, value| {
6393 language.formatter = value;
6394 })
6395 },
6396 }
6397 .unimplemented(),
6398 ),
6399 metadata: None,
6400 files: USER | PROJECT,
6401 }),
6402 SettingsPageItem::SettingItem(SettingItem {
6403 title: "Use On Type Format",
6404 description: "Whether to use additional LSP queries to format (and amend) the code after every \"trigger\" symbol input, defined by LSP server capabilities",
6405 field: Box::new(SettingField {
6406 json_path: Some("languages.$(language).use_on_type_format"),
6407 pick: |settings_content| {
6408 language_settings_field(settings_content, |language| {
6409 language.use_on_type_format.as_ref()
6410 })
6411 },
6412 write: |settings_content, value| {
6413 language_settings_field_mut(settings_content, value, |language, value| {
6414 language.use_on_type_format = value;
6415 })
6416 },
6417 }),
6418 metadata: None,
6419 files: USER | PROJECT,
6420 }),
6421 SettingsPageItem::SettingItem(SettingItem {
6422 title: "Code Actions On Format",
6423 description: "Additional code actions to run when formatting.",
6424 field: Box::new(
6425 SettingField {
6426 json_path: Some("languages.$(language).code_actions_on_format"),
6427 pick: |settings_content| {
6428 language_settings_field(settings_content, |language| {
6429 language.code_actions_on_format.as_ref()
6430 })
6431 },
6432 write: |settings_content, value| {
6433 language_settings_field_mut(settings_content, value, |language, value| {
6434 language.code_actions_on_format = value;
6435 })
6436 },
6437 }
6438 .unimplemented(),
6439 ),
6440 metadata: None,
6441 files: USER | PROJECT,
6442 }),
6443 SettingsPageItem::SectionHeader("Autoclose"),
6444 SettingsPageItem::SettingItem(SettingItem {
6445 title: "Use Autoclose",
6446 description: "Whether to automatically type closing characters for you. For example, when you type '(', Zed will automatically add a closing ')' at the correct position.",
6447 field: Box::new(SettingField {
6448 json_path: Some("languages.$(language).use_autoclose"),
6449 pick: |settings_content| {
6450 language_settings_field(settings_content, |language| {
6451 language.use_autoclose.as_ref()
6452 })
6453 },
6454 write: |settings_content, value| {
6455 language_settings_field_mut(settings_content, value, |language, value| {
6456 language.use_autoclose = value;
6457 })
6458 },
6459 }),
6460 metadata: None,
6461 files: USER | PROJECT,
6462 }),
6463 SettingsPageItem::SettingItem(SettingItem {
6464 title: "Use Auto Surround",
6465 description: "Whether to automatically surround text with characters for you. For example, when you select text and type '(', Zed will automatically surround text with ().",
6466 field: Box::new(SettingField {
6467 json_path: Some("languages.$(language).use_auto_surround"),
6468 pick: |settings_content| {
6469 language_settings_field(settings_content, |language| {
6470 language.use_auto_surround.as_ref()
6471 })
6472 },
6473 write: |settings_content, value| {
6474 language_settings_field_mut(settings_content, value, |language, value| {
6475 language.use_auto_surround = value;
6476 })
6477 },
6478 }),
6479 metadata: None,
6480 files: USER | PROJECT,
6481 }),
6482 SettingsPageItem::SettingItem(SettingItem {
6483 title: "Always Treat Brackets As Autoclosed",
6484 description: "Controls whether the closing characters are always skipped over and auto-removed no matter how they were inserted.",
6485 field: Box::new(SettingField {
6486 json_path: Some("languages.$(language).always_treat_brackets_as_autoclosed"),
6487 pick: |settings_content| {
6488 language_settings_field(settings_content, |language| {
6489 language.always_treat_brackets_as_autoclosed.as_ref()
6490 })
6491 },
6492 write: |settings_content, value| {
6493 language_settings_field_mut(settings_content, value, |language, value| {
6494 language.always_treat_brackets_as_autoclosed = value;
6495 })
6496 },
6497 }),
6498 metadata: None,
6499 files: USER | PROJECT,
6500 }),
6501 SettingsPageItem::SettingItem(SettingItem {
6502 title: "Jsx Tag Auto Close",
6503 description: "Whether to automatically close JSX tags.",
6504 field: Box::new(SettingField {
6505 json_path: Some("languages.$(language).jsx_tag_auto_close"),
6506 // TODO(settings_ui): this setting should just be a bool
6507 pick: |settings_content| {
6508 language_settings_field(settings_content, |language| {
6509 language.jsx_tag_auto_close.as_ref()?.enabled.as_ref()
6510 })
6511 },
6512 write: |settings_content, value| {
6513 language_settings_field_mut(settings_content, value, |language, value| {
6514 language.jsx_tag_auto_close.get_or_insert_default().enabled = value;
6515 })
6516 },
6517 }),
6518 metadata: None,
6519 files: USER | PROJECT,
6520 }),
6521 SettingsPageItem::SectionHeader("Whitespace"),
6522 SettingsPageItem::SettingItem(SettingItem {
6523 title: "Show Whitespaces",
6524 description: "Whether to show tabs and spaces in the editor.",
6525 field: Box::new(SettingField {
6526 json_path: Some("languages.$(language).show_whitespaces"),
6527 pick: |settings_content| {
6528 language_settings_field(settings_content, |language| {
6529 language.show_whitespaces.as_ref()
6530 })
6531 },
6532 write: |settings_content, value| {
6533 language_settings_field_mut(settings_content, value, |language, value| {
6534 language.show_whitespaces = value;
6535 })
6536 },
6537 }),
6538 metadata: None,
6539 files: USER | PROJECT,
6540 }),
6541 SettingsPageItem::SettingItem(SettingItem {
6542 title: "Space Whitespace Indicator",
6543 description: "Visible character used to render space characters when show_whitespaces is enabled (default: \"•\")",
6544 field: Box::new(
6545 SettingField {
6546 json_path: Some("languages.$(language).whitespace_map.space"),
6547 pick: |settings_content| {
6548 language_settings_field(settings_content, |language| {
6549 language.whitespace_map.as_ref()?.space.as_ref()
6550 })
6551 },
6552 write: |settings_content, value| {
6553 language_settings_field_mut(settings_content, value, |language, value| {
6554 language.whitespace_map.get_or_insert_default().space = value;
6555 })
6556 },
6557 }
6558 .unimplemented(),
6559 ),
6560 metadata: None,
6561 files: USER | PROJECT,
6562 }),
6563 SettingsPageItem::SettingItem(SettingItem {
6564 title: "Tab Whitespace Indicator",
6565 description: "Visible character used to render tab characters when show_whitespaces is enabled (default: \"→\")",
6566 field: Box::new(
6567 SettingField {
6568 json_path: Some("languages.$(language).whitespace_map.tab"),
6569 pick: |settings_content| {
6570 language_settings_field(settings_content, |language| {
6571 language.whitespace_map.as_ref()?.tab.as_ref()
6572 })
6573 },
6574 write: |settings_content, value| {
6575 language_settings_field_mut(settings_content, value, |language, value| {
6576 language.whitespace_map.get_or_insert_default().tab = value;
6577 })
6578 },
6579 }
6580 .unimplemented(),
6581 ),
6582 metadata: None,
6583 files: USER | PROJECT,
6584 }),
6585 SettingsPageItem::SectionHeader("Completions"),
6586 SettingsPageItem::SettingItem(SettingItem {
6587 title: "Show Completions On Input",
6588 description: "Whether to pop the completions menu while typing in an editor without explicitly requesting it.",
6589 field: Box::new(SettingField {
6590 json_path: Some("languages.$(language).show_completions_on_input"),
6591 pick: |settings_content| {
6592 language_settings_field(settings_content, |language| {
6593 language.show_completions_on_input.as_ref()
6594 })
6595 },
6596 write: |settings_content, value| {
6597 language_settings_field_mut(settings_content, value, |language, value| {
6598 language.show_completions_on_input = value;
6599 })
6600 },
6601 }),
6602 metadata: None,
6603 files: USER | PROJECT,
6604 }),
6605 SettingsPageItem::SettingItem(SettingItem {
6606 title: "Show Completion Documentation",
6607 description: "Whether to display inline and alongside documentation for items in the completions menu.",
6608 field: Box::new(SettingField {
6609 json_path: Some("languages.$(language).show_completion_documentation"),
6610 pick: |settings_content| {
6611 language_settings_field(settings_content, |language| {
6612 language.show_completion_documentation.as_ref()
6613 })
6614 },
6615 write: |settings_content, value| {
6616 language_settings_field_mut(settings_content, value, |language, value| {
6617 language.show_completion_documentation = value;
6618 })
6619 },
6620 }),
6621 metadata: None,
6622 files: USER | PROJECT,
6623 }),
6624 SettingsPageItem::SettingItem(SettingItem {
6625 title: "Words",
6626 description: "Controls how words are completed.",
6627 field: Box::new(SettingField {
6628 json_path: Some("languages.$(language).completions.words"),
6629 pick: |settings_content| {
6630 language_settings_field(settings_content, |language| {
6631 language.completions.as_ref()?.words.as_ref()
6632 })
6633 },
6634 write: |settings_content, value| {
6635 language_settings_field_mut(settings_content, value, |language, value| {
6636 language.completions.get_or_insert_default().words = value;
6637 })
6638 },
6639 }),
6640 metadata: None,
6641 files: USER | PROJECT,
6642 }),
6643 SettingsPageItem::SettingItem(SettingItem {
6644 title: "Words Min Length",
6645 description: "How many characters has to be in the completions query to automatically show the words-based completions.",
6646 field: Box::new(SettingField {
6647 json_path: Some("languages.$(language).completions.words_min_length"),
6648 pick: |settings_content| {
6649 language_settings_field(settings_content, |language| {
6650 language.completions.as_ref()?.words_min_length.as_ref()
6651 })
6652 },
6653 write: |settings_content, value| {
6654 language_settings_field_mut(settings_content, value, |language, value| {
6655 language
6656 .completions
6657 .get_or_insert_default()
6658 .words_min_length = value;
6659 })
6660 },
6661 }),
6662 metadata: None,
6663 files: USER | PROJECT,
6664 }),
6665 SettingsPageItem::SettingItem(SettingItem {
6666 title: "Completion Menu Scrollbar",
6667 description: "When to show the scrollbar in the completion menu.",
6668 field: Box::new(SettingField {
6669 json_path: Some("editor.completion_menu_scrollbar"),
6670 pick: |settings_content| settings_content.editor.completion_menu_scrollbar.as_ref(),
6671 write: |settings_content, value| {
6672 settings_content.editor.completion_menu_scrollbar = value;
6673 },
6674 }),
6675 metadata: None,
6676 files: USER,
6677 }),
6678 SettingsPageItem::SectionHeader("Inlay Hints"),
6679 SettingsPageItem::SettingItem(SettingItem {
6680 title: "Enabled",
6681 description: "Global switch to toggle hints on and off.",
6682 field: Box::new(SettingField {
6683 json_path: Some("languages.$(language).inlay_hints.enabled"),
6684 pick: |settings_content| {
6685 language_settings_field(settings_content, |language| {
6686 language.inlay_hints.as_ref()?.enabled.as_ref()
6687 })
6688 },
6689 write: |settings_content, value| {
6690 language_settings_field_mut(settings_content, value, |language, value| {
6691 language.inlay_hints.get_or_insert_default().enabled = value;
6692 })
6693 },
6694 }),
6695 metadata: None,
6696 files: USER | PROJECT,
6697 }),
6698 SettingsPageItem::SettingItem(SettingItem {
6699 title: "Show Value Hints",
6700 description: "Global switch to toggle inline values on and off when debugging.",
6701 field: Box::new(SettingField {
6702 json_path: Some("languages.$(language).inlay_hints.show_value_hints"),
6703 pick: |settings_content| {
6704 language_settings_field(settings_content, |language| {
6705 language.inlay_hints.as_ref()?.show_value_hints.as_ref()
6706 })
6707 },
6708 write: |settings_content, value| {
6709 language_settings_field_mut(settings_content, value, |language, value| {
6710 language
6711 .inlay_hints
6712 .get_or_insert_default()
6713 .show_value_hints = value;
6714 })
6715 },
6716 }),
6717 metadata: None,
6718 files: USER | PROJECT,
6719 }),
6720 SettingsPageItem::SettingItem(SettingItem {
6721 title: "Show Type Hints",
6722 description: "Whether type hints should be shown.",
6723 field: Box::new(SettingField {
6724 json_path: Some("languages.$(language).inlay_hints.show_type_hints"),
6725 pick: |settings_content| {
6726 language_settings_field(settings_content, |language| {
6727 language.inlay_hints.as_ref()?.show_type_hints.as_ref()
6728 })
6729 },
6730 write: |settings_content, value| {
6731 language_settings_field_mut(settings_content, value, |language, value| {
6732 language.inlay_hints.get_or_insert_default().show_type_hints = value;
6733 })
6734 },
6735 }),
6736 metadata: None,
6737 files: USER | PROJECT,
6738 }),
6739 SettingsPageItem::SettingItem(SettingItem {
6740 title: "Show Parameter Hints",
6741 description: "Whether parameter hints should be shown.",
6742 field: Box::new(SettingField {
6743 json_path: Some("languages.$(language).inlay_hints.show_parameter_hints"),
6744 pick: |settings_content| {
6745 language_settings_field(settings_content, |language| {
6746 language.inlay_hints.as_ref()?.show_parameter_hints.as_ref()
6747 })
6748 },
6749 write: |settings_content, value| {
6750 language_settings_field_mut(settings_content, value, |language, value| {
6751 language
6752 .inlay_hints
6753 .get_or_insert_default()
6754 .show_parameter_hints = value;
6755 })
6756 },
6757 }),
6758 metadata: None,
6759 files: USER | PROJECT,
6760 }),
6761 SettingsPageItem::SettingItem(SettingItem {
6762 title: "Show Other Hints",
6763 description: "Whether other hints should be shown.",
6764 field: Box::new(SettingField {
6765 json_path: Some("languages.$(language).inlay_hints.show_other_hints"),
6766 pick: |settings_content| {
6767 language_settings_field(settings_content, |language| {
6768 language.inlay_hints.as_ref()?.show_other_hints.as_ref()
6769 })
6770 },
6771 write: |settings_content, value| {
6772 language_settings_field_mut(settings_content, value, |language, value| {
6773 language
6774 .inlay_hints
6775 .get_or_insert_default()
6776 .show_other_hints = value;
6777 })
6778 },
6779 }),
6780 metadata: None,
6781 files: USER | PROJECT,
6782 }),
6783 SettingsPageItem::SettingItem(SettingItem {
6784 title: "Show Background",
6785 description: "Show a background for inlay hints.",
6786 field: Box::new(SettingField {
6787 json_path: Some("languages.$(language).inlay_hints.show_background"),
6788 pick: |settings_content| {
6789 language_settings_field(settings_content, |language| {
6790 language.inlay_hints.as_ref()?.show_background.as_ref()
6791 })
6792 },
6793 write: |settings_content, value| {
6794 language_settings_field_mut(settings_content, value, |language, value| {
6795 language.inlay_hints.get_or_insert_default().show_background = value;
6796 })
6797 },
6798 }),
6799 metadata: None,
6800 files: USER | PROJECT,
6801 }),
6802 SettingsPageItem::SettingItem(SettingItem {
6803 title: "Edit Debounce Ms",
6804 description: "Whether or not to debounce inlay hints updates after buffer edits (set to 0 to disable debouncing).",
6805 field: Box::new(SettingField {
6806 json_path: Some("languages.$(language).inlay_hints.edit_debounce_ms"),
6807 pick: |settings_content| {
6808 language_settings_field(settings_content, |language| {
6809 language.inlay_hints.as_ref()?.edit_debounce_ms.as_ref()
6810 })
6811 },
6812 write: |settings_content, value| {
6813 language_settings_field_mut(settings_content, value, |language, value| {
6814 language
6815 .inlay_hints
6816 .get_or_insert_default()
6817 .edit_debounce_ms = value;
6818 })
6819 },
6820 }),
6821 metadata: None,
6822 files: USER | PROJECT,
6823 }),
6824 SettingsPageItem::SettingItem(SettingItem {
6825 title: "Scroll Debounce Ms",
6826 description: "Whether or not to debounce inlay hints updates after buffer scrolls (set to 0 to disable debouncing).",
6827 field: Box::new(SettingField {
6828 json_path: Some("languages.$(language).inlay_hints.scroll_debounce_ms"),
6829 pick: |settings_content| {
6830 language_settings_field(settings_content, |language| {
6831 language.inlay_hints.as_ref()?.scroll_debounce_ms.as_ref()
6832 })
6833 },
6834 write: |settings_content, value| {
6835 language_settings_field_mut(settings_content, value, |language, value| {
6836 language
6837 .inlay_hints
6838 .get_or_insert_default()
6839 .scroll_debounce_ms = value;
6840 })
6841 },
6842 }),
6843 metadata: None,
6844 files: USER | PROJECT,
6845 }),
6846 SettingsPageItem::SettingItem(SettingItem {
6847 title: "Toggle On Modifiers Press",
6848 description: "Toggles inlay hints (hides or shows) when the user presses the modifiers specified.",
6849 field: Box::new(
6850 SettingField {
6851 json_path: Some("languages.$(language).inlay_hints.toggle_on_modifiers_press"),
6852 pick: |settings_content| {
6853 language_settings_field(settings_content, |language| {
6854 language
6855 .inlay_hints
6856 .as_ref()?
6857 .toggle_on_modifiers_press
6858 .as_ref()
6859 })
6860 },
6861 write: |settings_content, value| {
6862 language_settings_field_mut(settings_content, value, |language, value| {
6863 language
6864 .inlay_hints
6865 .get_or_insert_default()
6866 .toggle_on_modifiers_press = value;
6867 })
6868 },
6869 }
6870 .unimplemented(),
6871 ),
6872 metadata: None,
6873 files: USER | PROJECT,
6874 }),
6875 ];
6876 if current_language().is_none() {
6877 items.push(SettingsPageItem::SettingItem(SettingItem {
6878 title: "LSP Document Colors",
6879 description: "How to render LSP color previews in the editor.",
6880 field: Box::new(SettingField {
6881 json_path: Some("lsp_document_colors"),
6882 pick: |settings_content| settings_content.editor.lsp_document_colors.as_ref(),
6883 write: |settings_content, value| {
6884 settings_content.editor.lsp_document_colors = value;
6885 },
6886 }),
6887 metadata: None,
6888 files: USER,
6889 }))
6890 }
6891 items.extend([
6892 SettingsPageItem::SectionHeader("Tasks"),
6893 SettingsPageItem::SettingItem(SettingItem {
6894 title: "Enabled",
6895 description: "Whether tasks are enabled for this language.",
6896 field: Box::new(SettingField {
6897 json_path: Some("languages.$(language).tasks.enabled"),
6898 pick: |settings_content| {
6899 language_settings_field(settings_content, |language| {
6900 language.tasks.as_ref()?.enabled.as_ref()
6901 })
6902 },
6903 write: |settings_content, value| {
6904 language_settings_field_mut(settings_content, value, |language, value| {
6905 language.tasks.get_or_insert_default().enabled = value;
6906
6907 })
6908 },
6909 }),
6910 metadata: None,
6911 files: USER | PROJECT,
6912 }),
6913 SettingsPageItem::SettingItem(SettingItem {
6914 title: "Variables",
6915 description: "Extra task variables to set for a particular language.",
6916 field: Box::new(
6917 SettingField {
6918 json_path: Some("languages.$(language).tasks.variables"),
6919 pick: |settings_content| {
6920 language_settings_field(settings_content, |language| {
6921 language.tasks.as_ref()?.variables.as_ref()
6922 })
6923 },
6924 write: |settings_content, value| {
6925 language_settings_field_mut(settings_content, value, |language, value| {
6926 language.tasks.get_or_insert_default().variables = value;
6927
6928 })
6929 },
6930 }
6931 .unimplemented(),
6932 ),
6933 metadata: None,
6934 files: USER | PROJECT,
6935 }),
6936 SettingsPageItem::SettingItem(SettingItem {
6937 title: "Prefer LSP",
6938 description: "Use LSP tasks over Zed language extension tasks.",
6939 field: Box::new(SettingField {
6940 json_path: Some("languages.$(language).tasks.prefer_lsp"),
6941 pick: |settings_content| {
6942 language_settings_field(settings_content, |language| {
6943 language.tasks.as_ref()?.prefer_lsp.as_ref()
6944 })
6945 },
6946 write: |settings_content, value| {
6947 language_settings_field_mut(settings_content, value, |language, value| {
6948 language.tasks.get_or_insert_default().prefer_lsp = value;
6949
6950 })
6951 },
6952 }),
6953 metadata: None,
6954 files: USER | PROJECT,
6955 }),
6956 SettingsPageItem::SectionHeader("Miscellaneous"),
6957 SettingsPageItem::SettingItem(SettingItem {
6958 title: "Debuggers",
6959 description: "Preferred debuggers for this language.",
6960 field: Box::new(
6961 SettingField {
6962 json_path: Some("languages.$(language).debuggers"),
6963 pick: |settings_content| {
6964 language_settings_field(settings_content, |language| language.debuggers.as_ref())
6965 },
6966 write: |settings_content, value| {
6967 language_settings_field_mut(settings_content, value, |language, value| {
6968 language.debuggers = value;
6969
6970 })
6971 },
6972 }
6973 .unimplemented(),
6974 ),
6975 metadata: None,
6976 files: USER | PROJECT,
6977 }),
6978 SettingsPageItem::SettingItem(SettingItem {
6979 title: "Middle Click Paste",
6980 description: "Enable middle-click paste on Linux.",
6981 field: Box::new(SettingField {
6982 json_path: Some("languages.$(language).editor.middle_click_paste"),
6983 pick: |settings_content| settings_content.editor.middle_click_paste.as_ref(),
6984 write: |settings_content, value| {settings_content.editor.middle_click_paste = value;},
6985 }),
6986 metadata: None,
6987 files: USER,
6988 }),
6989 SettingsPageItem::SettingItem(SettingItem {
6990 title: "Extend Comment On Newline",
6991 description: "Whether to start a new line with a comment when a previous line is a comment as well.",
6992 field: Box::new(SettingField {
6993 json_path: Some("languages.$(language).extend_comment_on_newline"),
6994 pick: |settings_content| {
6995 language_settings_field(settings_content, |language| {
6996 language.extend_comment_on_newline.as_ref()
6997 })
6998 },
6999 write: |settings_content, value| {
7000 language_settings_field_mut(settings_content, value, |language, value| {
7001 language.extend_comment_on_newline = value;
7002
7003 })
7004 },
7005 }),
7006 metadata: None,
7007 files: USER | PROJECT,
7008 }),
7009 SettingsPageItem::SettingItem(SettingItem {
7010 title: "Colorize brackets",
7011 description: "Whether to colorize brackets in the editor.",
7012 field: Box::new(SettingField {
7013 json_path: Some("languages.$(language).colorize_brackets"),
7014 pick: |settings_content| {
7015 language_settings_field(settings_content, |language| {
7016 language.colorize_brackets.as_ref()
7017 })
7018 },
7019 write: |settings_content, value| {
7020 language_settings_field_mut(settings_content, value, |language, value| {
7021 language.colorize_brackets = value;
7022 })
7023 },
7024 }),
7025 metadata: None,
7026 files: USER | PROJECT,
7027 }),
7028 ]);
7029
7030 if current_language().is_none() {
7031 items.extend([
7032 SettingsPageItem::SettingItem(SettingItem {
7033 title: "Image Viewer",
7034 description: "The unit for image file sizes.",
7035 field: Box::new(SettingField {
7036 json_path: Some("image_viewer.unit"),
7037 pick: |settings_content| {
7038 settings_content.image_viewer.as_ref().and_then(|image_viewer| image_viewer.unit.as_ref())
7039 },
7040 write: |settings_content, value| {
7041 settings_content.image_viewer.get_or_insert_default().unit = value;
7042
7043 },
7044 }),
7045 metadata: None,
7046 files: USER,
7047 }),
7048 SettingsPageItem::SettingItem(SettingItem {
7049 title: "Auto Replace Emoji Shortcode",
7050 description: "Whether to automatically replace emoji shortcodes with emoji characters.",
7051 field: Box::new(SettingField {
7052 json_path: Some("message_editor.auto_replace_emoji_shortcode"),
7053 pick: |settings_content| {
7054 settings_content.message_editor.as_ref().and_then(|message_editor| message_editor.auto_replace_emoji_shortcode.as_ref())
7055 },
7056 write: |settings_content, value| {
7057 settings_content.message_editor.get_or_insert_default().auto_replace_emoji_shortcode = value;
7058
7059 },
7060 }),
7061 metadata: None,
7062 files: USER,
7063 }),
7064 SettingsPageItem::SettingItem(SettingItem {
7065 title: "Drop Size Target",
7066 description: "Relative size of the drop target in the editor that will open dropped file as a split pane.",
7067 field: Box::new(SettingField {
7068 json_path: Some("drop_target_size"),
7069 pick: |settings_content| {
7070 settings_content.workspace.drop_target_size.as_ref()
7071 },
7072 write: |settings_content, value| {
7073 settings_content.workspace.drop_target_size = value;
7074
7075 },
7076 }),
7077 metadata: None,
7078 files: USER,
7079 }),
7080 ]);
7081 }
7082 items
7083}
7084
7085/// LanguageSettings items that should be included in the "Languages & Tools" page
7086/// not the "Editor" page
7087fn non_editor_language_settings_data() -> Vec<SettingsPageItem> {
7088 vec![
7089 SettingsPageItem::SectionHeader("LSP"),
7090 SettingsPageItem::SettingItem(SettingItem {
7091 title: "Enable Language Server",
7092 description: "Whether to use language servers to provide code intelligence.",
7093 field: Box::new(SettingField {
7094 json_path: Some("languages.$(language).enable_language_server"),
7095 pick: |settings_content| {
7096 language_settings_field(settings_content, |language| {
7097 language.enable_language_server.as_ref()
7098 })
7099 },
7100 write: |settings_content, value| {
7101 language_settings_field_mut(settings_content, value, |language, value| {
7102 language.enable_language_server = value;
7103 })
7104 },
7105 }),
7106 metadata: None,
7107 files: USER | PROJECT,
7108 }),
7109 SettingsPageItem::SettingItem(SettingItem {
7110 title: "Language Servers",
7111 description: "The list of language servers to use (or disable) for this language.",
7112 field: Box::new(
7113 SettingField {
7114 json_path: Some("languages.$(language).language_servers"),
7115 pick: |settings_content| {
7116 language_settings_field(settings_content, |language| {
7117 language.language_servers.as_ref()
7118 })
7119 },
7120 write: |settings_content, value| {
7121 language_settings_field_mut(settings_content, value, |language, value| {
7122 language.language_servers = value;
7123 })
7124 },
7125 }
7126 .unimplemented(),
7127 ),
7128 metadata: None,
7129 files: USER | PROJECT,
7130 }),
7131 SettingsPageItem::SettingItem(SettingItem {
7132 title: "Linked Edits",
7133 description: "Whether to perform linked edits of associated ranges, if the LS supports it. For example, when editing opening <html> tag, the contents of the closing </html> tag will be edited as well.",
7134 field: Box::new(SettingField {
7135 json_path: Some("languages.$(language).linked_edits"),
7136 pick: |settings_content| {
7137 language_settings_field(settings_content, |language| {
7138 language.linked_edits.as_ref()
7139 })
7140 },
7141 write: |settings_content, value| {
7142 language_settings_field_mut(settings_content, value, |language, value| {
7143 language.linked_edits = value;
7144 })
7145 },
7146 }),
7147 metadata: None,
7148 files: USER | PROJECT,
7149 }),
7150 SettingsPageItem::SettingItem(SettingItem {
7151 title: "Go To Definition Fallback",
7152 description: "Whether to follow-up empty Go to definition responses from the language server.",
7153 field: Box::new(SettingField {
7154 json_path: Some("go_to_definition_fallback"),
7155 pick: |settings_content| settings_content.editor.go_to_definition_fallback.as_ref(),
7156 write: |settings_content, value| {
7157 settings_content.editor.go_to_definition_fallback = value;
7158 },
7159 }),
7160 metadata: None,
7161 files: USER,
7162 }),
7163 SettingsPageItem::SectionHeader("LSP Completions"),
7164 SettingsPageItem::SettingItem(SettingItem {
7165 title: "Enabled",
7166 description: "Whether to fetch LSP completions or not.",
7167 field: Box::new(SettingField {
7168 json_path: Some("languages.$(language).completions.lsp"),
7169 pick: |settings_content| {
7170 language_settings_field(settings_content, |language| {
7171 language.completions.as_ref()?.lsp.as_ref()
7172 })
7173 },
7174 write: |settings_content, value| {
7175 language_settings_field_mut(settings_content, value, |language, value| {
7176 language.completions.get_or_insert_default().lsp = value;
7177 })
7178 },
7179 }),
7180 metadata: None,
7181 files: USER | PROJECT,
7182 }),
7183 SettingsPageItem::SettingItem(SettingItem {
7184 title: "Fetch Timeout (milliseconds)",
7185 description: "When fetching LSP completions, determines how long to wait for a response of a particular server (set to 0 to wait indefinitely).",
7186 field: Box::new(SettingField {
7187 json_path: Some("languages.$(language).completions.lsp_fetch_timeout_ms"),
7188 pick: |settings_content| {
7189 language_settings_field(settings_content, |language| {
7190 language.completions.as_ref()?.lsp_fetch_timeout_ms.as_ref()
7191 })
7192 },
7193 write: |settings_content, value| {
7194 language_settings_field_mut(settings_content, value, |language, value| {
7195 language
7196 .completions
7197 .get_or_insert_default()
7198 .lsp_fetch_timeout_ms = value;
7199 })
7200 },
7201 }),
7202 metadata: None,
7203 files: USER | PROJECT,
7204 }),
7205 SettingsPageItem::SettingItem(SettingItem {
7206 title: "Insert Mode",
7207 description: "Controls how LSP completions are inserted.",
7208 field: Box::new(SettingField {
7209 json_path: Some("languages.$(language).completions.lsp_insert_mode"),
7210 pick: |settings_content| {
7211 language_settings_field(settings_content, |language| {
7212 language.completions.as_ref()?.lsp_insert_mode.as_ref()
7213 })
7214 },
7215 write: |settings_content, value| {
7216 language_settings_field_mut(settings_content, value, |language, value| {
7217 language.completions.get_or_insert_default().lsp_insert_mode = value;
7218 })
7219 },
7220 }),
7221 metadata: None,
7222 files: USER | PROJECT,
7223 }),
7224 SettingsPageItem::SectionHeader("Debuggers"),
7225 SettingsPageItem::SettingItem(SettingItem {
7226 title: "Debuggers",
7227 description: "Preferred debuggers for this language.",
7228 field: Box::new(
7229 SettingField {
7230 json_path: Some("languages.$(language).debuggers"),
7231 pick: |settings_content| {
7232 language_settings_field(settings_content, |language| {
7233 language.debuggers.as_ref()
7234 })
7235 },
7236 write: |settings_content, value| {
7237 language_settings_field_mut(settings_content, value, |language, value| {
7238 language.debuggers = value;
7239 })
7240 },
7241 }
7242 .unimplemented(),
7243 ),
7244 metadata: None,
7245 files: USER | PROJECT,
7246 }),
7247 SettingsPageItem::SectionHeader("Prettier"),
7248 SettingsPageItem::SettingItem(SettingItem {
7249 title: "Allowed",
7250 description: "Enables or disables formatting with Prettier for a given language.",
7251 field: Box::new(SettingField {
7252 json_path: Some("languages.$(language).prettier.allowed"),
7253 pick: |settings_content| {
7254 language_settings_field(settings_content, |language| {
7255 language.prettier.as_ref()?.allowed.as_ref()
7256 })
7257 },
7258 write: |settings_content, value| {
7259 language_settings_field_mut(settings_content, value, |language, value| {
7260 language.prettier.get_or_insert_default().allowed = value;
7261 })
7262 },
7263 }),
7264 metadata: None,
7265 files: USER | PROJECT,
7266 }),
7267 SettingsPageItem::SettingItem(SettingItem {
7268 title: "Parser",
7269 description: "Forces Prettier integration to use a specific parser name when formatting files with the language.",
7270 field: Box::new(SettingField {
7271 json_path: Some("languages.$(language).prettier.parser"),
7272 pick: |settings_content| {
7273 language_settings_field(settings_content, |language| {
7274 language.prettier.as_ref()?.parser.as_ref()
7275 })
7276 },
7277 write: |settings_content, value| {
7278 language_settings_field_mut(settings_content, value, |language, value| {
7279 language.prettier.get_or_insert_default().parser = value;
7280 })
7281 },
7282 }),
7283 metadata: None,
7284 files: USER | PROJECT,
7285 }),
7286 SettingsPageItem::SettingItem(SettingItem {
7287 title: "Plugins",
7288 description: "Forces Prettier integration to use specific plugins when formatting files with the language.",
7289 field: Box::new(
7290 SettingField {
7291 json_path: Some("languages.$(language).prettier.plugins"),
7292 pick: |settings_content| {
7293 language_settings_field(settings_content, |language| {
7294 language.prettier.as_ref()?.plugins.as_ref()
7295 })
7296 },
7297 write: |settings_content, value| {
7298 language_settings_field_mut(settings_content, value, |language, value| {
7299 language.prettier.get_or_insert_default().plugins = value;
7300 })
7301 },
7302 }
7303 .unimplemented(),
7304 ),
7305 metadata: None,
7306 files: USER | PROJECT,
7307 }),
7308 SettingsPageItem::SettingItem(SettingItem {
7309 title: "Options",
7310 description: "Default Prettier options, in the format as in package.json section for Prettier.",
7311 field: Box::new(
7312 SettingField {
7313 json_path: Some("languages.$(language).prettier.options"),
7314 pick: |settings_content| {
7315 language_settings_field(settings_content, |language| {
7316 language.prettier.as_ref()?.options.as_ref()
7317 })
7318 },
7319 write: |settings_content, value| {
7320 language_settings_field_mut(settings_content, value, |language, value| {
7321 language.prettier.get_or_insert_default().options = value;
7322 })
7323 },
7324 }
7325 .unimplemented(),
7326 ),
7327 metadata: None,
7328 files: USER | PROJECT,
7329 }),
7330 ]
7331}
7332
7333fn edit_prediction_language_settings_section() -> Vec<SettingsPageItem> {
7334 vec![
7335 SettingsPageItem::SectionHeader("Edit Predictions"),
7336 SettingsPageItem::SettingItem(SettingItem {
7337 title: "Show Edit Predictions",
7338 description: "Controls whether edit predictions are shown immediately or manually by triggering `editor::showeditprediction` (false).",
7339 field: Box::new(SettingField {
7340 json_path: Some("languages.$(language).show_edit_predictions"),
7341 pick: |settings_content| {
7342 language_settings_field(settings_content, |language| {
7343 language.show_edit_predictions.as_ref()
7344 })
7345 },
7346 write: |settings_content, value| {
7347 language_settings_field_mut(settings_content, value, |language, value| {
7348 language.show_edit_predictions = value;
7349 })
7350 },
7351 }),
7352 metadata: None,
7353 files: USER | PROJECT,
7354 }),
7355 SettingsPageItem::SettingItem(SettingItem {
7356 title: "Edit Predictions Disabled In",
7357 description: "Controls whether edit predictions are shown in the given language scopes.",
7358 field: Box::new(
7359 SettingField {
7360 json_path: Some("languages.$(language).edit_predictions_disabled_in"),
7361 pick: |settings_content| {
7362 language_settings_field(settings_content, |language| {
7363 language.edit_predictions_disabled_in.as_ref()
7364 })
7365 },
7366 write: |settings_content, value| {
7367 language_settings_field_mut(settings_content, value, |language, value| {
7368 language.edit_predictions_disabled_in = value;
7369 })
7370 },
7371 }
7372 .unimplemented(),
7373 ),
7374 metadata: None,
7375 files: USER | PROJECT,
7376 }),
7377 ]
7378}
7379
7380fn show_scrollbar_or_editor(
7381 settings_content: &SettingsContent,
7382 show: fn(&SettingsContent) -> Option<&settings::ShowScrollbar>,
7383) -> Option<&settings::ShowScrollbar> {
7384 show(settings_content).or(settings_content
7385 .editor
7386 .scrollbar
7387 .as_ref()
7388 .and_then(|scrollbar| scrollbar.show.as_ref()))
7389}
7390
7391fn dynamic_variants<T>() -> &'static [T::Discriminant]
7392where
7393 T: strum::IntoDiscriminant,
7394 T::Discriminant: strum::VariantArray,
7395{
7396 <<T as strum::IntoDiscriminant>::Discriminant as strum::VariantArray>::VARIANTS
7397}