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