page_data.rs

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