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