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 Gutter"),
5523                SettingsPageItem::SettingItem(SettingItem {
5524                    title: "Visibility",
5525                    description: "Control whether Git status is shown in the editor's gutter.",
5526                    field: Box::new(SettingField {
5527                        json_path: Some("git.git_gutter"),
5528                        pick: |settings_content| settings_content.git.as_ref()?.git_gutter.as_ref(),
5529                        write: |settings_content, value| {
5530                            settings_content.git.get_or_insert_default().git_gutter = value;
5531                        },
5532                    }),
5533                    metadata: None,
5534                    files: USER,
5535                }),
5536                // todo(settings_ui): Figure out the right default for this value in default.json
5537                SettingsPageItem::SettingItem(SettingItem {
5538                    title: "Debounce",
5539                    description: "Debounce threshold in milliseconds after which changes are reflected in the Git gutter.",
5540                    field: Box::new(SettingField {
5541                        json_path: Some("git.gutter_debounce"),
5542                        pick: |settings_content| {
5543                            settings_content.git.as_ref()?.gutter_debounce.as_ref()
5544                        },
5545                        write: |settings_content, value| {
5546                            settings_content.git.get_or_insert_default().gutter_debounce = value;
5547                        },
5548                    }),
5549                    metadata: None,
5550                    files: USER,
5551                }),
5552                SettingsPageItem::SectionHeader("Inline Git Blame"),
5553                SettingsPageItem::SettingItem(SettingItem {
5554                    title: "Enabled",
5555                    description: "Whether or not to show Git blame data inline in the currently focused line.",
5556                    field: Box::new(SettingField {
5557                        json_path: Some("git.inline_blame.enabled"),
5558                        pick: |settings_content| {
5559                            settings_content
5560                                .git
5561                                .as_ref()?
5562                                .inline_blame
5563                                .as_ref()?
5564                                .enabled
5565                                .as_ref()
5566                        },
5567                        write: |settings_content, value| {
5568                            settings_content
5569                                .git
5570                                .get_or_insert_default()
5571                                .inline_blame
5572                                .get_or_insert_default()
5573                                .enabled = value;
5574                        },
5575                    }),
5576                    metadata: None,
5577                    files: USER,
5578                }),
5579                SettingsPageItem::SettingItem(SettingItem {
5580                    title: "Delay",
5581                    description: "The delay after which the inline blame information is shown.",
5582                    field: Box::new(SettingField {
5583                        json_path: Some("git.inline_blame.delay_ms"),
5584                        pick: |settings_content| {
5585                            settings_content
5586                                .git
5587                                .as_ref()?
5588                                .inline_blame
5589                                .as_ref()?
5590                                .delay_ms
5591                                .as_ref()
5592                        },
5593                        write: |settings_content, value| {
5594                            settings_content
5595                                .git
5596                                .get_or_insert_default()
5597                                .inline_blame
5598                                .get_or_insert_default()
5599                                .delay_ms = value;
5600                        },
5601                    }),
5602                    metadata: None,
5603                    files: USER,
5604                }),
5605                SettingsPageItem::SettingItem(SettingItem {
5606                    title: "Padding",
5607                    description: "Padding between the end of the source line and the start of the inline blame in columns.",
5608                    field: Box::new(SettingField {
5609                        json_path: Some("git.inline_blame.padding"),
5610                        pick: |settings_content| {
5611                            settings_content
5612                                .git
5613                                .as_ref()?
5614                                .inline_blame
5615                                .as_ref()?
5616                                .padding
5617                                .as_ref()
5618                        },
5619                        write: |settings_content, value| {
5620                            settings_content
5621                                .git
5622                                .get_or_insert_default()
5623                                .inline_blame
5624                                .get_or_insert_default()
5625                                .padding = value;
5626                        },
5627                    }),
5628                    metadata: None,
5629                    files: USER,
5630                }),
5631                SettingsPageItem::SettingItem(SettingItem {
5632                    title: "Minimum Column",
5633                    description: "The minimum column number at which to show the inline blame information.",
5634                    field: Box::new(SettingField {
5635                        json_path: Some("git.inline_blame.min_column"),
5636                        pick: |settings_content| {
5637                            settings_content
5638                                .git
5639                                .as_ref()?
5640                                .inline_blame
5641                                .as_ref()?
5642                                .min_column
5643                                .as_ref()
5644                        },
5645                        write: |settings_content, value| {
5646                            settings_content
5647                                .git
5648                                .get_or_insert_default()
5649                                .inline_blame
5650                                .get_or_insert_default()
5651                                .min_column = value;
5652                        },
5653                    }),
5654                    metadata: None,
5655                    files: USER,
5656                }),
5657                SettingsPageItem::SettingItem(SettingItem {
5658                    title: "Show Commit Summary",
5659                    description: "Show commit summary as part of the inline blame.",
5660                    field: Box::new(SettingField {
5661                        json_path: Some("git.inline_blame.show_commit_summary"),
5662                        pick: |settings_content| {
5663                            settings_content
5664                                .git
5665                                .as_ref()?
5666                                .inline_blame
5667                                .as_ref()?
5668                                .show_commit_summary
5669                                .as_ref()
5670                        },
5671                        write: |settings_content, value| {
5672                            settings_content
5673                                .git
5674                                .get_or_insert_default()
5675                                .inline_blame
5676                                .get_or_insert_default()
5677                                .show_commit_summary = value;
5678                        },
5679                    }),
5680                    metadata: None,
5681                    files: USER,
5682                }),
5683                SettingsPageItem::SectionHeader("Git Blame View"),
5684                SettingsPageItem::SettingItem(SettingItem {
5685                    title: "Show Avatar",
5686                    description: "Show the avatar of the author of the commit.",
5687                    field: Box::new(SettingField {
5688                        json_path: Some("git.blame.show_avatar"),
5689                        pick: |settings_content| {
5690                            settings_content
5691                                .git
5692                                .as_ref()?
5693                                .blame
5694                                .as_ref()?
5695                                .show_avatar
5696                                .as_ref()
5697                        },
5698                        write: |settings_content, value| {
5699                            settings_content
5700                                .git
5701                                .get_or_insert_default()
5702                                .blame
5703                                .get_or_insert_default()
5704                                .show_avatar = value;
5705                        },
5706                    }),
5707                    metadata: None,
5708                    files: USER,
5709                }),
5710                SettingsPageItem::SectionHeader("Branch Picker"),
5711                SettingsPageItem::SettingItem(SettingItem {
5712                    title: "Show Author Name",
5713                    description: "Show author name as part of the commit information in branch picker.",
5714                    field: Box::new(SettingField {
5715                        json_path: Some("git.branch_picker.show_author_name"),
5716                        pick: |settings_content| {
5717                            settings_content
5718                                .git
5719                                .as_ref()?
5720                                .branch_picker
5721                                .as_ref()?
5722                                .show_author_name
5723                                .as_ref()
5724                        },
5725                        write: |settings_content, value| {
5726                            settings_content
5727                                .git
5728                                .get_or_insert_default()
5729                                .branch_picker
5730                                .get_or_insert_default()
5731                                .show_author_name = value;
5732                        },
5733                    }),
5734                    metadata: None,
5735                    files: USER,
5736                }),
5737                SettingsPageItem::SectionHeader("Git Hunks"),
5738                SettingsPageItem::SettingItem(SettingItem {
5739                    title: "Hunk Style",
5740                    description: "How Git hunks are displayed visually in the editor.",
5741                    field: Box::new(SettingField {
5742                        json_path: Some("git.hunk_style"),
5743                        pick: |settings_content| settings_content.git.as_ref()?.hunk_style.as_ref(),
5744                        write: |settings_content, value| {
5745                            settings_content.git.get_or_insert_default().hunk_style = value;
5746                        },
5747                    }),
5748                    metadata: None,
5749                    files: USER,
5750                }),
5751                SettingsPageItem::SettingItem(SettingItem {
5752                    title: "Path Style",
5753                    description: "Should the name or path be displayed first in the git view.",
5754                    field: Box::new(SettingField {
5755                        json_path: Some("git.path_style"),
5756                        pick: |settings_content| settings_content.git.as_ref()?.path_style.as_ref(),
5757                        write: |settings_content, value| {
5758                            settings_content.git.get_or_insert_default().path_style = value;
5759                        },
5760                    }),
5761                    metadata: None,
5762                    files: USER,
5763                }),
5764            ],
5765        },
5766        SettingsPage {
5767            title: "Collaboration",
5768            items: vec![
5769                SettingsPageItem::SectionHeader("Calls"),
5770                SettingsPageItem::SettingItem(SettingItem {
5771                    title: "Mute On Join",
5772                    description: "Whether the microphone should be muted when joining a channel or a call.",
5773                    field: Box::new(SettingField {
5774                        json_path: Some("calls.mute_on_join"),
5775                        pick: |settings_content| {
5776                            settings_content.calls.as_ref()?.mute_on_join.as_ref()
5777                        },
5778                        write: |settings_content, value| {
5779                            settings_content.calls.get_or_insert_default().mute_on_join = value;
5780                        },
5781                    }),
5782                    metadata: None,
5783                    files: USER,
5784                }),
5785                SettingsPageItem::SettingItem(SettingItem {
5786                    title: "Share On Join",
5787                    description: "Whether your current project should be shared when joining an empty channel.",
5788                    field: Box::new(SettingField {
5789                        json_path: Some("calls.share_on_join"),
5790                        pick: |settings_content| {
5791                            settings_content.calls.as_ref()?.share_on_join.as_ref()
5792                        },
5793                        write: |settings_content, value| {
5794                            settings_content.calls.get_or_insert_default().share_on_join = value;
5795                        },
5796                    }),
5797                    metadata: None,
5798                    files: USER,
5799                }),
5800                SettingsPageItem::SectionHeader("Experimental"),
5801                SettingsPageItem::SettingItem(SettingItem {
5802                    title: "Rodio Audio",
5803                    description: "Opt into the new audio system.",
5804                    field: Box::new(SettingField {
5805                        json_path: Some("audio.experimental.rodio_audio"),
5806                        pick: |settings_content| {
5807                            settings_content.audio.as_ref()?.rodio_audio.as_ref()
5808                        },
5809                        write: |settings_content, value| {
5810                            settings_content.audio.get_or_insert_default().rodio_audio = value;
5811                        },
5812                    }),
5813                    metadata: None,
5814                    files: USER,
5815                }),
5816                SettingsPageItem::SettingItem(SettingItem {
5817                    title: "Auto Microphone Volume",
5818                    description: "Automatically adjust microphone volume (requires rodio audio).",
5819                    field: Box::new(SettingField {
5820                        json_path: Some("audio.experimental.auto_microphone_volume"),
5821                        pick: |settings_content| {
5822                            settings_content
5823                                .audio
5824                                .as_ref()?
5825                                .auto_microphone_volume
5826                                .as_ref()
5827                        },
5828                        write: |settings_content, value| {
5829                            settings_content
5830                                .audio
5831                                .get_or_insert_default()
5832                                .auto_microphone_volume = value;
5833                        },
5834                    }),
5835                    metadata: None,
5836                    files: USER,
5837                }),
5838                SettingsPageItem::SettingItem(SettingItem {
5839                    title: "Auto Speaker Volume",
5840                    description: "Automatically adjust volume of other call members (requires rodio audio).",
5841                    field: Box::new(SettingField {
5842                        json_path: Some("audio.experimental.auto_speaker_volume"),
5843                        pick: |settings_content| {
5844                            settings_content
5845                                .audio
5846                                .as_ref()?
5847                                .auto_speaker_volume
5848                                .as_ref()
5849                        },
5850                        write: |settings_content, value| {
5851                            settings_content
5852                                .audio
5853                                .get_or_insert_default()
5854                                .auto_speaker_volume = value;
5855                        },
5856                    }),
5857                    metadata: None,
5858                    files: USER,
5859                }),
5860                SettingsPageItem::SettingItem(SettingItem {
5861                    title: "Denoise",
5862                    description: "Remove background noises (requires rodio audio).",
5863                    field: Box::new(SettingField {
5864                        json_path: Some("audio.experimental.denoise"),
5865                        pick: |settings_content| settings_content.audio.as_ref()?.denoise.as_ref(),
5866                        write: |settings_content, value| {
5867                            settings_content.audio.get_or_insert_default().denoise = value;
5868                        },
5869                    }),
5870                    metadata: None,
5871                    files: USER,
5872                }),
5873                SettingsPageItem::SettingItem(SettingItem {
5874                    title: "Legacy Audio Compatible",
5875                    description: "Use audio parameters compatible with previous versions (requires rodio audio).",
5876                    field: Box::new(SettingField {
5877                        json_path: Some("audio.experimental.legacy_audio_compatible"),
5878                        pick: |settings_content| {
5879                            settings_content
5880                                .audio
5881                                .as_ref()?
5882                                .legacy_audio_compatible
5883                                .as_ref()
5884                        },
5885                        write: |settings_content, value| {
5886                            settings_content
5887                                .audio
5888                                .get_or_insert_default()
5889                                .legacy_audio_compatible = value;
5890                        },
5891                    }),
5892                    metadata: None,
5893                    files: USER,
5894                }),
5895            ],
5896        },
5897        SettingsPage {
5898            title: "AI",
5899            items: {
5900                let mut items = vec![
5901                    SettingsPageItem::SectionHeader("General"),
5902                    SettingsPageItem::SettingItem(SettingItem {
5903                        title: "Disable AI",
5904                        description: "Whether to disable all AI features in Zed.",
5905                        field: Box::new(SettingField {
5906                            json_path: Some("disable_ai"),
5907                            pick: |settings_content| settings_content.disable_ai.as_ref(),
5908                            write: |settings_content, value| {
5909                                settings_content.disable_ai = value;
5910                            },
5911                        }),
5912                        metadata: None,
5913                        files: USER,
5914                    }),
5915                    SettingsPageItem::SectionHeader("Agent Configuration"),
5916                    SettingsPageItem::SettingItem(SettingItem {
5917                        title: "Always Allow Tool Actions",
5918                        description: "When enabled, the agent can run potentially destructive actions without asking for your confirmation. This setting has no effect on external agents.",
5919                        field: Box::new(SettingField {
5920                            json_path: Some("agent.always_allow_tool_actions"),
5921                            pick: |settings_content| {
5922                                settings_content
5923                                    .agent
5924                                    .as_ref()?
5925                                    .always_allow_tool_actions
5926                                    .as_ref()
5927                            },
5928                            write: |settings_content, value| {
5929                                settings_content
5930                                    .agent
5931                                    .get_or_insert_default()
5932                                    .always_allow_tool_actions = value;
5933                            },
5934                        }),
5935                        metadata: None,
5936                        files: USER,
5937                    }),
5938                    SettingsPageItem::SettingItem(SettingItem {
5939                        title: "Single File Review",
5940                        description: "When enabled, agent edits will also be displayed in single-file buffers for review.",
5941                        field: Box::new(SettingField {
5942                            json_path: Some("agent.single_file_review"),
5943                            pick: |settings_content| {
5944                                settings_content.agent.as_ref()?.single_file_review.as_ref()
5945                            },
5946                            write: |settings_content, value| {
5947                                settings_content
5948                                    .agent
5949                                    .get_or_insert_default()
5950                                    .single_file_review = value;
5951                            },
5952                        }),
5953                        metadata: None,
5954                        files: USER,
5955                    }),
5956                    SettingsPageItem::SettingItem(SettingItem {
5957                        title: "Enable Feedback",
5958                        description: "Show voting thumbs up/down icon buttons for feedback on agent edits.",
5959                        field: Box::new(SettingField {
5960                            json_path: Some("agent.enable_feedback"),
5961                            pick: |settings_content| {
5962                                settings_content.agent.as_ref()?.enable_feedback.as_ref()
5963                            },
5964                            write: |settings_content, value| {
5965                                settings_content
5966                                    .agent
5967                                    .get_or_insert_default()
5968                                    .enable_feedback = value;
5969                            },
5970                        }),
5971                        metadata: None,
5972                        files: USER,
5973                    }),
5974                    SettingsPageItem::SettingItem(SettingItem {
5975                        title: "Notify When Agent Waiting",
5976                        description: "Where to show notifications when the agent has completed its response or needs confirmation before running a tool action.",
5977                        field: Box::new(SettingField {
5978                            json_path: Some("agent.notify_when_agent_waiting"),
5979                            pick: |settings_content| {
5980                                settings_content
5981                                    .agent
5982                                    .as_ref()?
5983                                    .notify_when_agent_waiting
5984                                    .as_ref()
5985                            },
5986                            write: |settings_content, value| {
5987                                settings_content
5988                                    .agent
5989                                    .get_or_insert_default()
5990                                    .notify_when_agent_waiting = value;
5991                            },
5992                        }),
5993                        metadata: None,
5994                        files: USER,
5995                    }),
5996                    SettingsPageItem::SettingItem(SettingItem {
5997                        title: "Play Sound When Agent Done",
5998                        description: "Whether to play a sound when the agent has either completed its response, or needs user input.",
5999                        field: Box::new(SettingField {
6000                            json_path: Some("agent.play_sound_when_agent_done"),
6001                            pick: |settings_content| {
6002                                settings_content
6003                                    .agent
6004                                    .as_ref()?
6005                                    .play_sound_when_agent_done
6006                                    .as_ref()
6007                            },
6008                            write: |settings_content, value| {
6009                                settings_content
6010                                    .agent
6011                                    .get_or_insert_default()
6012                                    .play_sound_when_agent_done = value;
6013                            },
6014                        }),
6015                        metadata: None,
6016                        files: USER,
6017                    }),
6018                    SettingsPageItem::SettingItem(SettingItem {
6019                        title: "Expand Edit Card",
6020                        description: "Whether to have edit cards in the agent panel expanded, showing a Preview of the diff.",
6021                        field: Box::new(SettingField {
6022                            json_path: Some("agent.expand_edit_card"),
6023                            pick: |settings_content| {
6024                                settings_content.agent.as_ref()?.expand_edit_card.as_ref()
6025                            },
6026                            write: |settings_content, value| {
6027                                settings_content
6028                                    .agent
6029                                    .get_or_insert_default()
6030                                    .expand_edit_card = value;
6031                            },
6032                        }),
6033                        metadata: None,
6034                        files: USER,
6035                    }),
6036                    SettingsPageItem::SettingItem(SettingItem {
6037                        title: "Expand Terminal Card",
6038                        description: "Whether to have terminal cards in the agent panel expanded, showing the whole command output.",
6039                        field: Box::new(SettingField {
6040                            json_path: Some("agent.expand_terminal_card"),
6041                            pick: |settings_content| {
6042                                settings_content
6043                                    .agent
6044                                    .as_ref()?
6045                                    .expand_terminal_card
6046                                    .as_ref()
6047                            },
6048                            write: |settings_content, value| {
6049                                settings_content
6050                                    .agent
6051                                    .get_or_insert_default()
6052                                    .expand_terminal_card = value;
6053                            },
6054                        }),
6055                        metadata: None,
6056                        files: USER,
6057                    }),
6058                    SettingsPageItem::SettingItem(SettingItem {
6059                        title: "Use Modifier To Send",
6060                        description: "Whether to always use cmd-enter (or ctrl-enter on Linux or Windows) to send messages.",
6061                        field: Box::new(SettingField {
6062                            json_path: Some("agent.use_modifier_to_send"),
6063                            pick: |settings_content| {
6064                                settings_content
6065                                    .agent
6066                                    .as_ref()?
6067                                    .use_modifier_to_send
6068                                    .as_ref()
6069                            },
6070                            write: |settings_content, value| {
6071                                settings_content
6072                                    .agent
6073                                    .get_or_insert_default()
6074                                    .use_modifier_to_send = value;
6075                            },
6076                        }),
6077                        metadata: None,
6078                        files: USER,
6079                    }),
6080                    SettingsPageItem::SettingItem(SettingItem {
6081                        title: "Message Editor Min Lines",
6082                        description: "Minimum number of lines to display in the agent message editor.",
6083                        field: Box::new(SettingField {
6084                            json_path: Some("agent.message_editor_min_lines"),
6085                            pick: |settings_content| {
6086                                settings_content
6087                                    .agent
6088                                    .as_ref()?
6089                                    .message_editor_min_lines
6090                                    .as_ref()
6091                            },
6092                            write: |settings_content, value| {
6093                                settings_content
6094                                    .agent
6095                                    .get_or_insert_default()
6096                                    .message_editor_min_lines = value;
6097                            },
6098                        }),
6099                        metadata: None,
6100                        files: USER,
6101                    }),
6102                ];
6103                items.extend(edit_prediction_language_settings_section());
6104                items.extend(
6105                    [
6106                        SettingsPageItem::SettingItem(SettingItem {
6107                            title: "Display Mode",
6108                            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.",
6109                            field: Box::new(SettingField {
6110                                json_path: Some("edit_prediction.display_mode"),
6111                                pick: |settings_content| {
6112                                    settings_content.project.all_languages.edit_predictions.as_ref()?.mode.as_ref()
6113                                },
6114                                write: |settings_content, value| {
6115                                    settings_content.project.all_languages.edit_predictions.get_or_insert_default().mode = value;
6116                                },
6117                            }),
6118                            metadata: None,
6119                            files: USER,
6120                        }),
6121                        SettingsPageItem::SettingItem(SettingItem {
6122                            title: "Display In Text Threads",
6123                            description: "Whether edit predictions are enabled when editing text threads in the agent panel.",
6124                            field: Box::new(SettingField {
6125                                json_path: Some("edit_prediction.in_text_threads"),
6126                                pick: |settings_content| {
6127                                    settings_content.project.all_languages.edit_predictions.as_ref()?.enabled_in_text_threads.as_ref()
6128                                },
6129                                write: |settings_content, value| {
6130                                    settings_content.project.all_languages.edit_predictions.get_or_insert_default().enabled_in_text_threads = value;
6131                                },
6132                            }),
6133                            metadata: None,
6134                            files: USER,
6135                        }),
6136                    ]
6137                );
6138                items
6139            },
6140        },
6141        SettingsPage {
6142            title: "Network",
6143            items: vec![
6144                SettingsPageItem::SectionHeader("Network"),
6145                // todo(settings_ui): Proxy needs a default
6146                SettingsPageItem::SettingItem(SettingItem {
6147                    title: "Proxy",
6148                    description: "The proxy to use for network requests.",
6149                    field: Box::new(
6150                        SettingField {
6151                            json_path: Some("proxy"),
6152                            pick: |settings_content| settings_content.proxy.as_ref(),
6153                            write: |settings_content, value| {
6154                                settings_content.proxy = value;
6155                            },
6156                        }
6157                        .unimplemented(),
6158                    ),
6159                    metadata: Some(Box::new(SettingsFieldMetadata {
6160                        placeholder: Some("socks5h://localhost:10808"),
6161                        ..Default::default()
6162                    })),
6163                    files: USER,
6164                }),
6165                SettingsPageItem::SettingItem(SettingItem {
6166                    title: "Server URL",
6167                    description: "The URL of the Zed server to connect to.",
6168                    field: Box::new(SettingField {
6169                        json_path: Some("server_url"),
6170                        pick: |settings_content| settings_content.server_url.as_ref(),
6171                        write: |settings_content, value| {
6172                            settings_content.server_url = value;
6173                        },
6174                    }),
6175                    metadata: Some(Box::new(SettingsFieldMetadata {
6176                        placeholder: Some("https://zed.dev"),
6177                        ..Default::default()
6178                    })),
6179                    files: USER,
6180                }),
6181            ],
6182        },
6183    ]
6184}
6185
6186const LANGUAGES_SECTION_HEADER: &'static str = "Languages";
6187
6188fn current_language() -> Option<SharedString> {
6189    sub_page_stack().iter().find_map(|page| {
6190        (page.section_header == LANGUAGES_SECTION_HEADER).then(|| page.link.title.clone())
6191    })
6192}
6193
6194fn language_settings_field<T>(
6195    settings_content: &SettingsContent,
6196    get: fn(&LanguageSettingsContent) -> Option<&T>,
6197) -> Option<&T> {
6198    let all_languages = &settings_content.project.all_languages;
6199    if let Some(current_language_name) = current_language() {
6200        if let Some(current_language) = all_languages.languages.0.get(&current_language_name) {
6201            let value = get(current_language);
6202            if value.is_some() {
6203                return value;
6204            }
6205        }
6206    }
6207    let default_value = get(&all_languages.defaults);
6208    return default_value;
6209}
6210
6211fn language_settings_field_mut<T>(
6212    settings_content: &mut SettingsContent,
6213    value: Option<T>,
6214    write: fn(&mut LanguageSettingsContent, Option<T>),
6215) {
6216    let all_languages = &mut settings_content.project.all_languages;
6217    let language_content = if let Some(current_language) = current_language() {
6218        all_languages
6219            .languages
6220            .0
6221            .entry(current_language)
6222            .or_default()
6223    } else {
6224        &mut all_languages.defaults
6225    };
6226    write(language_content, value);
6227}
6228
6229fn language_settings_data() -> Vec<SettingsPageItem> {
6230    let mut items = vec![
6231        SettingsPageItem::SectionHeader("Indentation"),
6232        SettingsPageItem::SettingItem(SettingItem {
6233            title: "Tab Size",
6234            description: "How many columns a tab should occupy.",
6235            field: Box::new(SettingField {
6236                json_path: Some("languages.$(language).tab_size"), // TODO(cameron): not JQ syntax because not URL-safe
6237                pick: |settings_content| {
6238                    language_settings_field(settings_content, |language| language.tab_size.as_ref())
6239                },
6240                write: |settings_content, value| {
6241                    language_settings_field_mut(settings_content, value, |language, value| {
6242                        language.tab_size = value;
6243                    })
6244                },
6245            }),
6246            metadata: None,
6247            files: USER | PROJECT,
6248        }),
6249        SettingsPageItem::SettingItem(SettingItem {
6250            title: "Hard Tabs",
6251            description: "Whether to indent lines using tab characters, as opposed to multiple spaces.",
6252            field: Box::new(SettingField {
6253                json_path: Some("languages.$(language).hard_tabs"),
6254                pick: |settings_content| {
6255                    language_settings_field(settings_content, |language| {
6256                        language.hard_tabs.as_ref()
6257                    })
6258                },
6259                write: |settings_content, value| {
6260                    language_settings_field_mut(settings_content, value, |language, value| {
6261                        language.hard_tabs = value;
6262                    })
6263                },
6264            }),
6265            metadata: None,
6266            files: USER | PROJECT,
6267        }),
6268        SettingsPageItem::SettingItem(SettingItem {
6269            title: "Auto Indent",
6270            description: "Whether indentation should be adjusted based on the context whilst typing.",
6271            field: Box::new(SettingField {
6272                json_path: Some("languages.$(language).auto_indent"),
6273                pick: |settings_content| {
6274                    language_settings_field(settings_content, |language| {
6275                        language.auto_indent.as_ref()
6276                    })
6277                },
6278                write: |settings_content, value| {
6279                    language_settings_field_mut(settings_content, value, |language, value| {
6280                        language.auto_indent = value;
6281                    })
6282                },
6283            }),
6284            metadata: None,
6285            files: USER | PROJECT,
6286        }),
6287        SettingsPageItem::SettingItem(SettingItem {
6288            title: "Auto Indent On Paste",
6289            description: "Whether indentation of pasted content should be adjusted based on the context.",
6290            field: Box::new(SettingField {
6291                json_path: Some("languages.$(language).auto_indent_on_paste"),
6292                pick: |settings_content| {
6293                    language_settings_field(settings_content, |language| {
6294                        language.auto_indent_on_paste.as_ref()
6295                    })
6296                },
6297                write: |settings_content, value| {
6298                    language_settings_field_mut(settings_content, value, |language, value| {
6299                        language.auto_indent_on_paste = value;
6300                    })
6301                },
6302            }),
6303            metadata: None,
6304            files: USER | PROJECT,
6305        }),
6306        SettingsPageItem::SectionHeader("Wrapping"),
6307        SettingsPageItem::SettingItem(SettingItem {
6308            title: "Soft Wrap",
6309            description: "How to soft-wrap long lines of text.",
6310            field: Box::new(SettingField {
6311                json_path: Some("languages.$(language).soft_wrap"),
6312                pick: |settings_content| {
6313                    language_settings_field(settings_content, |language| {
6314                        language.soft_wrap.as_ref()
6315                    })
6316                },
6317                write: |settings_content, value| {
6318                    language_settings_field_mut(settings_content, value, |language, value| {
6319                        language.soft_wrap = value;
6320                    })
6321                },
6322            }),
6323            metadata: None,
6324            files: USER | PROJECT,
6325        }),
6326        SettingsPageItem::SettingItem(SettingItem {
6327            title: "Show Wrap Guides",
6328            description: "Show wrap guides in the editor.",
6329            field: Box::new(SettingField {
6330                json_path: Some("languages.$(language).show_wrap_guides"),
6331                pick: |settings_content| {
6332                    language_settings_field(settings_content, |language| {
6333                        language.show_wrap_guides.as_ref()
6334                    })
6335                },
6336                write: |settings_content, value| {
6337                    language_settings_field_mut(settings_content, value, |language, value| {
6338                        language.show_wrap_guides = value;
6339                    })
6340                },
6341            }),
6342            metadata: None,
6343            files: USER | PROJECT,
6344        }),
6345        SettingsPageItem::SettingItem(SettingItem {
6346            title: "Preferred Line Length",
6347            description: "The column at which to soft-wrap lines, for buffers where soft-wrap is enabled.",
6348            field: Box::new(SettingField {
6349                json_path: Some("languages.$(language).preferred_line_length"),
6350                pick: |settings_content| {
6351                    language_settings_field(settings_content, |language| {
6352                        language.preferred_line_length.as_ref()
6353                    })
6354                },
6355                write: |settings_content, value| {
6356                    language_settings_field_mut(settings_content, value, |language, value| {
6357                        language.preferred_line_length = value;
6358                    })
6359                },
6360            }),
6361            metadata: None,
6362            files: USER | PROJECT,
6363        }),
6364        SettingsPageItem::SettingItem(SettingItem {
6365            title: "Wrap Guides",
6366            description: "Character counts at which to show wrap guides in the editor.",
6367            field: Box::new(
6368                SettingField {
6369                    json_path: Some("languages.$(language).wrap_guides"),
6370                    pick: |settings_content| {
6371                        language_settings_field(settings_content, |language| {
6372                            language.wrap_guides.as_ref()
6373                        })
6374                    },
6375                    write: |settings_content, value| {
6376                        language_settings_field_mut(settings_content, value, |language, value| {
6377                            language.wrap_guides = value;
6378                        })
6379                    },
6380                }
6381                .unimplemented(),
6382            ),
6383            metadata: None,
6384            files: USER | PROJECT,
6385        }),
6386        SettingsPageItem::SettingItem(SettingItem {
6387            title: "Allow Rewrap",
6388            description: "Controls where the `editor::rewrap` action is allowed for this language.",
6389            field: Box::new(SettingField {
6390                json_path: Some("languages.$(language).allow_rewrap"),
6391                pick: |settings_content| {
6392                    language_settings_field(settings_content, |language| {
6393                        language.allow_rewrap.as_ref()
6394                    })
6395                },
6396                write: |settings_content, value| {
6397                    language_settings_field_mut(settings_content, value, |language, value| {
6398                        language.allow_rewrap = value;
6399                    })
6400                },
6401            }),
6402            metadata: None,
6403            files: USER | PROJECT,
6404        }),
6405        SettingsPageItem::SectionHeader("Indent Guides"),
6406        SettingsPageItem::SettingItem(SettingItem {
6407            title: "Enabled",
6408            description: "Display indent guides in the editor.",
6409            field: Box::new(SettingField {
6410                json_path: Some("languages.$(language).indent_guides.enabled"),
6411                pick: |settings_content| {
6412                    language_settings_field(settings_content, |language| {
6413                        language
6414                            .indent_guides
6415                            .as_ref()
6416                            .and_then(|indent_guides| indent_guides.enabled.as_ref())
6417                    })
6418                },
6419                write: |settings_content, value| {
6420                    language_settings_field_mut(settings_content, value, |language, value| {
6421                        language.indent_guides.get_or_insert_default().enabled = value;
6422                    })
6423                },
6424            }),
6425            metadata: None,
6426            files: USER | PROJECT,
6427        }),
6428        SettingsPageItem::SettingItem(SettingItem {
6429            title: "Line Width",
6430            description: "The width of the indent guides in pixels, between 1 and 10.",
6431            field: Box::new(SettingField {
6432                json_path: Some("languages.$(language).indent_guides.line_width"),
6433                pick: |settings_content| {
6434                    language_settings_field(settings_content, |language| {
6435                        language
6436                            .indent_guides
6437                            .as_ref()
6438                            .and_then(|indent_guides| indent_guides.line_width.as_ref())
6439                    })
6440                },
6441                write: |settings_content, value| {
6442                    language_settings_field_mut(settings_content, value, |language, value| {
6443                        language.indent_guides.get_or_insert_default().line_width = value;
6444                    })
6445                },
6446            }),
6447            metadata: None,
6448            files: USER | PROJECT,
6449        }),
6450        SettingsPageItem::SettingItem(SettingItem {
6451            title: "Active Line Width",
6452            description: "The width of the active indent guide in pixels, between 1 and 10.",
6453            field: Box::new(SettingField {
6454                json_path: Some("languages.$(language).indent_guides.active_line_width"),
6455                pick: |settings_content| {
6456                    language_settings_field(settings_content, |language| {
6457                        language
6458                            .indent_guides
6459                            .as_ref()
6460                            .and_then(|indent_guides| indent_guides.active_line_width.as_ref())
6461                    })
6462                },
6463                write: |settings_content, value| {
6464                    language_settings_field_mut(settings_content, value, |language, value| {
6465                        language
6466                            .indent_guides
6467                            .get_or_insert_default()
6468                            .active_line_width = value;
6469                    })
6470                },
6471            }),
6472            metadata: None,
6473            files: USER | PROJECT,
6474        }),
6475        SettingsPageItem::SettingItem(SettingItem {
6476            title: "Coloring",
6477            description: "Determines how indent guides are colored.",
6478            field: Box::new(SettingField {
6479                json_path: Some("languages.$(language).indent_guides.coloring"),
6480                pick: |settings_content| {
6481                    language_settings_field(settings_content, |language| {
6482                        language
6483                            .indent_guides
6484                            .as_ref()
6485                            .and_then(|indent_guides| indent_guides.coloring.as_ref())
6486                    })
6487                },
6488                write: |settings_content, value| {
6489                    language_settings_field_mut(settings_content, value, |language, value| {
6490                        language.indent_guides.get_or_insert_default().coloring = value;
6491                    })
6492                },
6493            }),
6494            metadata: None,
6495            files: USER | PROJECT,
6496        }),
6497        SettingsPageItem::SettingItem(SettingItem {
6498            title: "Background Coloring",
6499            description: "Determines how indent guide backgrounds are colored.",
6500            field: Box::new(SettingField {
6501                json_path: Some("languages.$(language).indent_guides.background_coloring"),
6502                pick: |settings_content| {
6503                    language_settings_field(settings_content, |language| {
6504                        language
6505                            .indent_guides
6506                            .as_ref()
6507                            .and_then(|indent_guides| indent_guides.background_coloring.as_ref())
6508                    })
6509                },
6510                write: |settings_content, value| {
6511                    language_settings_field_mut(settings_content, value, |language, value| {
6512                        language
6513                            .indent_guides
6514                            .get_or_insert_default()
6515                            .background_coloring = value;
6516                    })
6517                },
6518            }),
6519            metadata: None,
6520            files: USER | PROJECT,
6521        }),
6522        SettingsPageItem::SectionHeader("Formatting"),
6523        SettingsPageItem::SettingItem(SettingItem {
6524            title: "Format On Save",
6525            description: "Whether or not to perform a buffer format before saving.",
6526            field: Box::new(
6527                // TODO(settings_ui): this setting should just be a bool
6528                SettingField {
6529                    json_path: Some("languages.$(language).format_on_save"),
6530                    pick: |settings_content| {
6531                        language_settings_field(settings_content, |language| {
6532                            language.format_on_save.as_ref()
6533                        })
6534                    },
6535                    write: |settings_content, value| {
6536                        language_settings_field_mut(settings_content, value, |language, value| {
6537                            language.format_on_save = value;
6538                        })
6539                    },
6540                },
6541            ),
6542            metadata: None,
6543            files: USER | PROJECT,
6544        }),
6545        SettingsPageItem::SettingItem(SettingItem {
6546            title: "Remove Trailing Whitespace On Save",
6547            description: "Whether or not to remove any trailing whitespace from lines of a buffer before saving it.",
6548            field: Box::new(SettingField {
6549                json_path: Some("languages.$(language).remove_trailing_whitespace_on_save"),
6550                pick: |settings_content| {
6551                    language_settings_field(settings_content, |language| {
6552                        language.remove_trailing_whitespace_on_save.as_ref()
6553                    })
6554                },
6555                write: |settings_content, value| {
6556                    language_settings_field_mut(settings_content, value, |language, value| {
6557                        language.remove_trailing_whitespace_on_save = value;
6558                    })
6559                },
6560            }),
6561            metadata: None,
6562            files: USER | PROJECT,
6563        }),
6564        SettingsPageItem::SettingItem(SettingItem {
6565            title: "Ensure Final Newline On Save",
6566            description: "Whether or not to ensure there's a single newline at the end of a buffer when saving it.",
6567            field: Box::new(SettingField {
6568                json_path: Some("languages.$(language).ensure_final_newline_on_save"),
6569                pick: |settings_content| {
6570                    language_settings_field(settings_content, |language| {
6571                        language.ensure_final_newline_on_save.as_ref()
6572                    })
6573                },
6574                write: |settings_content, value| {
6575                    language_settings_field_mut(settings_content, value, |language, value| {
6576                        language.ensure_final_newline_on_save = value;
6577                    })
6578                },
6579            }),
6580            metadata: None,
6581            files: USER | PROJECT,
6582        }),
6583        SettingsPageItem::SettingItem(SettingItem {
6584            title: "Formatter",
6585            description: "How to perform a buffer format.",
6586            field: Box::new(
6587                SettingField {
6588                    json_path: Some("languages.$(language).formatter"),
6589                    pick: |settings_content| {
6590                        language_settings_field(settings_content, |language| {
6591                            language.formatter.as_ref()
6592                        })
6593                    },
6594                    write: |settings_content, value| {
6595                        language_settings_field_mut(settings_content, value, |language, value| {
6596                            language.formatter = value;
6597                        })
6598                    },
6599                }
6600                .unimplemented(),
6601            ),
6602            metadata: None,
6603            files: USER | PROJECT,
6604        }),
6605        SettingsPageItem::SettingItem(SettingItem {
6606            title: "Use On Type Format",
6607            description: "Whether to use additional LSP queries to format (and amend) the code after every \"trigger\" symbol input, defined by LSP server capabilities",
6608            field: Box::new(SettingField {
6609                json_path: Some("languages.$(language).use_on_type_format"),
6610                pick: |settings_content| {
6611                    language_settings_field(settings_content, |language| {
6612                        language.use_on_type_format.as_ref()
6613                    })
6614                },
6615                write: |settings_content, value| {
6616                    language_settings_field_mut(settings_content, value, |language, value| {
6617                        language.use_on_type_format = value;
6618                    })
6619                },
6620            }),
6621            metadata: None,
6622            files: USER | PROJECT,
6623        }),
6624        SettingsPageItem::SettingItem(SettingItem {
6625            title: "Code Actions On Format",
6626            description: "Additional code actions to run when formatting.",
6627            field: Box::new(
6628                SettingField {
6629                    json_path: Some("languages.$(language).code_actions_on_format"),
6630                    pick: |settings_content| {
6631                        language_settings_field(settings_content, |language| {
6632                            language.code_actions_on_format.as_ref()
6633                        })
6634                    },
6635                    write: |settings_content, value| {
6636                        language_settings_field_mut(settings_content, value, |language, value| {
6637                            language.code_actions_on_format = value;
6638                        })
6639                    },
6640                }
6641                .unimplemented(),
6642            ),
6643            metadata: None,
6644            files: USER | PROJECT,
6645        }),
6646        SettingsPageItem::SectionHeader("Autoclose"),
6647        SettingsPageItem::SettingItem(SettingItem {
6648            title: "Use Autoclose",
6649            description: "Whether to automatically type closing characters for you. For example, when you type '(', Zed will automatically add a closing ')' at the correct position.",
6650            field: Box::new(SettingField {
6651                json_path: Some("languages.$(language).use_autoclose"),
6652                pick: |settings_content| {
6653                    language_settings_field(settings_content, |language| {
6654                        language.use_autoclose.as_ref()
6655                    })
6656                },
6657                write: |settings_content, value| {
6658                    language_settings_field_mut(settings_content, value, |language, value| {
6659                        language.use_autoclose = value;
6660                    })
6661                },
6662            }),
6663            metadata: None,
6664            files: USER | PROJECT,
6665        }),
6666        SettingsPageItem::SettingItem(SettingItem {
6667            title: "Use Auto Surround",
6668            description: "Whether to automatically surround text with characters for you. For example, when you select text and type '(', Zed will automatically surround text with ().",
6669            field: Box::new(SettingField {
6670                json_path: Some("languages.$(language).use_auto_surround"),
6671                pick: |settings_content| {
6672                    language_settings_field(settings_content, |language| {
6673                        language.use_auto_surround.as_ref()
6674                    })
6675                },
6676                write: |settings_content, value| {
6677                    language_settings_field_mut(settings_content, value, |language, value| {
6678                        language.use_auto_surround = value;
6679                    })
6680                },
6681            }),
6682            metadata: None,
6683            files: USER | PROJECT,
6684        }),
6685        SettingsPageItem::SettingItem(SettingItem {
6686            title: "Always Treat Brackets As Autoclosed",
6687            description: "Controls whether the closing characters are always skipped over and auto-removed no matter how they were inserted.",
6688            field: Box::new(SettingField {
6689                json_path: Some("languages.$(language).always_treat_brackets_as_autoclosed"),
6690                pick: |settings_content| {
6691                    language_settings_field(settings_content, |language| {
6692                        language.always_treat_brackets_as_autoclosed.as_ref()
6693                    })
6694                },
6695                write: |settings_content, value| {
6696                    language_settings_field_mut(settings_content, value, |language, value| {
6697                        language.always_treat_brackets_as_autoclosed = value;
6698                    })
6699                },
6700            }),
6701            metadata: None,
6702            files: USER | PROJECT,
6703        }),
6704        SettingsPageItem::SettingItem(SettingItem {
6705            title: "JSX Tag Auto Close",
6706            description: "Whether to automatically close JSX tags.",
6707            field: Box::new(SettingField {
6708                json_path: Some("languages.$(language).jsx_tag_auto_close"),
6709                // TODO(settings_ui): this setting should just be a bool
6710                pick: |settings_content| {
6711                    language_settings_field(settings_content, |language| {
6712                        language.jsx_tag_auto_close.as_ref()?.enabled.as_ref()
6713                    })
6714                },
6715                write: |settings_content, value| {
6716                    language_settings_field_mut(settings_content, value, |language, value| {
6717                        language.jsx_tag_auto_close.get_or_insert_default().enabled = value;
6718                    })
6719                },
6720            }),
6721            metadata: None,
6722            files: USER | PROJECT,
6723        }),
6724        SettingsPageItem::SectionHeader("Whitespace"),
6725        SettingsPageItem::SettingItem(SettingItem {
6726            title: "Show Whitespaces",
6727            description: "Whether to show tabs and spaces in the editor.",
6728            field: Box::new(SettingField {
6729                json_path: Some("languages.$(language).show_whitespaces"),
6730                pick: |settings_content| {
6731                    language_settings_field(settings_content, |language| {
6732                        language.show_whitespaces.as_ref()
6733                    })
6734                },
6735                write: |settings_content, value| {
6736                    language_settings_field_mut(settings_content, value, |language, value| {
6737                        language.show_whitespaces = value;
6738                    })
6739                },
6740            }),
6741            metadata: None,
6742            files: USER | PROJECT,
6743        }),
6744        SettingsPageItem::SettingItem(SettingItem {
6745            title: "Space Whitespace Indicator",
6746            description: "Visible character used to render space characters when show_whitespaces is enabled (default: \"\")",
6747            field: Box::new(
6748                SettingField {
6749                    json_path: Some("languages.$(language).whitespace_map.space"),
6750                    pick: |settings_content| {
6751                        language_settings_field(settings_content, |language| {
6752                            language.whitespace_map.as_ref()?.space.as_ref()
6753                        })
6754                    },
6755                    write: |settings_content, value| {
6756                        language_settings_field_mut(settings_content, value, |language, value| {
6757                            language.whitespace_map.get_or_insert_default().space = value;
6758                        })
6759                    },
6760                }
6761                .unimplemented(),
6762            ),
6763            metadata: None,
6764            files: USER | PROJECT,
6765        }),
6766        SettingsPageItem::SettingItem(SettingItem {
6767            title: "Tab Whitespace Indicator",
6768            description: "Visible character used to render tab characters when show_whitespaces is enabled (default: \"\")",
6769            field: Box::new(
6770                SettingField {
6771                    json_path: Some("languages.$(language).whitespace_map.tab"),
6772                    pick: |settings_content| {
6773                        language_settings_field(settings_content, |language| {
6774                            language.whitespace_map.as_ref()?.tab.as_ref()
6775                        })
6776                    },
6777                    write: |settings_content, value| {
6778                        language_settings_field_mut(settings_content, value, |language, value| {
6779                            language.whitespace_map.get_or_insert_default().tab = value;
6780                        })
6781                    },
6782                }
6783                .unimplemented(),
6784            ),
6785            metadata: None,
6786            files: USER | PROJECT,
6787        }),
6788        SettingsPageItem::SectionHeader("Completions"),
6789        SettingsPageItem::SettingItem(SettingItem {
6790            title: "Show Completions On Input",
6791            description: "Whether to pop the completions menu while typing in an editor without explicitly requesting it.",
6792            field: Box::new(SettingField {
6793                json_path: Some("languages.$(language).show_completions_on_input"),
6794                pick: |settings_content| {
6795                    language_settings_field(settings_content, |language| {
6796                        language.show_completions_on_input.as_ref()
6797                    })
6798                },
6799                write: |settings_content, value| {
6800                    language_settings_field_mut(settings_content, value, |language, value| {
6801                        language.show_completions_on_input = value;
6802                    })
6803                },
6804            }),
6805            metadata: None,
6806            files: USER | PROJECT,
6807        }),
6808        SettingsPageItem::SettingItem(SettingItem {
6809            title: "Show Completion Documentation",
6810            description: "Whether to display inline and alongside documentation for items in the completions menu.",
6811            field: Box::new(SettingField {
6812                json_path: Some("languages.$(language).show_completion_documentation"),
6813                pick: |settings_content| {
6814                    language_settings_field(settings_content, |language| {
6815                        language.show_completion_documentation.as_ref()
6816                    })
6817                },
6818                write: |settings_content, value| {
6819                    language_settings_field_mut(settings_content, value, |language, value| {
6820                        language.show_completion_documentation = value;
6821                    })
6822                },
6823            }),
6824            metadata: None,
6825            files: USER | PROJECT,
6826        }),
6827        SettingsPageItem::SettingItem(SettingItem {
6828            title: "Words",
6829            description: "Controls how words are completed.",
6830            field: Box::new(SettingField {
6831                json_path: Some("languages.$(language).completions.words"),
6832                pick: |settings_content| {
6833                    language_settings_field(settings_content, |language| {
6834                        language.completions.as_ref()?.words.as_ref()
6835                    })
6836                },
6837                write: |settings_content, value| {
6838                    language_settings_field_mut(settings_content, value, |language, value| {
6839                        language.completions.get_or_insert_default().words = value;
6840                    })
6841                },
6842            }),
6843            metadata: None,
6844            files: USER | PROJECT,
6845        }),
6846        SettingsPageItem::SettingItem(SettingItem {
6847            title: "Words Min Length",
6848            description: "How many characters has to be in the completions query to automatically show the words-based completions.",
6849            field: Box::new(SettingField {
6850                json_path: Some("languages.$(language).completions.words_min_length"),
6851                pick: |settings_content| {
6852                    language_settings_field(settings_content, |language| {
6853                        language.completions.as_ref()?.words_min_length.as_ref()
6854                    })
6855                },
6856                write: |settings_content, value| {
6857                    language_settings_field_mut(settings_content, value, |language, value| {
6858                        language
6859                            .completions
6860                            .get_or_insert_default()
6861                            .words_min_length = value;
6862                    })
6863                },
6864            }),
6865            metadata: None,
6866            files: USER | PROJECT,
6867        }),
6868        SettingsPageItem::SettingItem(SettingItem {
6869            title: "Completion Menu Scrollbar",
6870            description: "When to show the scrollbar in the completion menu.",
6871            field: Box::new(SettingField {
6872                json_path: Some("editor.completion_menu_scrollbar"),
6873                pick: |settings_content| settings_content.editor.completion_menu_scrollbar.as_ref(),
6874                write: |settings_content, value| {
6875                    settings_content.editor.completion_menu_scrollbar = value;
6876                },
6877            }),
6878            metadata: None,
6879            files: USER,
6880        }),
6881        SettingsPageItem::SectionHeader("Inlay Hints"),
6882        SettingsPageItem::SettingItem(SettingItem {
6883            title: "Enabled",
6884            description: "Global switch to toggle hints on and off.",
6885            field: Box::new(SettingField {
6886                json_path: Some("languages.$(language).inlay_hints.enabled"),
6887                pick: |settings_content| {
6888                    language_settings_field(settings_content, |language| {
6889                        language.inlay_hints.as_ref()?.enabled.as_ref()
6890                    })
6891                },
6892                write: |settings_content, value| {
6893                    language_settings_field_mut(settings_content, value, |language, value| {
6894                        language.inlay_hints.get_or_insert_default().enabled = value;
6895                    })
6896                },
6897            }),
6898            metadata: None,
6899            files: USER | PROJECT,
6900        }),
6901        SettingsPageItem::SettingItem(SettingItem {
6902            title: "Show Value Hints",
6903            description: "Global switch to toggle inline values on and off when debugging.",
6904            field: Box::new(SettingField {
6905                json_path: Some("languages.$(language).inlay_hints.show_value_hints"),
6906                pick: |settings_content| {
6907                    language_settings_field(settings_content, |language| {
6908                        language.inlay_hints.as_ref()?.show_value_hints.as_ref()
6909                    })
6910                },
6911                write: |settings_content, value| {
6912                    language_settings_field_mut(settings_content, value, |language, value| {
6913                        language
6914                            .inlay_hints
6915                            .get_or_insert_default()
6916                            .show_value_hints = value;
6917                    })
6918                },
6919            }),
6920            metadata: None,
6921            files: USER | PROJECT,
6922        }),
6923        SettingsPageItem::SettingItem(SettingItem {
6924            title: "Show Type Hints",
6925            description: "Whether type hints should be shown.",
6926            field: Box::new(SettingField {
6927                json_path: Some("languages.$(language).inlay_hints.show_type_hints"),
6928                pick: |settings_content| {
6929                    language_settings_field(settings_content, |language| {
6930                        language.inlay_hints.as_ref()?.show_type_hints.as_ref()
6931                    })
6932                },
6933                write: |settings_content, value| {
6934                    language_settings_field_mut(settings_content, value, |language, value| {
6935                        language.inlay_hints.get_or_insert_default().show_type_hints = value;
6936                    })
6937                },
6938            }),
6939            metadata: None,
6940            files: USER | PROJECT,
6941        }),
6942        SettingsPageItem::SettingItem(SettingItem {
6943            title: "Show Parameter Hints",
6944            description: "Whether parameter hints should be shown.",
6945            field: Box::new(SettingField {
6946                json_path: Some("languages.$(language).inlay_hints.show_parameter_hints"),
6947                pick: |settings_content| {
6948                    language_settings_field(settings_content, |language| {
6949                        language.inlay_hints.as_ref()?.show_parameter_hints.as_ref()
6950                    })
6951                },
6952                write: |settings_content, value| {
6953                    language_settings_field_mut(settings_content, value, |language, value| {
6954                        language
6955                            .inlay_hints
6956                            .get_or_insert_default()
6957                            .show_parameter_hints = value;
6958                    })
6959                },
6960            }),
6961            metadata: None,
6962            files: USER | PROJECT,
6963        }),
6964        SettingsPageItem::SettingItem(SettingItem {
6965            title: "Show Other Hints",
6966            description: "Whether other hints should be shown.",
6967            field: Box::new(SettingField {
6968                json_path: Some("languages.$(language).inlay_hints.show_other_hints"),
6969                pick: |settings_content| {
6970                    language_settings_field(settings_content, |language| {
6971                        language.inlay_hints.as_ref()?.show_other_hints.as_ref()
6972                    })
6973                },
6974                write: |settings_content, value| {
6975                    language_settings_field_mut(settings_content, value, |language, value| {
6976                        language
6977                            .inlay_hints
6978                            .get_or_insert_default()
6979                            .show_other_hints = value;
6980                    })
6981                },
6982            }),
6983            metadata: None,
6984            files: USER | PROJECT,
6985        }),
6986        SettingsPageItem::SettingItem(SettingItem {
6987            title: "Show Background",
6988            description: "Show a background for inlay hints.",
6989            field: Box::new(SettingField {
6990                json_path: Some("languages.$(language).inlay_hints.show_background"),
6991                pick: |settings_content| {
6992                    language_settings_field(settings_content, |language| {
6993                        language.inlay_hints.as_ref()?.show_background.as_ref()
6994                    })
6995                },
6996                write: |settings_content, value| {
6997                    language_settings_field_mut(settings_content, value, |language, value| {
6998                        language.inlay_hints.get_or_insert_default().show_background = value;
6999                    })
7000                },
7001            }),
7002            metadata: None,
7003            files: USER | PROJECT,
7004        }),
7005        SettingsPageItem::SettingItem(SettingItem {
7006            title: "Edit Debounce Ms",
7007            description: "Whether or not to debounce inlay hints updates after buffer edits (set to 0 to disable debouncing).",
7008            field: Box::new(SettingField {
7009                json_path: Some("languages.$(language).inlay_hints.edit_debounce_ms"),
7010                pick: |settings_content| {
7011                    language_settings_field(settings_content, |language| {
7012                        language.inlay_hints.as_ref()?.edit_debounce_ms.as_ref()
7013                    })
7014                },
7015                write: |settings_content, value| {
7016                    language_settings_field_mut(settings_content, value, |language, value| {
7017                        language
7018                            .inlay_hints
7019                            .get_or_insert_default()
7020                            .edit_debounce_ms = value;
7021                    })
7022                },
7023            }),
7024            metadata: None,
7025            files: USER | PROJECT,
7026        }),
7027        SettingsPageItem::SettingItem(SettingItem {
7028            title: "Scroll Debounce Ms",
7029            description: "Whether or not to debounce inlay hints updates after buffer scrolls (set to 0 to disable debouncing).",
7030            field: Box::new(SettingField {
7031                json_path: Some("languages.$(language).inlay_hints.scroll_debounce_ms"),
7032                pick: |settings_content| {
7033                    language_settings_field(settings_content, |language| {
7034                        language.inlay_hints.as_ref()?.scroll_debounce_ms.as_ref()
7035                    })
7036                },
7037                write: |settings_content, value| {
7038                    language_settings_field_mut(settings_content, value, |language, value| {
7039                        language
7040                            .inlay_hints
7041                            .get_or_insert_default()
7042                            .scroll_debounce_ms = value;
7043                    })
7044                },
7045            }),
7046            metadata: None,
7047            files: USER | PROJECT,
7048        }),
7049        SettingsPageItem::SettingItem(SettingItem {
7050            title: "Toggle On Modifiers Press",
7051            description: "Toggles inlay hints (hides or shows) when the user presses the modifiers specified.",
7052            field: Box::new(
7053                SettingField {
7054                    json_path: Some("languages.$(language).inlay_hints.toggle_on_modifiers_press"),
7055                    pick: |settings_content| {
7056                        language_settings_field(settings_content, |language| {
7057                            language
7058                                .inlay_hints
7059                                .as_ref()?
7060                                .toggle_on_modifiers_press
7061                                .as_ref()
7062                        })
7063                    },
7064                    write: |settings_content, value| {
7065                        language_settings_field_mut(settings_content, value, |language, value| {
7066                            language
7067                                .inlay_hints
7068                                .get_or_insert_default()
7069                                .toggle_on_modifiers_press = value;
7070                        })
7071                    },
7072                }
7073                .unimplemented(),
7074            ),
7075            metadata: None,
7076            files: USER | PROJECT,
7077        }),
7078    ];
7079    if current_language().is_none() {
7080        items.push(SettingsPageItem::SettingItem(SettingItem {
7081            title: "LSP Document Colors",
7082            description: "How to render LSP color previews in the editor.",
7083            field: Box::new(SettingField {
7084                json_path: Some("lsp_document_colors"),
7085                pick: |settings_content| settings_content.editor.lsp_document_colors.as_ref(),
7086                write: |settings_content, value| {
7087                    settings_content.editor.lsp_document_colors = value;
7088                },
7089            }),
7090            metadata: None,
7091            files: USER,
7092        }))
7093    }
7094    items.extend([
7095        SettingsPageItem::SectionHeader("Tasks"),
7096        SettingsPageItem::SettingItem(SettingItem {
7097            title: "Enabled",
7098            description: "Whether tasks are enabled for this language.",
7099            field: Box::new(SettingField {
7100                json_path: Some("languages.$(language).tasks.enabled"),
7101                pick: |settings_content| {
7102                    language_settings_field(settings_content, |language| {
7103                        language.tasks.as_ref()?.enabled.as_ref()
7104                    })
7105                },
7106                write: |settings_content, value| {
7107                    language_settings_field_mut(settings_content, value, |language, value| {
7108                        language.tasks.get_or_insert_default().enabled = value;
7109
7110                    })
7111                },
7112            }),
7113            metadata: None,
7114            files: USER | PROJECT,
7115        }),
7116        SettingsPageItem::SettingItem(SettingItem {
7117            title: "Variables",
7118            description: "Extra task variables to set for a particular language.",
7119            field: Box::new(
7120                SettingField {
7121                    json_path: Some("languages.$(language).tasks.variables"),
7122                    pick: |settings_content| {
7123                        language_settings_field(settings_content, |language| {
7124                            language.tasks.as_ref()?.variables.as_ref()
7125                        })
7126                    },
7127                    write: |settings_content, value| {
7128                        language_settings_field_mut(settings_content, value, |language, value| {
7129                            language.tasks.get_or_insert_default().variables = value;
7130
7131                        })
7132                    },
7133                }
7134                .unimplemented(),
7135            ),
7136            metadata: None,
7137            files: USER | PROJECT,
7138        }),
7139        SettingsPageItem::SettingItem(SettingItem {
7140            title: "Prefer LSP",
7141            description: "Use LSP tasks over Zed language extension tasks.",
7142            field: Box::new(SettingField {
7143                json_path: Some("languages.$(language).tasks.prefer_lsp"),
7144                pick: |settings_content| {
7145                    language_settings_field(settings_content, |language| {
7146                        language.tasks.as_ref()?.prefer_lsp.as_ref()
7147                    })
7148                },
7149                write: |settings_content, value| {
7150                    language_settings_field_mut(settings_content, value, |language, value| {
7151                        language.tasks.get_or_insert_default().prefer_lsp = value;
7152
7153                    })
7154                },
7155            }),
7156            metadata: None,
7157            files: USER | PROJECT,
7158        }),
7159        SettingsPageItem::SectionHeader("Miscellaneous"),
7160        SettingsPageItem::SettingItem(SettingItem {
7161            title: "Word Diff Enabled",
7162            description: "Whether to enable word diff highlighting in the editor. When enabled, changed words within modified lines are highlighted to show exactly what changed.",
7163            field: Box::new(SettingField {
7164                json_path: Some("languages.$(language).word_diff_enabled"),
7165                pick: |settings_content| {
7166                    language_settings_field(settings_content, |language| {
7167                        language.word_diff_enabled.as_ref()
7168                    })
7169                },
7170                write: |settings_content, value| {
7171                    language_settings_field_mut(settings_content, value, |language, value| {
7172                        language.word_diff_enabled = value;
7173                    })
7174                },
7175            }),
7176            metadata: None,
7177            files: USER | PROJECT,
7178        }),
7179        SettingsPageItem::SettingItem(SettingItem {
7180            title: "Debuggers",
7181            description: "Preferred debuggers for this language.",
7182            field: Box::new(
7183                SettingField {
7184                    json_path: Some("languages.$(language).debuggers"),
7185                    pick: |settings_content| {
7186                        language_settings_field(settings_content, |language| language.debuggers.as_ref())
7187                    },
7188                    write: |settings_content, value| {
7189                        language_settings_field_mut(settings_content, value, |language, value| {
7190                            language.debuggers = value;
7191
7192                        })
7193                    },
7194                }
7195                .unimplemented(),
7196            ),
7197            metadata: None,
7198            files: USER | PROJECT,
7199        }),
7200        SettingsPageItem::SettingItem(SettingItem {
7201            title: "Middle Click Paste",
7202            description: "Enable middle-click paste on Linux.",
7203            field: Box::new(SettingField {
7204                json_path: Some("languages.$(language).editor.middle_click_paste"),
7205                pick: |settings_content| settings_content.editor.middle_click_paste.as_ref(),
7206                write: |settings_content, value| {settings_content.editor.middle_click_paste = value;},
7207            }),
7208            metadata: None,
7209            files: USER,
7210        }),
7211        SettingsPageItem::SettingItem(SettingItem {
7212            title: "Extend Comment On Newline",
7213            description: "Whether to start a new line with a comment when a previous line is a comment as well.",
7214            field: Box::new(SettingField {
7215                json_path: Some("languages.$(language).extend_comment_on_newline"),
7216                pick: |settings_content| {
7217                    language_settings_field(settings_content, |language| {
7218                        language.extend_comment_on_newline.as_ref()
7219                    })
7220                },
7221                write: |settings_content, value| {
7222                    language_settings_field_mut(settings_content, value, |language, value| {
7223                        language.extend_comment_on_newline = value;
7224
7225                    })
7226                },
7227            }),
7228            metadata: None,
7229            files: USER | PROJECT,
7230        }),
7231        SettingsPageItem::SettingItem(SettingItem {
7232            title: "Colorize Brackets",
7233            description: "Whether to colorize brackets in the editor.",
7234            field: Box::new(SettingField {
7235                json_path: Some("languages.$(language).colorize_brackets"),
7236                pick: |settings_content| {
7237                    language_settings_field(settings_content, |language| {
7238                        language.colorize_brackets.as_ref()
7239                    })
7240                },
7241                write: |settings_content, value| {
7242                    language_settings_field_mut(settings_content, value, |language, value| {
7243                        language.colorize_brackets = value;
7244                    })
7245                },
7246            }),
7247            metadata: None,
7248            files: USER | PROJECT,
7249        }),
7250    ]);
7251
7252    if current_language().is_none() {
7253        items.extend([
7254            SettingsPageItem::SettingItem(SettingItem {
7255                title: "Image Viewer",
7256                description: "The unit for image file sizes.",
7257                field: Box::new(SettingField {
7258                    json_path: Some("image_viewer.unit"),
7259                    pick: |settings_content| {
7260                        settings_content.image_viewer.as_ref().and_then(|image_viewer| image_viewer.unit.as_ref())
7261                    },
7262                    write: |settings_content, value| {
7263                        settings_content.image_viewer.get_or_insert_default().unit = value;
7264
7265                    },
7266                }),
7267                metadata: None,
7268                files: USER,
7269            }),
7270            SettingsPageItem::SettingItem(SettingItem {
7271                title: "Auto Replace Emoji Shortcode",
7272                description: "Whether to automatically replace emoji shortcodes with emoji characters.",
7273                field: Box::new(SettingField {
7274                    json_path: Some("message_editor.auto_replace_emoji_shortcode"),
7275                    pick: |settings_content| {
7276                        settings_content.message_editor.as_ref().and_then(|message_editor| message_editor.auto_replace_emoji_shortcode.as_ref())
7277                    },
7278                    write: |settings_content, value| {
7279                        settings_content.message_editor.get_or_insert_default().auto_replace_emoji_shortcode = value;
7280
7281                    },
7282                }),
7283                metadata: None,
7284                files: USER,
7285            }),
7286            SettingsPageItem::SettingItem(SettingItem {
7287                title: "Drop Size Target",
7288                description: "Relative size of the drop target in the editor that will open dropped file as a split pane.",
7289                field: Box::new(SettingField {
7290                    json_path: Some("drop_target_size"),
7291                    pick: |settings_content| {
7292                        settings_content.workspace.drop_target_size.as_ref()
7293                    },
7294                    write: |settings_content, value| {
7295                        settings_content.workspace.drop_target_size = value;
7296
7297                    },
7298                }),
7299                metadata: None,
7300                files: USER,
7301            }),
7302        ]);
7303    }
7304    items
7305}
7306
7307/// LanguageSettings items that should be included in the "Languages & Tools" page
7308/// not the "Editor" page
7309fn non_editor_language_settings_data() -> Vec<SettingsPageItem> {
7310    vec![
7311        SettingsPageItem::SectionHeader("LSP"),
7312        SettingsPageItem::SettingItem(SettingItem {
7313            title: "Enable Language Server",
7314            description: "Whether to use language servers to provide code intelligence.",
7315            field: Box::new(SettingField {
7316                json_path: Some("languages.$(language).enable_language_server"),
7317                pick: |settings_content| {
7318                    language_settings_field(settings_content, |language| {
7319                        language.enable_language_server.as_ref()
7320                    })
7321                },
7322                write: |settings_content, value| {
7323                    language_settings_field_mut(settings_content, value, |language, value| {
7324                        language.enable_language_server = value;
7325                    })
7326                },
7327            }),
7328            metadata: None,
7329            files: USER | PROJECT,
7330        }),
7331        SettingsPageItem::SettingItem(SettingItem {
7332            title: "Language Servers",
7333            description: "The list of language servers to use (or disable) for this language.",
7334            field: Box::new(
7335                SettingField {
7336                    json_path: Some("languages.$(language).language_servers"),
7337                    pick: |settings_content| {
7338                        language_settings_field(settings_content, |language| {
7339                            language.language_servers.as_ref()
7340                        })
7341                    },
7342                    write: |settings_content, value| {
7343                        language_settings_field_mut(settings_content, value, |language, value| {
7344                            language.language_servers = value;
7345                        })
7346                    },
7347                }
7348                .unimplemented(),
7349            ),
7350            metadata: None,
7351            files: USER | PROJECT,
7352        }),
7353        SettingsPageItem::SettingItem(SettingItem {
7354            title: "Linked Edits",
7355            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.",
7356            field: Box::new(SettingField {
7357                json_path: Some("languages.$(language).linked_edits"),
7358                pick: |settings_content| {
7359                    language_settings_field(settings_content, |language| {
7360                        language.linked_edits.as_ref()
7361                    })
7362                },
7363                write: |settings_content, value| {
7364                    language_settings_field_mut(settings_content, value, |language, value| {
7365                        language.linked_edits = value;
7366                    })
7367                },
7368            }),
7369            metadata: None,
7370            files: USER | PROJECT,
7371        }),
7372        SettingsPageItem::SettingItem(SettingItem {
7373            title: "Go To Definition Fallback",
7374            description: "Whether to follow-up empty Go to definition responses from the language server.",
7375            field: Box::new(SettingField {
7376                json_path: Some("go_to_definition_fallback"),
7377                pick: |settings_content| settings_content.editor.go_to_definition_fallback.as_ref(),
7378                write: |settings_content, value| {
7379                    settings_content.editor.go_to_definition_fallback = value;
7380                },
7381            }),
7382            metadata: None,
7383            files: USER,
7384        }),
7385        SettingsPageItem::SectionHeader("LSP Completions"),
7386        SettingsPageItem::SettingItem(SettingItem {
7387            title: "Enabled",
7388            description: "Whether to fetch LSP completions or not.",
7389            field: Box::new(SettingField {
7390                json_path: Some("languages.$(language).completions.lsp"),
7391                pick: |settings_content| {
7392                    language_settings_field(settings_content, |language| {
7393                        language.completions.as_ref()?.lsp.as_ref()
7394                    })
7395                },
7396                write: |settings_content, value| {
7397                    language_settings_field_mut(settings_content, value, |language, value| {
7398                        language.completions.get_or_insert_default().lsp = value;
7399                    })
7400                },
7401            }),
7402            metadata: None,
7403            files: USER | PROJECT,
7404        }),
7405        SettingsPageItem::SettingItem(SettingItem {
7406            title: "Fetch Timeout (milliseconds)",
7407            description: "When fetching LSP completions, determines how long to wait for a response of a particular server (set to 0 to wait indefinitely).",
7408            field: Box::new(SettingField {
7409                json_path: Some("languages.$(language).completions.lsp_fetch_timeout_ms"),
7410                pick: |settings_content| {
7411                    language_settings_field(settings_content, |language| {
7412                        language.completions.as_ref()?.lsp_fetch_timeout_ms.as_ref()
7413                    })
7414                },
7415                write: |settings_content, value| {
7416                    language_settings_field_mut(settings_content, value, |language, value| {
7417                        language
7418                            .completions
7419                            .get_or_insert_default()
7420                            .lsp_fetch_timeout_ms = value;
7421                    })
7422                },
7423            }),
7424            metadata: None,
7425            files: USER | PROJECT,
7426        }),
7427        SettingsPageItem::SettingItem(SettingItem {
7428            title: "Insert Mode",
7429            description: "Controls how LSP completions are inserted.",
7430            field: Box::new(SettingField {
7431                json_path: Some("languages.$(language).completions.lsp_insert_mode"),
7432                pick: |settings_content| {
7433                    language_settings_field(settings_content, |language| {
7434                        language.completions.as_ref()?.lsp_insert_mode.as_ref()
7435                    })
7436                },
7437                write: |settings_content, value| {
7438                    language_settings_field_mut(settings_content, value, |language, value| {
7439                        language.completions.get_or_insert_default().lsp_insert_mode = value;
7440                    })
7441                },
7442            }),
7443            metadata: None,
7444            files: USER | PROJECT,
7445        }),
7446        SettingsPageItem::SectionHeader("Debuggers"),
7447        SettingsPageItem::SettingItem(SettingItem {
7448            title: "Debuggers",
7449            description: "Preferred debuggers for this language.",
7450            field: Box::new(
7451                SettingField {
7452                    json_path: Some("languages.$(language).debuggers"),
7453                    pick: |settings_content| {
7454                        language_settings_field(settings_content, |language| {
7455                            language.debuggers.as_ref()
7456                        })
7457                    },
7458                    write: |settings_content, value| {
7459                        language_settings_field_mut(settings_content, value, |language, value| {
7460                            language.debuggers = value;
7461                        })
7462                    },
7463                }
7464                .unimplemented(),
7465            ),
7466            metadata: None,
7467            files: USER | PROJECT,
7468        }),
7469        SettingsPageItem::SectionHeader("Prettier"),
7470        SettingsPageItem::SettingItem(SettingItem {
7471            title: "Allowed",
7472            description: "Enables or disables formatting with Prettier for a given language.",
7473            field: Box::new(SettingField {
7474                json_path: Some("languages.$(language).prettier.allowed"),
7475                pick: |settings_content| {
7476                    language_settings_field(settings_content, |language| {
7477                        language.prettier.as_ref()?.allowed.as_ref()
7478                    })
7479                },
7480                write: |settings_content, value| {
7481                    language_settings_field_mut(settings_content, value, |language, value| {
7482                        language.prettier.get_or_insert_default().allowed = value;
7483                    })
7484                },
7485            }),
7486            metadata: None,
7487            files: USER | PROJECT,
7488        }),
7489        SettingsPageItem::SettingItem(SettingItem {
7490            title: "Parser",
7491            description: "Forces Prettier integration to use a specific parser name when formatting files with the language.",
7492            field: Box::new(SettingField {
7493                json_path: Some("languages.$(language).prettier.parser"),
7494                pick: |settings_content| {
7495                    language_settings_field(settings_content, |language| {
7496                        language.prettier.as_ref()?.parser.as_ref()
7497                    })
7498                },
7499                write: |settings_content, value| {
7500                    language_settings_field_mut(settings_content, value, |language, value| {
7501                        language.prettier.get_or_insert_default().parser = value;
7502                    })
7503                },
7504            }),
7505            metadata: None,
7506            files: USER | PROJECT,
7507        }),
7508        SettingsPageItem::SettingItem(SettingItem {
7509            title: "Plugins",
7510            description: "Forces Prettier integration to use specific plugins when formatting files with the language.",
7511            field: Box::new(
7512                SettingField {
7513                    json_path: Some("languages.$(language).prettier.plugins"),
7514                    pick: |settings_content| {
7515                        language_settings_field(settings_content, |language| {
7516                            language.prettier.as_ref()?.plugins.as_ref()
7517                        })
7518                    },
7519                    write: |settings_content, value| {
7520                        language_settings_field_mut(settings_content, value, |language, value| {
7521                            language.prettier.get_or_insert_default().plugins = value;
7522                        })
7523                    },
7524                }
7525                .unimplemented(),
7526            ),
7527            metadata: None,
7528            files: USER | PROJECT,
7529        }),
7530        SettingsPageItem::SettingItem(SettingItem {
7531            title: "Options",
7532            description: "Default Prettier options, in the format as in package.json section for Prettier.",
7533            field: Box::new(
7534                SettingField {
7535                    json_path: Some("languages.$(language).prettier.options"),
7536                    pick: |settings_content| {
7537                        language_settings_field(settings_content, |language| {
7538                            language.prettier.as_ref()?.options.as_ref()
7539                        })
7540                    },
7541                    write: |settings_content, value| {
7542                        language_settings_field_mut(settings_content, value, |language, value| {
7543                            language.prettier.get_or_insert_default().options = value;
7544                        })
7545                    },
7546                }
7547                .unimplemented(),
7548            ),
7549            metadata: None,
7550            files: USER | PROJECT,
7551        }),
7552    ]
7553}
7554
7555fn edit_prediction_language_settings_section() -> Vec<SettingsPageItem> {
7556    vec![
7557        SettingsPageItem::SectionHeader("Edit Predictions"),
7558        SettingsPageItem::SubPageLink(SubPageLink {
7559            title: "Configure Providers".into(),
7560            json_path: Some("edit_predictions.providers"),
7561            description: Some("Set up different edit prediction providers in complement to Zed's built-in Zeta model.".into()),
7562            in_json: false,
7563            files: USER,
7564            render: Arc::new(|_, window, cx| {
7565                let settings_window = cx.entity();
7566                let page = window.use_state(cx, |_, _| {
7567                    crate::pages::EditPredictionSetupPage::new(settings_window)
7568                });
7569                page.into_any_element()
7570            }),
7571        }),
7572        SettingsPageItem::SettingItem(SettingItem {
7573            title: "Show Edit Predictions",
7574            description: "Controls whether edit predictions are shown immediately or manually.",
7575            field: Box::new(SettingField {
7576                json_path: Some("languages.$(language).show_edit_predictions"),
7577                pick: |settings_content| {
7578                    language_settings_field(settings_content, |language| {
7579                        language.show_edit_predictions.as_ref()
7580                    })
7581                },
7582                write: |settings_content, value| {
7583                    language_settings_field_mut(settings_content, value, |language, value| {
7584                        language.show_edit_predictions = value;
7585                    })
7586                },
7587            }),
7588            metadata: None,
7589            files: USER | PROJECT,
7590        }),
7591        SettingsPageItem::SettingItem(SettingItem {
7592            title: "Disable in Language Scopes",
7593            description: "Controls whether edit predictions are shown in the given language scopes.",
7594            field: Box::new(
7595                SettingField {
7596                    json_path: Some("languages.$(language).edit_predictions_disabled_in"),
7597                    pick: |settings_content| {
7598                        language_settings_field(settings_content, |language| {
7599                            language.edit_predictions_disabled_in.as_ref()
7600                        })
7601                    },
7602                    write: |settings_content, value| {
7603                        language_settings_field_mut(settings_content, value, |language, value| {
7604                            language.edit_predictions_disabled_in = value;
7605                        })
7606                    },
7607                }
7608                .unimplemented(),
7609            ),
7610            metadata: None,
7611            files: USER | PROJECT,
7612        }),
7613    ]
7614}
7615
7616fn show_scrollbar_or_editor(
7617    settings_content: &SettingsContent,
7618    show: fn(&SettingsContent) -> Option<&settings::ShowScrollbar>,
7619) -> Option<&settings::ShowScrollbar> {
7620    show(settings_content).or(settings_content
7621        .editor
7622        .scrollbar
7623        .as_ref()
7624        .and_then(|scrollbar| scrollbar.show.as_ref()))
7625}
7626
7627fn dynamic_variants<T>() -> &'static [T::Discriminant]
7628where
7629    T: strum::IntoDiscriminant,
7630    T::Discriminant: strum::VariantArray,
7631{
7632    <<T as strum::IntoDiscriminant>::Discriminant as strum::VariantArray>::VARIANTS
7633}