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