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