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                ];
6197                items.extend(edit_prediction_language_settings_section());
6198                items.extend(
6199                    [
6200                        SettingsPageItem::SettingItem(SettingItem {
6201                            title: "Display Mode",
6202                            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.",
6203                            field: Box::new(SettingField {
6204                                json_path: Some("edit_prediction.display_mode"),
6205                                pick: |settings_content| {
6206                                    settings_content.project.all_languages.edit_predictions.as_ref()?.mode.as_ref()
6207                                },
6208                                write: |settings_content, value| {
6209                                    settings_content.project.all_languages.edit_predictions.get_or_insert_default().mode = value;
6210                                },
6211                            }),
6212                            metadata: None,
6213                            files: USER,
6214                        }),
6215                        SettingsPageItem::SettingItem(SettingItem {
6216                            title: "Display In Text Threads",
6217                            description: "Whether edit predictions are enabled when editing text threads in the agent panel.",
6218                            field: Box::new(SettingField {
6219                                json_path: Some("edit_prediction.in_text_threads"),
6220                                pick: |settings_content| {
6221                                    settings_content.project.all_languages.edit_predictions.as_ref()?.enabled_in_text_threads.as_ref()
6222                                },
6223                                write: |settings_content, value| {
6224                                    settings_content.project.all_languages.edit_predictions.get_or_insert_default().enabled_in_text_threads = value;
6225                                },
6226                            }),
6227                            metadata: None,
6228                            files: USER,
6229                        }),
6230                    ]
6231                );
6232                items
6233            },
6234        },
6235        SettingsPage {
6236            title: "Network",
6237            items: vec![
6238                SettingsPageItem::SectionHeader("Network"),
6239                // todo(settings_ui): Proxy needs a default
6240                SettingsPageItem::SettingItem(SettingItem {
6241                    title: "Proxy",
6242                    description: "The proxy to use for network requests.",
6243                    field: Box::new(
6244                        SettingField {
6245                            json_path: Some("proxy"),
6246                            pick: |settings_content| settings_content.proxy.as_ref(),
6247                            write: |settings_content, value| {
6248                                settings_content.proxy = value;
6249                            },
6250                        }
6251                        .unimplemented(),
6252                    ),
6253                    metadata: Some(Box::new(SettingsFieldMetadata {
6254                        placeholder: Some("socks5h://localhost:10808"),
6255                        ..Default::default()
6256                    })),
6257                    files: USER,
6258                }),
6259                SettingsPageItem::SettingItem(SettingItem {
6260                    title: "Server URL",
6261                    description: "The URL of the Zed server to connect to.",
6262                    field: Box::new(SettingField {
6263                        json_path: Some("server_url"),
6264                        pick: |settings_content| settings_content.server_url.as_ref(),
6265                        write: |settings_content, value| {
6266                            settings_content.server_url = value;
6267                        },
6268                    }),
6269                    metadata: Some(Box::new(SettingsFieldMetadata {
6270                        placeholder: Some("https://zed.dev"),
6271                        ..Default::default()
6272                    })),
6273                    files: USER,
6274                }),
6275            ],
6276        },
6277    ]
6278}
6279
6280const LANGUAGES_SECTION_HEADER: &'static str = "Languages";
6281
6282fn current_language() -> Option<SharedString> {
6283    sub_page_stack().iter().find_map(|page| {
6284        (page.section_header == LANGUAGES_SECTION_HEADER).then(|| page.link.title.clone())
6285    })
6286}
6287
6288fn language_settings_field<T>(
6289    settings_content: &SettingsContent,
6290    get: fn(&LanguageSettingsContent) -> Option<&T>,
6291) -> Option<&T> {
6292    let all_languages = &settings_content.project.all_languages;
6293    if let Some(current_language_name) = current_language() {
6294        if let Some(current_language) = all_languages.languages.0.get(&current_language_name) {
6295            let value = get(current_language);
6296            if value.is_some() {
6297                return value;
6298            }
6299        }
6300    }
6301    let default_value = get(&all_languages.defaults);
6302    return default_value;
6303}
6304
6305fn language_settings_field_mut<T>(
6306    settings_content: &mut SettingsContent,
6307    value: Option<T>,
6308    write: fn(&mut LanguageSettingsContent, Option<T>),
6309) {
6310    let all_languages = &mut settings_content.project.all_languages;
6311    let language_content = if let Some(current_language) = current_language() {
6312        all_languages
6313            .languages
6314            .0
6315            .entry(current_language)
6316            .or_default()
6317    } else {
6318        &mut all_languages.defaults
6319    };
6320    write(language_content, value);
6321}
6322
6323fn language_settings_data() -> Vec<SettingsPageItem> {
6324    let mut items = vec![
6325        SettingsPageItem::SectionHeader("Indentation"),
6326        SettingsPageItem::SettingItem(SettingItem {
6327            title: "Tab Size",
6328            description: "How many columns a tab should occupy.",
6329            field: Box::new(SettingField {
6330                json_path: Some("languages.$(language).tab_size"), // TODO(cameron): not JQ syntax because not URL-safe
6331                pick: |settings_content| {
6332                    language_settings_field(settings_content, |language| language.tab_size.as_ref())
6333                },
6334                write: |settings_content, value| {
6335                    language_settings_field_mut(settings_content, value, |language, value| {
6336                        language.tab_size = value;
6337                    })
6338                },
6339            }),
6340            metadata: None,
6341            files: USER | PROJECT,
6342        }),
6343        SettingsPageItem::SettingItem(SettingItem {
6344            title: "Hard Tabs",
6345            description: "Whether to indent lines using tab characters, as opposed to multiple spaces.",
6346            field: Box::new(SettingField {
6347                json_path: Some("languages.$(language).hard_tabs"),
6348                pick: |settings_content| {
6349                    language_settings_field(settings_content, |language| {
6350                        language.hard_tabs.as_ref()
6351                    })
6352                },
6353                write: |settings_content, value| {
6354                    language_settings_field_mut(settings_content, value, |language, value| {
6355                        language.hard_tabs = value;
6356                    })
6357                },
6358            }),
6359            metadata: None,
6360            files: USER | PROJECT,
6361        }),
6362        SettingsPageItem::SettingItem(SettingItem {
6363            title: "Auto Indent",
6364            description: "Whether indentation should be adjusted based on the context whilst typing.",
6365            field: Box::new(SettingField {
6366                json_path: Some("languages.$(language).auto_indent"),
6367                pick: |settings_content| {
6368                    language_settings_field(settings_content, |language| {
6369                        language.auto_indent.as_ref()
6370                    })
6371                },
6372                write: |settings_content, value| {
6373                    language_settings_field_mut(settings_content, value, |language, value| {
6374                        language.auto_indent = value;
6375                    })
6376                },
6377            }),
6378            metadata: None,
6379            files: USER | PROJECT,
6380        }),
6381        SettingsPageItem::SettingItem(SettingItem {
6382            title: "Auto Indent On Paste",
6383            description: "Whether indentation of pasted content should be adjusted based on the context.",
6384            field: Box::new(SettingField {
6385                json_path: Some("languages.$(language).auto_indent_on_paste"),
6386                pick: |settings_content| {
6387                    language_settings_field(settings_content, |language| {
6388                        language.auto_indent_on_paste.as_ref()
6389                    })
6390                },
6391                write: |settings_content, value| {
6392                    language_settings_field_mut(settings_content, value, |language, value| {
6393                        language.auto_indent_on_paste = value;
6394                    })
6395                },
6396            }),
6397            metadata: None,
6398            files: USER | PROJECT,
6399        }),
6400        SettingsPageItem::SectionHeader("Wrapping"),
6401        SettingsPageItem::SettingItem(SettingItem {
6402            title: "Soft Wrap",
6403            description: "How to soft-wrap long lines of text.",
6404            field: Box::new(SettingField {
6405                json_path: Some("languages.$(language).soft_wrap"),
6406                pick: |settings_content| {
6407                    language_settings_field(settings_content, |language| {
6408                        language.soft_wrap.as_ref()
6409                    })
6410                },
6411                write: |settings_content, value| {
6412                    language_settings_field_mut(settings_content, value, |language, value| {
6413                        language.soft_wrap = value;
6414                    })
6415                },
6416            }),
6417            metadata: None,
6418            files: USER | PROJECT,
6419        }),
6420        SettingsPageItem::SettingItem(SettingItem {
6421            title: "Show Wrap Guides",
6422            description: "Show wrap guides in the editor.",
6423            field: Box::new(SettingField {
6424                json_path: Some("languages.$(language).show_wrap_guides"),
6425                pick: |settings_content| {
6426                    language_settings_field(settings_content, |language| {
6427                        language.show_wrap_guides.as_ref()
6428                    })
6429                },
6430                write: |settings_content, value| {
6431                    language_settings_field_mut(settings_content, value, |language, value| {
6432                        language.show_wrap_guides = value;
6433                    })
6434                },
6435            }),
6436            metadata: None,
6437            files: USER | PROJECT,
6438        }),
6439        SettingsPageItem::SettingItem(SettingItem {
6440            title: "Preferred Line Length",
6441            description: "The column at which to soft-wrap lines, for buffers where soft-wrap is enabled.",
6442            field: Box::new(SettingField {
6443                json_path: Some("languages.$(language).preferred_line_length"),
6444                pick: |settings_content| {
6445                    language_settings_field(settings_content, |language| {
6446                        language.preferred_line_length.as_ref()
6447                    })
6448                },
6449                write: |settings_content, value| {
6450                    language_settings_field_mut(settings_content, value, |language, value| {
6451                        language.preferred_line_length = value;
6452                    })
6453                },
6454            }),
6455            metadata: None,
6456            files: USER | PROJECT,
6457        }),
6458        SettingsPageItem::SettingItem(SettingItem {
6459            title: "Wrap Guides",
6460            description: "Character counts at which to show wrap guides in the editor.",
6461            field: Box::new(
6462                SettingField {
6463                    json_path: Some("languages.$(language).wrap_guides"),
6464                    pick: |settings_content| {
6465                        language_settings_field(settings_content, |language| {
6466                            language.wrap_guides.as_ref()
6467                        })
6468                    },
6469                    write: |settings_content, value| {
6470                        language_settings_field_mut(settings_content, value, |language, value| {
6471                            language.wrap_guides = value;
6472                        })
6473                    },
6474                }
6475                .unimplemented(),
6476            ),
6477            metadata: None,
6478            files: USER | PROJECT,
6479        }),
6480        SettingsPageItem::SettingItem(SettingItem {
6481            title: "Allow Rewrap",
6482            description: "Controls where the `editor::rewrap` action is allowed for this language.",
6483            field: Box::new(SettingField {
6484                json_path: Some("languages.$(language).allow_rewrap"),
6485                pick: |settings_content| {
6486                    language_settings_field(settings_content, |language| {
6487                        language.allow_rewrap.as_ref()
6488                    })
6489                },
6490                write: |settings_content, value| {
6491                    language_settings_field_mut(settings_content, value, |language, value| {
6492                        language.allow_rewrap = value;
6493                    })
6494                },
6495            }),
6496            metadata: None,
6497            files: USER | PROJECT,
6498        }),
6499        SettingsPageItem::SectionHeader("Indent Guides"),
6500        SettingsPageItem::SettingItem(SettingItem {
6501            title: "Enabled",
6502            description: "Display indent guides in the editor.",
6503            field: Box::new(SettingField {
6504                json_path: Some("languages.$(language).indent_guides.enabled"),
6505                pick: |settings_content| {
6506                    language_settings_field(settings_content, |language| {
6507                        language
6508                            .indent_guides
6509                            .as_ref()
6510                            .and_then(|indent_guides| indent_guides.enabled.as_ref())
6511                    })
6512                },
6513                write: |settings_content, value| {
6514                    language_settings_field_mut(settings_content, value, |language, value| {
6515                        language.indent_guides.get_or_insert_default().enabled = value;
6516                    })
6517                },
6518            }),
6519            metadata: None,
6520            files: USER | PROJECT,
6521        }),
6522        SettingsPageItem::SettingItem(SettingItem {
6523            title: "Line Width",
6524            description: "The width of the indent guides in pixels, between 1 and 10.",
6525            field: Box::new(SettingField {
6526                json_path: Some("languages.$(language).indent_guides.line_width"),
6527                pick: |settings_content| {
6528                    language_settings_field(settings_content, |language| {
6529                        language
6530                            .indent_guides
6531                            .as_ref()
6532                            .and_then(|indent_guides| indent_guides.line_width.as_ref())
6533                    })
6534                },
6535                write: |settings_content, value| {
6536                    language_settings_field_mut(settings_content, value, |language, value| {
6537                        language.indent_guides.get_or_insert_default().line_width = value;
6538                    })
6539                },
6540            }),
6541            metadata: None,
6542            files: USER | PROJECT,
6543        }),
6544        SettingsPageItem::SettingItem(SettingItem {
6545            title: "Active Line Width",
6546            description: "The width of the active indent guide in pixels, between 1 and 10.",
6547            field: Box::new(SettingField {
6548                json_path: Some("languages.$(language).indent_guides.active_line_width"),
6549                pick: |settings_content| {
6550                    language_settings_field(settings_content, |language| {
6551                        language
6552                            .indent_guides
6553                            .as_ref()
6554                            .and_then(|indent_guides| indent_guides.active_line_width.as_ref())
6555                    })
6556                },
6557                write: |settings_content, value| {
6558                    language_settings_field_mut(settings_content, value, |language, value| {
6559                        language
6560                            .indent_guides
6561                            .get_or_insert_default()
6562                            .active_line_width = value;
6563                    })
6564                },
6565            }),
6566            metadata: None,
6567            files: USER | PROJECT,
6568        }),
6569        SettingsPageItem::SettingItem(SettingItem {
6570            title: "Coloring",
6571            description: "Determines how indent guides are colored.",
6572            field: Box::new(SettingField {
6573                json_path: Some("languages.$(language).indent_guides.coloring"),
6574                pick: |settings_content| {
6575                    language_settings_field(settings_content, |language| {
6576                        language
6577                            .indent_guides
6578                            .as_ref()
6579                            .and_then(|indent_guides| indent_guides.coloring.as_ref())
6580                    })
6581                },
6582                write: |settings_content, value| {
6583                    language_settings_field_mut(settings_content, value, |language, value| {
6584                        language.indent_guides.get_or_insert_default().coloring = value;
6585                    })
6586                },
6587            }),
6588            metadata: None,
6589            files: USER | PROJECT,
6590        }),
6591        SettingsPageItem::SettingItem(SettingItem {
6592            title: "Background Coloring",
6593            description: "Determines how indent guide backgrounds are colored.",
6594            field: Box::new(SettingField {
6595                json_path: Some("languages.$(language).indent_guides.background_coloring"),
6596                pick: |settings_content| {
6597                    language_settings_field(settings_content, |language| {
6598                        language
6599                            .indent_guides
6600                            .as_ref()
6601                            .and_then(|indent_guides| indent_guides.background_coloring.as_ref())
6602                    })
6603                },
6604                write: |settings_content, value| {
6605                    language_settings_field_mut(settings_content, value, |language, value| {
6606                        language
6607                            .indent_guides
6608                            .get_or_insert_default()
6609                            .background_coloring = value;
6610                    })
6611                },
6612            }),
6613            metadata: None,
6614            files: USER | PROJECT,
6615        }),
6616        SettingsPageItem::SectionHeader("Formatting"),
6617        SettingsPageItem::SettingItem(SettingItem {
6618            title: "Format On Save",
6619            description: "Whether or not to perform a buffer format before saving.",
6620            field: Box::new(
6621                // TODO(settings_ui): this setting should just be a bool
6622                SettingField {
6623                    json_path: Some("languages.$(language).format_on_save"),
6624                    pick: |settings_content| {
6625                        language_settings_field(settings_content, |language| {
6626                            language.format_on_save.as_ref()
6627                        })
6628                    },
6629                    write: |settings_content, value| {
6630                        language_settings_field_mut(settings_content, value, |language, value| {
6631                            language.format_on_save = value;
6632                        })
6633                    },
6634                },
6635            ),
6636            metadata: None,
6637            files: USER | PROJECT,
6638        }),
6639        SettingsPageItem::SettingItem(SettingItem {
6640            title: "Remove Trailing Whitespace On Save",
6641            description: "Whether or not to remove any trailing whitespace from lines of a buffer before saving it.",
6642            field: Box::new(SettingField {
6643                json_path: Some("languages.$(language).remove_trailing_whitespace_on_save"),
6644                pick: |settings_content| {
6645                    language_settings_field(settings_content, |language| {
6646                        language.remove_trailing_whitespace_on_save.as_ref()
6647                    })
6648                },
6649                write: |settings_content, value| {
6650                    language_settings_field_mut(settings_content, value, |language, value| {
6651                        language.remove_trailing_whitespace_on_save = value;
6652                    })
6653                },
6654            }),
6655            metadata: None,
6656            files: USER | PROJECT,
6657        }),
6658        SettingsPageItem::SettingItem(SettingItem {
6659            title: "Ensure Final Newline On Save",
6660            description: "Whether or not to ensure there's a single newline at the end of a buffer when saving it.",
6661            field: Box::new(SettingField {
6662                json_path: Some("languages.$(language).ensure_final_newline_on_save"),
6663                pick: |settings_content| {
6664                    language_settings_field(settings_content, |language| {
6665                        language.ensure_final_newline_on_save.as_ref()
6666                    })
6667                },
6668                write: |settings_content, value| {
6669                    language_settings_field_mut(settings_content, value, |language, value| {
6670                        language.ensure_final_newline_on_save = value;
6671                    })
6672                },
6673            }),
6674            metadata: None,
6675            files: USER | PROJECT,
6676        }),
6677        SettingsPageItem::SettingItem(SettingItem {
6678            title: "Formatter",
6679            description: "How to perform a buffer format.",
6680            field: Box::new(
6681                SettingField {
6682                    json_path: Some("languages.$(language).formatter"),
6683                    pick: |settings_content| {
6684                        language_settings_field(settings_content, |language| {
6685                            language.formatter.as_ref()
6686                        })
6687                    },
6688                    write: |settings_content, value| {
6689                        language_settings_field_mut(settings_content, value, |language, value| {
6690                            language.formatter = value;
6691                        })
6692                    },
6693                }
6694                .unimplemented(),
6695            ),
6696            metadata: None,
6697            files: USER | PROJECT,
6698        }),
6699        SettingsPageItem::SettingItem(SettingItem {
6700            title: "Use On Type Format",
6701            description: "Whether to use additional LSP queries to format (and amend) the code after every \"trigger\" symbol input, defined by LSP server capabilities",
6702            field: Box::new(SettingField {
6703                json_path: Some("languages.$(language).use_on_type_format"),
6704                pick: |settings_content| {
6705                    language_settings_field(settings_content, |language| {
6706                        language.use_on_type_format.as_ref()
6707                    })
6708                },
6709                write: |settings_content, value| {
6710                    language_settings_field_mut(settings_content, value, |language, value| {
6711                        language.use_on_type_format = value;
6712                    })
6713                },
6714            }),
6715            metadata: None,
6716            files: USER | PROJECT,
6717        }),
6718        SettingsPageItem::SettingItem(SettingItem {
6719            title: "Code Actions On Format",
6720            description: "Additional code actions to run when formatting.",
6721            field: Box::new(
6722                SettingField {
6723                    json_path: Some("languages.$(language).code_actions_on_format"),
6724                    pick: |settings_content| {
6725                        language_settings_field(settings_content, |language| {
6726                            language.code_actions_on_format.as_ref()
6727                        })
6728                    },
6729                    write: |settings_content, value| {
6730                        language_settings_field_mut(settings_content, value, |language, value| {
6731                            language.code_actions_on_format = value;
6732                        })
6733                    },
6734                }
6735                .unimplemented(),
6736            ),
6737            metadata: None,
6738            files: USER | PROJECT,
6739        }),
6740        SettingsPageItem::SectionHeader("Autoclose"),
6741        SettingsPageItem::SettingItem(SettingItem {
6742            title: "Use Autoclose",
6743            description: "Whether to automatically type closing characters for you. For example, when you type '(', Zed will automatically add a closing ')' at the correct position.",
6744            field: Box::new(SettingField {
6745                json_path: Some("languages.$(language).use_autoclose"),
6746                pick: |settings_content| {
6747                    language_settings_field(settings_content, |language| {
6748                        language.use_autoclose.as_ref()
6749                    })
6750                },
6751                write: |settings_content, value| {
6752                    language_settings_field_mut(settings_content, value, |language, value| {
6753                        language.use_autoclose = value;
6754                    })
6755                },
6756            }),
6757            metadata: None,
6758            files: USER | PROJECT,
6759        }),
6760        SettingsPageItem::SettingItem(SettingItem {
6761            title: "Use Auto Surround",
6762            description: "Whether to automatically surround text with characters for you. For example, when you select text and type '(', Zed will automatically surround text with ().",
6763            field: Box::new(SettingField {
6764                json_path: Some("languages.$(language).use_auto_surround"),
6765                pick: |settings_content| {
6766                    language_settings_field(settings_content, |language| {
6767                        language.use_auto_surround.as_ref()
6768                    })
6769                },
6770                write: |settings_content, value| {
6771                    language_settings_field_mut(settings_content, value, |language, value| {
6772                        language.use_auto_surround = value;
6773                    })
6774                },
6775            }),
6776            metadata: None,
6777            files: USER | PROJECT,
6778        }),
6779        SettingsPageItem::SettingItem(SettingItem {
6780            title: "Always Treat Brackets As Autoclosed",
6781            description: "Controls whether the closing characters are always skipped over and auto-removed no matter how they were inserted.",
6782            field: Box::new(SettingField {
6783                json_path: Some("languages.$(language).always_treat_brackets_as_autoclosed"),
6784                pick: |settings_content| {
6785                    language_settings_field(settings_content, |language| {
6786                        language.always_treat_brackets_as_autoclosed.as_ref()
6787                    })
6788                },
6789                write: |settings_content, value| {
6790                    language_settings_field_mut(settings_content, value, |language, value| {
6791                        language.always_treat_brackets_as_autoclosed = value;
6792                    })
6793                },
6794            }),
6795            metadata: None,
6796            files: USER | PROJECT,
6797        }),
6798        SettingsPageItem::SettingItem(SettingItem {
6799            title: "JSX Tag Auto Close",
6800            description: "Whether to automatically close JSX tags.",
6801            field: Box::new(SettingField {
6802                json_path: Some("languages.$(language).jsx_tag_auto_close"),
6803                // TODO(settings_ui): this setting should just be a bool
6804                pick: |settings_content| {
6805                    language_settings_field(settings_content, |language| {
6806                        language.jsx_tag_auto_close.as_ref()?.enabled.as_ref()
6807                    })
6808                },
6809                write: |settings_content, value| {
6810                    language_settings_field_mut(settings_content, value, |language, value| {
6811                        language.jsx_tag_auto_close.get_or_insert_default().enabled = value;
6812                    })
6813                },
6814            }),
6815            metadata: None,
6816            files: USER | PROJECT,
6817        }),
6818        SettingsPageItem::SectionHeader("Whitespace"),
6819        SettingsPageItem::SettingItem(SettingItem {
6820            title: "Show Whitespaces",
6821            description: "Whether to show tabs and spaces in the editor.",
6822            field: Box::new(SettingField {
6823                json_path: Some("languages.$(language).show_whitespaces"),
6824                pick: |settings_content| {
6825                    language_settings_field(settings_content, |language| {
6826                        language.show_whitespaces.as_ref()
6827                    })
6828                },
6829                write: |settings_content, value| {
6830                    language_settings_field_mut(settings_content, value, |language, value| {
6831                        language.show_whitespaces = value;
6832                    })
6833                },
6834            }),
6835            metadata: None,
6836            files: USER | PROJECT,
6837        }),
6838        SettingsPageItem::SettingItem(SettingItem {
6839            title: "Space Whitespace Indicator",
6840            description: "Visible character used to render space characters when show_whitespaces is enabled (default: \"\")",
6841            field: Box::new(
6842                SettingField {
6843                    json_path: Some("languages.$(language).whitespace_map.space"),
6844                    pick: |settings_content| {
6845                        language_settings_field(settings_content, |language| {
6846                            language.whitespace_map.as_ref()?.space.as_ref()
6847                        })
6848                    },
6849                    write: |settings_content, value| {
6850                        language_settings_field_mut(settings_content, value, |language, value| {
6851                            language.whitespace_map.get_or_insert_default().space = value;
6852                        })
6853                    },
6854                }
6855                .unimplemented(),
6856            ),
6857            metadata: None,
6858            files: USER | PROJECT,
6859        }),
6860        SettingsPageItem::SettingItem(SettingItem {
6861            title: "Tab Whitespace Indicator",
6862            description: "Visible character used to render tab characters when show_whitespaces is enabled (default: \"\")",
6863            field: Box::new(
6864                SettingField {
6865                    json_path: Some("languages.$(language).whitespace_map.tab"),
6866                    pick: |settings_content| {
6867                        language_settings_field(settings_content, |language| {
6868                            language.whitespace_map.as_ref()?.tab.as_ref()
6869                        })
6870                    },
6871                    write: |settings_content, value| {
6872                        language_settings_field_mut(settings_content, value, |language, value| {
6873                            language.whitespace_map.get_or_insert_default().tab = value;
6874                        })
6875                    },
6876                }
6877                .unimplemented(),
6878            ),
6879            metadata: None,
6880            files: USER | PROJECT,
6881        }),
6882        SettingsPageItem::SectionHeader("Completions"),
6883        SettingsPageItem::SettingItem(SettingItem {
6884            title: "Show Completions On Input",
6885            description: "Whether to pop the completions menu while typing in an editor without explicitly requesting it.",
6886            field: Box::new(SettingField {
6887                json_path: Some("languages.$(language).show_completions_on_input"),
6888                pick: |settings_content| {
6889                    language_settings_field(settings_content, |language| {
6890                        language.show_completions_on_input.as_ref()
6891                    })
6892                },
6893                write: |settings_content, value| {
6894                    language_settings_field_mut(settings_content, value, |language, value| {
6895                        language.show_completions_on_input = value;
6896                    })
6897                },
6898            }),
6899            metadata: None,
6900            files: USER | PROJECT,
6901        }),
6902        SettingsPageItem::SettingItem(SettingItem {
6903            title: "Show Completion Documentation",
6904            description: "Whether to display inline and alongside documentation for items in the completions menu.",
6905            field: Box::new(SettingField {
6906                json_path: Some("languages.$(language).show_completion_documentation"),
6907                pick: |settings_content| {
6908                    language_settings_field(settings_content, |language| {
6909                        language.show_completion_documentation.as_ref()
6910                    })
6911                },
6912                write: |settings_content, value| {
6913                    language_settings_field_mut(settings_content, value, |language, value| {
6914                        language.show_completion_documentation = value;
6915                    })
6916                },
6917            }),
6918            metadata: None,
6919            files: USER | PROJECT,
6920        }),
6921        SettingsPageItem::SettingItem(SettingItem {
6922            title: "Words",
6923            description: "Controls how words are completed.",
6924            field: Box::new(SettingField {
6925                json_path: Some("languages.$(language).completions.words"),
6926                pick: |settings_content| {
6927                    language_settings_field(settings_content, |language| {
6928                        language.completions.as_ref()?.words.as_ref()
6929                    })
6930                },
6931                write: |settings_content, value| {
6932                    language_settings_field_mut(settings_content, value, |language, value| {
6933                        language.completions.get_or_insert_default().words = value;
6934                    })
6935                },
6936            }),
6937            metadata: None,
6938            files: USER | PROJECT,
6939        }),
6940        SettingsPageItem::SettingItem(SettingItem {
6941            title: "Words Min Length",
6942            description: "How many characters has to be in the completions query to automatically show the words-based completions.",
6943            field: Box::new(SettingField {
6944                json_path: Some("languages.$(language).completions.words_min_length"),
6945                pick: |settings_content| {
6946                    language_settings_field(settings_content, |language| {
6947                        language.completions.as_ref()?.words_min_length.as_ref()
6948                    })
6949                },
6950                write: |settings_content, value| {
6951                    language_settings_field_mut(settings_content, value, |language, value| {
6952                        language
6953                            .completions
6954                            .get_or_insert_default()
6955                            .words_min_length = value;
6956                    })
6957                },
6958            }),
6959            metadata: None,
6960            files: USER | PROJECT,
6961        }),
6962        SettingsPageItem::SettingItem(SettingItem {
6963            title: "Completion Menu Scrollbar",
6964            description: "When to show the scrollbar in the completion menu.",
6965            field: Box::new(SettingField {
6966                json_path: Some("editor.completion_menu_scrollbar"),
6967                pick: |settings_content| settings_content.editor.completion_menu_scrollbar.as_ref(),
6968                write: |settings_content, value| {
6969                    settings_content.editor.completion_menu_scrollbar = value;
6970                },
6971            }),
6972            metadata: None,
6973            files: USER,
6974        }),
6975        SettingsPageItem::SettingItem(SettingItem {
6976            title: "Completion Detail Alignment",
6977            description: "Whether to align detail text in code completions context menus left or right.",
6978            field: Box::new(SettingField {
6979                json_path: Some("editor.completion_detail_alignment"),
6980                pick: |settings_content| {
6981                    settings_content.editor.completion_detail_alignment.as_ref()
6982                },
6983                write: |settings_content, value| {
6984                    settings_content.editor.completion_detail_alignment = value;
6985                },
6986            }),
6987            metadata: None,
6988            files: USER,
6989        }),
6990        SettingsPageItem::SectionHeader("Inlay Hints"),
6991        SettingsPageItem::SettingItem(SettingItem {
6992            title: "Enabled",
6993            description: "Global switch to toggle hints on and off.",
6994            field: Box::new(SettingField {
6995                json_path: Some("languages.$(language).inlay_hints.enabled"),
6996                pick: |settings_content| {
6997                    language_settings_field(settings_content, |language| {
6998                        language.inlay_hints.as_ref()?.enabled.as_ref()
6999                    })
7000                },
7001                write: |settings_content, value| {
7002                    language_settings_field_mut(settings_content, value, |language, value| {
7003                        language.inlay_hints.get_or_insert_default().enabled = value;
7004                    })
7005                },
7006            }),
7007            metadata: None,
7008            files: USER | PROJECT,
7009        }),
7010        SettingsPageItem::SettingItem(SettingItem {
7011            title: "Show Value Hints",
7012            description: "Global switch to toggle inline values on and off when debugging.",
7013            field: Box::new(SettingField {
7014                json_path: Some("languages.$(language).inlay_hints.show_value_hints"),
7015                pick: |settings_content| {
7016                    language_settings_field(settings_content, |language| {
7017                        language.inlay_hints.as_ref()?.show_value_hints.as_ref()
7018                    })
7019                },
7020                write: |settings_content, value| {
7021                    language_settings_field_mut(settings_content, value, |language, value| {
7022                        language
7023                            .inlay_hints
7024                            .get_or_insert_default()
7025                            .show_value_hints = value;
7026                    })
7027                },
7028            }),
7029            metadata: None,
7030            files: USER | PROJECT,
7031        }),
7032        SettingsPageItem::SettingItem(SettingItem {
7033            title: "Show Type Hints",
7034            description: "Whether type hints should be shown.",
7035            field: Box::new(SettingField {
7036                json_path: Some("languages.$(language).inlay_hints.show_type_hints"),
7037                pick: |settings_content| {
7038                    language_settings_field(settings_content, |language| {
7039                        language.inlay_hints.as_ref()?.show_type_hints.as_ref()
7040                    })
7041                },
7042                write: |settings_content, value| {
7043                    language_settings_field_mut(settings_content, value, |language, value| {
7044                        language.inlay_hints.get_or_insert_default().show_type_hints = value;
7045                    })
7046                },
7047            }),
7048            metadata: None,
7049            files: USER | PROJECT,
7050        }),
7051        SettingsPageItem::SettingItem(SettingItem {
7052            title: "Show Parameter Hints",
7053            description: "Whether parameter hints should be shown.",
7054            field: Box::new(SettingField {
7055                json_path: Some("languages.$(language).inlay_hints.show_parameter_hints"),
7056                pick: |settings_content| {
7057                    language_settings_field(settings_content, |language| {
7058                        language.inlay_hints.as_ref()?.show_parameter_hints.as_ref()
7059                    })
7060                },
7061                write: |settings_content, value| {
7062                    language_settings_field_mut(settings_content, value, |language, value| {
7063                        language
7064                            .inlay_hints
7065                            .get_or_insert_default()
7066                            .show_parameter_hints = value;
7067                    })
7068                },
7069            }),
7070            metadata: None,
7071            files: USER | PROJECT,
7072        }),
7073        SettingsPageItem::SettingItem(SettingItem {
7074            title: "Show Other Hints",
7075            description: "Whether other hints should be shown.",
7076            field: Box::new(SettingField {
7077                json_path: Some("languages.$(language).inlay_hints.show_other_hints"),
7078                pick: |settings_content| {
7079                    language_settings_field(settings_content, |language| {
7080                        language.inlay_hints.as_ref()?.show_other_hints.as_ref()
7081                    })
7082                },
7083                write: |settings_content, value| {
7084                    language_settings_field_mut(settings_content, value, |language, value| {
7085                        language
7086                            .inlay_hints
7087                            .get_or_insert_default()
7088                            .show_other_hints = value;
7089                    })
7090                },
7091            }),
7092            metadata: None,
7093            files: USER | PROJECT,
7094        }),
7095        SettingsPageItem::SettingItem(SettingItem {
7096            title: "Show Background",
7097            description: "Show a background for inlay hints.",
7098            field: Box::new(SettingField {
7099                json_path: Some("languages.$(language).inlay_hints.show_background"),
7100                pick: |settings_content| {
7101                    language_settings_field(settings_content, |language| {
7102                        language.inlay_hints.as_ref()?.show_background.as_ref()
7103                    })
7104                },
7105                write: |settings_content, value| {
7106                    language_settings_field_mut(settings_content, value, |language, value| {
7107                        language.inlay_hints.get_or_insert_default().show_background = value;
7108                    })
7109                },
7110            }),
7111            metadata: None,
7112            files: USER | PROJECT,
7113        }),
7114        SettingsPageItem::SettingItem(SettingItem {
7115            title: "Edit Debounce Ms",
7116            description: "Whether or not to debounce inlay hints updates after buffer edits (set to 0 to disable debouncing).",
7117            field: Box::new(SettingField {
7118                json_path: Some("languages.$(language).inlay_hints.edit_debounce_ms"),
7119                pick: |settings_content| {
7120                    language_settings_field(settings_content, |language| {
7121                        language.inlay_hints.as_ref()?.edit_debounce_ms.as_ref()
7122                    })
7123                },
7124                write: |settings_content, value| {
7125                    language_settings_field_mut(settings_content, value, |language, value| {
7126                        language
7127                            .inlay_hints
7128                            .get_or_insert_default()
7129                            .edit_debounce_ms = value;
7130                    })
7131                },
7132            }),
7133            metadata: None,
7134            files: USER | PROJECT,
7135        }),
7136        SettingsPageItem::SettingItem(SettingItem {
7137            title: "Scroll Debounce Ms",
7138            description: "Whether or not to debounce inlay hints updates after buffer scrolls (set to 0 to disable debouncing).",
7139            field: Box::new(SettingField {
7140                json_path: Some("languages.$(language).inlay_hints.scroll_debounce_ms"),
7141                pick: |settings_content| {
7142                    language_settings_field(settings_content, |language| {
7143                        language.inlay_hints.as_ref()?.scroll_debounce_ms.as_ref()
7144                    })
7145                },
7146                write: |settings_content, value| {
7147                    language_settings_field_mut(settings_content, value, |language, value| {
7148                        language
7149                            .inlay_hints
7150                            .get_or_insert_default()
7151                            .scroll_debounce_ms = value;
7152                    })
7153                },
7154            }),
7155            metadata: None,
7156            files: USER | PROJECT,
7157        }),
7158        SettingsPageItem::SettingItem(SettingItem {
7159            title: "Toggle On Modifiers Press",
7160            description: "Toggles inlay hints (hides or shows) when the user presses the modifiers specified.",
7161            field: Box::new(
7162                SettingField {
7163                    json_path: Some("languages.$(language).inlay_hints.toggle_on_modifiers_press"),
7164                    pick: |settings_content| {
7165                        language_settings_field(settings_content, |language| {
7166                            language
7167                                .inlay_hints
7168                                .as_ref()?
7169                                .toggle_on_modifiers_press
7170                                .as_ref()
7171                        })
7172                    },
7173                    write: |settings_content, value| {
7174                        language_settings_field_mut(settings_content, value, |language, value| {
7175                            language
7176                                .inlay_hints
7177                                .get_or_insert_default()
7178                                .toggle_on_modifiers_press = value;
7179                        })
7180                    },
7181                }
7182                .unimplemented(),
7183            ),
7184            metadata: None,
7185            files: USER | PROJECT,
7186        }),
7187    ];
7188    if current_language().is_none() {
7189        items.push(SettingsPageItem::SettingItem(SettingItem {
7190            title: "LSP Document Colors",
7191            description: "How to render LSP color previews in the editor.",
7192            field: Box::new(SettingField {
7193                json_path: Some("lsp_document_colors"),
7194                pick: |settings_content| settings_content.editor.lsp_document_colors.as_ref(),
7195                write: |settings_content, value| {
7196                    settings_content.editor.lsp_document_colors = value;
7197                },
7198            }),
7199            metadata: None,
7200            files: USER,
7201        }))
7202    }
7203    items.extend([
7204        SettingsPageItem::SectionHeader("Tasks"),
7205        SettingsPageItem::SettingItem(SettingItem {
7206            title: "Enabled",
7207            description: "Whether tasks are enabled for this language.",
7208            field: Box::new(SettingField {
7209                json_path: Some("languages.$(language).tasks.enabled"),
7210                pick: |settings_content| {
7211                    language_settings_field(settings_content, |language| {
7212                        language.tasks.as_ref()?.enabled.as_ref()
7213                    })
7214                },
7215                write: |settings_content, value| {
7216                    language_settings_field_mut(settings_content, value, |language, value| {
7217                        language.tasks.get_or_insert_default().enabled = value;
7218
7219                    })
7220                },
7221            }),
7222            metadata: None,
7223            files: USER | PROJECT,
7224        }),
7225        SettingsPageItem::SettingItem(SettingItem {
7226            title: "Variables",
7227            description: "Extra task variables to set for a particular language.",
7228            field: Box::new(
7229                SettingField {
7230                    json_path: Some("languages.$(language).tasks.variables"),
7231                    pick: |settings_content| {
7232                        language_settings_field(settings_content, |language| {
7233                            language.tasks.as_ref()?.variables.as_ref()
7234                        })
7235                    },
7236                    write: |settings_content, value| {
7237                        language_settings_field_mut(settings_content, value, |language, value| {
7238                            language.tasks.get_or_insert_default().variables = value;
7239
7240                        })
7241                    },
7242                }
7243                .unimplemented(),
7244            ),
7245            metadata: None,
7246            files: USER | PROJECT,
7247        }),
7248        SettingsPageItem::SettingItem(SettingItem {
7249            title: "Prefer LSP",
7250            description: "Use LSP tasks over Zed language extension tasks.",
7251            field: Box::new(SettingField {
7252                json_path: Some("languages.$(language).tasks.prefer_lsp"),
7253                pick: |settings_content| {
7254                    language_settings_field(settings_content, |language| {
7255                        language.tasks.as_ref()?.prefer_lsp.as_ref()
7256                    })
7257                },
7258                write: |settings_content, value| {
7259                    language_settings_field_mut(settings_content, value, |language, value| {
7260                        language.tasks.get_or_insert_default().prefer_lsp = value;
7261
7262                    })
7263                },
7264            }),
7265            metadata: None,
7266            files: USER | PROJECT,
7267        }),
7268        SettingsPageItem::SectionHeader("Miscellaneous"),
7269        SettingsPageItem::SettingItem(SettingItem {
7270            title: "Word Diff Enabled",
7271            description: "Whether to enable word diff highlighting in the editor. When enabled, changed words within modified lines are highlighted to show exactly what changed.",
7272            field: Box::new(SettingField {
7273                json_path: Some("languages.$(language).word_diff_enabled"),
7274                pick: |settings_content| {
7275                    language_settings_field(settings_content, |language| {
7276                        language.word_diff_enabled.as_ref()
7277                    })
7278                },
7279                write: |settings_content, value| {
7280                    language_settings_field_mut(settings_content, value, |language, value| {
7281                        language.word_diff_enabled = value;
7282                    })
7283                },
7284            }),
7285            metadata: None,
7286            files: USER | PROJECT,
7287        }),
7288        SettingsPageItem::SettingItem(SettingItem {
7289            title: "Debuggers",
7290            description: "Preferred debuggers for this language.",
7291            field: Box::new(
7292                SettingField {
7293                    json_path: Some("languages.$(language).debuggers"),
7294                    pick: |settings_content| {
7295                        language_settings_field(settings_content, |language| language.debuggers.as_ref())
7296                    },
7297                    write: |settings_content, value| {
7298                        language_settings_field_mut(settings_content, value, |language, value| {
7299                            language.debuggers = value;
7300
7301                        })
7302                    },
7303                }
7304                .unimplemented(),
7305            ),
7306            metadata: None,
7307            files: USER | PROJECT,
7308        }),
7309        SettingsPageItem::SettingItem(SettingItem {
7310            title: "Middle Click Paste",
7311            description: "Enable middle-click paste on Linux.",
7312            field: Box::new(SettingField {
7313                json_path: Some("languages.$(language).editor.middle_click_paste"),
7314                pick: |settings_content| settings_content.editor.middle_click_paste.as_ref(),
7315                write: |settings_content, value| {settings_content.editor.middle_click_paste = value;},
7316            }),
7317            metadata: None,
7318            files: USER,
7319        }),
7320        SettingsPageItem::SettingItem(SettingItem {
7321            title: "Extend Comment On Newline",
7322            description: "Whether to start a new line with a comment when a previous line is a comment as well.",
7323            field: Box::new(SettingField {
7324                json_path: Some("languages.$(language).extend_comment_on_newline"),
7325                pick: |settings_content| {
7326                    language_settings_field(settings_content, |language| {
7327                        language.extend_comment_on_newline.as_ref()
7328                    })
7329                },
7330                write: |settings_content, value| {
7331                    language_settings_field_mut(settings_content, value, |language, value| {
7332                        language.extend_comment_on_newline = value;
7333
7334                    })
7335                },
7336            }),
7337            metadata: None,
7338            files: USER | PROJECT,
7339        }),
7340        SettingsPageItem::SettingItem(SettingItem {
7341            title: "Colorize Brackets",
7342            description: "Whether to colorize brackets in the editor.",
7343            field: Box::new(SettingField {
7344                json_path: Some("languages.$(language).colorize_brackets"),
7345                pick: |settings_content| {
7346                    language_settings_field(settings_content, |language| {
7347                        language.colorize_brackets.as_ref()
7348                    })
7349                },
7350                write: |settings_content, value| {
7351                    language_settings_field_mut(settings_content, value, |language, value| {
7352                        language.colorize_brackets = value;
7353                    })
7354                },
7355            }),
7356            metadata: None,
7357            files: USER | PROJECT,
7358        }),
7359    ]);
7360
7361    if current_language().is_none() {
7362        items.extend([
7363            SettingsPageItem::SettingItem(SettingItem {
7364                title: "Image Viewer",
7365                description: "The unit for image file sizes.",
7366                field: Box::new(SettingField {
7367                    json_path: Some("image_viewer.unit"),
7368                    pick: |settings_content| {
7369                        settings_content.image_viewer.as_ref().and_then(|image_viewer| image_viewer.unit.as_ref())
7370                    },
7371                    write: |settings_content, value| {
7372                        settings_content.image_viewer.get_or_insert_default().unit = value;
7373
7374                    },
7375                }),
7376                metadata: None,
7377                files: USER,
7378            }),
7379            SettingsPageItem::SettingItem(SettingItem {
7380                title: "Auto Replace Emoji Shortcode",
7381                description: "Whether to automatically replace emoji shortcodes with emoji characters.",
7382                field: Box::new(SettingField {
7383                    json_path: Some("message_editor.auto_replace_emoji_shortcode"),
7384                    pick: |settings_content| {
7385                        settings_content.message_editor.as_ref().and_then(|message_editor| message_editor.auto_replace_emoji_shortcode.as_ref())
7386                    },
7387                    write: |settings_content, value| {
7388                        settings_content.message_editor.get_or_insert_default().auto_replace_emoji_shortcode = value;
7389
7390                    },
7391                }),
7392                metadata: None,
7393                files: USER,
7394            }),
7395            SettingsPageItem::SettingItem(SettingItem {
7396                title: "Drop Size Target",
7397                description: "Relative size of the drop target in the editor that will open dropped file as a split pane.",
7398                field: Box::new(SettingField {
7399                    json_path: Some("drop_target_size"),
7400                    pick: |settings_content| {
7401                        settings_content.workspace.drop_target_size.as_ref()
7402                    },
7403                    write: |settings_content, value| {
7404                        settings_content.workspace.drop_target_size = value;
7405
7406                    },
7407                }),
7408                metadata: None,
7409                files: USER,
7410            }),
7411        ]);
7412    }
7413    items
7414}
7415
7416/// LanguageSettings items that should be included in the "Languages & Tools" page
7417/// not the "Editor" page
7418fn non_editor_language_settings_data() -> Vec<SettingsPageItem> {
7419    vec![
7420        SettingsPageItem::SectionHeader("LSP"),
7421        SettingsPageItem::SettingItem(SettingItem {
7422            title: "Enable Language Server",
7423            description: "Whether to use language servers to provide code intelligence.",
7424            field: Box::new(SettingField {
7425                json_path: Some("languages.$(language).enable_language_server"),
7426                pick: |settings_content| {
7427                    language_settings_field(settings_content, |language| {
7428                        language.enable_language_server.as_ref()
7429                    })
7430                },
7431                write: |settings_content, value| {
7432                    language_settings_field_mut(settings_content, value, |language, value| {
7433                        language.enable_language_server = value;
7434                    })
7435                },
7436            }),
7437            metadata: None,
7438            files: USER | PROJECT,
7439        }),
7440        SettingsPageItem::SettingItem(SettingItem {
7441            title: "Language Servers",
7442            description: "The list of language servers to use (or disable) for this language.",
7443            field: Box::new(
7444                SettingField {
7445                    json_path: Some("languages.$(language).language_servers"),
7446                    pick: |settings_content| {
7447                        language_settings_field(settings_content, |language| {
7448                            language.language_servers.as_ref()
7449                        })
7450                    },
7451                    write: |settings_content, value| {
7452                        language_settings_field_mut(settings_content, value, |language, value| {
7453                            language.language_servers = value;
7454                        })
7455                    },
7456                }
7457                .unimplemented(),
7458            ),
7459            metadata: None,
7460            files: USER | PROJECT,
7461        }),
7462        SettingsPageItem::SettingItem(SettingItem {
7463            title: "Linked Edits",
7464            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.",
7465            field: Box::new(SettingField {
7466                json_path: Some("languages.$(language).linked_edits"),
7467                pick: |settings_content| {
7468                    language_settings_field(settings_content, |language| {
7469                        language.linked_edits.as_ref()
7470                    })
7471                },
7472                write: |settings_content, value| {
7473                    language_settings_field_mut(settings_content, value, |language, value| {
7474                        language.linked_edits = value;
7475                    })
7476                },
7477            }),
7478            metadata: None,
7479            files: USER | PROJECT,
7480        }),
7481        SettingsPageItem::SettingItem(SettingItem {
7482            title: "Go To Definition Fallback",
7483            description: "Whether to follow-up empty Go to definition responses from the language server.",
7484            field: Box::new(SettingField {
7485                json_path: Some("go_to_definition_fallback"),
7486                pick: |settings_content| settings_content.editor.go_to_definition_fallback.as_ref(),
7487                write: |settings_content, value| {
7488                    settings_content.editor.go_to_definition_fallback = value;
7489                },
7490            }),
7491            metadata: None,
7492            files: USER,
7493        }),
7494        SettingsPageItem::SectionHeader("LSP Completions"),
7495        SettingsPageItem::SettingItem(SettingItem {
7496            title: "Enabled",
7497            description: "Whether to fetch LSP completions or not.",
7498            field: Box::new(SettingField {
7499                json_path: Some("languages.$(language).completions.lsp"),
7500                pick: |settings_content| {
7501                    language_settings_field(settings_content, |language| {
7502                        language.completions.as_ref()?.lsp.as_ref()
7503                    })
7504                },
7505                write: |settings_content, value| {
7506                    language_settings_field_mut(settings_content, value, |language, value| {
7507                        language.completions.get_or_insert_default().lsp = value;
7508                    })
7509                },
7510            }),
7511            metadata: None,
7512            files: USER | PROJECT,
7513        }),
7514        SettingsPageItem::SettingItem(SettingItem {
7515            title: "Fetch Timeout (milliseconds)",
7516            description: "When fetching LSP completions, determines how long to wait for a response of a particular server (set to 0 to wait indefinitely).",
7517            field: Box::new(SettingField {
7518                json_path: Some("languages.$(language).completions.lsp_fetch_timeout_ms"),
7519                pick: |settings_content| {
7520                    language_settings_field(settings_content, |language| {
7521                        language.completions.as_ref()?.lsp_fetch_timeout_ms.as_ref()
7522                    })
7523                },
7524                write: |settings_content, value| {
7525                    language_settings_field_mut(settings_content, value, |language, value| {
7526                        language
7527                            .completions
7528                            .get_or_insert_default()
7529                            .lsp_fetch_timeout_ms = value;
7530                    })
7531                },
7532            }),
7533            metadata: None,
7534            files: USER | PROJECT,
7535        }),
7536        SettingsPageItem::SettingItem(SettingItem {
7537            title: "Insert Mode",
7538            description: "Controls how LSP completions are inserted.",
7539            field: Box::new(SettingField {
7540                json_path: Some("languages.$(language).completions.lsp_insert_mode"),
7541                pick: |settings_content| {
7542                    language_settings_field(settings_content, |language| {
7543                        language.completions.as_ref()?.lsp_insert_mode.as_ref()
7544                    })
7545                },
7546                write: |settings_content, value| {
7547                    language_settings_field_mut(settings_content, value, |language, value| {
7548                        language.completions.get_or_insert_default().lsp_insert_mode = value;
7549                    })
7550                },
7551            }),
7552            metadata: None,
7553            files: USER | PROJECT,
7554        }),
7555        SettingsPageItem::SectionHeader("Debuggers"),
7556        SettingsPageItem::SettingItem(SettingItem {
7557            title: "Debuggers",
7558            description: "Preferred debuggers for this language.",
7559            field: Box::new(
7560                SettingField {
7561                    json_path: Some("languages.$(language).debuggers"),
7562                    pick: |settings_content| {
7563                        language_settings_field(settings_content, |language| {
7564                            language.debuggers.as_ref()
7565                        })
7566                    },
7567                    write: |settings_content, value| {
7568                        language_settings_field_mut(settings_content, value, |language, value| {
7569                            language.debuggers = value;
7570                        })
7571                    },
7572                }
7573                .unimplemented(),
7574            ),
7575            metadata: None,
7576            files: USER | PROJECT,
7577        }),
7578        SettingsPageItem::SectionHeader("Prettier"),
7579        SettingsPageItem::SettingItem(SettingItem {
7580            title: "Allowed",
7581            description: "Enables or disables formatting with Prettier for a given language.",
7582            field: Box::new(SettingField {
7583                json_path: Some("languages.$(language).prettier.allowed"),
7584                pick: |settings_content| {
7585                    language_settings_field(settings_content, |language| {
7586                        language.prettier.as_ref()?.allowed.as_ref()
7587                    })
7588                },
7589                write: |settings_content, value| {
7590                    language_settings_field_mut(settings_content, value, |language, value| {
7591                        language.prettier.get_or_insert_default().allowed = value;
7592                    })
7593                },
7594            }),
7595            metadata: None,
7596            files: USER | PROJECT,
7597        }),
7598        SettingsPageItem::SettingItem(SettingItem {
7599            title: "Parser",
7600            description: "Forces Prettier integration to use a specific parser name when formatting files with the language.",
7601            field: Box::new(SettingField {
7602                json_path: Some("languages.$(language).prettier.parser"),
7603                pick: |settings_content| {
7604                    language_settings_field(settings_content, |language| {
7605                        language.prettier.as_ref()?.parser.as_ref()
7606                    })
7607                },
7608                write: |settings_content, value| {
7609                    language_settings_field_mut(settings_content, value, |language, value| {
7610                        language.prettier.get_or_insert_default().parser = value;
7611                    })
7612                },
7613            }),
7614            metadata: None,
7615            files: USER | PROJECT,
7616        }),
7617        SettingsPageItem::SettingItem(SettingItem {
7618            title: "Plugins",
7619            description: "Forces Prettier integration to use specific plugins when formatting files with the language.",
7620            field: Box::new(
7621                SettingField {
7622                    json_path: Some("languages.$(language).prettier.plugins"),
7623                    pick: |settings_content| {
7624                        language_settings_field(settings_content, |language| {
7625                            language.prettier.as_ref()?.plugins.as_ref()
7626                        })
7627                    },
7628                    write: |settings_content, value| {
7629                        language_settings_field_mut(settings_content, value, |language, value| {
7630                            language.prettier.get_or_insert_default().plugins = value;
7631                        })
7632                    },
7633                }
7634                .unimplemented(),
7635            ),
7636            metadata: None,
7637            files: USER | PROJECT,
7638        }),
7639        SettingsPageItem::SettingItem(SettingItem {
7640            title: "Options",
7641            description: "Default Prettier options, in the format as in package.json section for Prettier.",
7642            field: Box::new(
7643                SettingField {
7644                    json_path: Some("languages.$(language).prettier.options"),
7645                    pick: |settings_content| {
7646                        language_settings_field(settings_content, |language| {
7647                            language.prettier.as_ref()?.options.as_ref()
7648                        })
7649                    },
7650                    write: |settings_content, value| {
7651                        language_settings_field_mut(settings_content, value, |language, value| {
7652                            language.prettier.get_or_insert_default().options = value;
7653                        })
7654                    },
7655                }
7656                .unimplemented(),
7657            ),
7658            metadata: None,
7659            files: USER | PROJECT,
7660        }),
7661    ]
7662}
7663
7664fn edit_prediction_language_settings_section() -> Vec<SettingsPageItem> {
7665    vec![
7666        SettingsPageItem::SectionHeader("Edit Predictions"),
7667        SettingsPageItem::SubPageLink(SubPageLink {
7668            title: "Configure Providers".into(),
7669            json_path: Some("edit_predictions.providers"),
7670            description: Some("Set up different edit prediction providers in complement to Zed's built-in Zeta model.".into()),
7671            in_json: false,
7672            files: USER,
7673            render: Arc::new(|_, window, cx| {
7674                let settings_window = cx.entity();
7675                let page = window.use_state(cx, |_, _| {
7676                    crate::pages::EditPredictionSetupPage::new(settings_window)
7677                });
7678                page.into_any_element()
7679            }),
7680        }),
7681        SettingsPageItem::SettingItem(SettingItem {
7682            title: "Show Edit Predictions",
7683            description: "Controls whether edit predictions are shown immediately or manually.",
7684            field: Box::new(SettingField {
7685                json_path: Some("languages.$(language).show_edit_predictions"),
7686                pick: |settings_content| {
7687                    language_settings_field(settings_content, |language| {
7688                        language.show_edit_predictions.as_ref()
7689                    })
7690                },
7691                write: |settings_content, value| {
7692                    language_settings_field_mut(settings_content, value, |language, value| {
7693                        language.show_edit_predictions = value;
7694                    })
7695                },
7696            }),
7697            metadata: None,
7698            files: USER | PROJECT,
7699        }),
7700        SettingsPageItem::SettingItem(SettingItem {
7701            title: "Disable in Language Scopes",
7702            description: "Controls whether edit predictions are shown in the given language scopes.",
7703            field: Box::new(
7704                SettingField {
7705                    json_path: Some("languages.$(language).edit_predictions_disabled_in"),
7706                    pick: |settings_content| {
7707                        language_settings_field(settings_content, |language| {
7708                            language.edit_predictions_disabled_in.as_ref()
7709                        })
7710                    },
7711                    write: |settings_content, value| {
7712                        language_settings_field_mut(settings_content, value, |language, value| {
7713                            language.edit_predictions_disabled_in = value;
7714                        })
7715                    },
7716                }
7717                .unimplemented(),
7718            ),
7719            metadata: None,
7720            files: USER | PROJECT,
7721        }),
7722    ]
7723}
7724
7725fn show_scrollbar_or_editor(
7726    settings_content: &SettingsContent,
7727    show: fn(&SettingsContent) -> Option<&settings::ShowScrollbar>,
7728) -> Option<&settings::ShowScrollbar> {
7729    show(settings_content).or(settings_content
7730        .editor
7731        .scrollbar
7732        .as_ref()
7733        .and_then(|scrollbar| scrollbar.show.as_ref()))
7734}
7735
7736fn dynamic_variants<T>() -> &'static [T::Discriminant]
7737where
7738    T: strum::IntoDiscriminant,
7739    T::Discriminant: strum::VariantArray,
7740{
7741    <<T as strum::IntoDiscriminant>::Discriminant as strum::VariantArray>::VARIANTS
7742}