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