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