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