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