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