page_data.rs

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