page_data.rs

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