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::SettingItem(SettingItem {
3069 title: "Show Tab Bar Buttons",
3070 description: "Show the tab bar buttons (New, Split Pane, Zoom).",
3071 field: Box::new(SettingField {
3072 json_path: Some("tab_bar.show_tab_bar_buttons"),
3073 pick: |settings_content| {
3074 settings_content
3075 .tab_bar
3076 .as_ref()?
3077 .show_tab_bar_buttons
3078 .as_ref()
3079 },
3080 write: |settings_content, value| {
3081 settings_content
3082 .tab_bar
3083 .get_or_insert_default()
3084 .show_tab_bar_buttons = value;
3085 },
3086 }),
3087 metadata: None,
3088 files: USER,
3089 }),
3090 SettingsPageItem::SectionHeader("Tab Settings"),
3091 SettingsPageItem::SettingItem(SettingItem {
3092 title: "Activate On Close",
3093 description: "What to do after closing the current tab.",
3094 field: Box::new(SettingField {
3095 json_path: Some("tabs.activate_on_close"),
3096 pick: |settings_content| {
3097 settings_content.tabs.as_ref()?.activate_on_close.as_ref()
3098 },
3099 write: |settings_content, value| {
3100 settings_content
3101 .tabs
3102 .get_or_insert_default()
3103 .activate_on_close = value;
3104 },
3105 }),
3106 metadata: None,
3107 files: USER,
3108 }),
3109 SettingsPageItem::SettingItem(SettingItem {
3110 title: "Tab Show Diagnostics",
3111 description: "Which files containing diagnostic errors/warnings to mark in the tabs.",
3112 field: Box::new(SettingField {
3113 json_path: Some("tabs.show_diagnostics"),
3114 pick: |settings_content| {
3115 settings_content.tabs.as_ref()?.show_diagnostics.as_ref()
3116 },
3117 write: |settings_content, value| {
3118 settings_content
3119 .tabs
3120 .get_or_insert_default()
3121 .show_diagnostics = value;
3122 },
3123 }),
3124 metadata: None,
3125 files: USER,
3126 }),
3127 SettingsPageItem::SettingItem(SettingItem {
3128 title: "Show Close Button",
3129 description: "Controls the appearance behavior of the tab's close button.",
3130 field: Box::new(SettingField {
3131 json_path: Some("tabs.show_close_button"),
3132 pick: |settings_content| {
3133 settings_content.tabs.as_ref()?.show_close_button.as_ref()
3134 },
3135 write: |settings_content, value| {
3136 settings_content
3137 .tabs
3138 .get_or_insert_default()
3139 .show_close_button = value;
3140 },
3141 }),
3142 metadata: None,
3143 files: USER,
3144 }),
3145 SettingsPageItem::SectionHeader("Preview Tabs"),
3146 SettingsPageItem::SettingItem(SettingItem {
3147 title: "Preview Tabs Enabled",
3148 description: "Show opened editors as Preview tabs.",
3149 field: Box::new(SettingField {
3150 json_path: Some("preview_tabs.enabled"),
3151 pick: |settings_content| {
3152 settings_content.preview_tabs.as_ref()?.enabled.as_ref()
3153 },
3154 write: |settings_content, value| {
3155 settings_content
3156 .preview_tabs
3157 .get_or_insert_default()
3158 .enabled = value;
3159 },
3160 }),
3161 metadata: None,
3162 files: USER,
3163 }),
3164 SettingsPageItem::SettingItem(SettingItem {
3165 title: "Enable Preview From File Finder",
3166 description: "Whether to open tabs in Preview mode when selected from the file finder.",
3167 field: Box::new(SettingField {
3168 json_path: Some("preview_tabs.enable_preview_from_file_finder"),
3169 pick: |settings_content| {
3170 settings_content
3171 .preview_tabs
3172 .as_ref()?
3173 .enable_preview_from_file_finder
3174 .as_ref()
3175 },
3176 write: |settings_content, value| {
3177 settings_content
3178 .preview_tabs
3179 .get_or_insert_default()
3180 .enable_preview_from_file_finder = value;
3181 },
3182 }),
3183 metadata: None,
3184 files: USER,
3185 }),
3186 SettingsPageItem::SettingItem(SettingItem {
3187 title: "Enable Preview From Code Navigation",
3188 description: "Whether a preview tab gets replaced when code navigation is used to navigate away from the tab.",
3189 field: Box::new(SettingField {
3190 json_path: Some("preview_tabs.enable_preview_from_code_navigation"),
3191 pick: |settings_content| {
3192 settings_content
3193 .preview_tabs
3194 .as_ref()?
3195 .enable_preview_from_code_navigation
3196 .as_ref()
3197 },
3198 write: |settings_content, value| {
3199 settings_content
3200 .preview_tabs
3201 .get_or_insert_default()
3202 .enable_preview_from_code_navigation = value;
3203 },
3204 }),
3205 metadata: None,
3206 files: USER,
3207 }),
3208 SettingsPageItem::SectionHeader("Layout"),
3209 SettingsPageItem::SettingItem(SettingItem {
3210 title: "Bottom Dock Layout",
3211 description: "Layout mode for the bottom dock.",
3212 field: Box::new(SettingField {
3213 json_path: Some("bottom_dock_layout"),
3214 pick: |settings_content| {
3215 settings_content.workspace.bottom_dock_layout.as_ref()
3216 },
3217 write: |settings_content, value| {
3218 settings_content.workspace.bottom_dock_layout = value;
3219 },
3220 }),
3221 metadata: None,
3222 files: USER,
3223 }),
3224 SettingsPageItem::SettingItem(SettingItem {
3225 files: USER,
3226 title: "Centered Layout Left Padding",
3227 description: "Left padding for centered layout.",
3228 field: Box::new(SettingField {
3229 json_path: Some("centered_layout.left_padding"),
3230 pick: |settings_content| {
3231 settings_content
3232 .workspace
3233 .centered_layout
3234 .as_ref()?
3235 .left_padding
3236 .as_ref()
3237 },
3238 write: |settings_content, value| {
3239 settings_content
3240 .workspace
3241 .centered_layout
3242 .get_or_insert_default()
3243 .left_padding = value;
3244 },
3245 }),
3246 metadata: None,
3247 }),
3248 SettingsPageItem::SettingItem(SettingItem {
3249 files: USER,
3250 title: "Centered Layout Right Padding",
3251 description: "Right padding for centered layout.",
3252 field: Box::new(SettingField {
3253 json_path: Some("centered_layout.right_padding"),
3254 pick: |settings_content| {
3255 settings_content
3256 .workspace
3257 .centered_layout
3258 .as_ref()?
3259 .right_padding
3260 .as_ref()
3261 },
3262 write: |settings_content, value| {
3263 settings_content
3264 .workspace
3265 .centered_layout
3266 .get_or_insert_default()
3267 .right_padding = value;
3268 },
3269 }),
3270 metadata: None,
3271 }),
3272 SettingsPageItem::SectionHeader("Window"),
3273 // todo(settings_ui): Should we filter by platform.as_ref()?
3274 SettingsPageItem::SettingItem(SettingItem {
3275 title: "Use System Window Tabs",
3276 description: "(macOS only) whether to allow Windows to tab together.",
3277 field: Box::new(SettingField {
3278 json_path: Some("use_system_window_tabs"),
3279 pick: |settings_content| {
3280 settings_content.workspace.use_system_window_tabs.as_ref()
3281 },
3282 write: |settings_content, value| {
3283 settings_content.workspace.use_system_window_tabs = value;
3284 },
3285 }),
3286 metadata: None,
3287 files: USER,
3288 }),
3289 SettingsPageItem::SettingItem(SettingItem {
3290 title: "Window Decorations",
3291 description: "(Linux only) whether Zed or your compositor should draw window decorations.",
3292 field: Box::new(SettingField {
3293 json_path: Some("window_decorations"),
3294 pick: |settings_content| {
3295 settings_content.workspace.window_decorations.as_ref()
3296 },
3297 write: |settings_content, value| {
3298 settings_content.workspace.window_decorations = value;
3299 },
3300 }),
3301 metadata: None,
3302 files: USER,
3303 }),
3304 SettingsPageItem::SectionHeader("Pane Modifiers"),
3305 SettingsPageItem::SettingItem(SettingItem {
3306 title: "Inactive Opacity",
3307 description: "Opacity of inactive panels (0.0 - 1.0).",
3308 field: Box::new(SettingField {
3309 json_path: Some("active_pane_modifiers.inactive_opacity"),
3310 pick: |settings_content| {
3311 settings_content
3312 .workspace
3313 .active_pane_modifiers
3314 .as_ref()?
3315 .inactive_opacity
3316 .as_ref()
3317 },
3318 write: |settings_content, value| {
3319 settings_content
3320 .workspace
3321 .active_pane_modifiers
3322 .get_or_insert_default()
3323 .inactive_opacity = value;
3324 },
3325 }),
3326 metadata: None,
3327 files: USER,
3328 }),
3329 SettingsPageItem::SettingItem(SettingItem {
3330 title: "Border Size",
3331 description: "Size of the border surrounding the active pane.",
3332 field: Box::new(SettingField {
3333 json_path: Some("active_pane_modifiers.border_size"),
3334 pick: |settings_content| {
3335 settings_content
3336 .workspace
3337 .active_pane_modifiers
3338 .as_ref()?
3339 .border_size
3340 .as_ref()
3341 },
3342 write: |settings_content, value| {
3343 settings_content
3344 .workspace
3345 .active_pane_modifiers
3346 .get_or_insert_default()
3347 .border_size = value;
3348 },
3349 }),
3350 metadata: None,
3351 files: USER,
3352 }),
3353 SettingsPageItem::SettingItem(SettingItem {
3354 title: "Zoomed Padding",
3355 description: "Show padding for zoomed panes.",
3356 field: Box::new(SettingField {
3357 json_path: Some("zoomed_padding"),
3358 pick: |settings_content| settings_content.workspace.zoomed_padding.as_ref(),
3359 write: |settings_content, value| {
3360 settings_content.workspace.zoomed_padding = value;
3361 },
3362 }),
3363 metadata: None,
3364 files: USER,
3365 }),
3366 SettingsPageItem::SectionHeader("Pane Split Direction"),
3367 SettingsPageItem::SettingItem(SettingItem {
3368 title: "Vertical Split Direction",
3369 description: "Direction to split vertically.",
3370 field: Box::new(SettingField {
3371 json_path: Some("pane_split_direction_vertical"),
3372 pick: |settings_content| {
3373 settings_content
3374 .workspace
3375 .pane_split_direction_vertical
3376 .as_ref()
3377 },
3378 write: |settings_content, value| {
3379 settings_content.workspace.pane_split_direction_vertical = value;
3380 },
3381 }),
3382 metadata: None,
3383 files: USER,
3384 }),
3385 SettingsPageItem::SettingItem(SettingItem {
3386 title: "Horizontal Split Direction",
3387 description: "Direction to split horizontally.",
3388 field: Box::new(SettingField {
3389 json_path: Some("pane_split_direction_horizontal"),
3390 pick: |settings_content| {
3391 settings_content
3392 .workspace
3393 .pane_split_direction_horizontal
3394 .as_ref()
3395 },
3396 write: |settings_content, value| {
3397 settings_content.workspace.pane_split_direction_horizontal = value;
3398 },
3399 }),
3400 metadata: None,
3401 files: USER,
3402 }),
3403 ],
3404 },
3405 SettingsPage {
3406 title: "Panels",
3407 items: vec![
3408 SettingsPageItem::SectionHeader("Project Panel"),
3409 SettingsPageItem::SettingItem(SettingItem {
3410 title: "Project Panel Dock",
3411 description: "Where to dock the project panel.",
3412 field: Box::new(SettingField {
3413 json_path: Some("project_panel.dock"),
3414 pick: |settings_content| {
3415 settings_content.project_panel.as_ref()?.dock.as_ref()
3416 },
3417 write: |settings_content, value| {
3418 settings_content.project_panel.get_or_insert_default().dock = value;
3419 },
3420 }),
3421 metadata: None,
3422 files: USER,
3423 }),
3424 SettingsPageItem::SettingItem(SettingItem {
3425 title: "Project Panel Default Width",
3426 description: "Default width of the project panel in pixels.",
3427 field: Box::new(SettingField {
3428 json_path: Some("project_panel.default_width"),
3429 pick: |settings_content| {
3430 settings_content
3431 .project_panel
3432 .as_ref()?
3433 .default_width
3434 .as_ref()
3435 },
3436 write: |settings_content, value| {
3437 settings_content
3438 .project_panel
3439 .get_or_insert_default()
3440 .default_width = value;
3441 },
3442 }),
3443 metadata: None,
3444 files: USER,
3445 }),
3446 SettingsPageItem::SettingItem(SettingItem {
3447 title: "Hide .gitignore",
3448 description: "Whether to hide the gitignore entries in the project panel.",
3449 field: Box::new(SettingField {
3450 json_path: Some("project_panel.hide_gitignore"),
3451 pick: |settings_content| {
3452 settings_content
3453 .project_panel
3454 .as_ref()?
3455 .hide_gitignore
3456 .as_ref()
3457 },
3458 write: |settings_content, value| {
3459 settings_content
3460 .project_panel
3461 .get_or_insert_default()
3462 .hide_gitignore = value;
3463 },
3464 }),
3465 metadata: None,
3466 files: USER,
3467 }),
3468 SettingsPageItem::SettingItem(SettingItem {
3469 title: "Entry Spacing",
3470 description: "Spacing between worktree entries in the project panel.",
3471 field: Box::new(SettingField {
3472 json_path: Some("project_panel.entry_spacing"),
3473 pick: |settings_content| {
3474 settings_content
3475 .project_panel
3476 .as_ref()?
3477 .entry_spacing
3478 .as_ref()
3479 },
3480 write: |settings_content, value| {
3481 settings_content
3482 .project_panel
3483 .get_or_insert_default()
3484 .entry_spacing = value;
3485 },
3486 }),
3487 metadata: None,
3488 files: USER,
3489 }),
3490 SettingsPageItem::SettingItem(SettingItem {
3491 title: "File Icons",
3492 description: "Show file icons in the project panel.",
3493 field: Box::new(SettingField {
3494 json_path: Some("project_panel.file_icons"),
3495 pick: |settings_content| {
3496 settings_content.project_panel.as_ref()?.file_icons.as_ref()
3497 },
3498 write: |settings_content, value| {
3499 settings_content
3500 .project_panel
3501 .get_or_insert_default()
3502 .file_icons = value;
3503 },
3504 }),
3505 metadata: None,
3506 files: USER,
3507 }),
3508 SettingsPageItem::SettingItem(SettingItem {
3509 title: "Folder Icons",
3510 description: "Whether to show folder icons or chevrons for directories in the project panel.",
3511 field: Box::new(SettingField {
3512 json_path: Some("project_panel.folder_icons"),
3513 pick: |settings_content| {
3514 settings_content
3515 .project_panel
3516 .as_ref()?
3517 .folder_icons
3518 .as_ref()
3519 },
3520 write: |settings_content, value| {
3521 settings_content
3522 .project_panel
3523 .get_or_insert_default()
3524 .folder_icons = value;
3525 },
3526 }),
3527 metadata: None,
3528 files: USER,
3529 }),
3530 SettingsPageItem::SettingItem(SettingItem {
3531 title: "Git Status",
3532 description: "Show the Git status in the project panel.",
3533 field: Box::new(SettingField {
3534 json_path: Some("project_panel.git_status"),
3535 pick: |settings_content| {
3536 settings_content.project_panel.as_ref()?.git_status.as_ref()
3537 },
3538 write: |settings_content, value| {
3539 settings_content
3540 .project_panel
3541 .get_or_insert_default()
3542 .git_status = value;
3543 },
3544 }),
3545 metadata: None,
3546 files: USER,
3547 }),
3548 SettingsPageItem::SettingItem(SettingItem {
3549 title: "Indent Size",
3550 description: "Amount of indentation for nested items.",
3551 field: Box::new(SettingField {
3552 json_path: Some("project_panel.indent_size"),
3553 pick: |settings_content| {
3554 settings_content
3555 .project_panel
3556 .as_ref()?
3557 .indent_size
3558 .as_ref()
3559 },
3560 write: |settings_content, value| {
3561 settings_content
3562 .project_panel
3563 .get_or_insert_default()
3564 .indent_size = value;
3565 },
3566 }),
3567 metadata: None,
3568 files: USER,
3569 }),
3570 SettingsPageItem::SettingItem(SettingItem {
3571 title: "Auto Reveal Entries",
3572 description: "Whether to reveal entries in the project panel automatically when a corresponding project entry becomes active.",
3573 field: Box::new(SettingField {
3574 json_path: Some("project_panel.auto_reveal_entries"),
3575 pick: |settings_content| {
3576 settings_content
3577 .project_panel
3578 .as_ref()?
3579 .auto_reveal_entries
3580 .as_ref()
3581 },
3582 write: |settings_content, value| {
3583 settings_content
3584 .project_panel
3585 .get_or_insert_default()
3586 .auto_reveal_entries = value;
3587 },
3588 }),
3589 metadata: None,
3590 files: USER,
3591 }),
3592 SettingsPageItem::SettingItem(SettingItem {
3593 title: "Starts Open",
3594 description: "Whether the project panel should open on startup.",
3595 field: Box::new(SettingField {
3596 json_path: Some("project_panel.starts_open"),
3597 pick: |settings_content| {
3598 settings_content
3599 .project_panel
3600 .as_ref()?
3601 .starts_open
3602 .as_ref()
3603 },
3604 write: |settings_content, value| {
3605 settings_content
3606 .project_panel
3607 .get_or_insert_default()
3608 .starts_open = value;
3609 },
3610 }),
3611 metadata: None,
3612 files: USER,
3613 }),
3614 SettingsPageItem::SettingItem(SettingItem {
3615 title: "Auto Fold Directories",
3616 description: "Whether to fold directories automatically and show compact folders when a directory has only one subdirectory inside.",
3617 field: Box::new(SettingField {
3618 json_path: Some("project_panel.auto_fold_dirs"),
3619 pick: |settings_content| {
3620 settings_content
3621 .project_panel
3622 .as_ref()?
3623 .auto_fold_dirs
3624 .as_ref()
3625 },
3626 write: |settings_content, value| {
3627 settings_content
3628 .project_panel
3629 .get_or_insert_default()
3630 .auto_fold_dirs = value;
3631 },
3632 }),
3633 metadata: None,
3634 files: USER,
3635 }),
3636 SettingsPageItem::SettingItem(SettingItem {
3637 title: "Show Scrollbar",
3638 description: "Show the scrollbar in the project panel.",
3639 field: Box::new(SettingField {
3640 json_path: Some("project_panel.scrollbar.show"),
3641 pick: |settings_content| {
3642 show_scrollbar_or_editor(settings_content, |settings_content| {
3643 settings_content
3644 .project_panel
3645 .as_ref()?
3646 .scrollbar
3647 .as_ref()?
3648 .show
3649 .as_ref()
3650 })
3651 },
3652 write: |settings_content, value| {
3653 settings_content
3654 .project_panel
3655 .get_or_insert_default()
3656 .scrollbar
3657 .get_or_insert_default()
3658 .show = value;
3659 },
3660 }),
3661 metadata: None,
3662 files: USER,
3663 }),
3664 SettingsPageItem::SettingItem(SettingItem {
3665 title: "Show Diagnostics",
3666 description: "Which files containing diagnostic errors/warnings to mark in the project panel.",
3667 field: Box::new(SettingField {
3668 json_path: Some("project_panel.show_diagnostics"),
3669 pick: |settings_content| {
3670 settings_content
3671 .project_panel
3672 .as_ref()?
3673 .show_diagnostics
3674 .as_ref()
3675 },
3676 write: |settings_content, value| {
3677 settings_content
3678 .project_panel
3679 .get_or_insert_default()
3680 .show_diagnostics = value;
3681 },
3682 }),
3683 metadata: None,
3684 files: USER,
3685 }),
3686 SettingsPageItem::SettingItem(SettingItem {
3687 title: "Sticky Scroll",
3688 description: "Whether to stick parent directories at top of the project panel.",
3689 field: Box::new(SettingField {
3690 json_path: Some("project_panel.sticky_scroll"),
3691 pick: |settings_content| {
3692 settings_content
3693 .project_panel
3694 .as_ref()?
3695 .sticky_scroll
3696 .as_ref()
3697 },
3698 write: |settings_content, value| {
3699 settings_content
3700 .project_panel
3701 .get_or_insert_default()
3702 .sticky_scroll = value;
3703 },
3704 }),
3705 metadata: None,
3706 files: USER,
3707 }),
3708 SettingsPageItem::SettingItem(SettingItem {
3709 files: USER,
3710 title: "Show Indent Guides",
3711 description: "Show indent guides in the project panel.",
3712 field: Box::new(
3713 SettingField {
3714 json_path: Some("project_panel.indent_guides.show"),
3715 pick: |settings_content| {
3716 settings_content
3717 .project_panel
3718 .as_ref()?
3719 .indent_guides
3720 .as_ref()?
3721 .show
3722 .as_ref()
3723 },
3724 write: |settings_content, value| {
3725 settings_content
3726 .project_panel
3727 .get_or_insert_default()
3728 .indent_guides
3729 .get_or_insert_default()
3730 .show = value;
3731 },
3732 }
3733 ),
3734 metadata: None,
3735 }),
3736 SettingsPageItem::SettingItem(SettingItem {
3737 title: "Drag and Drop",
3738 description: "Whether to enable drag-and-drop operations in the project panel.",
3739 field: Box::new(SettingField {
3740 json_path: Some("project_panel.drag_and_drop"),
3741 pick: |settings_content| {
3742 settings_content
3743 .project_panel
3744 .as_ref()?
3745 .drag_and_drop
3746 .as_ref()
3747 },
3748 write: |settings_content, value| {
3749 settings_content
3750 .project_panel
3751 .get_or_insert_default()
3752 .drag_and_drop = value;
3753 },
3754 }),
3755 metadata: None,
3756 files: USER,
3757 }),
3758 SettingsPageItem::SettingItem(SettingItem {
3759 title: "Hide Root",
3760 description: "Whether to hide the root entry when only one folder is open in the window.",
3761 field: Box::new(SettingField {
3762 json_path: Some("project_panel.drag_and_drop"),
3763 pick: |settings_content| {
3764 settings_content.project_panel.as_ref()?.hide_root.as_ref()
3765 },
3766 write: |settings_content, value| {
3767 settings_content
3768 .project_panel
3769 .get_or_insert_default()
3770 .hide_root = value;
3771 },
3772 }),
3773 metadata: None,
3774 files: USER,
3775 }),
3776 SettingsPageItem::SettingItem(SettingItem {
3777 title: "Hide Hidden",
3778 description: "Whether to hide the hidden entries in the project panel.",
3779 field: Box::new(SettingField {
3780 json_path: Some("project_panel.hide_hidden"),
3781 pick: |settings_content| {
3782 settings_content
3783 .project_panel
3784 .as_ref()?
3785 .hide_hidden
3786 .as_ref()
3787 },
3788 write: |settings_content, value| {
3789 settings_content
3790 .project_panel
3791 .get_or_insert_default()
3792 .hide_hidden = value;
3793 },
3794 }),
3795 metadata: None,
3796 files: USER,
3797 }),
3798 SettingsPageItem::SettingItem(SettingItem {
3799 title: "Hidden Files",
3800 description: "Globs to match files that will be considered \"hidden\" and can be hidden from the project panel.",
3801 field: Box::new(
3802 SettingField {
3803 json_path: Some("worktree.hidden_files"),
3804 pick: |settings_content| {
3805 settings_content.project.worktree.hidden_files.as_ref()
3806 },
3807 write: |settings_content, value| {
3808 settings_content.project.worktree.hidden_files = value;
3809 },
3810 }
3811 .unimplemented(),
3812 ),
3813 metadata: None,
3814 files: USER,
3815 }),
3816 SettingsPageItem::SectionHeader("Auto Open Files"),
3817 SettingsPageItem::SettingItem(SettingItem {
3818 title: "On Create",
3819 description: "Whether to automatically open newly created files in the editor.",
3820 field: Box::new(SettingField {
3821 json_path: Some("project_panel.auto_open.on_create"),
3822 pick: |settings_content| {
3823 settings_content.project_panel.as_ref()?.auto_open.as_ref()?.on_create.as_ref()
3824 },
3825 write: |settings_content, value| {
3826 settings_content.project_panel.get_or_insert_default().auto_open.get_or_insert_default().on_create = value;
3827 },
3828 }),
3829 metadata: None,
3830 files: USER,
3831 }),
3832 SettingsPageItem::SettingItem(SettingItem {
3833 title: "On Paste",
3834 description: "Whether to automatically open files after pasting or duplicating them.",
3835 field: Box::new(SettingField {
3836 json_path: Some("project_panel.auto_open.on_paste"),
3837 pick: |settings_content| {
3838 settings_content.project_panel.as_ref()?.auto_open.as_ref()?.on_paste.as_ref()
3839 },
3840 write: |settings_content, value| {
3841 settings_content.project_panel.get_or_insert_default().auto_open.get_or_insert_default().on_paste = value;
3842 },
3843 }),
3844 metadata: None,
3845 files: USER,
3846 }),
3847 SettingsPageItem::SettingItem(SettingItem {
3848 title: "On Drop",
3849 description: "Whether to automatically open files dropped from external sources.",
3850 field: Box::new(SettingField {
3851 json_path: Some("project_panel.auto_open.on_drop"),
3852 pick: |settings_content| {
3853 settings_content.project_panel.as_ref()?.auto_open.as_ref()?.on_drop.as_ref()
3854 },
3855 write: |settings_content, value| {
3856 settings_content.project_panel.get_or_insert_default().auto_open.get_or_insert_default().on_drop = value;
3857 },
3858 }),
3859 metadata: None,
3860 files: USER,
3861 }),
3862 SettingsPageItem::SettingItem(SettingItem {
3863 title: "Sort Mode",
3864 description: "Sort order for entries in the project panel.",
3865 field: Box::new(SettingField {
3866 pick: |settings_content| {
3867 settings_content.project_panel.as_ref()?.sort_mode.as_ref()
3868 },
3869 write: |settings_content, value| {
3870 settings_content
3871 .project_panel
3872 .get_or_insert_default()
3873 .sort_mode = value;
3874 },
3875 json_path: Some("project_panel.sort_mode"),
3876 }),
3877 metadata: None,
3878 files: USER,
3879 }),
3880 SettingsPageItem::SectionHeader("Terminal Panel"),
3881 SettingsPageItem::SettingItem(SettingItem {
3882 title: "Terminal Dock",
3883 description: "Where to dock the terminal panel.",
3884 field: Box::new(SettingField {
3885 json_path: Some("terminal.dock"),
3886 pick: |settings_content| settings_content.terminal.as_ref()?.dock.as_ref(),
3887 write: |settings_content, value| {
3888 settings_content.terminal.get_or_insert_default().dock = value;
3889 },
3890 }),
3891 metadata: None,
3892 files: USER,
3893 }),
3894 SettingsPageItem::SectionHeader("Outline Panel"),
3895 SettingsPageItem::SettingItem(SettingItem {
3896 title: "Outline Panel Button",
3897 description: "Show the outline panel button in the status bar.",
3898 field: Box::new(SettingField {
3899 json_path: Some("outline_panel.button"),
3900 pick: |settings_content| {
3901 settings_content.outline_panel.as_ref()?.button.as_ref()
3902 },
3903 write: |settings_content, value| {
3904 settings_content
3905 .outline_panel
3906 .get_or_insert_default()
3907 .button = value;
3908 },
3909 }),
3910 metadata: None,
3911 files: USER,
3912 }),
3913 SettingsPageItem::SettingItem(SettingItem {
3914 title: "Outline Panel Dock",
3915 description: "Where to dock the outline panel.",
3916 field: Box::new(SettingField {
3917 json_path: Some("outline_panel.dock"),
3918 pick: |settings_content| {
3919 settings_content.outline_panel.as_ref()?.dock.as_ref()
3920 },
3921 write: |settings_content, value| {
3922 settings_content.outline_panel.get_or_insert_default().dock = value;
3923 },
3924 }),
3925 metadata: None,
3926 files: USER,
3927 }),
3928 SettingsPageItem::SettingItem(SettingItem {
3929 title: "Outline Panel Default Width",
3930 description: "Default width of the outline panel in pixels.",
3931 field: Box::new(SettingField {
3932 json_path: Some("outline_panel.default_width"),
3933 pick: |settings_content| {
3934 settings_content
3935 .outline_panel
3936 .as_ref()?
3937 .default_width
3938 .as_ref()
3939 },
3940 write: |settings_content, value| {
3941 settings_content
3942 .outline_panel
3943 .get_or_insert_default()
3944 .default_width = value;
3945 },
3946 }),
3947 metadata: None,
3948 files: USER,
3949 }),
3950 SettingsPageItem::SettingItem(SettingItem {
3951 title: "File Icons",
3952 description: "Show file icons in the outline panel.",
3953 field: Box::new(SettingField {
3954 json_path: Some("outline_panel.file_icons"),
3955 pick: |settings_content| {
3956 settings_content.outline_panel.as_ref()?.file_icons.as_ref()
3957 },
3958 write: |settings_content, value| {
3959 settings_content
3960 .outline_panel
3961 .get_or_insert_default()
3962 .file_icons = value;
3963 },
3964 }),
3965 metadata: None,
3966 files: USER,
3967 }),
3968 SettingsPageItem::SettingItem(SettingItem {
3969 title: "Folder Icons",
3970 description: "Whether to show folder icons or chevrons for directories in the outline panel.",
3971 field: Box::new(SettingField {
3972 json_path: Some("outline_panel.folder_icons"),
3973 pick: |settings_content| {
3974 settings_content
3975 .outline_panel
3976 .as_ref()?
3977 .folder_icons
3978 .as_ref()
3979 },
3980 write: |settings_content, value| {
3981 settings_content
3982 .outline_panel
3983 .get_or_insert_default()
3984 .folder_icons = value;
3985 },
3986 }),
3987 metadata: None,
3988 files: USER,
3989 }),
3990 SettingsPageItem::SettingItem(SettingItem {
3991 title: "Git Status",
3992 description: "Show the Git status in the outline panel.",
3993 field: Box::new(SettingField {
3994 json_path: Some("outline_panel.git_status"),
3995 pick: |settings_content| {
3996 settings_content.outline_panel.as_ref()?.git_status.as_ref()
3997 },
3998 write: |settings_content, value| {
3999 settings_content
4000 .outline_panel
4001 .get_or_insert_default()
4002 .git_status = value;
4003 },
4004 }),
4005 metadata: None,
4006 files: USER,
4007 }),
4008 SettingsPageItem::SettingItem(SettingItem {
4009 title: "Indent Size",
4010 description: "Amount of indentation for nested items.",
4011 field: Box::new(SettingField {
4012 json_path: Some("outline_panel.indent_size"),
4013 pick: |settings_content| {
4014 settings_content
4015 .outline_panel
4016 .as_ref()?
4017 .indent_size
4018 .as_ref()
4019 },
4020 write: |settings_content, value| {
4021 settings_content
4022 .outline_panel
4023 .get_or_insert_default()
4024 .indent_size = value;
4025 },
4026 }),
4027 metadata: None,
4028 files: USER,
4029 }),
4030 SettingsPageItem::SettingItem(SettingItem {
4031 title: "Auto Reveal Entries",
4032 description: "Whether to reveal when a corresponding outline entry becomes active.",
4033 field: Box::new(SettingField {
4034 json_path: Some("outline_panel.auto_reveal_entries"),
4035 pick: |settings_content| {
4036 settings_content
4037 .outline_panel
4038 .as_ref()?
4039 .auto_reveal_entries
4040 .as_ref()
4041 },
4042 write: |settings_content, value| {
4043 settings_content
4044 .outline_panel
4045 .get_or_insert_default()
4046 .auto_reveal_entries = value;
4047 },
4048 }),
4049 metadata: None,
4050 files: USER,
4051 }),
4052 SettingsPageItem::SettingItem(SettingItem {
4053 title: "Auto Fold Directories",
4054 description: "Whether to fold directories automatically when a directory contains only one subdirectory.",
4055 field: Box::new(SettingField {
4056 json_path: Some("outline_panel.auto_fold_dirs"),
4057 pick: |settings_content| {
4058 settings_content
4059 .outline_panel
4060 .as_ref()?
4061 .auto_fold_dirs
4062 .as_ref()
4063 },
4064 write: |settings_content, value| {
4065 settings_content
4066 .outline_panel
4067 .get_or_insert_default()
4068 .auto_fold_dirs = value;
4069 },
4070 }),
4071 metadata: None,
4072 files: USER,
4073 }),
4074 SettingsPageItem::SettingItem(SettingItem {
4075 files: USER,
4076 title: "Show Indent Guides",
4077 description: "When to show indent guides in the outline panel.",
4078 field: Box::new(
4079 SettingField {
4080 json_path: Some("outline_panel.indent_guides.show"),
4081 pick: |settings_content| {
4082 settings_content
4083 .outline_panel
4084 .as_ref()?
4085 .indent_guides
4086 .as_ref()?
4087 .show
4088 .as_ref()
4089 },
4090 write: |settings_content, value| {
4091 settings_content
4092 .outline_panel
4093 .get_or_insert_default()
4094 .indent_guides
4095 .get_or_insert_default()
4096 .show = value;
4097 },
4098 }
4099 ),
4100 metadata: None,
4101 }),
4102 SettingsPageItem::SectionHeader("Git Panel"),
4103 SettingsPageItem::SettingItem(SettingItem {
4104 title: "Git Panel Button",
4105 description: "Show the Git panel button in the status bar.",
4106 field: Box::new(SettingField {
4107 json_path: Some("git_panel.button"),
4108 pick: |settings_content| {
4109 settings_content.git_panel.as_ref()?.button.as_ref()
4110 },
4111 write: |settings_content, value| {
4112 settings_content.git_panel.get_or_insert_default().button = value;
4113 },
4114 }),
4115 metadata: None,
4116 files: USER,
4117 }),
4118 SettingsPageItem::SettingItem(SettingItem {
4119 title: "Git Panel Dock",
4120 description: "Where to dock the Git panel.",
4121 field: Box::new(SettingField {
4122 json_path: Some("git_panel.dock"),
4123 pick: |settings_content| settings_content.git_panel.as_ref()?.dock.as_ref(),
4124 write: |settings_content, value| {
4125 settings_content.git_panel.get_or_insert_default().dock = value;
4126 },
4127 }),
4128 metadata: None,
4129 files: USER,
4130 }),
4131 SettingsPageItem::SettingItem(SettingItem {
4132 title: "Git Panel Default Width",
4133 description: "Default width of the Git panel in pixels.",
4134 field: Box::new(SettingField {
4135 json_path: Some("git_panel.default_width"),
4136 pick: |settings_content| {
4137 settings_content.git_panel.as_ref()?.default_width.as_ref()
4138 },
4139 write: |settings_content, value| {
4140 settings_content
4141 .git_panel
4142 .get_or_insert_default()
4143 .default_width = value;
4144 },
4145 }),
4146 metadata: None,
4147 files: USER,
4148 }),
4149 SettingsPageItem::SettingItem(SettingItem {
4150 title: "Git Panel Status Style",
4151 description: "How entry statuses are displayed.",
4152 field: Box::new(SettingField {
4153 json_path: Some("git_panel.status_style"),
4154 pick: |settings_content| {
4155 settings_content.git_panel.as_ref()?.status_style.as_ref()
4156 },
4157 write: |settings_content, value| {
4158 settings_content
4159 .git_panel
4160 .get_or_insert_default()
4161 .status_style = value;
4162 },
4163 }),
4164 metadata: None,
4165 files: USER,
4166 }),
4167 SettingsPageItem::SettingItem(SettingItem {
4168 title: "Fallback Branch Name",
4169 description: "Default branch name will be when init.defaultbranch is not set in Git.",
4170 field: Box::new(SettingField {
4171 json_path: Some("git_panel.fallback_branch_name"),
4172 pick: |settings_content| {
4173 settings_content
4174 .git_panel
4175 .as_ref()?
4176 .fallback_branch_name
4177 .as_ref()
4178 },
4179 write: |settings_content, value| {
4180 settings_content
4181 .git_panel
4182 .get_or_insert_default()
4183 .fallback_branch_name = value;
4184 },
4185 }),
4186 metadata: None,
4187 files: USER,
4188 }),
4189 SettingsPageItem::SettingItem(SettingItem {
4190 title: "Sort By Path",
4191 description: "Enable to sort entries in the panel by path, disable to sort by status.",
4192 field: Box::new(SettingField {
4193 json_path: Some("git_panel.sort_by_path"),
4194 pick: |settings_content| {
4195 settings_content.git_panel.as_ref()?.sort_by_path.as_ref()
4196 },
4197 write: |settings_content, value| {
4198 settings_content
4199 .git_panel
4200 .get_or_insert_default()
4201 .sort_by_path = value;
4202 },
4203 }),
4204 metadata: None,
4205 files: USER,
4206 }),
4207 SettingsPageItem::SettingItem(SettingItem {
4208 title: "Collapse Untracked Diff",
4209 description: "Whether to collapse untracked files in the diff panel.",
4210 field: Box::new(SettingField {
4211 json_path: Some("git_panel.collapse_untracked_diff"),
4212 pick: |settings_content| {
4213 settings_content
4214 .git_panel
4215 .as_ref()?
4216 .collapse_untracked_diff
4217 .as_ref()
4218 },
4219 write: |settings_content, value| {
4220 settings_content
4221 .git_panel
4222 .get_or_insert_default()
4223 .collapse_untracked_diff = value;
4224 },
4225 }),
4226 metadata: None,
4227 files: USER,
4228 }),
4229 SettingsPageItem::SettingItem(SettingItem {
4230 title: "Scroll Bar",
4231 description: "How and when the scrollbar should be displayed.",
4232 field: Box::new(SettingField {
4233 json_path: Some("git_panel.scrollbar.show"),
4234 pick: |settings_content| {
4235 show_scrollbar_or_editor(settings_content, |settings_content| {
4236 settings_content
4237 .git_panel
4238 .as_ref()?
4239 .scrollbar
4240 .as_ref()?
4241 .show
4242 .as_ref()
4243 })
4244 },
4245 write: |settings_content, value| {
4246 settings_content
4247 .git_panel
4248 .get_or_insert_default()
4249 .scrollbar
4250 .get_or_insert_default()
4251 .show = value;
4252 },
4253 }),
4254 metadata: None,
4255 files: USER,
4256 }),
4257 SettingsPageItem::SectionHeader("Debugger Panel"),
4258 SettingsPageItem::SettingItem(SettingItem {
4259 title: "Debugger Panel Dock",
4260 description: "The dock position of the debug panel.",
4261 field: Box::new(SettingField {
4262 json_path: Some("debugger.dock"),
4263 pick: |settings_content| settings_content.debugger.as_ref()?.dock.as_ref(),
4264 write: |settings_content, value| {
4265 settings_content.debugger.get_or_insert_default().dock = value;
4266 },
4267 }),
4268 metadata: None,
4269 files: USER,
4270 }),
4271 SettingsPageItem::SectionHeader("Notification Panel"),
4272 SettingsPageItem::SettingItem(SettingItem {
4273 title: "Notification Panel Button",
4274 description: "Show the notification panel button in the status bar.",
4275 field: Box::new(SettingField {
4276 json_path: Some("notification_panel.button"),
4277 pick: |settings_content| {
4278 settings_content
4279 .notification_panel
4280 .as_ref()?
4281 .button
4282 .as_ref()
4283 },
4284 write: |settings_content, value| {
4285 settings_content
4286 .notification_panel
4287 .get_or_insert_default()
4288 .button = value;
4289 },
4290 }),
4291 metadata: None,
4292 files: USER,
4293 }),
4294 SettingsPageItem::SettingItem(SettingItem {
4295 title: "Notification Panel Dock",
4296 description: "Where to dock the notification panel.",
4297 field: Box::new(SettingField {
4298 json_path: Some("notification_panel.dock"),
4299 pick: |settings_content| {
4300 settings_content.notification_panel.as_ref()?.dock.as_ref()
4301 },
4302 write: |settings_content, value| {
4303 settings_content
4304 .notification_panel
4305 .get_or_insert_default()
4306 .dock = value;
4307 },
4308 }),
4309 metadata: None,
4310 files: USER,
4311 }),
4312 SettingsPageItem::SettingItem(SettingItem {
4313 title: "Notification Panel Default Width",
4314 description: "Default width of the notification panel in pixels.",
4315 field: Box::new(SettingField {
4316 json_path: Some("notification_panel.default_width"),
4317 pick: |settings_content| {
4318 settings_content
4319 .notification_panel
4320 .as_ref()?
4321 .default_width
4322 .as_ref()
4323 },
4324 write: |settings_content, value| {
4325 settings_content
4326 .notification_panel
4327 .get_or_insert_default()
4328 .default_width = value;
4329 },
4330 }),
4331 metadata: None,
4332 files: USER,
4333 }),
4334 SettingsPageItem::SectionHeader("Collaboration Panel"),
4335 SettingsPageItem::SettingItem(SettingItem {
4336 title: "Collaboration Panel Button",
4337 description: "Show the collaboration panel button in the status bar.",
4338 field: Box::new(SettingField {
4339 json_path: Some("collaboration_panel.button"),
4340 pick: |settings_content| {
4341 settings_content
4342 .collaboration_panel
4343 .as_ref()?
4344 .button
4345 .as_ref()
4346 },
4347 write: |settings_content, value| {
4348 settings_content
4349 .collaboration_panel
4350 .get_or_insert_default()
4351 .button = value;
4352 },
4353 }),
4354 metadata: None,
4355 files: USER,
4356 }),
4357 SettingsPageItem::SettingItem(SettingItem {
4358 title: "Collaboration Panel Dock",
4359 description: "Where to dock the collaboration panel.",
4360 field: Box::new(SettingField {
4361 json_path: Some("collaboration_panel.dock"),
4362 pick: |settings_content| {
4363 settings_content.collaboration_panel.as_ref()?.dock.as_ref()
4364 },
4365 write: |settings_content, value| {
4366 settings_content
4367 .collaboration_panel
4368 .get_or_insert_default()
4369 .dock = value;
4370 },
4371 }),
4372 metadata: None,
4373 files: USER,
4374 }),
4375 SettingsPageItem::SettingItem(SettingItem {
4376 title: "Collaboration Panel Default Width",
4377 description: "Default width of the collaboration panel in pixels.",
4378 field: Box::new(SettingField {
4379 json_path: Some("collaboration_panel.dock"),
4380 pick: |settings_content| {
4381 settings_content
4382 .collaboration_panel
4383 .as_ref()?
4384 .default_width
4385 .as_ref()
4386 },
4387 write: |settings_content, value| {
4388 settings_content
4389 .collaboration_panel
4390 .get_or_insert_default()
4391 .default_width = value;
4392 },
4393 }),
4394 metadata: None,
4395 files: USER,
4396 }),
4397 SettingsPageItem::SectionHeader("Agent Panel"),
4398 SettingsPageItem::SettingItem(SettingItem {
4399 title: "Agent Panel Button",
4400 description: "Whether to show the agent panel button in the status bar.",
4401 field: Box::new(SettingField {
4402 json_path: Some("agent.button"),
4403 pick: |settings_content| settings_content.agent.as_ref()?.button.as_ref(),
4404 write: |settings_content, value| {
4405 settings_content.agent.get_or_insert_default().button = value;
4406 },
4407 }),
4408 metadata: None,
4409 files: USER,
4410 }),
4411 SettingsPageItem::SettingItem(SettingItem {
4412 title: "Agent Panel Dock",
4413 description: "Where to dock the agent panel.",
4414 field: Box::new(SettingField {
4415 json_path: Some("agent.dock"),
4416 pick: |settings_content| settings_content.agent.as_ref()?.dock.as_ref(),
4417 write: |settings_content, value| {
4418 settings_content.agent.get_or_insert_default().dock = value;
4419 },
4420 }),
4421 metadata: None,
4422 files: USER,
4423 }),
4424 SettingsPageItem::SettingItem(SettingItem {
4425 title: "Agent Panel Default Width",
4426 description: "Default width when the agent panel is docked to the left or right.",
4427 field: Box::new(SettingField {
4428 json_path: Some("agent.default_width"),
4429 pick: |settings_content| {
4430 settings_content.agent.as_ref()?.default_width.as_ref()
4431 },
4432 write: |settings_content, value| {
4433 settings_content.agent.get_or_insert_default().default_width = value;
4434 },
4435 }),
4436 metadata: None,
4437 files: USER,
4438 }),
4439 SettingsPageItem::SettingItem(SettingItem {
4440 title: "Agent Panel Default Height",
4441 description: "Default height when the agent panel is docked to the bottom.",
4442 field: Box::new(SettingField {
4443 json_path: Some("agent.default_height"),
4444 pick: |settings_content| {
4445 settings_content.agent.as_ref()?.default_height.as_ref()
4446 },
4447 write: |settings_content, value| {
4448 settings_content
4449 .agent
4450 .get_or_insert_default()
4451 .default_height = value;
4452 },
4453 }),
4454 metadata: None,
4455 files: USER,
4456 }),
4457 ],
4458 },
4459 SettingsPage {
4460 title: "Debugger",
4461 items: vec![
4462 SettingsPageItem::SectionHeader("General"),
4463 SettingsPageItem::SettingItem(SettingItem {
4464 title: "Stepping Granularity",
4465 description: "Determines the stepping granularity for debug operations.",
4466 field: Box::new(SettingField {
4467 json_path: Some("debugger.stepping_granularity"),
4468 pick: |settings_content| {
4469 settings_content
4470 .debugger
4471 .as_ref()?
4472 .stepping_granularity
4473 .as_ref()
4474 },
4475 write: |settings_content, value| {
4476 settings_content
4477 .debugger
4478 .get_or_insert_default()
4479 .stepping_granularity = value;
4480 },
4481 }),
4482 metadata: None,
4483 files: USER,
4484 }),
4485 SettingsPageItem::SettingItem(SettingItem {
4486 title: "Save Breakpoints",
4487 description: "Whether breakpoints should be reused across Zed sessions.",
4488 field: Box::new(SettingField {
4489 json_path: Some("debugger.save_breakpoints"),
4490 pick: |settings_content| {
4491 settings_content
4492 .debugger
4493 .as_ref()?
4494 .save_breakpoints
4495 .as_ref()
4496 },
4497 write: |settings_content, value| {
4498 settings_content
4499 .debugger
4500 .get_or_insert_default()
4501 .save_breakpoints = value;
4502 },
4503 }),
4504 metadata: None,
4505 files: USER,
4506 }),
4507 SettingsPageItem::SettingItem(SettingItem {
4508 title: "Timeout",
4509 description: "Time in milliseconds until timeout error when connecting to a TCP debug adapter.",
4510 field: Box::new(SettingField {
4511 json_path: Some("debugger.timeout"),
4512 pick: |settings_content| {
4513 settings_content.debugger.as_ref()?.timeout.as_ref()
4514 },
4515 write: |settings_content, value| {
4516 settings_content.debugger.get_or_insert_default().timeout = value;
4517 },
4518 }),
4519 metadata: None,
4520 files: USER,
4521 }),
4522 SettingsPageItem::SettingItem(SettingItem {
4523 title: "Log DAP Communications",
4524 description: "Whether to log messages between active debug adapters and Zed.",
4525 field: Box::new(SettingField {
4526 json_path: Some("debugger.log_dap_communications"),
4527 pick: |settings_content| {
4528 settings_content
4529 .debugger
4530 .as_ref()?
4531 .log_dap_communications
4532 .as_ref()
4533 },
4534 write: |settings_content, value| {
4535 settings_content
4536 .debugger
4537 .get_or_insert_default()
4538 .log_dap_communications = value;
4539 },
4540 }),
4541 metadata: None,
4542 files: USER,
4543 }),
4544 SettingsPageItem::SettingItem(SettingItem {
4545 title: "Format DAP Log Messages",
4546 description: "Whether to format DAP messages when adding them to debug adapter logger.",
4547 field: Box::new(SettingField {
4548 json_path: Some("debugger.format_dap_log_messages"),
4549 pick: |settings_content| {
4550 settings_content
4551 .debugger
4552 .as_ref()?
4553 .format_dap_log_messages
4554 .as_ref()
4555 },
4556 write: |settings_content, value| {
4557 settings_content
4558 .debugger
4559 .get_or_insert_default()
4560 .format_dap_log_messages = value;
4561 },
4562 }),
4563 metadata: None,
4564 files: USER,
4565 }),
4566 ],
4567 },
4568 SettingsPage {
4569 title: "Terminal",
4570 items: vec![
4571 SettingsPageItem::SectionHeader("Environment"),
4572 SettingsPageItem::DynamicItem(DynamicItem {
4573 discriminant: SettingItem {
4574 files: USER | PROJECT,
4575 title: "Shell",
4576 description: "What shell to use when opening a terminal.",
4577 field: Box::new(SettingField {
4578 json_path: Some("terminal.shell$"),
4579 pick: |settings_content| {
4580 Some(&dynamic_variants::<settings::Shell>()[
4581 settings_content
4582 .terminal
4583 .as_ref()?
4584 .project
4585 .shell
4586 .as_ref()?
4587 .discriminant() as usize])
4588 },
4589 write: |settings_content, value| {
4590 let Some(value) = value else {
4591 if let Some(terminal) = settings_content.terminal.as_mut() {
4592 terminal.project.shell = None;
4593 }
4594 return;
4595 };
4596 let settings_value = settings_content
4597 .terminal
4598 .get_or_insert_default()
4599 .project
4600 .shell
4601 .get_or_insert_with(|| settings::Shell::default());
4602 let default_shell = if cfg!(target_os = "windows") {
4603 "powershell.exe"
4604 } else {
4605 "sh"
4606 };
4607 *settings_value = match value {
4608 settings::ShellDiscriminants::System => {
4609 settings::Shell::System
4610 },
4611 settings::ShellDiscriminants::Program => {
4612 let program = match settings_value {
4613 settings::Shell::Program(p) => p.clone(),
4614 settings::Shell::WithArguments { program, .. } => program.clone(),
4615 _ => String::from(default_shell),
4616 };
4617 settings::Shell::Program(program)
4618 },
4619 settings::ShellDiscriminants::WithArguments => {
4620 let (program, args, title_override) = match settings_value {
4621 settings::Shell::Program(p) => (p.clone(), vec![], None),
4622 settings::Shell::WithArguments { program, args, title_override } => {
4623 (program.clone(), args.clone(), title_override.clone())
4624 },
4625 _ => (String::from(default_shell), vec![], None),
4626 };
4627 settings::Shell::WithArguments {
4628 program,
4629 args,
4630 title_override,
4631 }
4632 },
4633 };
4634 },
4635 }),
4636 metadata: None,
4637 },
4638 pick_discriminant: |settings_content| {
4639 Some(settings_content.terminal.as_ref()?.project.shell.as_ref()?.discriminant() as usize)
4640 },
4641 fields: dynamic_variants::<settings::Shell>().into_iter().map(|variant| {
4642 match variant {
4643 settings::ShellDiscriminants::System => vec![],
4644 settings::ShellDiscriminants::Program => vec![
4645 SettingItem {
4646 files: USER | PROJECT,
4647 title: "Program",
4648 description: "The shell program to use.",
4649 field: Box::new(SettingField {
4650 json_path: Some("terminal.shell"),
4651 pick: |settings_content| {
4652 match settings_content.terminal.as_ref()?.project.shell.as_ref() {
4653 Some(settings::Shell::Program(program)) => Some(program),
4654 _ => None
4655 }
4656 },
4657 write: |settings_content, value| {
4658 let Some(value) = value else {
4659 return;
4660 };
4661 match settings_content
4662 .terminal
4663 .get_or_insert_default()
4664 .project
4665 .shell.as_mut() {
4666 Some(settings::Shell::Program(program)) => *program = value,
4667 _ => return
4668 }
4669 },
4670 }),
4671 metadata: None,
4672 }
4673 ],
4674 settings::ShellDiscriminants::WithArguments => vec![
4675 SettingItem {
4676 files: USER | PROJECT,
4677 title: "Program",
4678 description: "The shell program to run.",
4679 field: Box::new(SettingField {
4680 json_path: Some("terminal.shell.program"),
4681 pick: |settings_content| {
4682 match settings_content.terminal.as_ref()?.project.shell.as_ref() {
4683 Some(settings::Shell::WithArguments { program, .. }) => Some(program),
4684 _ => None
4685 }
4686 },
4687 write: |settings_content, value| {
4688 let Some(value) = value else {
4689 return;
4690 };
4691 match settings_content
4692 .terminal
4693 .get_or_insert_default()
4694 .project
4695 .shell.as_mut() {
4696 Some(settings::Shell::WithArguments { program, .. }) => *program = value,
4697 _ => return
4698 }
4699 },
4700 }),
4701 metadata: None,
4702 },
4703 SettingItem {
4704 files: USER | PROJECT,
4705 title: "Arguments",
4706 description: "The arguments to pass to the shell program.",
4707 field: Box::new(
4708 SettingField {
4709 json_path: Some("terminal.shell.args"),
4710 pick: |settings_content| {
4711 match settings_content.terminal.as_ref()?.project.shell.as_ref() {
4712 Some(settings::Shell::WithArguments { args, .. }) => Some(args),
4713 _ => None
4714 }
4715 },
4716 write: |settings_content, value| {
4717 let Some(value) = value else {
4718 return;
4719 };
4720 match settings_content
4721 .terminal
4722 .get_or_insert_default()
4723 .project
4724 .shell.as_mut() {
4725 Some(settings::Shell::WithArguments { args, .. }) => *args = value,
4726 _ => return
4727 }
4728 },
4729 }
4730 .unimplemented(),
4731 ),
4732 metadata: None,
4733 },
4734 SettingItem {
4735 files: USER | PROJECT,
4736 title: "Title Override",
4737 description: "An optional string to override the title of the terminal tab.",
4738 field: Box::new(SettingField {
4739 json_path: Some("terminal.shell.title_override"),
4740 pick: |settings_content| {
4741 match settings_content.terminal.as_ref()?.project.shell.as_ref() {
4742 Some(settings::Shell::WithArguments { title_override, .. }) => title_override.as_ref().or(DEFAULT_EMPTY_SHARED_STRING),
4743 _ => None
4744 }
4745 },
4746 write: |settings_content, value| {
4747 match settings_content
4748 .terminal
4749 .get_or_insert_default()
4750 .project
4751 .shell.as_mut() {
4752 Some(settings::Shell::WithArguments { title_override, .. }) => *title_override = value.filter(|s| !s.is_empty()),
4753 _ => return
4754 }
4755 },
4756 }),
4757 metadata: None,
4758 }
4759 ],
4760 }
4761 }).collect(),
4762 }),
4763 SettingsPageItem::DynamicItem(DynamicItem {
4764 discriminant: SettingItem {
4765 files: USER | PROJECT,
4766 title: "Working Directory",
4767 description: "What working directory to use when launching the terminal.",
4768 field: Box::new(SettingField {
4769 json_path: Some("terminal.working_directory$"),
4770 pick: |settings_content| {
4771 Some(&dynamic_variants::<settings::WorkingDirectory>()[
4772 settings_content
4773 .terminal
4774 .as_ref()?
4775 .project
4776 .working_directory
4777 .as_ref()?
4778 .discriminant() as usize])
4779 },
4780 write: |settings_content, value| {
4781 let Some(value) = value else {
4782 if let Some(terminal) = settings_content.terminal.as_mut() {
4783 terminal.project.working_directory = None;
4784 }
4785 return;
4786 };
4787 let settings_value = settings_content
4788 .terminal
4789 .get_or_insert_default()
4790 .project
4791 .working_directory
4792 .get_or_insert_with(|| settings::WorkingDirectory::CurrentProjectDirectory);
4793 *settings_value = match value {
4794 settings::WorkingDirectoryDiscriminants::CurrentProjectDirectory => {
4795 settings::WorkingDirectory::CurrentProjectDirectory
4796 },
4797 settings::WorkingDirectoryDiscriminants::FirstProjectDirectory => {
4798 settings::WorkingDirectory::FirstProjectDirectory
4799 },
4800 settings::WorkingDirectoryDiscriminants::AlwaysHome => {
4801 settings::WorkingDirectory::AlwaysHome
4802 },
4803 settings::WorkingDirectoryDiscriminants::Always => {
4804 let directory = match settings_value {
4805 settings::WorkingDirectory::Always { .. } => return,
4806 _ => String::new(),
4807 };
4808 settings::WorkingDirectory::Always { directory }
4809 },
4810 };
4811 },
4812 }),
4813 metadata: None,
4814 },
4815 pick_discriminant: |settings_content| {
4816 Some(settings_content.terminal.as_ref()?.project.working_directory.as_ref()?.discriminant() as usize)
4817 },
4818 fields: dynamic_variants::<settings::WorkingDirectory>().into_iter().map(|variant| {
4819 match variant {
4820 settings::WorkingDirectoryDiscriminants::CurrentProjectDirectory => vec![],
4821 settings::WorkingDirectoryDiscriminants::FirstProjectDirectory => vec![],
4822 settings::WorkingDirectoryDiscriminants::AlwaysHome => vec![],
4823 settings::WorkingDirectoryDiscriminants::Always => vec![
4824 SettingItem {
4825 files: USER | PROJECT,
4826 title: "Directory",
4827 description: "The directory path to use (will be shell expanded).",
4828 field: Box::new(SettingField {
4829 json_path: Some("terminal.working_directory.always"),
4830 pick: |settings_content| {
4831 match settings_content.terminal.as_ref()?.project.working_directory.as_ref() {
4832 Some(settings::WorkingDirectory::Always { directory }) => Some(directory),
4833 _ => None
4834 }
4835 },
4836 write: |settings_content, value| {
4837 let value = value.unwrap_or_default();
4838 match settings_content
4839 .terminal
4840 .get_or_insert_default()
4841 .project
4842 .working_directory.as_mut() {
4843 Some(settings::WorkingDirectory::Always { directory }) => *directory = value,
4844 _ => return
4845 }
4846 },
4847 }),
4848 metadata: None,
4849 }
4850 ],
4851 }
4852 }).collect(),
4853 }),
4854 SettingsPageItem::SettingItem(SettingItem {
4855 title: "Environment Variables",
4856 description: "Key-value pairs to add to the terminal's environment.",
4857 field: Box::new(
4858 SettingField {
4859 json_path: Some("terminal.env"),
4860 pick: |settings_content| {
4861 settings_content.terminal.as_ref()?.project.env.as_ref()
4862 },
4863 write: |settings_content, value| {
4864 settings_content
4865 .terminal
4866 .get_or_insert_default()
4867 .project
4868 .env = value;
4869 },
4870 }
4871 .unimplemented(),
4872 ),
4873 metadata: None,
4874 files: USER | PROJECT,
4875 }),
4876 SettingsPageItem::SettingItem(SettingItem {
4877 title: "Detect Virtual Environment",
4878 description: "Activates the Python virtual environment, if one is found, in the terminal's working directory.",
4879 field: Box::new(
4880 SettingField {
4881 json_path: Some("terminal.detect_venv"),
4882 pick: |settings_content| {
4883 settings_content
4884 .terminal
4885 .as_ref()?
4886 .project
4887 .detect_venv
4888 .as_ref()
4889 },
4890 write: |settings_content, value| {
4891 settings_content
4892 .terminal
4893 .get_or_insert_default()
4894 .project
4895 .detect_venv = value;
4896 },
4897 }
4898 .unimplemented(),
4899 ),
4900 metadata: None,
4901 files: USER | PROJECT,
4902 }),
4903 SettingsPageItem::SectionHeader("Font"),
4904 SettingsPageItem::SettingItem(SettingItem {
4905 title: "Font Size",
4906 description: "Font size for terminal text. If not set, defaults to buffer font size.",
4907 field: Box::new(SettingField {
4908 json_path: Some("terminal.font_size"),
4909 pick: |settings_content| {
4910 settings_content
4911 .terminal
4912 .as_ref()
4913 .and_then(|terminal| terminal.font_size.as_ref())
4914 .or(settings_content.theme.buffer_font_size.as_ref())
4915 },
4916 write: |settings_content, value| {
4917 settings_content.terminal.get_or_insert_default().font_size = value;
4918 },
4919 }),
4920 metadata: None,
4921 files: USER,
4922 }),
4923 SettingsPageItem::SettingItem(SettingItem {
4924 title: "Font Family",
4925 description: "Font family for terminal text. If not set, defaults to buffer font family.",
4926 field: Box::new(SettingField {
4927 json_path: Some("terminal.font_family"),
4928 pick: |settings_content| {
4929 settings_content
4930 .terminal
4931 .as_ref()
4932 .and_then(|terminal| terminal.font_family.as_ref())
4933 .or(settings_content.theme.buffer_font_family.as_ref())
4934 },
4935 write: |settings_content, value| {
4936 settings_content
4937 .terminal
4938 .get_or_insert_default()
4939 .font_family = value;
4940 },
4941 }),
4942 metadata: None,
4943 files: USER,
4944 }),
4945 SettingsPageItem::SettingItem(SettingItem {
4946 title: "Font Fallbacks",
4947 description: "Font fallbacks for terminal text. If not set, defaults to buffer font fallbacks.",
4948 field: Box::new(
4949 SettingField {
4950 json_path: Some("terminal.font_fallbacks"),
4951 pick: |settings_content| {
4952 settings_content
4953 .terminal
4954 .as_ref()
4955 .and_then(|terminal| terminal.font_fallbacks.as_ref())
4956 .or(settings_content.theme.buffer_font_fallbacks.as_ref())
4957 },
4958 write: |settings_content, value| {
4959 settings_content
4960 .terminal
4961 .get_or_insert_default()
4962 .font_fallbacks = value;
4963 },
4964 }
4965 .unimplemented(),
4966 ),
4967 metadata: None,
4968 files: USER,
4969 }),
4970 SettingsPageItem::SettingItem(SettingItem {
4971 title: "Font Weight",
4972 description: "Font weight for terminal text in CSS weight units (100-900).",
4973 field: Box::new(SettingField {
4974 json_path: Some("terminal.font_weight"),
4975 pick: |settings_content| {
4976 settings_content.terminal.as_ref()?.font_weight.as_ref()
4977 },
4978 write: |settings_content, value| {
4979 settings_content
4980 .terminal
4981 .get_or_insert_default()
4982 .font_weight = value;
4983 },
4984 }),
4985 metadata: None,
4986 files: USER,
4987 }),
4988 SettingsPageItem::SettingItem(SettingItem {
4989 title: "Font Features",
4990 description: "Font features for terminal text.",
4991 field: Box::new(
4992 SettingField {
4993 json_path: Some("terminal.font_features"),
4994 pick: |settings_content| {
4995 settings_content
4996 .terminal
4997 .as_ref()
4998 .and_then(|terminal| terminal.font_features.as_ref())
4999 .or(settings_content.theme.buffer_font_features.as_ref())
5000 },
5001 write: |settings_content, value| {
5002 settings_content
5003 .terminal
5004 .get_or_insert_default()
5005 .font_features = value;
5006 },
5007 }
5008 .unimplemented(),
5009 ),
5010 metadata: None,
5011 files: USER,
5012 }),
5013 SettingsPageItem::SectionHeader("Display Settings"),
5014 SettingsPageItem::SettingItem(SettingItem {
5015 title: "Line Height",
5016 description: "Line height for terminal text.",
5017 field: Box::new(
5018 SettingField {
5019 json_path: Some("terminal.line_height"),
5020 pick: |settings_content| {
5021 settings_content.terminal.as_ref()?.line_height.as_ref()
5022 },
5023 write: |settings_content, value| {
5024 settings_content
5025 .terminal
5026 .get_or_insert_default()
5027 .line_height = value;
5028 },
5029 }
5030 .unimplemented(),
5031 ),
5032 metadata: None,
5033 files: USER,
5034 }),
5035 SettingsPageItem::SettingItem(SettingItem {
5036 title: "Cursor Shape",
5037 description: "Default cursor shape for the terminal (bar, block, underline, or hollow).",
5038 field: Box::new(SettingField {
5039 json_path: Some("terminal.cursor_shape"),
5040 pick: |settings_content| {
5041 settings_content.terminal.as_ref()?.cursor_shape.as_ref()
5042 },
5043 write: |settings_content, value| {
5044 settings_content
5045 .terminal
5046 .get_or_insert_default()
5047 .cursor_shape = value;
5048 },
5049 }),
5050 metadata: None,
5051 files: USER,
5052 }),
5053 SettingsPageItem::SettingItem(SettingItem {
5054 title: "Cursor Blinking",
5055 description: "Sets the cursor blinking behavior in the terminal.",
5056 field: Box::new(SettingField {
5057 json_path: Some("terminal.blinking"),
5058 pick: |settings_content| {
5059 settings_content.terminal.as_ref()?.blinking.as_ref()
5060 },
5061 write: |settings_content, value| {
5062 settings_content.terminal.get_or_insert_default().blinking = value;
5063 },
5064 }),
5065 metadata: None,
5066 files: USER,
5067 }),
5068 SettingsPageItem::SettingItem(SettingItem {
5069 title: "Alternate Scroll",
5070 description: "Whether alternate scroll mode is active by default (converts mouse scroll to arrow keys in apps like Vim).",
5071 field: Box::new(SettingField {
5072 json_path: Some("terminal.alternate_scroll"),
5073 pick: |settings_content| {
5074 settings_content
5075 .terminal
5076 .as_ref()?
5077 .alternate_scroll
5078 .as_ref()
5079 },
5080 write: |settings_content, value| {
5081 settings_content
5082 .terminal
5083 .get_or_insert_default()
5084 .alternate_scroll = value;
5085 },
5086 }),
5087 metadata: None,
5088 files: USER,
5089 }),
5090 SettingsPageItem::SettingItem(SettingItem {
5091 title: "Minimum Contrast",
5092 description: "The minimum APCA perceptual contrast between foreground and background colors (0-106).",
5093 field: Box::new(SettingField {
5094 json_path: Some("terminal.minimum_contrast"),
5095 pick: |settings_content| {
5096 settings_content
5097 .terminal
5098 .as_ref()?
5099 .minimum_contrast
5100 .as_ref()
5101 },
5102 write: |settings_content, value| {
5103 settings_content
5104 .terminal
5105 .get_or_insert_default()
5106 .minimum_contrast = value;
5107 },
5108 }),
5109 metadata: None,
5110 files: USER,
5111 }),
5112 SettingsPageItem::SectionHeader("Behavior Settings"),
5113 SettingsPageItem::SettingItem(SettingItem {
5114 title: "Option As Meta",
5115 description: "Whether the option key behaves as the meta key.",
5116 field: Box::new(SettingField {
5117 json_path: Some("terminal.option_as_meta"),
5118 pick: |settings_content| {
5119 settings_content.terminal.as_ref()?.option_as_meta.as_ref()
5120 },
5121 write: |settings_content, value| {
5122 settings_content
5123 .terminal
5124 .get_or_insert_default()
5125 .option_as_meta = value;
5126 },
5127 }),
5128 metadata: None,
5129 files: USER,
5130 }),
5131 SettingsPageItem::SettingItem(SettingItem {
5132 title: "Copy On Select",
5133 description: "Whether selecting text in the terminal automatically copies to the system clipboard.",
5134 field: Box::new(SettingField {
5135 json_path: Some("terminal.copy_on_select"),
5136 pick: |settings_content| {
5137 settings_content.terminal.as_ref()?.copy_on_select.as_ref()
5138 },
5139 write: |settings_content, value| {
5140 settings_content
5141 .terminal
5142 .get_or_insert_default()
5143 .copy_on_select = value;
5144 },
5145 }),
5146 metadata: None,
5147 files: USER,
5148 }),
5149 SettingsPageItem::SettingItem(SettingItem {
5150 title: "Keep Selection On Copy",
5151 description: "Whether to keep the text selection after copying it to the clipboard.",
5152 field: Box::new(SettingField {
5153 json_path: Some("terminal.keep_selection_on_copy"),
5154 pick: |settings_content| {
5155 settings_content
5156 .terminal
5157 .as_ref()?
5158 .keep_selection_on_copy
5159 .as_ref()
5160 },
5161 write: |settings_content, value| {
5162 settings_content
5163 .terminal
5164 .get_or_insert_default()
5165 .keep_selection_on_copy = value;
5166 },
5167 }),
5168 metadata: None,
5169 files: USER,
5170 }),
5171 SettingsPageItem::SectionHeader("Layout Settings"),
5172 SettingsPageItem::SettingItem(SettingItem {
5173 title: "Default Width",
5174 description: "Default width when the terminal is docked to the left or right (in pixels).",
5175 field: Box::new(SettingField {
5176 json_path: Some("terminal.default_width"),
5177 pick: |settings_content| {
5178 settings_content.terminal.as_ref()?.default_width.as_ref()
5179 },
5180 write: |settings_content, value| {
5181 settings_content
5182 .terminal
5183 .get_or_insert_default()
5184 .default_width = value;
5185 },
5186 }),
5187 metadata: None,
5188 files: USER,
5189 }),
5190 SettingsPageItem::SettingItem(SettingItem {
5191 title: "Default Height",
5192 description: "Default height when the terminal is docked to the bottom (in pixels).",
5193 field: Box::new(SettingField {
5194 json_path: Some("terminal.default_height"),
5195 pick: |settings_content| {
5196 settings_content.terminal.as_ref()?.default_height.as_ref()
5197 },
5198 write: |settings_content, value| {
5199 settings_content
5200 .terminal
5201 .get_or_insert_default()
5202 .default_height = value;
5203 },
5204 }),
5205 metadata: None,
5206 files: USER,
5207 }),
5208 SettingsPageItem::SectionHeader("Advanced Settings"),
5209 SettingsPageItem::SettingItem(SettingItem {
5210 title: "Max Scroll History Lines",
5211 description: "Maximum number of lines to keep in scrollback history (max: 100,000; 0 disables scrolling).",
5212 field: Box::new(SettingField {
5213 json_path: Some("terminal.max_scroll_history_lines"),
5214 pick: |settings_content| {
5215 settings_content
5216 .terminal
5217 .as_ref()?
5218 .max_scroll_history_lines
5219 .as_ref()
5220 },
5221 write: |settings_content, value| {
5222 settings_content
5223 .terminal
5224 .get_or_insert_default()
5225 .max_scroll_history_lines = value;
5226 },
5227 }),
5228 metadata: None,
5229 files: USER,
5230 }),
5231 SettingsPageItem::SettingItem(SettingItem {
5232 title: "Scroll Multiplier",
5233 description: "The multiplier for scrolling in the terminal with the mouse wheel",
5234 field: Box::new(SettingField {
5235 json_path: Some("terminal.scroll_multiplier"),
5236 pick: |settings_content| {
5237 settings_content.terminal.as_ref()?.scroll_multiplier.as_ref()
5238 },
5239 write: |settings_content, value| {
5240 settings_content
5241 .terminal
5242 .get_or_insert_default()
5243 .scroll_multiplier = value;
5244 },
5245 }),
5246 metadata: None,
5247 files: USER,
5248 }),
5249 SettingsPageItem::SectionHeader("Toolbar"),
5250 SettingsPageItem::SettingItem(SettingItem {
5251 title: "Breadcrumbs",
5252 description: "Display the terminal title in breadcrumbs inside the terminal pane.",
5253 field: Box::new(SettingField {
5254 json_path: Some("terminal.toolbar.breadcrumbs"),
5255 pick: |settings_content| {
5256 settings_content
5257 .terminal
5258 .as_ref()?
5259 .toolbar
5260 .as_ref()?
5261 .breadcrumbs
5262 .as_ref()
5263 },
5264 write: |settings_content, value| {
5265 settings_content
5266 .terminal
5267 .get_or_insert_default()
5268 .toolbar
5269 .get_or_insert_default()
5270 .breadcrumbs = value;
5271 },
5272 }),
5273 metadata: None,
5274 files: USER,
5275 }),
5276 SettingsPageItem::SectionHeader("Scrollbar"),
5277 SettingsPageItem::SettingItem(SettingItem {
5278 title: "Show Scrollbar",
5279 description: "When to show the scrollbar in the terminal.",
5280 field: Box::new(SettingField {
5281 json_path: Some("terminal.scrollbar.show"),
5282 pick: |settings_content| {
5283 show_scrollbar_or_editor(settings_content, |settings_content| {
5284 settings_content
5285 .terminal
5286 .as_ref()?
5287 .scrollbar
5288 .as_ref()?
5289 .show
5290 .as_ref()
5291 })
5292 },
5293 write: |settings_content, value| {
5294 settings_content
5295 .terminal
5296 .get_or_insert_default()
5297 .scrollbar
5298 .get_or_insert_default()
5299 .show = value;
5300 },
5301 }),
5302 metadata: None,
5303 files: USER,
5304 }),
5305 ],
5306 },
5307 SettingsPage {
5308 title: "Version Control",
5309 items: vec![
5310 SettingsPageItem::SectionHeader("Git Gutter"),
5311 SettingsPageItem::SettingItem(SettingItem {
5312 title: "Visibility",
5313 description: "Control whether Git status is shown in the editor's gutter.",
5314 field: Box::new(SettingField {
5315 json_path: Some("git.git_gutter"),
5316 pick: |settings_content| settings_content.git.as_ref()?.git_gutter.as_ref(),
5317 write: |settings_content, value| {
5318 settings_content.git.get_or_insert_default().git_gutter = value;
5319 },
5320 }),
5321 metadata: None,
5322 files: USER,
5323 }),
5324 // todo(settings_ui): Figure out the right default for this value in default.json
5325 SettingsPageItem::SettingItem(SettingItem {
5326 title: "Debounce",
5327 description: "Debounce threshold in milliseconds after which changes are reflected in the Git gutter.",
5328 field: Box::new(SettingField {
5329 json_path: Some("git.gutter_debounce"),
5330 pick: |settings_content| {
5331 settings_content.git.as_ref()?.gutter_debounce.as_ref()
5332 },
5333 write: |settings_content, value| {
5334 settings_content.git.get_or_insert_default().gutter_debounce = value;
5335 },
5336 }),
5337 metadata: None,
5338 files: USER,
5339 }),
5340 SettingsPageItem::SectionHeader("Inline Git Blame"),
5341 SettingsPageItem::SettingItem(SettingItem {
5342 title: "Enabled",
5343 description: "Whether or not to show Git blame data inline in the currently focused line.",
5344 field: Box::new(SettingField {
5345 json_path: Some("git.inline_blame.enabled"),
5346 pick: |settings_content| {
5347 settings_content
5348 .git
5349 .as_ref()?
5350 .inline_blame
5351 .as_ref()?
5352 .enabled
5353 .as_ref()
5354 },
5355 write: |settings_content, value| {
5356 settings_content
5357 .git
5358 .get_or_insert_default()
5359 .inline_blame
5360 .get_or_insert_default()
5361 .enabled = value;
5362 },
5363 }),
5364 metadata: None,
5365 files: USER,
5366 }),
5367 SettingsPageItem::SettingItem(SettingItem {
5368 title: "Delay",
5369 description: "The delay after which the inline blame information is shown.",
5370 field: Box::new(SettingField {
5371 json_path: Some("git.inline_blame.delay_ms"),
5372 pick: |settings_content| {
5373 settings_content
5374 .git
5375 .as_ref()?
5376 .inline_blame
5377 .as_ref()?
5378 .delay_ms
5379 .as_ref()
5380 },
5381 write: |settings_content, value| {
5382 settings_content
5383 .git
5384 .get_or_insert_default()
5385 .inline_blame
5386 .get_or_insert_default()
5387 .delay_ms = value;
5388 },
5389 }),
5390 metadata: None,
5391 files: USER,
5392 }),
5393 SettingsPageItem::SettingItem(SettingItem {
5394 title: "Padding",
5395 description: "Padding between the end of the source line and the start of the inline blame in columns.",
5396 field: Box::new(SettingField {
5397 json_path: Some("git.inline_blame.padding"),
5398 pick: |settings_content| {
5399 settings_content
5400 .git
5401 .as_ref()?
5402 .inline_blame
5403 .as_ref()?
5404 .padding
5405 .as_ref()
5406 },
5407 write: |settings_content, value| {
5408 settings_content
5409 .git
5410 .get_or_insert_default()
5411 .inline_blame
5412 .get_or_insert_default()
5413 .padding = value;
5414 },
5415 }),
5416 metadata: None,
5417 files: USER,
5418 }),
5419 SettingsPageItem::SettingItem(SettingItem {
5420 title: "Minimum Column",
5421 description: "The minimum column number at which to show the inline blame information.",
5422 field: Box::new(SettingField {
5423 json_path: Some("git.inline_blame.min_column"),
5424 pick: |settings_content| {
5425 settings_content
5426 .git
5427 .as_ref()?
5428 .inline_blame
5429 .as_ref()?
5430 .min_column
5431 .as_ref()
5432 },
5433 write: |settings_content, value| {
5434 settings_content
5435 .git
5436 .get_or_insert_default()
5437 .inline_blame
5438 .get_or_insert_default()
5439 .min_column = value;
5440 },
5441 }),
5442 metadata: None,
5443 files: USER,
5444 }),
5445 SettingsPageItem::SettingItem(SettingItem {
5446 title: "Show Commit Summary",
5447 description: "Show commit summary as part of the inline blame.",
5448 field: Box::new(SettingField {
5449 json_path: Some("git.inline_blame.show_commit_summary"),
5450 pick: |settings_content| {
5451 settings_content
5452 .git
5453 .as_ref()?
5454 .inline_blame
5455 .as_ref()?
5456 .show_commit_summary
5457 .as_ref()
5458 },
5459 write: |settings_content, value| {
5460 settings_content
5461 .git
5462 .get_or_insert_default()
5463 .inline_blame
5464 .get_or_insert_default()
5465 .show_commit_summary = value;
5466 },
5467 }),
5468 metadata: None,
5469 files: USER,
5470 }),
5471 SettingsPageItem::SectionHeader("Git Blame View"),
5472 SettingsPageItem::SettingItem(SettingItem {
5473 title: "Show Avatar",
5474 description: "Show the avatar of the author of the commit.",
5475 field: Box::new(SettingField {
5476 json_path: Some("git.blame.show_avatar"),
5477 pick: |settings_content| {
5478 settings_content
5479 .git
5480 .as_ref()?
5481 .blame
5482 .as_ref()?
5483 .show_avatar
5484 .as_ref()
5485 },
5486 write: |settings_content, value| {
5487 settings_content
5488 .git
5489 .get_or_insert_default()
5490 .blame
5491 .get_or_insert_default()
5492 .show_avatar = value;
5493 },
5494 }),
5495 metadata: None,
5496 files: USER,
5497 }),
5498 SettingsPageItem::SectionHeader("Branch Picker"),
5499 SettingsPageItem::SettingItem(SettingItem {
5500 title: "Show Author Name",
5501 description: "Show author name as part of the commit information in branch picker.",
5502 field: Box::new(SettingField {
5503 json_path: Some("git.branch_picker.show_author_name"),
5504 pick: |settings_content| {
5505 settings_content
5506 .git
5507 .as_ref()?
5508 .branch_picker
5509 .as_ref()?
5510 .show_author_name
5511 .as_ref()
5512 },
5513 write: |settings_content, value| {
5514 settings_content
5515 .git
5516 .get_or_insert_default()
5517 .branch_picker
5518 .get_or_insert_default()
5519 .show_author_name = value;
5520 },
5521 }),
5522 metadata: None,
5523 files: USER,
5524 }),
5525 SettingsPageItem::SectionHeader("Git Hunks"),
5526 SettingsPageItem::SettingItem(SettingItem {
5527 title: "Hunk Style",
5528 description: "How Git hunks are displayed visually in the editor.",
5529 field: Box::new(SettingField {
5530 json_path: Some("git.hunk_style"),
5531 pick: |settings_content| settings_content.git.as_ref()?.hunk_style.as_ref(),
5532 write: |settings_content, value| {
5533 settings_content.git.get_or_insert_default().hunk_style = value;
5534 },
5535 }),
5536 metadata: None,
5537 files: USER,
5538 }),
5539 SettingsPageItem::SettingItem(SettingItem {
5540 title: "Path Style",
5541 description: "Should the name or path be displayed first in the git view.",
5542 field: Box::new(SettingField {
5543 json_path: Some("git.path_style"),
5544 pick: |settings_content| settings_content.git.as_ref()?.path_style.as_ref(),
5545 write: |settings_content, value| {
5546 settings_content.git.get_or_insert_default().path_style = value;
5547 },
5548 }),
5549 metadata: None,
5550 files: USER,
5551 }),
5552 ],
5553 },
5554 SettingsPage {
5555 title: "Collaboration",
5556 items: vec![
5557 SettingsPageItem::SectionHeader("Calls"),
5558 SettingsPageItem::SettingItem(SettingItem {
5559 title: "Mute On Join",
5560 description: "Whether the microphone should be muted when joining a channel or a call.",
5561 field: Box::new(SettingField {
5562 json_path: Some("calls.mute_on_join"),
5563 pick: |settings_content| {
5564 settings_content.calls.as_ref()?.mute_on_join.as_ref()
5565 },
5566 write: |settings_content, value| {
5567 settings_content.calls.get_or_insert_default().mute_on_join = value;
5568 },
5569 }),
5570 metadata: None,
5571 files: USER,
5572 }),
5573 SettingsPageItem::SettingItem(SettingItem {
5574 title: "Share On Join",
5575 description: "Whether your current project should be shared when joining an empty channel.",
5576 field: Box::new(SettingField {
5577 json_path: Some("calls.share_on_join"),
5578 pick: |settings_content| {
5579 settings_content.calls.as_ref()?.share_on_join.as_ref()
5580 },
5581 write: |settings_content, value| {
5582 settings_content.calls.get_or_insert_default().share_on_join = value;
5583 },
5584 }),
5585 metadata: None,
5586 files: USER,
5587 }),
5588 SettingsPageItem::SectionHeader("Experimental"),
5589 SettingsPageItem::SettingItem(SettingItem {
5590 title: "Rodio Audio",
5591 description: "Opt into the new audio system.",
5592 field: Box::new(SettingField {
5593 json_path: Some("audio.experimental.rodio_audio"),
5594 pick: |settings_content| {
5595 settings_content.audio.as_ref()?.rodio_audio.as_ref()
5596 },
5597 write: |settings_content, value| {
5598 settings_content.audio.get_or_insert_default().rodio_audio = value;
5599 },
5600 }),
5601 metadata: None,
5602 files: USER,
5603 }),
5604 SettingsPageItem::SettingItem(SettingItem {
5605 title: "Auto Microphone Volume",
5606 description: "Automatically adjust microphone volume (requires rodio audio).",
5607 field: Box::new(SettingField {
5608 json_path: Some("audio.experimental.auto_microphone_volume"),
5609 pick: |settings_content| {
5610 settings_content
5611 .audio
5612 .as_ref()?
5613 .auto_microphone_volume
5614 .as_ref()
5615 },
5616 write: |settings_content, value| {
5617 settings_content
5618 .audio
5619 .get_or_insert_default()
5620 .auto_microphone_volume = value;
5621 },
5622 }),
5623 metadata: None,
5624 files: USER,
5625 }),
5626 SettingsPageItem::SettingItem(SettingItem {
5627 title: "Auto Speaker Volume",
5628 description: "Automatically adjust volume of other call members (requires rodio audio).",
5629 field: Box::new(SettingField {
5630 json_path: Some("audio.experimental.auto_speaker_volume"),
5631 pick: |settings_content| {
5632 settings_content
5633 .audio
5634 .as_ref()?
5635 .auto_speaker_volume
5636 .as_ref()
5637 },
5638 write: |settings_content, value| {
5639 settings_content
5640 .audio
5641 .get_or_insert_default()
5642 .auto_speaker_volume = value;
5643 },
5644 }),
5645 metadata: None,
5646 files: USER,
5647 }),
5648 SettingsPageItem::SettingItem(SettingItem {
5649 title: "Denoise",
5650 description: "Remove background noises (requires rodio audio).",
5651 field: Box::new(SettingField {
5652 json_path: Some("audio.experimental.denoise"),
5653 pick: |settings_content| settings_content.audio.as_ref()?.denoise.as_ref(),
5654 write: |settings_content, value| {
5655 settings_content.audio.get_or_insert_default().denoise = value;
5656 },
5657 }),
5658 metadata: None,
5659 files: USER,
5660 }),
5661 SettingsPageItem::SettingItem(SettingItem {
5662 title: "Legacy Audio Compatible",
5663 description: "Use audio parameters compatible with previous versions (requires rodio audio).",
5664 field: Box::new(SettingField {
5665 json_path: Some("audio.experimental.legacy_audio_compatible"),
5666 pick: |settings_content| {
5667 settings_content
5668 .audio
5669 .as_ref()?
5670 .legacy_audio_compatible
5671 .as_ref()
5672 },
5673 write: |settings_content, value| {
5674 settings_content
5675 .audio
5676 .get_or_insert_default()
5677 .legacy_audio_compatible = value;
5678 },
5679 }),
5680 metadata: None,
5681 files: USER,
5682 }),
5683 ],
5684 },
5685 SettingsPage {
5686 title: "AI",
5687 items: {
5688 let mut items = vec![
5689 SettingsPageItem::SectionHeader("General"),
5690 SettingsPageItem::SettingItem(SettingItem {
5691 title: "Disable AI",
5692 description: "Whether to disable all AI features in Zed.",
5693 field: Box::new(SettingField {
5694 json_path: Some("disable_ai"),
5695 pick: |settings_content| settings_content.disable_ai.as_ref(),
5696 write: |settings_content, value| {
5697 settings_content.disable_ai = value;
5698 },
5699 }),
5700 metadata: None,
5701 files: USER,
5702 }),
5703 SettingsPageItem::SectionHeader("Agent Configuration"),
5704 SettingsPageItem::SettingItem(SettingItem {
5705 title: "Always Allow Tool Actions",
5706 description: "When enabled, the agent can run potentially destructive actions without asking for your confirmation. This setting has no effect on external agents.",
5707 field: Box::new(SettingField {
5708 json_path: Some("agent.always_allow_tool_actions"),
5709 pick: |settings_content| {
5710 settings_content
5711 .agent
5712 .as_ref()?
5713 .always_allow_tool_actions
5714 .as_ref()
5715 },
5716 write: |settings_content, value| {
5717 settings_content
5718 .agent
5719 .get_or_insert_default()
5720 .always_allow_tool_actions = value;
5721 },
5722 }),
5723 metadata: None,
5724 files: USER,
5725 }),
5726 SettingsPageItem::SettingItem(SettingItem {
5727 title: "Single File Review",
5728 description: "When enabled, agent edits will also be displayed in single-file buffers for review.",
5729 field: Box::new(SettingField {
5730 json_path: Some("agent.single_file_review"),
5731 pick: |settings_content| {
5732 settings_content.agent.as_ref()?.single_file_review.as_ref()
5733 },
5734 write: |settings_content, value| {
5735 settings_content
5736 .agent
5737 .get_or_insert_default()
5738 .single_file_review = value;
5739 },
5740 }),
5741 metadata: None,
5742 files: USER,
5743 }),
5744 SettingsPageItem::SettingItem(SettingItem {
5745 title: "Enable Feedback",
5746 description: "Show voting thumbs up/down icon buttons for feedback on agent edits.",
5747 field: Box::new(SettingField {
5748 json_path: Some("agent.enable_feedback"),
5749 pick: |settings_content| {
5750 settings_content.agent.as_ref()?.enable_feedback.as_ref()
5751 },
5752 write: |settings_content, value| {
5753 settings_content
5754 .agent
5755 .get_or_insert_default()
5756 .enable_feedback = value;
5757 },
5758 }),
5759 metadata: None,
5760 files: USER,
5761 }),
5762 SettingsPageItem::SettingItem(SettingItem {
5763 title: "Notify When Agent Waiting",
5764 description: "Where to show notifications when the agent has completed its response or needs confirmation before running a tool action.",
5765 field: Box::new(SettingField {
5766 json_path: Some("agent.notify_when_agent_waiting"),
5767 pick: |settings_content| {
5768 settings_content
5769 .agent
5770 .as_ref()?
5771 .notify_when_agent_waiting
5772 .as_ref()
5773 },
5774 write: |settings_content, value| {
5775 settings_content
5776 .agent
5777 .get_or_insert_default()
5778 .notify_when_agent_waiting = value;
5779 },
5780 }),
5781 metadata: None,
5782 files: USER,
5783 }),
5784 SettingsPageItem::SettingItem(SettingItem {
5785 title: "Play Sound When Agent Done",
5786 description: "Whether to play a sound when the agent has either completed its response, or needs user input.",
5787 field: Box::new(SettingField {
5788 json_path: Some("agent.play_sound_when_agent_done"),
5789 pick: |settings_content| {
5790 settings_content
5791 .agent
5792 .as_ref()?
5793 .play_sound_when_agent_done
5794 .as_ref()
5795 },
5796 write: |settings_content, value| {
5797 settings_content
5798 .agent
5799 .get_or_insert_default()
5800 .play_sound_when_agent_done = value;
5801 },
5802 }),
5803 metadata: None,
5804 files: USER,
5805 }),
5806 SettingsPageItem::SettingItem(SettingItem {
5807 title: "Expand Edit Card",
5808 description: "Whether to have edit cards in the agent panel expanded, showing a Preview of the diff.",
5809 field: Box::new(SettingField {
5810 json_path: Some("agent.expand_edit_card"),
5811 pick: |settings_content| {
5812 settings_content.agent.as_ref()?.expand_edit_card.as_ref()
5813 },
5814 write: |settings_content, value| {
5815 settings_content
5816 .agent
5817 .get_or_insert_default()
5818 .expand_edit_card = value;
5819 },
5820 }),
5821 metadata: None,
5822 files: USER,
5823 }),
5824 SettingsPageItem::SettingItem(SettingItem {
5825 title: "Expand Terminal Card",
5826 description: "Whether to have terminal cards in the agent panel expanded, showing the whole command output.",
5827 field: Box::new(SettingField {
5828 json_path: Some("agent.expand_terminal_card"),
5829 pick: |settings_content| {
5830 settings_content
5831 .agent
5832 .as_ref()?
5833 .expand_terminal_card
5834 .as_ref()
5835 },
5836 write: |settings_content, value| {
5837 settings_content
5838 .agent
5839 .get_or_insert_default()
5840 .expand_terminal_card = value;
5841 },
5842 }),
5843 metadata: None,
5844 files: USER,
5845 }),
5846 SettingsPageItem::SettingItem(SettingItem {
5847 title: "Use Modifier To Send",
5848 description: "Whether to always use cmd-enter (or ctrl-enter on Linux or Windows) to send messages.",
5849 field: Box::new(SettingField {
5850 json_path: Some("agent.use_modifier_to_send"),
5851 pick: |settings_content| {
5852 settings_content
5853 .agent
5854 .as_ref()?
5855 .use_modifier_to_send
5856 .as_ref()
5857 },
5858 write: |settings_content, value| {
5859 settings_content
5860 .agent
5861 .get_or_insert_default()
5862 .use_modifier_to_send = value;
5863 },
5864 }),
5865 metadata: None,
5866 files: USER,
5867 }),
5868 SettingsPageItem::SettingItem(SettingItem {
5869 title: "Message Editor Min Lines",
5870 description: "Minimum number of lines to display in the agent message editor.",
5871 field: Box::new(SettingField {
5872 json_path: Some("agent.message_editor_min_lines"),
5873 pick: |settings_content| {
5874 settings_content
5875 .agent
5876 .as_ref()?
5877 .message_editor_min_lines
5878 .as_ref()
5879 },
5880 write: |settings_content, value| {
5881 settings_content
5882 .agent
5883 .get_or_insert_default()
5884 .message_editor_min_lines = value;
5885 },
5886 }),
5887 metadata: None,
5888 files: USER,
5889 }),
5890 ];
5891 items.extend(edit_prediction_language_settings_section());
5892 items.extend(
5893 [
5894 SettingsPageItem::SettingItem(SettingItem {
5895 title: "Display Mode",
5896 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.",
5897 field: Box::new(SettingField {
5898 json_path: Some("edit_prediction.display_mode"),
5899 pick: |settings_content| {
5900 settings_content.project.all_languages.edit_predictions.as_ref()?.mode.as_ref()
5901 },
5902 write: |settings_content, value| {
5903 settings_content.project.all_languages.edit_predictions.get_or_insert_default().mode = value;
5904 },
5905 }),
5906 metadata: None,
5907 files: USER,
5908 }),
5909 SettingsPageItem::SettingItem(SettingItem {
5910 title: "In Text Threads",
5911 description: "Whether edit predictions are enabled when editing text threads in the agent panel.",
5912 field: Box::new(SettingField {
5913 json_path: Some("edit_prediction.in_text_threads"),
5914 pick: |settings_content| {
5915 settings_content.project.all_languages.edit_predictions.as_ref()?.enabled_in_text_threads.as_ref()
5916 },
5917 write: |settings_content, value| {
5918 settings_content.project.all_languages.edit_predictions.get_or_insert_default().enabled_in_text_threads = value;
5919 },
5920 }),
5921 metadata: None,
5922 files: USER,
5923 }),
5924 SettingsPageItem::SettingItem(SettingItem {
5925 title: "Copilot Provider",
5926 description: "Use GitHub Copilot as your edit prediction provider.",
5927 field: Box::new(
5928 SettingField {
5929 json_path: Some("edit_prediction.copilot_provider"),
5930 pick: |settings_content| {
5931 settings_content.project.all_languages.edit_predictions.as_ref()?.copilot.as_ref()
5932 },
5933 write: |settings_content, value| {
5934 settings_content.project.all_languages.edit_predictions.get_or_insert_default().copilot = value;
5935 },
5936 }
5937 .unimplemented(),
5938 ),
5939 metadata: None,
5940 files: USER | PROJECT,
5941 }),
5942 SettingsPageItem::SettingItem(SettingItem {
5943 title: "Codestral Provider",
5944 description: "Use Mistral's Codestral as your edit prediction provider.",
5945 field: Box::new(
5946 SettingField {
5947 json_path: Some("edit_prediction.codestral_provider"),
5948 pick: |settings_content| {
5949 settings_content.project.all_languages.edit_predictions.as_ref()?.codestral.as_ref()
5950 },
5951 write: |settings_content, value| {
5952 settings_content.project.all_languages.edit_predictions.get_or_insert_default().codestral = value;
5953 },
5954 }
5955 .unimplemented(),
5956 ),
5957 metadata: None,
5958 files: USER | PROJECT,
5959 }),
5960 ]
5961 );
5962 items
5963 },
5964 },
5965 SettingsPage {
5966 title: "Network",
5967 items: vec![
5968 SettingsPageItem::SectionHeader("Network"),
5969 // todo(settings_ui): Proxy needs a default
5970 SettingsPageItem::SettingItem(SettingItem {
5971 title: "Proxy",
5972 description: "The proxy to use for network requests.",
5973 field: Box::new(
5974 SettingField {
5975 json_path: Some("proxy"),
5976 pick: |settings_content| settings_content.proxy.as_ref(),
5977 write: |settings_content, value| {
5978 settings_content.proxy = value;
5979 },
5980 }
5981 .unimplemented(),
5982 ),
5983 metadata: Some(Box::new(SettingsFieldMetadata {
5984 placeholder: Some("socks5h://localhost:10808"),
5985 ..Default::default()
5986 })),
5987 files: USER,
5988 }),
5989 SettingsPageItem::SettingItem(SettingItem {
5990 title: "Server URL",
5991 description: "The URL of the Zed server to connect to.",
5992 field: Box::new(SettingField {
5993 json_path: Some("server_url"),
5994 pick: |settings_content| settings_content.server_url.as_ref(),
5995 write: |settings_content, value| {
5996 settings_content.server_url = value;
5997 },
5998 }),
5999 metadata: Some(Box::new(SettingsFieldMetadata {
6000 placeholder: Some("https://zed.dev"),
6001 ..Default::default()
6002 })),
6003 files: USER,
6004 }),
6005 ],
6006 },
6007 ]
6008}
6009
6010const LANGUAGES_SECTION_HEADER: &'static str = "Languages";
6011
6012fn current_language() -> Option<SharedString> {
6013 sub_page_stack().iter().find_map(|page| {
6014 (page.section_header == LANGUAGES_SECTION_HEADER).then(|| page.link.title.clone())
6015 })
6016}
6017
6018fn language_settings_field<T>(
6019 settings_content: &SettingsContent,
6020 get: fn(&LanguageSettingsContent) -> Option<&T>,
6021) -> Option<&T> {
6022 let all_languages = &settings_content.project.all_languages;
6023 if let Some(current_language_name) = current_language() {
6024 if let Some(current_language) = all_languages.languages.0.get(¤t_language_name) {
6025 let value = get(current_language);
6026 if value.is_some() {
6027 return value;
6028 }
6029 }
6030 }
6031 let default_value = get(&all_languages.defaults);
6032 return default_value;
6033}
6034
6035fn language_settings_field_mut<T>(
6036 settings_content: &mut SettingsContent,
6037 value: Option<T>,
6038 write: fn(&mut LanguageSettingsContent, Option<T>),
6039) {
6040 let all_languages = &mut settings_content.project.all_languages;
6041 let language_content = if let Some(current_language) = current_language() {
6042 all_languages
6043 .languages
6044 .0
6045 .entry(current_language)
6046 .or_default()
6047 } else {
6048 &mut all_languages.defaults
6049 };
6050 write(language_content, value);
6051}
6052
6053fn language_settings_data() -> Vec<SettingsPageItem> {
6054 let mut items = vec![
6055 SettingsPageItem::SectionHeader("Indentation"),
6056 SettingsPageItem::SettingItem(SettingItem {
6057 title: "Tab Size",
6058 description: "How many columns a tab should occupy.",
6059 field: Box::new(SettingField {
6060 json_path: Some("languages.$(language).tab_size"), // TODO(cameron): not JQ syntax because not URL-safe
6061 pick: |settings_content| {
6062 language_settings_field(settings_content, |language| language.tab_size.as_ref())
6063 },
6064 write: |settings_content, value| {
6065 language_settings_field_mut(settings_content, value, |language, value| {
6066 language.tab_size = value;
6067 })
6068 },
6069 }),
6070 metadata: None,
6071 files: USER | PROJECT,
6072 }),
6073 SettingsPageItem::SettingItem(SettingItem {
6074 title: "Hard Tabs",
6075 description: "Whether to indent lines using tab characters, as opposed to multiple spaces.",
6076 field: Box::new(SettingField {
6077 json_path: Some("languages.$(language).hard_tabs"),
6078 pick: |settings_content| {
6079 language_settings_field(settings_content, |language| {
6080 language.hard_tabs.as_ref()
6081 })
6082 },
6083 write: |settings_content, value| {
6084 language_settings_field_mut(settings_content, value, |language, value| {
6085 language.hard_tabs = value;
6086 })
6087 },
6088 }),
6089 metadata: None,
6090 files: USER | PROJECT,
6091 }),
6092 SettingsPageItem::SettingItem(SettingItem {
6093 title: "Auto Indent",
6094 description: "Whether indentation should be adjusted based on the context whilst typing.",
6095 field: Box::new(SettingField {
6096 json_path: Some("languages.$(language).auto_indent"),
6097 pick: |settings_content| {
6098 language_settings_field(settings_content, |language| {
6099 language.auto_indent.as_ref()
6100 })
6101 },
6102 write: |settings_content, value| {
6103 language_settings_field_mut(settings_content, value, |language, value| {
6104 language.auto_indent = value;
6105 })
6106 },
6107 }),
6108 metadata: None,
6109 files: USER | PROJECT,
6110 }),
6111 SettingsPageItem::SettingItem(SettingItem {
6112 title: "Auto Indent On Paste",
6113 description: "Whether indentation of pasted content should be adjusted based on the context.",
6114 field: Box::new(SettingField {
6115 json_path: Some("languages.$(language).auto_indent_on_paste"),
6116 pick: |settings_content| {
6117 language_settings_field(settings_content, |language| {
6118 language.auto_indent_on_paste.as_ref()
6119 })
6120 },
6121 write: |settings_content, value| {
6122 language_settings_field_mut(settings_content, value, |language, value| {
6123 language.auto_indent_on_paste = value;
6124 })
6125 },
6126 }),
6127 metadata: None,
6128 files: USER | PROJECT,
6129 }),
6130 SettingsPageItem::SectionHeader("Wrapping"),
6131 SettingsPageItem::SettingItem(SettingItem {
6132 title: "Soft Wrap",
6133 description: "How to soft-wrap long lines of text.",
6134 field: Box::new(SettingField {
6135 json_path: Some("languages.$(language).soft_wrap"),
6136 pick: |settings_content| {
6137 language_settings_field(settings_content, |language| {
6138 language.soft_wrap.as_ref()
6139 })
6140 },
6141 write: |settings_content, value| {
6142 language_settings_field_mut(settings_content, value, |language, value| {
6143 language.soft_wrap = value;
6144 })
6145 },
6146 }),
6147 metadata: None,
6148 files: USER | PROJECT,
6149 }),
6150 SettingsPageItem::SettingItem(SettingItem {
6151 title: "Show Wrap Guides",
6152 description: "Show wrap guides in the editor.",
6153 field: Box::new(SettingField {
6154 json_path: Some("languages.$(language).show_wrap_guides"),
6155 pick: |settings_content| {
6156 language_settings_field(settings_content, |language| {
6157 language.show_wrap_guides.as_ref()
6158 })
6159 },
6160 write: |settings_content, value| {
6161 language_settings_field_mut(settings_content, value, |language, value| {
6162 language.show_wrap_guides = value;
6163 })
6164 },
6165 }),
6166 metadata: None,
6167 files: USER | PROJECT,
6168 }),
6169 SettingsPageItem::SettingItem(SettingItem {
6170 title: "Preferred Line Length",
6171 description: "The column at which to soft-wrap lines, for buffers where soft-wrap is enabled.",
6172 field: Box::new(SettingField {
6173 json_path: Some("languages.$(language).preferred_line_length"),
6174 pick: |settings_content| {
6175 language_settings_field(settings_content, |language| {
6176 language.preferred_line_length.as_ref()
6177 })
6178 },
6179 write: |settings_content, value| {
6180 language_settings_field_mut(settings_content, value, |language, value| {
6181 language.preferred_line_length = value;
6182 })
6183 },
6184 }),
6185 metadata: None,
6186 files: USER | PROJECT,
6187 }),
6188 SettingsPageItem::SettingItem(SettingItem {
6189 title: "Wrap Guides",
6190 description: "Character counts at which to show wrap guides in the editor.",
6191 field: Box::new(
6192 SettingField {
6193 json_path: Some("languages.$(language).wrap_guides"),
6194 pick: |settings_content| {
6195 language_settings_field(settings_content, |language| {
6196 language.wrap_guides.as_ref()
6197 })
6198 },
6199 write: |settings_content, value| {
6200 language_settings_field_mut(settings_content, value, |language, value| {
6201 language.wrap_guides = value;
6202 })
6203 },
6204 }
6205 .unimplemented(),
6206 ),
6207 metadata: None,
6208 files: USER | PROJECT,
6209 }),
6210 SettingsPageItem::SettingItem(SettingItem {
6211 title: "Allow Rewrap",
6212 description: "Controls where the `editor::rewrap` action is allowed for this language.",
6213 field: Box::new(SettingField {
6214 json_path: Some("languages.$(language).allow_rewrap"),
6215 pick: |settings_content| {
6216 language_settings_field(settings_content, |language| {
6217 language.allow_rewrap.as_ref()
6218 })
6219 },
6220 write: |settings_content, value| {
6221 language_settings_field_mut(settings_content, value, |language, value| {
6222 language.allow_rewrap = value;
6223 })
6224 },
6225 }),
6226 metadata: None,
6227 files: USER | PROJECT,
6228 }),
6229 SettingsPageItem::SectionHeader("Indent Guides"),
6230 SettingsPageItem::SettingItem(SettingItem {
6231 title: "Enabled",
6232 description: "Display indent guides in the editor.",
6233 field: Box::new(SettingField {
6234 json_path: Some("languages.$(language).indent_guides.enabled"),
6235 pick: |settings_content| {
6236 language_settings_field(settings_content, |language| {
6237 language
6238 .indent_guides
6239 .as_ref()
6240 .and_then(|indent_guides| indent_guides.enabled.as_ref())
6241 })
6242 },
6243 write: |settings_content, value| {
6244 language_settings_field_mut(settings_content, value, |language, value| {
6245 language.indent_guides.get_or_insert_default().enabled = value;
6246 })
6247 },
6248 }),
6249 metadata: None,
6250 files: USER | PROJECT,
6251 }),
6252 SettingsPageItem::SettingItem(SettingItem {
6253 title: "Line Width",
6254 description: "The width of the indent guides in pixels, between 1 and 10.",
6255 field: Box::new(SettingField {
6256 json_path: Some("languages.$(language).indent_guides.line_width"),
6257 pick: |settings_content| {
6258 language_settings_field(settings_content, |language| {
6259 language
6260 .indent_guides
6261 .as_ref()
6262 .and_then(|indent_guides| indent_guides.line_width.as_ref())
6263 })
6264 },
6265 write: |settings_content, value| {
6266 language_settings_field_mut(settings_content, value, |language, value| {
6267 language.indent_guides.get_or_insert_default().line_width = value;
6268 })
6269 },
6270 }),
6271 metadata: None,
6272 files: USER | PROJECT,
6273 }),
6274 SettingsPageItem::SettingItem(SettingItem {
6275 title: "Active Line Width",
6276 description: "The width of the active indent guide in pixels, between 1 and 10.",
6277 field: Box::new(SettingField {
6278 json_path: Some("languages.$(language).indent_guides.active_line_width"),
6279 pick: |settings_content| {
6280 language_settings_field(settings_content, |language| {
6281 language
6282 .indent_guides
6283 .as_ref()
6284 .and_then(|indent_guides| indent_guides.active_line_width.as_ref())
6285 })
6286 },
6287 write: |settings_content, value| {
6288 language_settings_field_mut(settings_content, value, |language, value| {
6289 language
6290 .indent_guides
6291 .get_or_insert_default()
6292 .active_line_width = value;
6293 })
6294 },
6295 }),
6296 metadata: None,
6297 files: USER | PROJECT,
6298 }),
6299 SettingsPageItem::SettingItem(SettingItem {
6300 title: "Coloring",
6301 description: "Determines how indent guides are colored.",
6302 field: Box::new(SettingField {
6303 json_path: Some("languages.$(language).indent_guides.coloring"),
6304 pick: |settings_content| {
6305 language_settings_field(settings_content, |language| {
6306 language
6307 .indent_guides
6308 .as_ref()
6309 .and_then(|indent_guides| indent_guides.coloring.as_ref())
6310 })
6311 },
6312 write: |settings_content, value| {
6313 language_settings_field_mut(settings_content, value, |language, value| {
6314 language.indent_guides.get_or_insert_default().coloring = value;
6315 })
6316 },
6317 }),
6318 metadata: None,
6319 files: USER | PROJECT,
6320 }),
6321 SettingsPageItem::SettingItem(SettingItem {
6322 title: "Background Coloring",
6323 description: "Determines how indent guide backgrounds are colored.",
6324 field: Box::new(SettingField {
6325 json_path: Some("languages.$(language).indent_guides.background_coloring"),
6326 pick: |settings_content| {
6327 language_settings_field(settings_content, |language| {
6328 language
6329 .indent_guides
6330 .as_ref()
6331 .and_then(|indent_guides| indent_guides.background_coloring.as_ref())
6332 })
6333 },
6334 write: |settings_content, value| {
6335 language_settings_field_mut(settings_content, value, |language, value| {
6336 language
6337 .indent_guides
6338 .get_or_insert_default()
6339 .background_coloring = value;
6340 })
6341 },
6342 }),
6343 metadata: None,
6344 files: USER | PROJECT,
6345 }),
6346 SettingsPageItem::SectionHeader("Formatting"),
6347 SettingsPageItem::SettingItem(SettingItem {
6348 title: "Format On Save",
6349 description: "Whether or not to perform a buffer format before saving.",
6350 field: Box::new(
6351 // TODO(settings_ui): this setting should just be a bool
6352 SettingField {
6353 json_path: Some("languages.$(language).format_on_save"),
6354 pick: |settings_content| {
6355 language_settings_field(settings_content, |language| {
6356 language.format_on_save.as_ref()
6357 })
6358 },
6359 write: |settings_content, value| {
6360 language_settings_field_mut(settings_content, value, |language, value| {
6361 language.format_on_save = value;
6362 })
6363 },
6364 },
6365 ),
6366 metadata: None,
6367 files: USER | PROJECT,
6368 }),
6369 SettingsPageItem::SettingItem(SettingItem {
6370 title: "Remove Trailing Whitespace On Save",
6371 description: "Whether or not to remove any trailing whitespace from lines of a buffer before saving it.",
6372 field: Box::new(SettingField {
6373 json_path: Some("languages.$(language).remove_trailing_whitespace_on_save"),
6374 pick: |settings_content| {
6375 language_settings_field(settings_content, |language| {
6376 language.remove_trailing_whitespace_on_save.as_ref()
6377 })
6378 },
6379 write: |settings_content, value| {
6380 language_settings_field_mut(settings_content, value, |language, value| {
6381 language.remove_trailing_whitespace_on_save = value;
6382 })
6383 },
6384 }),
6385 metadata: None,
6386 files: USER | PROJECT,
6387 }),
6388 SettingsPageItem::SettingItem(SettingItem {
6389 title: "Ensure Final Newline On Save",
6390 description: "Whether or not to ensure there's a single newline at the end of a buffer when saving it.",
6391 field: Box::new(SettingField {
6392 json_path: Some("languages.$(language).ensure_final_newline_on_save"),
6393 pick: |settings_content| {
6394 language_settings_field(settings_content, |language| {
6395 language.ensure_final_newline_on_save.as_ref()
6396 })
6397 },
6398 write: |settings_content, value| {
6399 language_settings_field_mut(settings_content, value, |language, value| {
6400 language.ensure_final_newline_on_save = value;
6401 })
6402 },
6403 }),
6404 metadata: None,
6405 files: USER | PROJECT,
6406 }),
6407 SettingsPageItem::SettingItem(SettingItem {
6408 title: "Formatter",
6409 description: "How to perform a buffer format.",
6410 field: Box::new(
6411 SettingField {
6412 json_path: Some("languages.$(language).formatter"),
6413 pick: |settings_content| {
6414 language_settings_field(settings_content, |language| {
6415 language.formatter.as_ref()
6416 })
6417 },
6418 write: |settings_content, value| {
6419 language_settings_field_mut(settings_content, value, |language, value| {
6420 language.formatter = value;
6421 })
6422 },
6423 }
6424 .unimplemented(),
6425 ),
6426 metadata: None,
6427 files: USER | PROJECT,
6428 }),
6429 SettingsPageItem::SettingItem(SettingItem {
6430 title: "Use On Type Format",
6431 description: "Whether to use additional LSP queries to format (and amend) the code after every \"trigger\" symbol input, defined by LSP server capabilities",
6432 field: Box::new(SettingField {
6433 json_path: Some("languages.$(language).use_on_type_format"),
6434 pick: |settings_content| {
6435 language_settings_field(settings_content, |language| {
6436 language.use_on_type_format.as_ref()
6437 })
6438 },
6439 write: |settings_content, value| {
6440 language_settings_field_mut(settings_content, value, |language, value| {
6441 language.use_on_type_format = value;
6442 })
6443 },
6444 }),
6445 metadata: None,
6446 files: USER | PROJECT,
6447 }),
6448 SettingsPageItem::SettingItem(SettingItem {
6449 title: "Code Actions On Format",
6450 description: "Additional code actions to run when formatting.",
6451 field: Box::new(
6452 SettingField {
6453 json_path: Some("languages.$(language).code_actions_on_format"),
6454 pick: |settings_content| {
6455 language_settings_field(settings_content, |language| {
6456 language.code_actions_on_format.as_ref()
6457 })
6458 },
6459 write: |settings_content, value| {
6460 language_settings_field_mut(settings_content, value, |language, value| {
6461 language.code_actions_on_format = value;
6462 })
6463 },
6464 }
6465 .unimplemented(),
6466 ),
6467 metadata: None,
6468 files: USER | PROJECT,
6469 }),
6470 SettingsPageItem::SectionHeader("Autoclose"),
6471 SettingsPageItem::SettingItem(SettingItem {
6472 title: "Use Autoclose",
6473 description: "Whether to automatically type closing characters for you. For example, when you type '(', Zed will automatically add a closing ')' at the correct position.",
6474 field: Box::new(SettingField {
6475 json_path: Some("languages.$(language).use_autoclose"),
6476 pick: |settings_content| {
6477 language_settings_field(settings_content, |language| {
6478 language.use_autoclose.as_ref()
6479 })
6480 },
6481 write: |settings_content, value| {
6482 language_settings_field_mut(settings_content, value, |language, value| {
6483 language.use_autoclose = value;
6484 })
6485 },
6486 }),
6487 metadata: None,
6488 files: USER | PROJECT,
6489 }),
6490 SettingsPageItem::SettingItem(SettingItem {
6491 title: "Use Auto Surround",
6492 description: "Whether to automatically surround text with characters for you. For example, when you select text and type '(', Zed will automatically surround text with ().",
6493 field: Box::new(SettingField {
6494 json_path: Some("languages.$(language).use_auto_surround"),
6495 pick: |settings_content| {
6496 language_settings_field(settings_content, |language| {
6497 language.use_auto_surround.as_ref()
6498 })
6499 },
6500 write: |settings_content, value| {
6501 language_settings_field_mut(settings_content, value, |language, value| {
6502 language.use_auto_surround = value;
6503 })
6504 },
6505 }),
6506 metadata: None,
6507 files: USER | PROJECT,
6508 }),
6509 SettingsPageItem::SettingItem(SettingItem {
6510 title: "Always Treat Brackets As Autoclosed",
6511 description: "Controls whether the closing characters are always skipped over and auto-removed no matter how they were inserted.",
6512 field: Box::new(SettingField {
6513 json_path: Some("languages.$(language).always_treat_brackets_as_autoclosed"),
6514 pick: |settings_content| {
6515 language_settings_field(settings_content, |language| {
6516 language.always_treat_brackets_as_autoclosed.as_ref()
6517 })
6518 },
6519 write: |settings_content, value| {
6520 language_settings_field_mut(settings_content, value, |language, value| {
6521 language.always_treat_brackets_as_autoclosed = value;
6522 })
6523 },
6524 }),
6525 metadata: None,
6526 files: USER | PROJECT,
6527 }),
6528 SettingsPageItem::SettingItem(SettingItem {
6529 title: "Jsx Tag Auto Close",
6530 description: "Whether to automatically close JSX tags.",
6531 field: Box::new(SettingField {
6532 json_path: Some("languages.$(language).jsx_tag_auto_close"),
6533 // TODO(settings_ui): this setting should just be a bool
6534 pick: |settings_content| {
6535 language_settings_field(settings_content, |language| {
6536 language.jsx_tag_auto_close.as_ref()?.enabled.as_ref()
6537 })
6538 },
6539 write: |settings_content, value| {
6540 language_settings_field_mut(settings_content, value, |language, value| {
6541 language.jsx_tag_auto_close.get_or_insert_default().enabled = value;
6542 })
6543 },
6544 }),
6545 metadata: None,
6546 files: USER | PROJECT,
6547 }),
6548 SettingsPageItem::SectionHeader("Whitespace"),
6549 SettingsPageItem::SettingItem(SettingItem {
6550 title: "Show Whitespaces",
6551 description: "Whether to show tabs and spaces in the editor.",
6552 field: Box::new(SettingField {
6553 json_path: Some("languages.$(language).show_whitespaces"),
6554 pick: |settings_content| {
6555 language_settings_field(settings_content, |language| {
6556 language.show_whitespaces.as_ref()
6557 })
6558 },
6559 write: |settings_content, value| {
6560 language_settings_field_mut(settings_content, value, |language, value| {
6561 language.show_whitespaces = value;
6562 })
6563 },
6564 }),
6565 metadata: None,
6566 files: USER | PROJECT,
6567 }),
6568 SettingsPageItem::SettingItem(SettingItem {
6569 title: "Space Whitespace Indicator",
6570 description: "Visible character used to render space characters when show_whitespaces is enabled (default: \"•\")",
6571 field: Box::new(
6572 SettingField {
6573 json_path: Some("languages.$(language).whitespace_map.space"),
6574 pick: |settings_content| {
6575 language_settings_field(settings_content, |language| {
6576 language.whitespace_map.as_ref()?.space.as_ref()
6577 })
6578 },
6579 write: |settings_content, value| {
6580 language_settings_field_mut(settings_content, value, |language, value| {
6581 language.whitespace_map.get_or_insert_default().space = value;
6582 })
6583 },
6584 }
6585 .unimplemented(),
6586 ),
6587 metadata: None,
6588 files: USER | PROJECT,
6589 }),
6590 SettingsPageItem::SettingItem(SettingItem {
6591 title: "Tab Whitespace Indicator",
6592 description: "Visible character used to render tab characters when show_whitespaces is enabled (default: \"→\")",
6593 field: Box::new(
6594 SettingField {
6595 json_path: Some("languages.$(language).whitespace_map.tab"),
6596 pick: |settings_content| {
6597 language_settings_field(settings_content, |language| {
6598 language.whitespace_map.as_ref()?.tab.as_ref()
6599 })
6600 },
6601 write: |settings_content, value| {
6602 language_settings_field_mut(settings_content, value, |language, value| {
6603 language.whitespace_map.get_or_insert_default().tab = value;
6604 })
6605 },
6606 }
6607 .unimplemented(),
6608 ),
6609 metadata: None,
6610 files: USER | PROJECT,
6611 }),
6612 SettingsPageItem::SectionHeader("Completions"),
6613 SettingsPageItem::SettingItem(SettingItem {
6614 title: "Show Completions On Input",
6615 description: "Whether to pop the completions menu while typing in an editor without explicitly requesting it.",
6616 field: Box::new(SettingField {
6617 json_path: Some("languages.$(language).show_completions_on_input"),
6618 pick: |settings_content| {
6619 language_settings_field(settings_content, |language| {
6620 language.show_completions_on_input.as_ref()
6621 })
6622 },
6623 write: |settings_content, value| {
6624 language_settings_field_mut(settings_content, value, |language, value| {
6625 language.show_completions_on_input = value;
6626 })
6627 },
6628 }),
6629 metadata: None,
6630 files: USER | PROJECT,
6631 }),
6632 SettingsPageItem::SettingItem(SettingItem {
6633 title: "Show Completion Documentation",
6634 description: "Whether to display inline and alongside documentation for items in the completions menu.",
6635 field: Box::new(SettingField {
6636 json_path: Some("languages.$(language).show_completion_documentation"),
6637 pick: |settings_content| {
6638 language_settings_field(settings_content, |language| {
6639 language.show_completion_documentation.as_ref()
6640 })
6641 },
6642 write: |settings_content, value| {
6643 language_settings_field_mut(settings_content, value, |language, value| {
6644 language.show_completion_documentation = value;
6645 })
6646 },
6647 }),
6648 metadata: None,
6649 files: USER | PROJECT,
6650 }),
6651 SettingsPageItem::SettingItem(SettingItem {
6652 title: "Words",
6653 description: "Controls how words are completed.",
6654 field: Box::new(SettingField {
6655 json_path: Some("languages.$(language).completions.words"),
6656 pick: |settings_content| {
6657 language_settings_field(settings_content, |language| {
6658 language.completions.as_ref()?.words.as_ref()
6659 })
6660 },
6661 write: |settings_content, value| {
6662 language_settings_field_mut(settings_content, value, |language, value| {
6663 language.completions.get_or_insert_default().words = value;
6664 })
6665 },
6666 }),
6667 metadata: None,
6668 files: USER | PROJECT,
6669 }),
6670 SettingsPageItem::SettingItem(SettingItem {
6671 title: "Words Min Length",
6672 description: "How many characters has to be in the completions query to automatically show the words-based completions.",
6673 field: Box::new(SettingField {
6674 json_path: Some("languages.$(language).completions.words_min_length"),
6675 pick: |settings_content| {
6676 language_settings_field(settings_content, |language| {
6677 language.completions.as_ref()?.words_min_length.as_ref()
6678 })
6679 },
6680 write: |settings_content, value| {
6681 language_settings_field_mut(settings_content, value, |language, value| {
6682 language
6683 .completions
6684 .get_or_insert_default()
6685 .words_min_length = value;
6686 })
6687 },
6688 }),
6689 metadata: None,
6690 files: USER | PROJECT,
6691 }),
6692 SettingsPageItem::SettingItem(SettingItem {
6693 title: "Completion Menu Scrollbar",
6694 description: "When to show the scrollbar in the completion menu.",
6695 field: Box::new(SettingField {
6696 json_path: Some("editor.completion_menu_scrollbar"),
6697 pick: |settings_content| settings_content.editor.completion_menu_scrollbar.as_ref(),
6698 write: |settings_content, value| {
6699 settings_content.editor.completion_menu_scrollbar = value;
6700 },
6701 }),
6702 metadata: None,
6703 files: USER,
6704 }),
6705 SettingsPageItem::SectionHeader("Inlay Hints"),
6706 SettingsPageItem::SettingItem(SettingItem {
6707 title: "Enabled",
6708 description: "Global switch to toggle hints on and off.",
6709 field: Box::new(SettingField {
6710 json_path: Some("languages.$(language).inlay_hints.enabled"),
6711 pick: |settings_content| {
6712 language_settings_field(settings_content, |language| {
6713 language.inlay_hints.as_ref()?.enabled.as_ref()
6714 })
6715 },
6716 write: |settings_content, value| {
6717 language_settings_field_mut(settings_content, value, |language, value| {
6718 language.inlay_hints.get_or_insert_default().enabled = value;
6719 })
6720 },
6721 }),
6722 metadata: None,
6723 files: USER | PROJECT,
6724 }),
6725 SettingsPageItem::SettingItem(SettingItem {
6726 title: "Show Value Hints",
6727 description: "Global switch to toggle inline values on and off when debugging.",
6728 field: Box::new(SettingField {
6729 json_path: Some("languages.$(language).inlay_hints.show_value_hints"),
6730 pick: |settings_content| {
6731 language_settings_field(settings_content, |language| {
6732 language.inlay_hints.as_ref()?.show_value_hints.as_ref()
6733 })
6734 },
6735 write: |settings_content, value| {
6736 language_settings_field_mut(settings_content, value, |language, value| {
6737 language
6738 .inlay_hints
6739 .get_or_insert_default()
6740 .show_value_hints = value;
6741 })
6742 },
6743 }),
6744 metadata: None,
6745 files: USER | PROJECT,
6746 }),
6747 SettingsPageItem::SettingItem(SettingItem {
6748 title: "Show Type Hints",
6749 description: "Whether type hints should be shown.",
6750 field: Box::new(SettingField {
6751 json_path: Some("languages.$(language).inlay_hints.show_type_hints"),
6752 pick: |settings_content| {
6753 language_settings_field(settings_content, |language| {
6754 language.inlay_hints.as_ref()?.show_type_hints.as_ref()
6755 })
6756 },
6757 write: |settings_content, value| {
6758 language_settings_field_mut(settings_content, value, |language, value| {
6759 language.inlay_hints.get_or_insert_default().show_type_hints = value;
6760 })
6761 },
6762 }),
6763 metadata: None,
6764 files: USER | PROJECT,
6765 }),
6766 SettingsPageItem::SettingItem(SettingItem {
6767 title: "Show Parameter Hints",
6768 description: "Whether parameter hints should be shown.",
6769 field: Box::new(SettingField {
6770 json_path: Some("languages.$(language).inlay_hints.show_parameter_hints"),
6771 pick: |settings_content| {
6772 language_settings_field(settings_content, |language| {
6773 language.inlay_hints.as_ref()?.show_parameter_hints.as_ref()
6774 })
6775 },
6776 write: |settings_content, value| {
6777 language_settings_field_mut(settings_content, value, |language, value| {
6778 language
6779 .inlay_hints
6780 .get_or_insert_default()
6781 .show_parameter_hints = value;
6782 })
6783 },
6784 }),
6785 metadata: None,
6786 files: USER | PROJECT,
6787 }),
6788 SettingsPageItem::SettingItem(SettingItem {
6789 title: "Show Other Hints",
6790 description: "Whether other hints should be shown.",
6791 field: Box::new(SettingField {
6792 json_path: Some("languages.$(language).inlay_hints.show_other_hints"),
6793 pick: |settings_content| {
6794 language_settings_field(settings_content, |language| {
6795 language.inlay_hints.as_ref()?.show_other_hints.as_ref()
6796 })
6797 },
6798 write: |settings_content, value| {
6799 language_settings_field_mut(settings_content, value, |language, value| {
6800 language
6801 .inlay_hints
6802 .get_or_insert_default()
6803 .show_other_hints = value;
6804 })
6805 },
6806 }),
6807 metadata: None,
6808 files: USER | PROJECT,
6809 }),
6810 SettingsPageItem::SettingItem(SettingItem {
6811 title: "Show Background",
6812 description: "Show a background for inlay hints.",
6813 field: Box::new(SettingField {
6814 json_path: Some("languages.$(language).inlay_hints.show_background"),
6815 pick: |settings_content| {
6816 language_settings_field(settings_content, |language| {
6817 language.inlay_hints.as_ref()?.show_background.as_ref()
6818 })
6819 },
6820 write: |settings_content, value| {
6821 language_settings_field_mut(settings_content, value, |language, value| {
6822 language.inlay_hints.get_or_insert_default().show_background = value;
6823 })
6824 },
6825 }),
6826 metadata: None,
6827 files: USER | PROJECT,
6828 }),
6829 SettingsPageItem::SettingItem(SettingItem {
6830 title: "Edit Debounce Ms",
6831 description: "Whether or not to debounce inlay hints updates after buffer edits (set to 0 to disable debouncing).",
6832 field: Box::new(SettingField {
6833 json_path: Some("languages.$(language).inlay_hints.edit_debounce_ms"),
6834 pick: |settings_content| {
6835 language_settings_field(settings_content, |language| {
6836 language.inlay_hints.as_ref()?.edit_debounce_ms.as_ref()
6837 })
6838 },
6839 write: |settings_content, value| {
6840 language_settings_field_mut(settings_content, value, |language, value| {
6841 language
6842 .inlay_hints
6843 .get_or_insert_default()
6844 .edit_debounce_ms = value;
6845 })
6846 },
6847 }),
6848 metadata: None,
6849 files: USER | PROJECT,
6850 }),
6851 SettingsPageItem::SettingItem(SettingItem {
6852 title: "Scroll Debounce Ms",
6853 description: "Whether or not to debounce inlay hints updates after buffer scrolls (set to 0 to disable debouncing).",
6854 field: Box::new(SettingField {
6855 json_path: Some("languages.$(language).inlay_hints.scroll_debounce_ms"),
6856 pick: |settings_content| {
6857 language_settings_field(settings_content, |language| {
6858 language.inlay_hints.as_ref()?.scroll_debounce_ms.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 .scroll_debounce_ms = value;
6867 })
6868 },
6869 }),
6870 metadata: None,
6871 files: USER | PROJECT,
6872 }),
6873 SettingsPageItem::SettingItem(SettingItem {
6874 title: "Toggle On Modifiers Press",
6875 description: "Toggles inlay hints (hides or shows) when the user presses the modifiers specified.",
6876 field: Box::new(
6877 SettingField {
6878 json_path: Some("languages.$(language).inlay_hints.toggle_on_modifiers_press"),
6879 pick: |settings_content| {
6880 language_settings_field(settings_content, |language| {
6881 language
6882 .inlay_hints
6883 .as_ref()?
6884 .toggle_on_modifiers_press
6885 .as_ref()
6886 })
6887 },
6888 write: |settings_content, value| {
6889 language_settings_field_mut(settings_content, value, |language, value| {
6890 language
6891 .inlay_hints
6892 .get_or_insert_default()
6893 .toggle_on_modifiers_press = value;
6894 })
6895 },
6896 }
6897 .unimplemented(),
6898 ),
6899 metadata: None,
6900 files: USER | PROJECT,
6901 }),
6902 ];
6903 if current_language().is_none() {
6904 items.push(SettingsPageItem::SettingItem(SettingItem {
6905 title: "LSP Document Colors",
6906 description: "How to render LSP color previews in the editor.",
6907 field: Box::new(SettingField {
6908 json_path: Some("lsp_document_colors"),
6909 pick: |settings_content| settings_content.editor.lsp_document_colors.as_ref(),
6910 write: |settings_content, value| {
6911 settings_content.editor.lsp_document_colors = value;
6912 },
6913 }),
6914 metadata: None,
6915 files: USER,
6916 }))
6917 }
6918 items.extend([
6919 SettingsPageItem::SectionHeader("Tasks"),
6920 SettingsPageItem::SettingItem(SettingItem {
6921 title: "Enabled",
6922 description: "Whether tasks are enabled for this language.",
6923 field: Box::new(SettingField {
6924 json_path: Some("languages.$(language).tasks.enabled"),
6925 pick: |settings_content| {
6926 language_settings_field(settings_content, |language| {
6927 language.tasks.as_ref()?.enabled.as_ref()
6928 })
6929 },
6930 write: |settings_content, value| {
6931 language_settings_field_mut(settings_content, value, |language, value| {
6932 language.tasks.get_or_insert_default().enabled = value;
6933
6934 })
6935 },
6936 }),
6937 metadata: None,
6938 files: USER | PROJECT,
6939 }),
6940 SettingsPageItem::SettingItem(SettingItem {
6941 title: "Variables",
6942 description: "Extra task variables to set for a particular language.",
6943 field: Box::new(
6944 SettingField {
6945 json_path: Some("languages.$(language).tasks.variables"),
6946 pick: |settings_content| {
6947 language_settings_field(settings_content, |language| {
6948 language.tasks.as_ref()?.variables.as_ref()
6949 })
6950 },
6951 write: |settings_content, value| {
6952 language_settings_field_mut(settings_content, value, |language, value| {
6953 language.tasks.get_or_insert_default().variables = value;
6954
6955 })
6956 },
6957 }
6958 .unimplemented(),
6959 ),
6960 metadata: None,
6961 files: USER | PROJECT,
6962 }),
6963 SettingsPageItem::SettingItem(SettingItem {
6964 title: "Prefer LSP",
6965 description: "Use LSP tasks over Zed language extension tasks.",
6966 field: Box::new(SettingField {
6967 json_path: Some("languages.$(language).tasks.prefer_lsp"),
6968 pick: |settings_content| {
6969 language_settings_field(settings_content, |language| {
6970 language.tasks.as_ref()?.prefer_lsp.as_ref()
6971 })
6972 },
6973 write: |settings_content, value| {
6974 language_settings_field_mut(settings_content, value, |language, value| {
6975 language.tasks.get_or_insert_default().prefer_lsp = value;
6976
6977 })
6978 },
6979 }),
6980 metadata: None,
6981 files: USER | PROJECT,
6982 }),
6983 SettingsPageItem::SectionHeader("Miscellaneous"),
6984 SettingsPageItem::SettingItem(SettingItem {
6985 title: "Debuggers",
6986 description: "Preferred debuggers for this language.",
6987 field: Box::new(
6988 SettingField {
6989 json_path: Some("languages.$(language).debuggers"),
6990 pick: |settings_content| {
6991 language_settings_field(settings_content, |language| language.debuggers.as_ref())
6992 },
6993 write: |settings_content, value| {
6994 language_settings_field_mut(settings_content, value, |language, value| {
6995 language.debuggers = value;
6996
6997 })
6998 },
6999 }
7000 .unimplemented(),
7001 ),
7002 metadata: None,
7003 files: USER | PROJECT,
7004 }),
7005 SettingsPageItem::SettingItem(SettingItem {
7006 title: "Middle Click Paste",
7007 description: "Enable middle-click paste on Linux.",
7008 field: Box::new(SettingField {
7009 json_path: Some("languages.$(language).editor.middle_click_paste"),
7010 pick: |settings_content| settings_content.editor.middle_click_paste.as_ref(),
7011 write: |settings_content, value| {settings_content.editor.middle_click_paste = value;},
7012 }),
7013 metadata: None,
7014 files: USER,
7015 }),
7016 SettingsPageItem::SettingItem(SettingItem {
7017 title: "Extend Comment On Newline",
7018 description: "Whether to start a new line with a comment when a previous line is a comment as well.",
7019 field: Box::new(SettingField {
7020 json_path: Some("languages.$(language).extend_comment_on_newline"),
7021 pick: |settings_content| {
7022 language_settings_field(settings_content, |language| {
7023 language.extend_comment_on_newline.as_ref()
7024 })
7025 },
7026 write: |settings_content, value| {
7027 language_settings_field_mut(settings_content, value, |language, value| {
7028 language.extend_comment_on_newline = value;
7029
7030 })
7031 },
7032 }),
7033 metadata: None,
7034 files: USER | PROJECT,
7035 }),
7036 SettingsPageItem::SettingItem(SettingItem {
7037 title: "Colorize brackets",
7038 description: "Whether to colorize brackets in the editor.",
7039 field: Box::new(SettingField {
7040 json_path: Some("languages.$(language).colorize_brackets"),
7041 pick: |settings_content| {
7042 language_settings_field(settings_content, |language| {
7043 language.colorize_brackets.as_ref()
7044 })
7045 },
7046 write: |settings_content, value| {
7047 language_settings_field_mut(settings_content, value, |language, value| {
7048 language.colorize_brackets = value;
7049 })
7050 },
7051 }),
7052 metadata: None,
7053 files: USER | PROJECT,
7054 }),
7055 ]);
7056
7057 if current_language().is_none() {
7058 items.extend([
7059 SettingsPageItem::SettingItem(SettingItem {
7060 title: "Image Viewer",
7061 description: "The unit for image file sizes.",
7062 field: Box::new(SettingField {
7063 json_path: Some("image_viewer.unit"),
7064 pick: |settings_content| {
7065 settings_content.image_viewer.as_ref().and_then(|image_viewer| image_viewer.unit.as_ref())
7066 },
7067 write: |settings_content, value| {
7068 settings_content.image_viewer.get_or_insert_default().unit = value;
7069
7070 },
7071 }),
7072 metadata: None,
7073 files: USER,
7074 }),
7075 SettingsPageItem::SettingItem(SettingItem {
7076 title: "Auto Replace Emoji Shortcode",
7077 description: "Whether to automatically replace emoji shortcodes with emoji characters.",
7078 field: Box::new(SettingField {
7079 json_path: Some("message_editor.auto_replace_emoji_shortcode"),
7080 pick: |settings_content| {
7081 settings_content.message_editor.as_ref().and_then(|message_editor| message_editor.auto_replace_emoji_shortcode.as_ref())
7082 },
7083 write: |settings_content, value| {
7084 settings_content.message_editor.get_or_insert_default().auto_replace_emoji_shortcode = value;
7085
7086 },
7087 }),
7088 metadata: None,
7089 files: USER,
7090 }),
7091 SettingsPageItem::SettingItem(SettingItem {
7092 title: "Drop Size Target",
7093 description: "Relative size of the drop target in the editor that will open dropped file as a split pane.",
7094 field: Box::new(SettingField {
7095 json_path: Some("drop_target_size"),
7096 pick: |settings_content| {
7097 settings_content.workspace.drop_target_size.as_ref()
7098 },
7099 write: |settings_content, value| {
7100 settings_content.workspace.drop_target_size = value;
7101
7102 },
7103 }),
7104 metadata: None,
7105 files: USER,
7106 }),
7107 ]);
7108 }
7109 items
7110}
7111
7112/// LanguageSettings items that should be included in the "Languages & Tools" page
7113/// not the "Editor" page
7114fn non_editor_language_settings_data() -> Vec<SettingsPageItem> {
7115 vec![
7116 SettingsPageItem::SectionHeader("LSP"),
7117 SettingsPageItem::SettingItem(SettingItem {
7118 title: "Enable Language Server",
7119 description: "Whether to use language servers to provide code intelligence.",
7120 field: Box::new(SettingField {
7121 json_path: Some("languages.$(language).enable_language_server"),
7122 pick: |settings_content| {
7123 language_settings_field(settings_content, |language| {
7124 language.enable_language_server.as_ref()
7125 })
7126 },
7127 write: |settings_content, value| {
7128 language_settings_field_mut(settings_content, value, |language, value| {
7129 language.enable_language_server = value;
7130 })
7131 },
7132 }),
7133 metadata: None,
7134 files: USER | PROJECT,
7135 }),
7136 SettingsPageItem::SettingItem(SettingItem {
7137 title: "Language Servers",
7138 description: "The list of language servers to use (or disable) for this language.",
7139 field: Box::new(
7140 SettingField {
7141 json_path: Some("languages.$(language).language_servers"),
7142 pick: |settings_content| {
7143 language_settings_field(settings_content, |language| {
7144 language.language_servers.as_ref()
7145 })
7146 },
7147 write: |settings_content, value| {
7148 language_settings_field_mut(settings_content, value, |language, value| {
7149 language.language_servers = value;
7150 })
7151 },
7152 }
7153 .unimplemented(),
7154 ),
7155 metadata: None,
7156 files: USER | PROJECT,
7157 }),
7158 SettingsPageItem::SettingItem(SettingItem {
7159 title: "Linked Edits",
7160 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.",
7161 field: Box::new(SettingField {
7162 json_path: Some("languages.$(language).linked_edits"),
7163 pick: |settings_content| {
7164 language_settings_field(settings_content, |language| {
7165 language.linked_edits.as_ref()
7166 })
7167 },
7168 write: |settings_content, value| {
7169 language_settings_field_mut(settings_content, value, |language, value| {
7170 language.linked_edits = value;
7171 })
7172 },
7173 }),
7174 metadata: None,
7175 files: USER | PROJECT,
7176 }),
7177 SettingsPageItem::SettingItem(SettingItem {
7178 title: "Go To Definition Fallback",
7179 description: "Whether to follow-up empty Go to definition responses from the language server.",
7180 field: Box::new(SettingField {
7181 json_path: Some("go_to_definition_fallback"),
7182 pick: |settings_content| settings_content.editor.go_to_definition_fallback.as_ref(),
7183 write: |settings_content, value| {
7184 settings_content.editor.go_to_definition_fallback = value;
7185 },
7186 }),
7187 metadata: None,
7188 files: USER,
7189 }),
7190 SettingsPageItem::SectionHeader("LSP Completions"),
7191 SettingsPageItem::SettingItem(SettingItem {
7192 title: "Enabled",
7193 description: "Whether to fetch LSP completions or not.",
7194 field: Box::new(SettingField {
7195 json_path: Some("languages.$(language).completions.lsp"),
7196 pick: |settings_content| {
7197 language_settings_field(settings_content, |language| {
7198 language.completions.as_ref()?.lsp.as_ref()
7199 })
7200 },
7201 write: |settings_content, value| {
7202 language_settings_field_mut(settings_content, value, |language, value| {
7203 language.completions.get_or_insert_default().lsp = value;
7204 })
7205 },
7206 }),
7207 metadata: None,
7208 files: USER | PROJECT,
7209 }),
7210 SettingsPageItem::SettingItem(SettingItem {
7211 title: "Fetch Timeout (milliseconds)",
7212 description: "When fetching LSP completions, determines how long to wait for a response of a particular server (set to 0 to wait indefinitely).",
7213 field: Box::new(SettingField {
7214 json_path: Some("languages.$(language).completions.lsp_fetch_timeout_ms"),
7215 pick: |settings_content| {
7216 language_settings_field(settings_content, |language| {
7217 language.completions.as_ref()?.lsp_fetch_timeout_ms.as_ref()
7218 })
7219 },
7220 write: |settings_content, value| {
7221 language_settings_field_mut(settings_content, value, |language, value| {
7222 language
7223 .completions
7224 .get_or_insert_default()
7225 .lsp_fetch_timeout_ms = value;
7226 })
7227 },
7228 }),
7229 metadata: None,
7230 files: USER | PROJECT,
7231 }),
7232 SettingsPageItem::SettingItem(SettingItem {
7233 title: "Insert Mode",
7234 description: "Controls how LSP completions are inserted.",
7235 field: Box::new(SettingField {
7236 json_path: Some("languages.$(language).completions.lsp_insert_mode"),
7237 pick: |settings_content| {
7238 language_settings_field(settings_content, |language| {
7239 language.completions.as_ref()?.lsp_insert_mode.as_ref()
7240 })
7241 },
7242 write: |settings_content, value| {
7243 language_settings_field_mut(settings_content, value, |language, value| {
7244 language.completions.get_or_insert_default().lsp_insert_mode = value;
7245 })
7246 },
7247 }),
7248 metadata: None,
7249 files: USER | PROJECT,
7250 }),
7251 SettingsPageItem::SectionHeader("Debuggers"),
7252 SettingsPageItem::SettingItem(SettingItem {
7253 title: "Debuggers",
7254 description: "Preferred debuggers for this language.",
7255 field: Box::new(
7256 SettingField {
7257 json_path: Some("languages.$(language).debuggers"),
7258 pick: |settings_content| {
7259 language_settings_field(settings_content, |language| {
7260 language.debuggers.as_ref()
7261 })
7262 },
7263 write: |settings_content, value| {
7264 language_settings_field_mut(settings_content, value, |language, value| {
7265 language.debuggers = value;
7266 })
7267 },
7268 }
7269 .unimplemented(),
7270 ),
7271 metadata: None,
7272 files: USER | PROJECT,
7273 }),
7274 SettingsPageItem::SectionHeader("Prettier"),
7275 SettingsPageItem::SettingItem(SettingItem {
7276 title: "Allowed",
7277 description: "Enables or disables formatting with Prettier for a given language.",
7278 field: Box::new(SettingField {
7279 json_path: Some("languages.$(language).prettier.allowed"),
7280 pick: |settings_content| {
7281 language_settings_field(settings_content, |language| {
7282 language.prettier.as_ref()?.allowed.as_ref()
7283 })
7284 },
7285 write: |settings_content, value| {
7286 language_settings_field_mut(settings_content, value, |language, value| {
7287 language.prettier.get_or_insert_default().allowed = value;
7288 })
7289 },
7290 }),
7291 metadata: None,
7292 files: USER | PROJECT,
7293 }),
7294 SettingsPageItem::SettingItem(SettingItem {
7295 title: "Parser",
7296 description: "Forces Prettier integration to use a specific parser name when formatting files with the language.",
7297 field: Box::new(SettingField {
7298 json_path: Some("languages.$(language).prettier.parser"),
7299 pick: |settings_content| {
7300 language_settings_field(settings_content, |language| {
7301 language.prettier.as_ref()?.parser.as_ref()
7302 })
7303 },
7304 write: |settings_content, value| {
7305 language_settings_field_mut(settings_content, value, |language, value| {
7306 language.prettier.get_or_insert_default().parser = value;
7307 })
7308 },
7309 }),
7310 metadata: None,
7311 files: USER | PROJECT,
7312 }),
7313 SettingsPageItem::SettingItem(SettingItem {
7314 title: "Plugins",
7315 description: "Forces Prettier integration to use specific plugins when formatting files with the language.",
7316 field: Box::new(
7317 SettingField {
7318 json_path: Some("languages.$(language).prettier.plugins"),
7319 pick: |settings_content| {
7320 language_settings_field(settings_content, |language| {
7321 language.prettier.as_ref()?.plugins.as_ref()
7322 })
7323 },
7324 write: |settings_content, value| {
7325 language_settings_field_mut(settings_content, value, |language, value| {
7326 language.prettier.get_or_insert_default().plugins = value;
7327 })
7328 },
7329 }
7330 .unimplemented(),
7331 ),
7332 metadata: None,
7333 files: USER | PROJECT,
7334 }),
7335 SettingsPageItem::SettingItem(SettingItem {
7336 title: "Options",
7337 description: "Default Prettier options, in the format as in package.json section for Prettier.",
7338 field: Box::new(
7339 SettingField {
7340 json_path: Some("languages.$(language).prettier.options"),
7341 pick: |settings_content| {
7342 language_settings_field(settings_content, |language| {
7343 language.prettier.as_ref()?.options.as_ref()
7344 })
7345 },
7346 write: |settings_content, value| {
7347 language_settings_field_mut(settings_content, value, |language, value| {
7348 language.prettier.get_or_insert_default().options = value;
7349 })
7350 },
7351 }
7352 .unimplemented(),
7353 ),
7354 metadata: None,
7355 files: USER | PROJECT,
7356 }),
7357 ]
7358}
7359
7360fn edit_prediction_language_settings_section() -> Vec<SettingsPageItem> {
7361 vec![
7362 SettingsPageItem::SectionHeader("Edit Predictions"),
7363 SettingsPageItem::SettingItem(SettingItem {
7364 title: "Show Edit Predictions",
7365 description: "Controls whether edit predictions are shown immediately or manually by triggering `editor::showeditprediction` (false).",
7366 field: Box::new(SettingField {
7367 json_path: Some("languages.$(language).show_edit_predictions"),
7368 pick: |settings_content| {
7369 language_settings_field(settings_content, |language| {
7370 language.show_edit_predictions.as_ref()
7371 })
7372 },
7373 write: |settings_content, value| {
7374 language_settings_field_mut(settings_content, value, |language, value| {
7375 language.show_edit_predictions = value;
7376 })
7377 },
7378 }),
7379 metadata: None,
7380 files: USER | PROJECT,
7381 }),
7382 SettingsPageItem::SettingItem(SettingItem {
7383 title: "Edit Predictions Disabled In",
7384 description: "Controls whether edit predictions are shown in the given language scopes.",
7385 field: Box::new(
7386 SettingField {
7387 json_path: Some("languages.$(language).edit_predictions_disabled_in"),
7388 pick: |settings_content| {
7389 language_settings_field(settings_content, |language| {
7390 language.edit_predictions_disabled_in.as_ref()
7391 })
7392 },
7393 write: |settings_content, value| {
7394 language_settings_field_mut(settings_content, value, |language, value| {
7395 language.edit_predictions_disabled_in = value;
7396 })
7397 },
7398 }
7399 .unimplemented(),
7400 ),
7401 metadata: None,
7402 files: USER | PROJECT,
7403 }),
7404 ]
7405}
7406
7407fn show_scrollbar_or_editor(
7408 settings_content: &SettingsContent,
7409 show: fn(&SettingsContent) -> Option<&settings::ShowScrollbar>,
7410) -> Option<&settings::ShowScrollbar> {
7411 show(settings_content).or(settings_content
7412 .editor
7413 .scrollbar
7414 .as_ref()
7415 .and_then(|scrollbar| scrollbar.show.as_ref()))
7416}
7417
7418fn dynamic_variants<T>() -> &'static [T::Discriminant]
7419where
7420 T: strum::IntoDiscriminant,
7421 T::Discriminant: strum::VariantArray,
7422{
7423 <<T as strum::IntoDiscriminant>::Discriminant as strum::VariantArray>::VARIANTS
7424}