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: "Active Encoding Button",
2840                    description: "Control when to show the active encoding in the status bar.",
2841                    field: Box::new(SettingField {
2842                        json_path: Some("status_bar.active_encoding_button"),
2843                        pick: |settings_content| {
2844                            settings_content
2845                                .status_bar
2846                                .as_ref()?
2847                                .active_encoding_button
2848                                .as_ref()
2849                        },
2850                        write: |settings_content, value| {
2851                            settings_content
2852                                .status_bar
2853                                .get_or_insert_default()
2854                                .active_encoding_button = value;
2855                        },
2856                    }),
2857                    metadata: None,
2858                    files: USER,
2859                }),
2860                SettingsPageItem::SettingItem(SettingItem {
2861                    title: "Cursor Position Button",
2862                    description: "Show the cursor position button in the status bar.",
2863                    field: Box::new(SettingField {
2864                        json_path: Some("status_bar.cursor_position_button"),
2865                        pick: |settings_content| {
2866                            settings_content
2867                                .status_bar
2868                                .as_ref()?
2869                                .cursor_position_button
2870                                .as_ref()
2871                        },
2872                        write: |settings_content, value| {
2873                            settings_content
2874                                .status_bar
2875                                .get_or_insert_default()
2876                                .cursor_position_button = value;
2877                        },
2878                    }),
2879                    metadata: None,
2880                    files: USER,
2881                }),
2882                SettingsPageItem::SettingItem(SettingItem {
2883                    title: "Terminal Button",
2884                    description: "Show the terminal button in the status bar.",
2885                    field: Box::new(SettingField {
2886                        json_path: Some("terminal.button"),
2887                        pick: |settings_content| {
2888                            settings_content.terminal.as_ref()?.button.as_ref()
2889                        },
2890                        write: |settings_content, value| {
2891                            settings_content.terminal.get_or_insert_default().button = value;
2892                        },
2893                    }),
2894                    metadata: None,
2895                    files: USER,
2896                }),
2897                SettingsPageItem::SettingItem(SettingItem {
2898                    title: "Diagnostics Button",
2899                    description: "Show the project diagnostics button in the status bar.",
2900                    field: Box::new(SettingField {
2901                        json_path: Some("diagnostics.button"),
2902                        pick: |settings_content| {
2903                            settings_content.diagnostics.as_ref()?.button.as_ref()
2904                        },
2905                        write: |settings_content, value| {
2906                            settings_content.diagnostics.get_or_insert_default().button = value;
2907                        },
2908                    }),
2909                    metadata: None,
2910                    files: USER,
2911                }),
2912                SettingsPageItem::SettingItem(SettingItem {
2913                    title: "Project Search Button",
2914                    description: "Show the project search button in the status bar.",
2915                    field: Box::new(SettingField {
2916                        json_path: Some("search.button"),
2917                        pick: |settings_content| {
2918                            settings_content.editor.search.as_ref()?.button.as_ref()
2919                        },
2920                        write: |settings_content, value| {
2921                            settings_content
2922                                .editor
2923                                .search
2924                                .get_or_insert_default()
2925                                .button = value;
2926                        },
2927                    }),
2928                    metadata: None,
2929                    files: USER,
2930                }),
2931                SettingsPageItem::SettingItem(SettingItem {
2932                    title: "Debugger Button",
2933                    description: "Show the debugger button in the status bar.",
2934                    field: Box::new(SettingField {
2935                        json_path: Some("debugger.button"),
2936                        pick: |settings_content| {
2937                            settings_content.debugger.as_ref()?.button.as_ref()
2938                        },
2939                        write: |settings_content, value| {
2940                            settings_content.debugger.get_or_insert_default().button = value;
2941                        },
2942                    }),
2943                    metadata: None,
2944                    files: USER,
2945                }),
2946                SettingsPageItem::SectionHeader("Title Bar"),
2947                SettingsPageItem::SettingItem(SettingItem {
2948                    title: "Show Branch Icon",
2949                    description: "Show the branch icon beside branch switcher in the titlebar.",
2950                    field: Box::new(SettingField {
2951                        json_path: Some("title_bar.show_branch_icon"),
2952                        pick: |settings_content| {
2953                            settings_content
2954                                .title_bar
2955                                .as_ref()?
2956                                .show_branch_icon
2957                                .as_ref()
2958                        },
2959                        write: |settings_content, value| {
2960                            settings_content
2961                                .title_bar
2962                                .get_or_insert_default()
2963                                .show_branch_icon = value;
2964                        },
2965                    }),
2966                    metadata: None,
2967                    files: USER,
2968                }),
2969                SettingsPageItem::SettingItem(SettingItem {
2970                    title: "Show Branch Name",
2971                    description: "Show the branch name button in the titlebar.",
2972                    field: Box::new(SettingField {
2973                        json_path: Some("title_bar.show_branch_name"),
2974                        pick: |settings_content| {
2975                            settings_content
2976                                .title_bar
2977                                .as_ref()?
2978                                .show_branch_name
2979                                .as_ref()
2980                        },
2981                        write: |settings_content, value| {
2982                            settings_content
2983                                .title_bar
2984                                .get_or_insert_default()
2985                                .show_branch_name = value;
2986                        },
2987                    }),
2988                    metadata: None,
2989                    files: USER,
2990                }),
2991                SettingsPageItem::SettingItem(SettingItem {
2992                    title: "Show Project Items",
2993                    description: "Show the project host and name in the titlebar.",
2994                    field: Box::new(SettingField {
2995                        json_path: Some("title_bar.show_project_items"),
2996                        pick: |settings_content| {
2997                            settings_content
2998                                .title_bar
2999                                .as_ref()?
3000                                .show_project_items
3001                                .as_ref()
3002                        },
3003                        write: |settings_content, value| {
3004                            settings_content
3005                                .title_bar
3006                                .get_or_insert_default()
3007                                .show_project_items = value;
3008                        },
3009                    }),
3010                    metadata: None,
3011                    files: USER,
3012                }),
3013                SettingsPageItem::SettingItem(SettingItem {
3014                    title: "Show Onboarding Banner",
3015                    description: "Show banners announcing new features in the titlebar.",
3016                    field: Box::new(SettingField {
3017                        json_path: Some("title_bar.show_onboarding_banner"),
3018                        pick: |settings_content| {
3019                            settings_content
3020                                .title_bar
3021                                .as_ref()?
3022                                .show_onboarding_banner
3023                                .as_ref()
3024                        },
3025                        write: |settings_content, value| {
3026                            settings_content
3027                                .title_bar
3028                                .get_or_insert_default()
3029                                .show_onboarding_banner = value;
3030                        },
3031                    }),
3032                    metadata: None,
3033                    files: USER,
3034                }),
3035                SettingsPageItem::SettingItem(SettingItem {
3036                    title: "Show Sign In",
3037                    description: "Show the sign in button in the titlebar.",
3038                    field: Box::new(SettingField {
3039                        json_path: Some("title_bar.show_sign_in"),
3040                        pick: |settings_content| {
3041                            settings_content.title_bar.as_ref()?.show_sign_in.as_ref()
3042                        },
3043                        write: |settings_content, value| {
3044                            settings_content
3045                                .title_bar
3046                                .get_or_insert_default()
3047                                .show_sign_in = value;
3048                        },
3049                    }),
3050                    metadata: None,
3051                    files: USER,
3052                }),
3053                SettingsPageItem::SettingItem(SettingItem {
3054                    title: "Show User Menu",
3055                    description: "Show the user menu button in the titlebar.",
3056                    field: Box::new(SettingField {
3057                        json_path: Some("title_bar.show_user_menu"),
3058                        pick: |settings_content| {
3059                            settings_content.title_bar.as_ref()?.show_user_menu.as_ref()
3060                        },
3061                        write: |settings_content, value| {
3062                            settings_content
3063                                .title_bar
3064                                .get_or_insert_default()
3065                                .show_user_menu = value;
3066                        },
3067                    }),
3068                    metadata: None,
3069                    files: USER,
3070                }),
3071                SettingsPageItem::SettingItem(SettingItem {
3072                    title: "Show User Picture",
3073                    description: "Show user picture in the titlebar.",
3074                    field: Box::new(SettingField {
3075                        json_path: Some("title_bar.show_user_picture"),
3076                        pick: |settings_content| {
3077                            settings_content
3078                                .title_bar
3079                                .as_ref()?
3080                                .show_user_picture
3081                                .as_ref()
3082                        },
3083                        write: |settings_content, value| {
3084                            settings_content
3085                                .title_bar
3086                                .get_or_insert_default()
3087                                .show_user_picture = value;
3088                        },
3089                    }),
3090                    metadata: None,
3091                    files: USER,
3092                }),
3093                SettingsPageItem::SettingItem(SettingItem {
3094                    title: "Show Menus",
3095                    description: "Show the menus in the titlebar.",
3096                    field: Box::new(SettingField {
3097                        json_path: Some("title_bar.show_menus"),
3098                        pick: |settings_content| {
3099                            settings_content.title_bar.as_ref()?.show_menus.as_ref()
3100                        },
3101                        write: |settings_content, value| {
3102                            settings_content
3103                                .title_bar
3104                                .get_or_insert_default()
3105                                .show_menus = value;
3106                        },
3107                    }),
3108                    metadata: None,
3109                    files: USER,
3110                }),
3111                SettingsPageItem::SectionHeader("Tab Bar"),
3112                SettingsPageItem::SettingItem(SettingItem {
3113                    title: "Show Tab Bar",
3114                    description: "Show the tab bar in the editor.",
3115                    field: Box::new(SettingField {
3116                        json_path: Some("tab_bar.show"),
3117                        pick: |settings_content| settings_content.tab_bar.as_ref()?.show.as_ref(),
3118                        write: |settings_content, value| {
3119                            settings_content.tab_bar.get_or_insert_default().show = value;
3120                        },
3121                    }),
3122                    metadata: None,
3123                    files: USER,
3124                }),
3125                SettingsPageItem::SettingItem(SettingItem {
3126                    title: "Show Git Status In Tabs",
3127                    description: "Show the Git file status on a tab item.",
3128                    field: Box::new(SettingField {
3129                        json_path: Some("tabs.git_status"),
3130                        pick: |settings_content| {
3131                            settings_content.tabs.as_ref()?.git_status.as_ref()
3132                        },
3133                        write: |settings_content, value| {
3134                            settings_content.tabs.get_or_insert_default().git_status = value;
3135                        },
3136                    }),
3137                    metadata: None,
3138                    files: USER,
3139                }),
3140                SettingsPageItem::SettingItem(SettingItem {
3141                    title: "Show File Icons In Tabs",
3142                    description: "Show the file icon for a tab.",
3143                    field: Box::new(SettingField {
3144                        json_path: Some("tabs.file_icons"),
3145                        pick: |settings_content| {
3146                            settings_content.tabs.as_ref()?.file_icons.as_ref()
3147                        },
3148                        write: |settings_content, value| {
3149                            settings_content.tabs.get_or_insert_default().file_icons = value;
3150                        },
3151                    }),
3152                    metadata: None,
3153                    files: USER,
3154                }),
3155                SettingsPageItem::SettingItem(SettingItem {
3156                    title: "Tab Close Position",
3157                    description: "Position of the close button in a tab.",
3158                    field: Box::new(SettingField {
3159                        json_path: Some("tabs.close_position"),
3160                        pick: |settings_content| {
3161                            settings_content.tabs.as_ref()?.close_position.as_ref()
3162                        },
3163                        write: |settings_content, value| {
3164                            settings_content.tabs.get_or_insert_default().close_position = value;
3165                        },
3166                    }),
3167                    metadata: None,
3168                    files: USER,
3169                }),
3170                SettingsPageItem::SettingItem(SettingItem {
3171                    files: USER,
3172                    title: "Maximum Tabs",
3173                    description: "Maximum open tabs in a pane. Will not close an unsaved tab.",
3174                    // todo(settings_ui): The default for this value is null and it's use in code
3175                    // is complex, so I'm going to come back to this later
3176                    field: Box::new(
3177                        SettingField {
3178                            json_path: Some("max_tabs"),
3179                            pick: |settings_content| settings_content.workspace.max_tabs.as_ref(),
3180                            write: |settings_content, value| {
3181                                settings_content.workspace.max_tabs = value;
3182                            },
3183                        }
3184                        .unimplemented(),
3185                    ),
3186                    metadata: None,
3187                }),
3188                SettingsPageItem::SettingItem(SettingItem {
3189                    title: "Show Navigation History Buttons",
3190                    description: "Show the navigation history buttons in the tab bar.",
3191                    field: Box::new(SettingField {
3192                        json_path: Some("tab_bar.show_nav_history_buttons"),
3193                        pick: |settings_content| {
3194                            settings_content
3195                                .tab_bar
3196                                .as_ref()?
3197                                .show_nav_history_buttons
3198                                .as_ref()
3199                        },
3200                        write: |settings_content, value| {
3201                            settings_content
3202                                .tab_bar
3203                                .get_or_insert_default()
3204                                .show_nav_history_buttons = value;
3205                        },
3206                    }),
3207                    metadata: None,
3208                    files: USER,
3209                }),
3210                SettingsPageItem::SettingItem(SettingItem {
3211                    title: "Show Tab Bar Buttons",
3212                    description: "Show the tab bar buttons (New, Split Pane, Zoom).",
3213                    field: Box::new(SettingField {
3214                        json_path: Some("tab_bar.show_tab_bar_buttons"),
3215                        pick: |settings_content| {
3216                            settings_content
3217                                .tab_bar
3218                                .as_ref()?
3219                                .show_tab_bar_buttons
3220                                .as_ref()
3221                        },
3222                        write: |settings_content, value| {
3223                            settings_content
3224                                .tab_bar
3225                                .get_or_insert_default()
3226                                .show_tab_bar_buttons = value;
3227                        },
3228                    }),
3229                    metadata: None,
3230                    files: USER,
3231                }),
3232                SettingsPageItem::SectionHeader("Tab Settings"),
3233                SettingsPageItem::SettingItem(SettingItem {
3234                    title: "Activate On Close",
3235                    description: "What to do after closing the current tab.",
3236                    field: Box::new(SettingField {
3237                        json_path: Some("tabs.activate_on_close"),
3238                        pick: |settings_content| {
3239                            settings_content.tabs.as_ref()?.activate_on_close.as_ref()
3240                        },
3241                        write: |settings_content, value| {
3242                            settings_content
3243                                .tabs
3244                                .get_or_insert_default()
3245                                .activate_on_close = value;
3246                        },
3247                    }),
3248                    metadata: None,
3249                    files: USER,
3250                }),
3251                SettingsPageItem::SettingItem(SettingItem {
3252                    title: "Tab Show Diagnostics",
3253                    description: "Which files containing diagnostic errors/warnings to mark in the tabs.",
3254                    field: Box::new(SettingField {
3255                        json_path: Some("tabs.show_diagnostics"),
3256                        pick: |settings_content| {
3257                            settings_content.tabs.as_ref()?.show_diagnostics.as_ref()
3258                        },
3259                        write: |settings_content, value| {
3260                            settings_content
3261                                .tabs
3262                                .get_or_insert_default()
3263                                .show_diagnostics = value;
3264                        },
3265                    }),
3266                    metadata: None,
3267                    files: USER,
3268                }),
3269                SettingsPageItem::SettingItem(SettingItem {
3270                    title: "Show Close Button",
3271                    description: "Controls the appearance behavior of the tab's close button.",
3272                    field: Box::new(SettingField {
3273                        json_path: Some("tabs.show_close_button"),
3274                        pick: |settings_content| {
3275                            settings_content.tabs.as_ref()?.show_close_button.as_ref()
3276                        },
3277                        write: |settings_content, value| {
3278                            settings_content
3279                                .tabs
3280                                .get_or_insert_default()
3281                                .show_close_button = value;
3282                        },
3283                    }),
3284                    metadata: None,
3285                    files: USER,
3286                }),
3287                SettingsPageItem::SectionHeader("Preview Tabs"),
3288                SettingsPageItem::SettingItem(SettingItem {
3289                    title: "Preview Tabs Enabled",
3290                    description: "Show opened editors as preview tabs.",
3291                    field: Box::new(SettingField {
3292                        json_path: Some("preview_tabs.enabled"),
3293                        pick: |settings_content| {
3294                            settings_content.preview_tabs.as_ref()?.enabled.as_ref()
3295                        },
3296                        write: |settings_content, value| {
3297                            settings_content
3298                                .preview_tabs
3299                                .get_or_insert_default()
3300                                .enabled = value;
3301                        },
3302                    }),
3303                    metadata: None,
3304                    files: USER,
3305                }),
3306                SettingsPageItem::SettingItem(SettingItem {
3307                    title: "Enable Preview From Project Panel",
3308                    description: "Whether to open tabs in preview mode when opened from the project panel with a single click.",
3309                    field: Box::new(SettingField {
3310                        json_path: Some("preview_tabs.enable_preview_from_project_panel"),
3311                        pick: |settings_content| {
3312                            settings_content
3313                                .preview_tabs
3314                                .as_ref()?
3315                                .enable_preview_from_project_panel
3316                                .as_ref()
3317                        },
3318                        write: |settings_content, value| {
3319                            settings_content
3320                                .preview_tabs
3321                                .get_or_insert_default()
3322                                .enable_preview_from_project_panel = value;
3323                        },
3324                    }),
3325                    metadata: None,
3326                    files: USER,
3327                }),
3328                SettingsPageItem::SettingItem(SettingItem {
3329                    title: "Enable Preview From File Finder",
3330                    description: "Whether to open tabs in preview mode when selected from the file finder.",
3331                    field: Box::new(SettingField {
3332                        json_path: Some("preview_tabs.enable_preview_from_file_finder"),
3333                        pick: |settings_content| {
3334                            settings_content
3335                                .preview_tabs
3336                                .as_ref()?
3337                                .enable_preview_from_file_finder
3338                                .as_ref()
3339                        },
3340                        write: |settings_content, value| {
3341                            settings_content
3342                                .preview_tabs
3343                                .get_or_insert_default()
3344                                .enable_preview_from_file_finder = value;
3345                        },
3346                    }),
3347                    metadata: None,
3348                    files: USER,
3349                }),
3350                SettingsPageItem::SettingItem(SettingItem {
3351                    title: "Enable Preview From Multibuffer",
3352                    description: "Whether to open tabs in preview mode when opened from a multibuffer.",
3353                    field: Box::new(SettingField {
3354                        json_path: Some("preview_tabs.enable_preview_from_multibuffer"),
3355                        pick: |settings_content| {
3356                            settings_content
3357                                .preview_tabs
3358                                .as_ref()?
3359                                .enable_preview_from_multibuffer
3360                                .as_ref()
3361                        },
3362                        write: |settings_content, value| {
3363                            settings_content
3364                                .preview_tabs
3365                                .get_or_insert_default()
3366                                .enable_preview_from_multibuffer = value;
3367                        },
3368                    }),
3369                    metadata: None,
3370                    files: USER,
3371                }),
3372                SettingsPageItem::SettingItem(SettingItem {
3373                    title: "Enable Preview Multibuffer From Code Navigation",
3374                    description: "Whether to open tabs in preview mode when code navigation is used to open a multibuffer.",
3375                    field: Box::new(SettingField {
3376                        json_path: Some("preview_tabs.enable_preview_multibuffer_from_code_navigation"),
3377                        pick: |settings_content| {
3378                            settings_content
3379                                .preview_tabs
3380                                .as_ref()?
3381                                .enable_preview_multibuffer_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_multibuffer_from_code_navigation = value;
3389                        },
3390                    }),
3391                    metadata: None,
3392                    files: USER,
3393                }),
3394                SettingsPageItem::SettingItem(SettingItem {
3395                    title: "Enable Preview File From Code Navigation",
3396                    description: "Whether to open tabs in preview mode when code navigation is used to open a single file.",
3397                    field: Box::new(SettingField {
3398                        json_path: Some("preview_tabs.enable_preview_file_from_code_navigation"),
3399                        pick: |settings_content| {
3400                            settings_content
3401                                .preview_tabs
3402                                .as_ref()?
3403                                .enable_preview_file_from_code_navigation
3404                                .as_ref()
3405                        },
3406                        write: |settings_content, value| {
3407                            settings_content
3408                                .preview_tabs
3409                                .get_or_insert_default()
3410                                .enable_preview_file_from_code_navigation = value;
3411                        },
3412                    }),
3413                    metadata: None,
3414                    files: USER,
3415                }),
3416                SettingsPageItem::SettingItem(SettingItem {
3417                    title: "Enable Keep Preview On Code Navigation",
3418                    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.",
3419                    field: Box::new(SettingField {
3420                        json_path: Some("preview_tabs.enable_keep_preview_on_code_navigation"),
3421                        pick: |settings_content| {
3422                            settings_content
3423                                .preview_tabs
3424                                .as_ref()?
3425                                .enable_keep_preview_on_code_navigation
3426                                .as_ref()
3427                        },
3428                        write: |settings_content, value| {
3429                            settings_content
3430                                .preview_tabs
3431                                .get_or_insert_default()
3432                                .enable_keep_preview_on_code_navigation = value;
3433                        },
3434                    }),
3435                    metadata: None,
3436                    files: USER,
3437                }),
3438                SettingsPageItem::SectionHeader("Layout"),
3439                SettingsPageItem::SettingItem(SettingItem {
3440                    title: "Bottom Dock Layout",
3441                    description: "Layout mode for the bottom dock.",
3442                    field: Box::new(SettingField {
3443                        json_path: Some("bottom_dock_layout"),
3444                        pick: |settings_content| {
3445                            settings_content.workspace.bottom_dock_layout.as_ref()
3446                        },
3447                        write: |settings_content, value| {
3448                            settings_content.workspace.bottom_dock_layout = value;
3449                        },
3450                    }),
3451                    metadata: None,
3452                    files: USER,
3453                }),
3454                SettingsPageItem::SettingItem(SettingItem {
3455                    files: USER,
3456                    title: "Centered Layout Left Padding",
3457                    description: "Left padding for centered layout.",
3458                    field: Box::new(SettingField {
3459                        json_path: Some("centered_layout.left_padding"),
3460                        pick: |settings_content| {
3461                            settings_content
3462                                .workspace
3463                                .centered_layout
3464                                .as_ref()?
3465                                .left_padding
3466                                .as_ref()
3467                        },
3468                        write: |settings_content, value| {
3469                            settings_content
3470                                .workspace
3471                                .centered_layout
3472                                .get_or_insert_default()
3473                                .left_padding = value;
3474                        },
3475                    }),
3476                    metadata: None,
3477                }),
3478                SettingsPageItem::SettingItem(SettingItem {
3479                    files: USER,
3480                    title: "Centered Layout Right Padding",
3481                    description: "Right padding for centered layout.",
3482                    field: Box::new(SettingField {
3483                        json_path: Some("centered_layout.right_padding"),
3484                        pick: |settings_content| {
3485                            settings_content
3486                                .workspace
3487                                .centered_layout
3488                                .as_ref()?
3489                                .right_padding
3490                                .as_ref()
3491                        },
3492                        write: |settings_content, value| {
3493                            settings_content
3494                                .workspace
3495                                .centered_layout
3496                                .get_or_insert_default()
3497                                .right_padding = value;
3498                        },
3499                    }),
3500                    metadata: None,
3501                }),
3502                SettingsPageItem::SectionHeader("Window"),
3503                // todo(settings_ui): Should we filter by platform.as_ref()?
3504                SettingsPageItem::SettingItem(SettingItem {
3505                    title: "Use System Window Tabs",
3506                    description: "(macOS only) whether to allow Windows to tab together.",
3507                    field: Box::new(SettingField {
3508                        json_path: Some("use_system_window_tabs"),
3509                        pick: |settings_content| {
3510                            settings_content.workspace.use_system_window_tabs.as_ref()
3511                        },
3512                        write: |settings_content, value| {
3513                            settings_content.workspace.use_system_window_tabs = value;
3514                        },
3515                    }),
3516                    metadata: None,
3517                    files: USER,
3518                }),
3519                SettingsPageItem::SettingItem(SettingItem {
3520                    title: "Window Decorations",
3521                    description: "(Linux only) whether Zed or your compositor should draw window decorations.",
3522                    field: Box::new(SettingField {
3523                        json_path: Some("window_decorations"),
3524                        pick: |settings_content| {
3525                            settings_content.workspace.window_decorations.as_ref()
3526                        },
3527                        write: |settings_content, value| {
3528                            settings_content.workspace.window_decorations = value;
3529                        },
3530                    }),
3531                    metadata: None,
3532                    files: USER,
3533                }),
3534                SettingsPageItem::SectionHeader("Pane Modifiers"),
3535                SettingsPageItem::SettingItem(SettingItem {
3536                    title: "Inactive Opacity",
3537                    description: "Opacity of inactive panels (0.0 - 1.0).",
3538                    field: Box::new(SettingField {
3539                        json_path: Some("active_pane_modifiers.inactive_opacity"),
3540                        pick: |settings_content| {
3541                            settings_content
3542                                .workspace
3543                                .active_pane_modifiers
3544                                .as_ref()?
3545                                .inactive_opacity
3546                                .as_ref()
3547                        },
3548                        write: |settings_content, value| {
3549                            settings_content
3550                                .workspace
3551                                .active_pane_modifiers
3552                                .get_or_insert_default()
3553                                .inactive_opacity = value;
3554                        },
3555                    }),
3556                    metadata: None,
3557                    files: USER,
3558                }),
3559                SettingsPageItem::SettingItem(SettingItem {
3560                    title: "Border Size",
3561                    description: "Size of the border surrounding the active pane.",
3562                    field: Box::new(SettingField {
3563                        json_path: Some("active_pane_modifiers.border_size"),
3564                        pick: |settings_content| {
3565                            settings_content
3566                                .workspace
3567                                .active_pane_modifiers
3568                                .as_ref()?
3569                                .border_size
3570                                .as_ref()
3571                        },
3572                        write: |settings_content, value| {
3573                            settings_content
3574                                .workspace
3575                                .active_pane_modifiers
3576                                .get_or_insert_default()
3577                                .border_size = value;
3578                        },
3579                    }),
3580                    metadata: None,
3581                    files: USER,
3582                }),
3583                SettingsPageItem::SettingItem(SettingItem {
3584                    title: "Zoomed Padding",
3585                    description: "Show padding for zoomed panes.",
3586                    field: Box::new(SettingField {
3587                        json_path: Some("zoomed_padding"),
3588                        pick: |settings_content| settings_content.workspace.zoomed_padding.as_ref(),
3589                        write: |settings_content, value| {
3590                            settings_content.workspace.zoomed_padding = value;
3591                        },
3592                    }),
3593                    metadata: None,
3594                    files: USER,
3595                }),
3596                SettingsPageItem::SectionHeader("Pane Split Direction"),
3597                SettingsPageItem::SettingItem(SettingItem {
3598                    title: "Vertical Split Direction",
3599                    description: "Direction to split vertically.",
3600                    field: Box::new(SettingField {
3601                        json_path: Some("pane_split_direction_vertical"),
3602                        pick: |settings_content| {
3603                            settings_content
3604                                .workspace
3605                                .pane_split_direction_vertical
3606                                .as_ref()
3607                        },
3608                        write: |settings_content, value| {
3609                            settings_content.workspace.pane_split_direction_vertical = value;
3610                        },
3611                    }),
3612                    metadata: None,
3613                    files: USER,
3614                }),
3615                SettingsPageItem::SettingItem(SettingItem {
3616                    title: "Horizontal Split Direction",
3617                    description: "Direction to split horizontally.",
3618                    field: Box::new(SettingField {
3619                        json_path: Some("pane_split_direction_horizontal"),
3620                        pick: |settings_content| {
3621                            settings_content
3622                                .workspace
3623                                .pane_split_direction_horizontal
3624                                .as_ref()
3625                        },
3626                        write: |settings_content, value| {
3627                            settings_content.workspace.pane_split_direction_horizontal = value;
3628                        },
3629                    }),
3630                    metadata: None,
3631                    files: USER,
3632                }),
3633            ],
3634        },
3635        SettingsPage {
3636            title: "Panels",
3637            items: vec![
3638                SettingsPageItem::SectionHeader("Project Panel"),
3639                SettingsPageItem::SettingItem(SettingItem {
3640                    title: "Project Panel Dock",
3641                    description: "Where to dock the project panel.",
3642                    field: Box::new(SettingField {
3643                        json_path: Some("project_panel.dock"),
3644                        pick: |settings_content| {
3645                            settings_content.project_panel.as_ref()?.dock.as_ref()
3646                        },
3647                        write: |settings_content, value| {
3648                            settings_content.project_panel.get_or_insert_default().dock = value;
3649                        },
3650                    }),
3651                    metadata: None,
3652                    files: USER,
3653                }),
3654                SettingsPageItem::SettingItem(SettingItem {
3655                    title: "Project Panel Default Width",
3656                    description: "Default width of the project panel in pixels.",
3657                    field: Box::new(SettingField {
3658                        json_path: Some("project_panel.default_width"),
3659                        pick: |settings_content| {
3660                            settings_content
3661                                .project_panel
3662                                .as_ref()?
3663                                .default_width
3664                                .as_ref()
3665                        },
3666                        write: |settings_content, value| {
3667                            settings_content
3668                                .project_panel
3669                                .get_or_insert_default()
3670                                .default_width = value;
3671                        },
3672                    }),
3673                    metadata: None,
3674                    files: USER,
3675                }),
3676                SettingsPageItem::SettingItem(SettingItem {
3677                    title: "Hide .gitignore",
3678                    description: "Whether to hide the gitignore entries in the project panel.",
3679                    field: Box::new(SettingField {
3680                        json_path: Some("project_panel.hide_gitignore"),
3681                        pick: |settings_content| {
3682                            settings_content
3683                                .project_panel
3684                                .as_ref()?
3685                                .hide_gitignore
3686                                .as_ref()
3687                        },
3688                        write: |settings_content, value| {
3689                            settings_content
3690                                .project_panel
3691                                .get_or_insert_default()
3692                                .hide_gitignore = value;
3693                        },
3694                    }),
3695                    metadata: None,
3696                    files: USER,
3697                }),
3698                SettingsPageItem::SettingItem(SettingItem {
3699                    title: "Entry Spacing",
3700                    description: "Spacing between worktree entries in the project panel.",
3701                    field: Box::new(SettingField {
3702                        json_path: Some("project_panel.entry_spacing"),
3703                        pick: |settings_content| {
3704                            settings_content
3705                                .project_panel
3706                                .as_ref()?
3707                                .entry_spacing
3708                                .as_ref()
3709                        },
3710                        write: |settings_content, value| {
3711                            settings_content
3712                                .project_panel
3713                                .get_or_insert_default()
3714                                .entry_spacing = value;
3715                        },
3716                    }),
3717                    metadata: None,
3718                    files: USER,
3719                }),
3720                SettingsPageItem::SettingItem(SettingItem {
3721                    title: "File Icons",
3722                    description: "Show file icons in the project panel.",
3723                    field: Box::new(SettingField {
3724                        json_path: Some("project_panel.file_icons"),
3725                        pick: |settings_content| {
3726                            settings_content.project_panel.as_ref()?.file_icons.as_ref()
3727                        },
3728                        write: |settings_content, value| {
3729                            settings_content
3730                                .project_panel
3731                                .get_or_insert_default()
3732                                .file_icons = value;
3733                        },
3734                    }),
3735                    metadata: None,
3736                    files: USER,
3737                }),
3738                SettingsPageItem::SettingItem(SettingItem {
3739                    title: "Folder Icons",
3740                    description: "Whether to show folder icons or chevrons for directories in the project panel.",
3741                    field: Box::new(SettingField {
3742                        json_path: Some("project_panel.folder_icons"),
3743                        pick: |settings_content| {
3744                            settings_content
3745                                .project_panel
3746                                .as_ref()?
3747                                .folder_icons
3748                                .as_ref()
3749                        },
3750                        write: |settings_content, value| {
3751                            settings_content
3752                                .project_panel
3753                                .get_or_insert_default()
3754                                .folder_icons = value;
3755                        },
3756                    }),
3757                    metadata: None,
3758                    files: USER,
3759                }),
3760                SettingsPageItem::SettingItem(SettingItem {
3761                    title: "Git Status",
3762                    description: "Show the Git status in the project panel.",
3763                    field: Box::new(SettingField {
3764                        json_path: Some("project_panel.git_status"),
3765                        pick: |settings_content| {
3766                            settings_content.project_panel.as_ref()?.git_status.as_ref()
3767                        },
3768                        write: |settings_content, value| {
3769                            settings_content
3770                                .project_panel
3771                                .get_or_insert_default()
3772                                .git_status = value;
3773                        },
3774                    }),
3775                    metadata: None,
3776                    files: USER,
3777                }),
3778                SettingsPageItem::SettingItem(SettingItem {
3779                    title: "Indent Size",
3780                    description: "Amount of indentation for nested items.",
3781                    field: Box::new(SettingField {
3782                        json_path: Some("project_panel.indent_size"),
3783                        pick: |settings_content| {
3784                            settings_content
3785                                .project_panel
3786                                .as_ref()?
3787                                .indent_size
3788                                .as_ref()
3789                        },
3790                        write: |settings_content, value| {
3791                            settings_content
3792                                .project_panel
3793                                .get_or_insert_default()
3794                                .indent_size = value;
3795                        },
3796                    }),
3797                    metadata: None,
3798                    files: USER,
3799                }),
3800                SettingsPageItem::SettingItem(SettingItem {
3801                    title: "Auto Reveal Entries",
3802                    description: "Whether to reveal entries in the project panel automatically when a corresponding project entry becomes active.",
3803                    field: Box::new(SettingField {
3804                        json_path: Some("project_panel.auto_reveal_entries"),
3805                        pick: |settings_content| {
3806                            settings_content
3807                                .project_panel
3808                                .as_ref()?
3809                                .auto_reveal_entries
3810                                .as_ref()
3811                        },
3812                        write: |settings_content, value| {
3813                            settings_content
3814                                .project_panel
3815                                .get_or_insert_default()
3816                                .auto_reveal_entries = value;
3817                        },
3818                    }),
3819                    metadata: None,
3820                    files: USER,
3821                }),
3822                SettingsPageItem::SettingItem(SettingItem {
3823                    title: "Starts Open",
3824                    description: "Whether the project panel should open on startup.",
3825                    field: Box::new(SettingField {
3826                        json_path: Some("project_panel.starts_open"),
3827                        pick: |settings_content| {
3828                            settings_content
3829                                .project_panel
3830                                .as_ref()?
3831                                .starts_open
3832                                .as_ref()
3833                        },
3834                        write: |settings_content, value| {
3835                            settings_content
3836                                .project_panel
3837                                .get_or_insert_default()
3838                                .starts_open = value;
3839                        },
3840                    }),
3841                    metadata: None,
3842                    files: USER,
3843                }),
3844                SettingsPageItem::SettingItem(SettingItem {
3845                    title: "Auto Fold Directories",
3846                    description: "Whether to fold directories automatically and show compact folders when a directory has only one subdirectory inside.",
3847                    field: Box::new(SettingField {
3848                        json_path: Some("project_panel.auto_fold_dirs"),
3849                        pick: |settings_content| {
3850                            settings_content
3851                                .project_panel
3852                                .as_ref()?
3853                                .auto_fold_dirs
3854                                .as_ref()
3855                        },
3856                        write: |settings_content, value| {
3857                            settings_content
3858                                .project_panel
3859                                .get_or_insert_default()
3860                                .auto_fold_dirs = value;
3861                        },
3862                    }),
3863                    metadata: None,
3864                    files: USER,
3865                }),
3866                SettingsPageItem::SettingItem(SettingItem {
3867                    title: "Show Scrollbar",
3868                    description: "Show the scrollbar in the project panel.",
3869                    field: Box::new(SettingField {
3870                        json_path: Some("project_panel.scrollbar.show"),
3871                        pick: |settings_content| {
3872                            show_scrollbar_or_editor(settings_content, |settings_content| {
3873                                settings_content
3874                                    .project_panel
3875                                    .as_ref()?
3876                                    .scrollbar
3877                                    .as_ref()?
3878                                    .show
3879                                    .as_ref()
3880                            })
3881                        },
3882                        write: |settings_content, value| {
3883                            settings_content
3884                                .project_panel
3885                                .get_or_insert_default()
3886                                .scrollbar
3887                                .get_or_insert_default()
3888                                .show = value;
3889                        },
3890                    }),
3891                    metadata: None,
3892                    files: USER,
3893                }),
3894                SettingsPageItem::SettingItem(SettingItem {
3895                    title: "Show Diagnostics",
3896                    description: "Which files containing diagnostic errors/warnings to mark in the project panel.",
3897                    field: Box::new(SettingField {
3898                        json_path: Some("project_panel.show_diagnostics"),
3899                        pick: |settings_content| {
3900                            settings_content
3901                                .project_panel
3902                                .as_ref()?
3903                                .show_diagnostics
3904                                .as_ref()
3905                        },
3906                        write: |settings_content, value| {
3907                            settings_content
3908                                .project_panel
3909                                .get_or_insert_default()
3910                                .show_diagnostics = value;
3911                        },
3912                    }),
3913                    metadata: None,
3914                    files: USER,
3915                }),
3916                SettingsPageItem::SettingItem(SettingItem {
3917                    title: "Sticky Scroll",
3918                    description: "Whether to stick parent directories at top of the project panel.",
3919                    field: Box::new(SettingField {
3920                        json_path: Some("project_panel.sticky_scroll"),
3921                        pick: |settings_content| {
3922                            settings_content
3923                                .project_panel
3924                                .as_ref()?
3925                                .sticky_scroll
3926                                .as_ref()
3927                        },
3928                        write: |settings_content, value| {
3929                            settings_content
3930                                .project_panel
3931                                .get_or_insert_default()
3932                                .sticky_scroll = value;
3933                        },
3934                    }),
3935                    metadata: None,
3936                    files: USER,
3937                }),
3938                SettingsPageItem::SettingItem(SettingItem {
3939                    files: USER,
3940                    title: "Show Indent Guides",
3941                    description: "Show indent guides in the project panel.",
3942                    field: Box::new(
3943                        SettingField {
3944                            json_path: Some("project_panel.indent_guides.show"),
3945                            pick: |settings_content| {
3946                                settings_content
3947                                    .project_panel
3948                                    .as_ref()?
3949                                    .indent_guides
3950                                    .as_ref()?
3951                                    .show
3952                                    .as_ref()
3953                            },
3954                            write: |settings_content, value| {
3955                                settings_content
3956                                    .project_panel
3957                                    .get_or_insert_default()
3958                                    .indent_guides
3959                                    .get_or_insert_default()
3960                                    .show = value;
3961                            },
3962                        }
3963                    ),
3964                    metadata: None,
3965                }),
3966                SettingsPageItem::SettingItem(SettingItem {
3967                    title: "Drag and Drop",
3968                    description: "Whether to enable drag-and-drop operations in the project panel.",
3969                    field: Box::new(SettingField {
3970                        json_path: Some("project_panel.drag_and_drop"),
3971                        pick: |settings_content| {
3972                            settings_content
3973                                .project_panel
3974                                .as_ref()?
3975                                .drag_and_drop
3976                                .as_ref()
3977                        },
3978                        write: |settings_content, value| {
3979                            settings_content
3980                                .project_panel
3981                                .get_or_insert_default()
3982                                .drag_and_drop = value;
3983                        },
3984                    }),
3985                    metadata: None,
3986                    files: USER,
3987                }),
3988                SettingsPageItem::SettingItem(SettingItem {
3989                    title: "Hide Root",
3990                    description: "Whether to hide the root entry when only one folder is open in the window.",
3991                    field: Box::new(SettingField {
3992                        json_path: Some("project_panel.drag_and_drop"),
3993                        pick: |settings_content| {
3994                            settings_content.project_panel.as_ref()?.hide_root.as_ref()
3995                        },
3996                        write: |settings_content, value| {
3997                            settings_content
3998                                .project_panel
3999                                .get_or_insert_default()
4000                                .hide_root = value;
4001                        },
4002                    }),
4003                    metadata: None,
4004                    files: USER,
4005                }),
4006                SettingsPageItem::SettingItem(SettingItem {
4007                    title: "Hide Hidden",
4008                    description: "Whether to hide the hidden entries in the project panel.",
4009                    field: Box::new(SettingField {
4010                        json_path: Some("project_panel.hide_hidden"),
4011                        pick: |settings_content| {
4012                            settings_content
4013                                .project_panel
4014                                .as_ref()?
4015                                .hide_hidden
4016                                .as_ref()
4017                        },
4018                        write: |settings_content, value| {
4019                            settings_content
4020                                .project_panel
4021                                .get_or_insert_default()
4022                                .hide_hidden = value;
4023                        },
4024                    }),
4025                    metadata: None,
4026                    files: USER,
4027                }),
4028                SettingsPageItem::SettingItem(SettingItem {
4029                    title: "Hidden Files",
4030                    description: "Globs to match files that will be considered \"hidden\" and can be hidden from the project panel.",
4031                    field: Box::new(
4032                        SettingField {
4033                            json_path: Some("worktree.hidden_files"),
4034                            pick: |settings_content| {
4035                                settings_content.project.worktree.hidden_files.as_ref()
4036                            },
4037                            write: |settings_content, value| {
4038                                settings_content.project.worktree.hidden_files = value;
4039                            },
4040                        }
4041                        .unimplemented(),
4042                    ),
4043                    metadata: None,
4044                    files: USER,
4045                }),
4046                SettingsPageItem::SectionHeader("Auto Open Files"),
4047                SettingsPageItem::SettingItem(SettingItem {
4048                    title: "On Create",
4049                    description: "Whether to automatically open newly created files in the editor.",
4050                    field: Box::new(SettingField {
4051                        json_path: Some("project_panel.auto_open.on_create"),
4052                        pick: |settings_content| {
4053                            settings_content.project_panel.as_ref()?.auto_open.as_ref()?.on_create.as_ref()
4054                        },
4055                        write: |settings_content, value| {
4056                            settings_content.project_panel.get_or_insert_default().auto_open.get_or_insert_default().on_create = value;
4057                        },
4058                    }),
4059                    metadata: None,
4060                    files: USER,
4061                }),
4062                SettingsPageItem::SettingItem(SettingItem {
4063                    title: "On Paste",
4064                    description: "Whether to automatically open files after pasting or duplicating them.",
4065                    field: Box::new(SettingField {
4066                        json_path: Some("project_panel.auto_open.on_paste"),
4067                        pick: |settings_content| {
4068                            settings_content.project_panel.as_ref()?.auto_open.as_ref()?.on_paste.as_ref()
4069                        },
4070                        write: |settings_content, value| {
4071                            settings_content.project_panel.get_or_insert_default().auto_open.get_or_insert_default().on_paste = value;
4072                        },
4073                    }),
4074                    metadata: None,
4075                    files: USER,
4076                }),
4077                SettingsPageItem::SettingItem(SettingItem {
4078                    title: "On Drop",
4079                    description: "Whether to automatically open files dropped from external sources.",
4080                    field: Box::new(SettingField {
4081                        json_path: Some("project_panel.auto_open.on_drop"),
4082                        pick: |settings_content| {
4083                            settings_content.project_panel.as_ref()?.auto_open.as_ref()?.on_drop.as_ref()
4084                        },
4085                        write: |settings_content, value| {
4086                            settings_content.project_panel.get_or_insert_default().auto_open.get_or_insert_default().on_drop = value;
4087                        },
4088                    }),
4089                    metadata: None,
4090                    files: USER,
4091                }),
4092                SettingsPageItem::SettingItem(SettingItem {
4093                    title: "Sort Mode",
4094                    description: "Sort order for entries in the project panel.",
4095                    field: Box::new(SettingField {
4096                        pick: |settings_content| {
4097                            settings_content.project_panel.as_ref()?.sort_mode.as_ref()
4098                        },
4099                        write: |settings_content, value| {
4100                            settings_content
4101                                .project_panel
4102                                .get_or_insert_default()
4103                                .sort_mode = value;
4104                        },
4105                        json_path: Some("project_panel.sort_mode"),
4106                    }),
4107                    metadata: None,
4108                    files: USER,
4109                }),
4110                SettingsPageItem::SectionHeader("Terminal Panel"),
4111                SettingsPageItem::SettingItem(SettingItem {
4112                    title: "Terminal Dock",
4113                    description: "Where to dock the terminal panel.",
4114                    field: Box::new(SettingField {
4115                        json_path: Some("terminal.dock"),
4116                        pick: |settings_content| settings_content.terminal.as_ref()?.dock.as_ref(),
4117                        write: |settings_content, value| {
4118                            settings_content.terminal.get_or_insert_default().dock = value;
4119                        },
4120                    }),
4121                    metadata: None,
4122                    files: USER,
4123                }),
4124                SettingsPageItem::SectionHeader("Outline Panel"),
4125                SettingsPageItem::SettingItem(SettingItem {
4126                    title: "Outline Panel Button",
4127                    description: "Show the outline panel button in the status bar.",
4128                    field: Box::new(SettingField {
4129                        json_path: Some("outline_panel.button"),
4130                        pick: |settings_content| {
4131                            settings_content.outline_panel.as_ref()?.button.as_ref()
4132                        },
4133                        write: |settings_content, value| {
4134                            settings_content
4135                                .outline_panel
4136                                .get_or_insert_default()
4137                                .button = value;
4138                        },
4139                    }),
4140                    metadata: None,
4141                    files: USER,
4142                }),
4143                SettingsPageItem::SettingItem(SettingItem {
4144                    title: "Outline Panel Dock",
4145                    description: "Where to dock the outline panel.",
4146                    field: Box::new(SettingField {
4147                        json_path: Some("outline_panel.dock"),
4148                        pick: |settings_content| {
4149                            settings_content.outline_panel.as_ref()?.dock.as_ref()
4150                        },
4151                        write: |settings_content, value| {
4152                            settings_content.outline_panel.get_or_insert_default().dock = value;
4153                        },
4154                    }),
4155                    metadata: None,
4156                    files: USER,
4157                }),
4158                SettingsPageItem::SettingItem(SettingItem {
4159                    title: "Outline Panel Default Width",
4160                    description: "Default width of the outline panel in pixels.",
4161                    field: Box::new(SettingField {
4162                        json_path: Some("outline_panel.default_width"),
4163                        pick: |settings_content| {
4164                            settings_content
4165                                .outline_panel
4166                                .as_ref()?
4167                                .default_width
4168                                .as_ref()
4169                        },
4170                        write: |settings_content, value| {
4171                            settings_content
4172                                .outline_panel
4173                                .get_or_insert_default()
4174                                .default_width = value;
4175                        },
4176                    }),
4177                    metadata: None,
4178                    files: USER,
4179                }),
4180                SettingsPageItem::SettingItem(SettingItem {
4181                    title: "File Icons",
4182                    description: "Show file icons in the outline panel.",
4183                    field: Box::new(SettingField {
4184                        json_path: Some("outline_panel.file_icons"),
4185                        pick: |settings_content| {
4186                            settings_content.outline_panel.as_ref()?.file_icons.as_ref()
4187                        },
4188                        write: |settings_content, value| {
4189                            settings_content
4190                                .outline_panel
4191                                .get_or_insert_default()
4192                                .file_icons = value;
4193                        },
4194                    }),
4195                    metadata: None,
4196                    files: USER,
4197                }),
4198                SettingsPageItem::SettingItem(SettingItem {
4199                    title: "Folder Icons",
4200                    description: "Whether to show folder icons or chevrons for directories in the outline panel.",
4201                    field: Box::new(SettingField {
4202                        json_path: Some("outline_panel.folder_icons"),
4203                        pick: |settings_content| {
4204                            settings_content
4205                                .outline_panel
4206                                .as_ref()?
4207                                .folder_icons
4208                                .as_ref()
4209                        },
4210                        write: |settings_content, value| {
4211                            settings_content
4212                                .outline_panel
4213                                .get_or_insert_default()
4214                                .folder_icons = value;
4215                        },
4216                    }),
4217                    metadata: None,
4218                    files: USER,
4219                }),
4220                SettingsPageItem::SettingItem(SettingItem {
4221                    title: "Git Status",
4222                    description: "Show the Git status in the outline panel.",
4223                    field: Box::new(SettingField {
4224                        json_path: Some("outline_panel.git_status"),
4225                        pick: |settings_content| {
4226                            settings_content.outline_panel.as_ref()?.git_status.as_ref()
4227                        },
4228                        write: |settings_content, value| {
4229                            settings_content
4230                                .outline_panel
4231                                .get_or_insert_default()
4232                                .git_status = value;
4233                        },
4234                    }),
4235                    metadata: None,
4236                    files: USER,
4237                }),
4238                SettingsPageItem::SettingItem(SettingItem {
4239                    title: "Indent Size",
4240                    description: "Amount of indentation for nested items.",
4241                    field: Box::new(SettingField {
4242                        json_path: Some("outline_panel.indent_size"),
4243                        pick: |settings_content| {
4244                            settings_content
4245                                .outline_panel
4246                                .as_ref()?
4247                                .indent_size
4248                                .as_ref()
4249                        },
4250                        write: |settings_content, value| {
4251                            settings_content
4252                                .outline_panel
4253                                .get_or_insert_default()
4254                                .indent_size = value;
4255                        },
4256                    }),
4257                    metadata: None,
4258                    files: USER,
4259                }),
4260                SettingsPageItem::SettingItem(SettingItem {
4261                    title: "Auto Reveal Entries",
4262                    description: "Whether to reveal when a corresponding outline entry becomes active.",
4263                    field: Box::new(SettingField {
4264                        json_path: Some("outline_panel.auto_reveal_entries"),
4265                        pick: |settings_content| {
4266                            settings_content
4267                                .outline_panel
4268                                .as_ref()?
4269                                .auto_reveal_entries
4270                                .as_ref()
4271                        },
4272                        write: |settings_content, value| {
4273                            settings_content
4274                                .outline_panel
4275                                .get_or_insert_default()
4276                                .auto_reveal_entries = value;
4277                        },
4278                    }),
4279                    metadata: None,
4280                    files: USER,
4281                }),
4282                SettingsPageItem::SettingItem(SettingItem {
4283                    title: "Auto Fold Directories",
4284                    description: "Whether to fold directories automatically when a directory contains only one subdirectory.",
4285                    field: Box::new(SettingField {
4286                        json_path: Some("outline_panel.auto_fold_dirs"),
4287                        pick: |settings_content| {
4288                            settings_content
4289                                .outline_panel
4290                                .as_ref()?
4291                                .auto_fold_dirs
4292                                .as_ref()
4293                        },
4294                        write: |settings_content, value| {
4295                            settings_content
4296                                .outline_panel
4297                                .get_or_insert_default()
4298                                .auto_fold_dirs = value;
4299                        },
4300                    }),
4301                    metadata: None,
4302                    files: USER,
4303                }),
4304                SettingsPageItem::SettingItem(SettingItem {
4305                    files: USER,
4306                    title: "Show Indent Guides",
4307                    description: "When to show indent guides in the outline panel.",
4308                    field: Box::new(
4309                        SettingField {
4310                            json_path: Some("outline_panel.indent_guides.show"),
4311                            pick: |settings_content| {
4312                                settings_content
4313                                    .outline_panel
4314                                    .as_ref()?
4315                                    .indent_guides
4316                                    .as_ref()?
4317                                    .show
4318                                    .as_ref()
4319                            },
4320                            write: |settings_content, value| {
4321                                settings_content
4322                                    .outline_panel
4323                                    .get_or_insert_default()
4324                                    .indent_guides
4325                                    .get_or_insert_default()
4326                                    .show = value;
4327                            },
4328                        }
4329                    ),
4330                    metadata: None,
4331                }),
4332                SettingsPageItem::SectionHeader("Git Panel"),
4333                SettingsPageItem::SettingItem(SettingItem {
4334                    title: "Git Panel Button",
4335                    description: "Show the Git panel button in the status bar.",
4336                    field: Box::new(SettingField {
4337                        json_path: Some("git_panel.button"),
4338                        pick: |settings_content| {
4339                            settings_content.git_panel.as_ref()?.button.as_ref()
4340                        },
4341                        write: |settings_content, value| {
4342                            settings_content.git_panel.get_or_insert_default().button = value;
4343                        },
4344                    }),
4345                    metadata: None,
4346                    files: USER,
4347                }),
4348                SettingsPageItem::SettingItem(SettingItem {
4349                    title: "Git Panel Dock",
4350                    description: "Where to dock the Git panel.",
4351                    field: Box::new(SettingField {
4352                        json_path: Some("git_panel.dock"),
4353                        pick: |settings_content| settings_content.git_panel.as_ref()?.dock.as_ref(),
4354                        write: |settings_content, value| {
4355                            settings_content.git_panel.get_or_insert_default().dock = value;
4356                        },
4357                    }),
4358                    metadata: None,
4359                    files: USER,
4360                }),
4361                SettingsPageItem::SettingItem(SettingItem {
4362                    title: "Git Panel Default Width",
4363                    description: "Default width of the Git panel in pixels.",
4364                    field: Box::new(SettingField {
4365                        json_path: Some("git_panel.default_width"),
4366                        pick: |settings_content| {
4367                            settings_content.git_panel.as_ref()?.default_width.as_ref()
4368                        },
4369                        write: |settings_content, value| {
4370                            settings_content
4371                                .git_panel
4372                                .get_or_insert_default()
4373                                .default_width = value;
4374                        },
4375                    }),
4376                    metadata: None,
4377                    files: USER,
4378                }),
4379                SettingsPageItem::SettingItem(SettingItem {
4380                    title: "Git Panel Status Style",
4381                    description: "How entry statuses are displayed.",
4382                    field: Box::new(SettingField {
4383                        json_path: Some("git_panel.status_style"),
4384                        pick: |settings_content| {
4385                            settings_content.git_panel.as_ref()?.status_style.as_ref()
4386                        },
4387                        write: |settings_content, value| {
4388                            settings_content
4389                                .git_panel
4390                                .get_or_insert_default()
4391                                .status_style = value;
4392                        },
4393                    }),
4394                    metadata: None,
4395                    files: USER,
4396                }),
4397                SettingsPageItem::SettingItem(SettingItem {
4398                    title: "Fallback Branch Name",
4399                    description: "Default branch name will be when init.defaultbranch is not set in Git.",
4400                    field: Box::new(SettingField {
4401                        json_path: Some("git_panel.fallback_branch_name"),
4402                        pick: |settings_content| {
4403                            settings_content
4404                                .git_panel
4405                                .as_ref()?
4406                                .fallback_branch_name
4407                                .as_ref()
4408                        },
4409                        write: |settings_content, value| {
4410                            settings_content
4411                                .git_panel
4412                                .get_or_insert_default()
4413                                .fallback_branch_name = value;
4414                        },
4415                    }),
4416                    metadata: None,
4417                    files: USER,
4418                }),
4419                SettingsPageItem::SettingItem(SettingItem {
4420                    title: "Sort By Path",
4421                    description: "Enable to sort entries in the panel by path, disable to sort by status.",
4422                    field: Box::new(SettingField {
4423                        json_path: Some("git_panel.sort_by_path"),
4424                        pick: |settings_content| {
4425                            settings_content.git_panel.as_ref()?.sort_by_path.as_ref()
4426                        },
4427                        write: |settings_content, value| {
4428                            settings_content
4429                                .git_panel
4430                                .get_or_insert_default()
4431                                .sort_by_path = value;
4432                        },
4433                    }),
4434                    metadata: None,
4435                    files: USER,
4436                }),
4437                SettingsPageItem::SettingItem(SettingItem {
4438                    title: "Collapse Untracked Diff",
4439                    description: "Whether to collapse untracked files in the diff panel.",
4440                    field: Box::new(SettingField {
4441                        json_path: Some("git_panel.collapse_untracked_diff"),
4442                        pick: |settings_content| {
4443                            settings_content
4444                                .git_panel
4445                                .as_ref()?
4446                                .collapse_untracked_diff
4447                                .as_ref()
4448                        },
4449                        write: |settings_content, value| {
4450                            settings_content
4451                                .git_panel
4452                                .get_or_insert_default()
4453                                .collapse_untracked_diff = value;
4454                        },
4455                    }),
4456                    metadata: None,
4457                    files: USER,
4458                }),
4459                SettingsPageItem::SettingItem(SettingItem {
4460                    title: "Tree View",
4461                    description: "Enable to show entries in tree view list, disable to show in flat view list.",
4462                    field: Box::new(SettingField {
4463                        json_path: Some("git_panel.tree_view"),
4464                        pick: |settings_content| {
4465                            settings_content.git_panel.as_ref()?.tree_view.as_ref()
4466                        },
4467                        write: |settings_content, value| {
4468                            settings_content
4469                                .git_panel
4470                                .get_or_insert_default()
4471                                .tree_view = value;
4472                        },
4473                    }),
4474                    metadata: None,
4475                    files: USER,
4476                }),
4477                SettingsPageItem::SettingItem(SettingItem {
4478                    title: "Scroll Bar",
4479                    description: "How and when the scrollbar should be displayed.",
4480                    field: Box::new(SettingField {
4481                        json_path: Some("git_panel.scrollbar.show"),
4482                        pick: |settings_content| {
4483                            show_scrollbar_or_editor(settings_content, |settings_content| {
4484                                settings_content
4485                                    .git_panel
4486                                    .as_ref()?
4487                                    .scrollbar
4488                                    .as_ref()?
4489                                    .show
4490                                    .as_ref()
4491                            })
4492                        },
4493                        write: |settings_content, value| {
4494                            settings_content
4495                                .git_panel
4496                                .get_or_insert_default()
4497                                .scrollbar
4498                                .get_or_insert_default()
4499                                .show = value;
4500                        },
4501                    }),
4502                    metadata: None,
4503                    files: USER,
4504                }),
4505                SettingsPageItem::SectionHeader("Debugger Panel"),
4506                SettingsPageItem::SettingItem(SettingItem {
4507                    title: "Debugger Panel Dock",
4508                    description: "The dock position of the debug panel.",
4509                    field: Box::new(SettingField {
4510                        json_path: Some("debugger.dock"),
4511                        pick: |settings_content| settings_content.debugger.as_ref()?.dock.as_ref(),
4512                        write: |settings_content, value| {
4513                            settings_content.debugger.get_or_insert_default().dock = value;
4514                        },
4515                    }),
4516                    metadata: None,
4517                    files: USER,
4518                }),
4519                SettingsPageItem::SectionHeader("Notification Panel"),
4520                SettingsPageItem::SettingItem(SettingItem {
4521                    title: "Notification Panel Button",
4522                    description: "Show the notification panel button in the status bar.",
4523                    field: Box::new(SettingField {
4524                        json_path: Some("notification_panel.button"),
4525                        pick: |settings_content| {
4526                            settings_content
4527                                .notification_panel
4528                                .as_ref()?
4529                                .button
4530                                .as_ref()
4531                        },
4532                        write: |settings_content, value| {
4533                            settings_content
4534                                .notification_panel
4535                                .get_or_insert_default()
4536                                .button = value;
4537                        },
4538                    }),
4539                    metadata: None,
4540                    files: USER,
4541                }),
4542                SettingsPageItem::SettingItem(SettingItem {
4543                    title: "Notification Panel Dock",
4544                    description: "Where to dock the notification panel.",
4545                    field: Box::new(SettingField {
4546                        json_path: Some("notification_panel.dock"),
4547                        pick: |settings_content| {
4548                            settings_content.notification_panel.as_ref()?.dock.as_ref()
4549                        },
4550                        write: |settings_content, value| {
4551                            settings_content
4552                                .notification_panel
4553                                .get_or_insert_default()
4554                                .dock = value;
4555                        },
4556                    }),
4557                    metadata: None,
4558                    files: USER,
4559                }),
4560                SettingsPageItem::SettingItem(SettingItem {
4561                    title: "Notification Panel Default Width",
4562                    description: "Default width of the notification panel in pixels.",
4563                    field: Box::new(SettingField {
4564                        json_path: Some("notification_panel.default_width"),
4565                        pick: |settings_content| {
4566                            settings_content
4567                                .notification_panel
4568                                .as_ref()?
4569                                .default_width
4570                                .as_ref()
4571                        },
4572                        write: |settings_content, value| {
4573                            settings_content
4574                                .notification_panel
4575                                .get_or_insert_default()
4576                                .default_width = value;
4577                        },
4578                    }),
4579                    metadata: None,
4580                    files: USER,
4581                }),
4582                SettingsPageItem::SectionHeader("Collaboration Panel"),
4583                SettingsPageItem::SettingItem(SettingItem {
4584                    title: "Collaboration Panel Button",
4585                    description: "Show the collaboration panel button in the status bar.",
4586                    field: Box::new(SettingField {
4587                        json_path: Some("collaboration_panel.button"),
4588                        pick: |settings_content| {
4589                            settings_content
4590                                .collaboration_panel
4591                                .as_ref()?
4592                                .button
4593                                .as_ref()
4594                        },
4595                        write: |settings_content, value| {
4596                            settings_content
4597                                .collaboration_panel
4598                                .get_or_insert_default()
4599                                .button = value;
4600                        },
4601                    }),
4602                    metadata: None,
4603                    files: USER,
4604                }),
4605                SettingsPageItem::SettingItem(SettingItem {
4606                    title: "Collaboration Panel Dock",
4607                    description: "Where to dock the collaboration panel.",
4608                    field: Box::new(SettingField {
4609                        json_path: Some("collaboration_panel.dock"),
4610                        pick: |settings_content| {
4611                            settings_content.collaboration_panel.as_ref()?.dock.as_ref()
4612                        },
4613                        write: |settings_content, value| {
4614                            settings_content
4615                                .collaboration_panel
4616                                .get_or_insert_default()
4617                                .dock = value;
4618                        },
4619                    }),
4620                    metadata: None,
4621                    files: USER,
4622                }),
4623                SettingsPageItem::SettingItem(SettingItem {
4624                    title: "Collaboration Panel Default Width",
4625                    description: "Default width of the collaboration panel in pixels.",
4626                    field: Box::new(SettingField {
4627                        json_path: Some("collaboration_panel.dock"),
4628                        pick: |settings_content| {
4629                            settings_content
4630                                .collaboration_panel
4631                                .as_ref()?
4632                                .default_width
4633                                .as_ref()
4634                        },
4635                        write: |settings_content, value| {
4636                            settings_content
4637                                .collaboration_panel
4638                                .get_or_insert_default()
4639                                .default_width = value;
4640                        },
4641                    }),
4642                    metadata: None,
4643                    files: USER,
4644                }),
4645                SettingsPageItem::SectionHeader("Agent Panel"),
4646                SettingsPageItem::SettingItem(SettingItem {
4647                    title: "Agent Panel Button",
4648                    description: "Whether to show the agent panel button in the status bar.",
4649                    field: Box::new(SettingField {
4650                        json_path: Some("agent.button"),
4651                        pick: |settings_content| settings_content.agent.as_ref()?.button.as_ref(),
4652                        write: |settings_content, value| {
4653                            settings_content.agent.get_or_insert_default().button = value;
4654                        },
4655                    }),
4656                    metadata: None,
4657                    files: USER,
4658                }),
4659                SettingsPageItem::SettingItem(SettingItem {
4660                    title: "Agent Panel Dock",
4661                    description: "Where to dock the agent panel.",
4662                    field: Box::new(SettingField {
4663                        json_path: Some("agent.dock"),
4664                        pick: |settings_content| settings_content.agent.as_ref()?.dock.as_ref(),
4665                        write: |settings_content, value| {
4666                            settings_content.agent.get_or_insert_default().dock = value;
4667                        },
4668                    }),
4669                    metadata: None,
4670                    files: USER,
4671                }),
4672                SettingsPageItem::SettingItem(SettingItem {
4673                    title: "Agent Panel Default Width",
4674                    description: "Default width when the agent panel is docked to the left or right.",
4675                    field: Box::new(SettingField {
4676                        json_path: Some("agent.default_width"),
4677                        pick: |settings_content| {
4678                            settings_content.agent.as_ref()?.default_width.as_ref()
4679                        },
4680                        write: |settings_content, value| {
4681                            settings_content.agent.get_or_insert_default().default_width = value;
4682                        },
4683                    }),
4684                    metadata: None,
4685                    files: USER,
4686                }),
4687                SettingsPageItem::SettingItem(SettingItem {
4688                    title: "Agent Panel Default Height",
4689                    description: "Default height when the agent panel is docked to the bottom.",
4690                    field: Box::new(SettingField {
4691                        json_path: Some("agent.default_height"),
4692                        pick: |settings_content| {
4693                            settings_content.agent.as_ref()?.default_height.as_ref()
4694                        },
4695                        write: |settings_content, value| {
4696                            settings_content
4697                                .agent
4698                                .get_or_insert_default()
4699                                .default_height = value;
4700                        },
4701                    }),
4702                    metadata: None,
4703                    files: USER,
4704                }),
4705            ],
4706        },
4707        SettingsPage {
4708            title: "Debugger",
4709            items: vec![
4710                SettingsPageItem::SectionHeader("General"),
4711                SettingsPageItem::SettingItem(SettingItem {
4712                    title: "Stepping Granularity",
4713                    description: "Determines the stepping granularity for debug operations.",
4714                    field: Box::new(SettingField {
4715                        json_path: Some("debugger.stepping_granularity"),
4716                        pick: |settings_content| {
4717                            settings_content
4718                                .debugger
4719                                .as_ref()?
4720                                .stepping_granularity
4721                                .as_ref()
4722                        },
4723                        write: |settings_content, value| {
4724                            settings_content
4725                                .debugger
4726                                .get_or_insert_default()
4727                                .stepping_granularity = value;
4728                        },
4729                    }),
4730                    metadata: None,
4731                    files: USER,
4732                }),
4733                SettingsPageItem::SettingItem(SettingItem {
4734                    title: "Save Breakpoints",
4735                    description: "Whether breakpoints should be reused across Zed sessions.",
4736                    field: Box::new(SettingField {
4737                        json_path: Some("debugger.save_breakpoints"),
4738                        pick: |settings_content| {
4739                            settings_content
4740                                .debugger
4741                                .as_ref()?
4742                                .save_breakpoints
4743                                .as_ref()
4744                        },
4745                        write: |settings_content, value| {
4746                            settings_content
4747                                .debugger
4748                                .get_or_insert_default()
4749                                .save_breakpoints = value;
4750                        },
4751                    }),
4752                    metadata: None,
4753                    files: USER,
4754                }),
4755                SettingsPageItem::SettingItem(SettingItem {
4756                    title: "Timeout",
4757                    description: "Time in milliseconds until timeout error when connecting to a TCP debug adapter.",
4758                    field: Box::new(SettingField {
4759                        json_path: Some("debugger.timeout"),
4760                        pick: |settings_content| {
4761                            settings_content.debugger.as_ref()?.timeout.as_ref()
4762                        },
4763                        write: |settings_content, value| {
4764                            settings_content.debugger.get_or_insert_default().timeout = value;
4765                        },
4766                    }),
4767                    metadata: None,
4768                    files: USER,
4769                }),
4770                SettingsPageItem::SettingItem(SettingItem {
4771                    title: "Log DAP Communications",
4772                    description: "Whether to log messages between active debug adapters and Zed.",
4773                    field: Box::new(SettingField {
4774                        json_path: Some("debugger.log_dap_communications"),
4775                        pick: |settings_content| {
4776                            settings_content
4777                                .debugger
4778                                .as_ref()?
4779                                .log_dap_communications
4780                                .as_ref()
4781                        },
4782                        write: |settings_content, value| {
4783                            settings_content
4784                                .debugger
4785                                .get_or_insert_default()
4786                                .log_dap_communications = value;
4787                        },
4788                    }),
4789                    metadata: None,
4790                    files: USER,
4791                }),
4792                SettingsPageItem::SettingItem(SettingItem {
4793                    title: "Format DAP Log Messages",
4794                    description: "Whether to format DAP messages when adding them to debug adapter logger.",
4795                    field: Box::new(SettingField {
4796                        json_path: Some("debugger.format_dap_log_messages"),
4797                        pick: |settings_content| {
4798                            settings_content
4799                                .debugger
4800                                .as_ref()?
4801                                .format_dap_log_messages
4802                                .as_ref()
4803                        },
4804                        write: |settings_content, value| {
4805                            settings_content
4806                                .debugger
4807                                .get_or_insert_default()
4808                                .format_dap_log_messages = value;
4809                        },
4810                    }),
4811                    metadata: None,
4812                    files: USER,
4813                }),
4814            ],
4815        },
4816        SettingsPage {
4817            title: "Terminal",
4818            items: vec![
4819                SettingsPageItem::SectionHeader("Environment"),
4820                SettingsPageItem::DynamicItem(DynamicItem {
4821                    discriminant: SettingItem {
4822                        files: USER | PROJECT,
4823                        title: "Shell",
4824                        description: "What shell to use when opening a terminal.",
4825                        field: Box::new(SettingField {
4826                            json_path: Some("terminal.shell$"),
4827                            pick: |settings_content| {
4828                                Some(&dynamic_variants::<settings::Shell>()[
4829                                    settings_content
4830                                        .terminal
4831                                        .as_ref()?
4832                                        .project
4833                                        .shell
4834                                        .as_ref()?
4835                                        .discriminant() as usize])
4836                            },
4837                            write: |settings_content, value| {
4838                                let Some(value) = value else {
4839                                    if let Some(terminal) = settings_content.terminal.as_mut() {
4840                                        terminal.project.shell = None;
4841                                    }
4842                                    return;
4843                                };
4844                                let settings_value = settings_content
4845                                    .terminal
4846                                    .get_or_insert_default()
4847                                    .project
4848                                    .shell
4849                                    .get_or_insert_with(|| settings::Shell::default());
4850                                let default_shell = if cfg!(target_os = "windows") {
4851                                    "powershell.exe"
4852                                } else {
4853                                    "sh"
4854                                };
4855                                *settings_value = match value {
4856                                    settings::ShellDiscriminants::System => {
4857                                        settings::Shell::System
4858                                    },
4859                                    settings::ShellDiscriminants::Program => {
4860                                        let program = match settings_value {
4861                                            settings::Shell::Program(p) => p.clone(),
4862                                            settings::Shell::WithArguments { program, .. } => program.clone(),
4863                                            _ => String::from(default_shell),
4864                                        };
4865                                        settings::Shell::Program(program)
4866                                    },
4867                                    settings::ShellDiscriminants::WithArguments => {
4868                                        let (program, args, title_override) = match settings_value {
4869                                            settings::Shell::Program(p) => (p.clone(), vec![], None),
4870                                            settings::Shell::WithArguments { program, args, title_override } => {
4871                                                (program.clone(), args.clone(), title_override.clone())
4872                                            },
4873                                            _ => (String::from(default_shell), vec![], None),
4874                                        };
4875                                        settings::Shell::WithArguments {
4876                                            program,
4877                                            args,
4878                                            title_override,
4879                                        }
4880                                    },
4881                                };
4882                            },
4883                        }),
4884                        metadata: None,
4885                    },
4886                    pick_discriminant: |settings_content| {
4887                        Some(settings_content.terminal.as_ref()?.project.shell.as_ref()?.discriminant() as usize)
4888                    },
4889                    fields: dynamic_variants::<settings::Shell>().into_iter().map(|variant| {
4890                        match variant {
4891                            settings::ShellDiscriminants::System => vec![],
4892                            settings::ShellDiscriminants::Program => vec![
4893                                SettingItem {
4894                                    files: USER | PROJECT,
4895                                    title: "Program",
4896                                    description: "The shell program to use.",
4897                                    field: Box::new(SettingField {
4898                                        json_path: Some("terminal.shell"),
4899                                        pick: |settings_content| {
4900                                            match settings_content.terminal.as_ref()?.project.shell.as_ref() {
4901                                                Some(settings::Shell::Program(program)) => Some(program),
4902                                                _ => None
4903                                            }
4904                                        },
4905                                        write: |settings_content, value| {
4906                                            let Some(value) = value else {
4907                                                return;
4908                                            };
4909                                            match settings_content
4910                                                .terminal
4911                                                .get_or_insert_default()
4912                                                .project
4913                                                .shell.as_mut() {
4914                                                    Some(settings::Shell::Program(program)) => *program = value,
4915                                                    _ => return
4916                                                }
4917                                        },
4918                                    }),
4919                                    metadata: None,
4920                                }
4921                            ],
4922                            settings::ShellDiscriminants::WithArguments => vec![
4923                                SettingItem {
4924                                    files: USER | PROJECT,
4925                                    title: "Program",
4926                                    description: "The shell program to run.",
4927                                    field: Box::new(SettingField {
4928                                        json_path: Some("terminal.shell.program"),
4929                                        pick: |settings_content| {
4930                                            match settings_content.terminal.as_ref()?.project.shell.as_ref() {
4931                                                Some(settings::Shell::WithArguments { program, .. }) => Some(program),
4932                                                _ => None
4933                                            }
4934                                        },
4935                                        write: |settings_content, value| {
4936                                            let Some(value) = value else {
4937                                                return;
4938                                            };
4939                                            match settings_content
4940                                                .terminal
4941                                                .get_or_insert_default()
4942                                                .project
4943                                                .shell.as_mut() {
4944                                                    Some(settings::Shell::WithArguments { program, .. }) => *program = value,
4945                                                    _ => return
4946                                                }
4947                                        },
4948                                    }),
4949                                    metadata: None,
4950                                },
4951                                SettingItem {
4952                                    files: USER | PROJECT,
4953                                    title: "Arguments",
4954                                    description: "The arguments to pass to the shell program.",
4955                                    field: Box::new(
4956                                        SettingField {
4957                                            json_path: Some("terminal.shell.args"),
4958                                            pick: |settings_content| {
4959                                                match settings_content.terminal.as_ref()?.project.shell.as_ref() {
4960                                                    Some(settings::Shell::WithArguments { args, .. }) => Some(args),
4961                                                    _ => None
4962                                                }
4963                                            },
4964                                            write: |settings_content, value| {
4965                                                let Some(value) = value else {
4966                                                    return;
4967                                                };
4968                                                match settings_content
4969                                                    .terminal
4970                                                    .get_or_insert_default()
4971                                                    .project
4972                                                    .shell.as_mut() {
4973                                                        Some(settings::Shell::WithArguments { args, .. }) => *args = value,
4974                                                        _ => return
4975                                                    }
4976                                            },
4977                                        }
4978                                        .unimplemented(),
4979                                    ),
4980                                    metadata: None,
4981                                },
4982                                SettingItem {
4983                                    files: USER | PROJECT,
4984                                    title: "Title Override",
4985                                    description: "An optional string to override the title of the terminal tab.",
4986                                    field: Box::new(SettingField {
4987                                        json_path: Some("terminal.shell.title_override"),
4988                                        pick: |settings_content| {
4989                                            match settings_content.terminal.as_ref()?.project.shell.as_ref() {
4990                                                Some(settings::Shell::WithArguments { title_override, .. }) => title_override.as_ref().or(DEFAULT_EMPTY_SHARED_STRING),
4991                                                _ => None
4992                                            }
4993                                        },
4994                                        write: |settings_content, value| {
4995                                            match settings_content
4996                                                .terminal
4997                                                .get_or_insert_default()
4998                                                .project
4999                                                .shell.as_mut() {
5000                                                    Some(settings::Shell::WithArguments { title_override, .. }) => *title_override = value.filter(|s| !s.is_empty()),
5001                                                    _ => return
5002                                                }
5003                                        },
5004                                    }),
5005                                    metadata: None,
5006                                }
5007                            ],
5008                        }
5009                    }).collect(),
5010                }),
5011                SettingsPageItem::DynamicItem(DynamicItem {
5012                    discriminant: SettingItem {
5013                        files: USER | PROJECT,
5014                        title: "Working Directory",
5015                        description: "What working directory to use when launching the terminal.",
5016                        field: Box::new(SettingField {
5017                            json_path: Some("terminal.working_directory$"),
5018                            pick: |settings_content| {
5019                                Some(&dynamic_variants::<settings::WorkingDirectory>()[
5020                                    settings_content
5021                                        .terminal
5022                                        .as_ref()?
5023                                        .project
5024                                        .working_directory
5025                                        .as_ref()?
5026                                        .discriminant() as usize])
5027                            },
5028                            write: |settings_content, value| {
5029                                let Some(value) = value else {
5030                                    if let Some(terminal) = settings_content.terminal.as_mut() {
5031                                        terminal.project.working_directory = None;
5032                                    }
5033                                    return;
5034                                };
5035                                let settings_value = settings_content
5036                                    .terminal
5037                                    .get_or_insert_default()
5038                                    .project
5039                                    .working_directory
5040                                    .get_or_insert_with(|| settings::WorkingDirectory::CurrentProjectDirectory);
5041                                *settings_value = match value {
5042                                    settings::WorkingDirectoryDiscriminants::CurrentProjectDirectory => {
5043                                        settings::WorkingDirectory::CurrentProjectDirectory
5044                                    },
5045                                    settings::WorkingDirectoryDiscriminants::FirstProjectDirectory => {
5046                                        settings::WorkingDirectory::FirstProjectDirectory
5047                                    },
5048                                    settings::WorkingDirectoryDiscriminants::AlwaysHome => {
5049                                        settings::WorkingDirectory::AlwaysHome
5050                                    },
5051                                    settings::WorkingDirectoryDiscriminants::Always => {
5052                                        let directory = match settings_value {
5053                                            settings::WorkingDirectory::Always { .. } => return,
5054                                            _ => String::new(),
5055                                        };
5056                                        settings::WorkingDirectory::Always { directory }
5057                                    },
5058                                };
5059                            },
5060                        }),
5061                        metadata: None,
5062                    },
5063                    pick_discriminant: |settings_content| {
5064                        Some(settings_content.terminal.as_ref()?.project.working_directory.as_ref()?.discriminant() as usize)
5065                    },
5066                    fields: dynamic_variants::<settings::WorkingDirectory>().into_iter().map(|variant| {
5067                        match variant {
5068                            settings::WorkingDirectoryDiscriminants::CurrentProjectDirectory => vec![],
5069                            settings::WorkingDirectoryDiscriminants::FirstProjectDirectory => vec![],
5070                            settings::WorkingDirectoryDiscriminants::AlwaysHome => vec![],
5071                            settings::WorkingDirectoryDiscriminants::Always => vec![
5072                                SettingItem {
5073                                    files: USER | PROJECT,
5074                                    title: "Directory",
5075                                    description: "The directory path to use (will be shell expanded).",
5076                                    field: Box::new(SettingField {
5077                                        json_path: Some("terminal.working_directory.always"),
5078                                        pick: |settings_content| {
5079                                            match settings_content.terminal.as_ref()?.project.working_directory.as_ref() {
5080                                                Some(settings::WorkingDirectory::Always { directory }) => Some(directory),
5081                                                _ => None
5082                                            }
5083                                        },
5084                                        write: |settings_content, value| {
5085                                            let value = value.unwrap_or_default();
5086                                            match settings_content
5087                                                .terminal
5088                                                .get_or_insert_default()
5089                                                .project
5090                                                .working_directory.as_mut() {
5091                                                    Some(settings::WorkingDirectory::Always { directory }) => *directory = value,
5092                                                    _ => return
5093                                                }
5094                                        },
5095                                    }),
5096                                    metadata: None,
5097                                }
5098                            ],
5099                        }
5100                    }).collect(),
5101                }),
5102                SettingsPageItem::SettingItem(SettingItem {
5103                    title: "Environment Variables",
5104                    description: "Key-value pairs to add to the terminal's environment.",
5105                    field: Box::new(
5106                        SettingField {
5107                            json_path: Some("terminal.env"),
5108                            pick: |settings_content| {
5109                                settings_content.terminal.as_ref()?.project.env.as_ref()
5110                            },
5111                            write: |settings_content, value| {
5112                                settings_content
5113                                    .terminal
5114                                    .get_or_insert_default()
5115                                    .project
5116                                    .env = value;
5117                            },
5118                        }
5119                        .unimplemented(),
5120                    ),
5121                    metadata: None,
5122                    files: USER | PROJECT,
5123                }),
5124                SettingsPageItem::SettingItem(SettingItem {
5125                    title: "Detect Virtual Environment",
5126                    description: "Activates the Python virtual environment, if one is found, in the terminal's working directory.",
5127                    field: Box::new(
5128                        SettingField {
5129                            json_path: Some("terminal.detect_venv"),
5130                            pick: |settings_content| {
5131                                settings_content
5132                                    .terminal
5133                                    .as_ref()?
5134                                    .project
5135                                    .detect_venv
5136                                    .as_ref()
5137                            },
5138                            write: |settings_content, value| {
5139                                settings_content
5140                                    .terminal
5141                                    .get_or_insert_default()
5142                                    .project
5143                                    .detect_venv = value;
5144                            },
5145                        }
5146                        .unimplemented(),
5147                    ),
5148                    metadata: None,
5149                    files: USER | PROJECT,
5150                }),
5151                SettingsPageItem::SectionHeader("Font"),
5152                SettingsPageItem::SettingItem(SettingItem {
5153                    title: "Font Size",
5154                    description: "Font size for terminal text. If not set, defaults to buffer font size.",
5155                    field: Box::new(SettingField {
5156                        json_path: Some("terminal.font_size"),
5157                        pick: |settings_content| {
5158                            settings_content
5159                                .terminal
5160                                .as_ref()
5161                                .and_then(|terminal| terminal.font_size.as_ref())
5162                                .or(settings_content.theme.buffer_font_size.as_ref())
5163                        },
5164                        write: |settings_content, value| {
5165                            settings_content.terminal.get_or_insert_default().font_size = value;
5166                        },
5167                    }),
5168                    metadata: None,
5169                    files: USER,
5170                }),
5171                SettingsPageItem::SettingItem(SettingItem {
5172                    title: "Font Family",
5173                    description: "Font family for terminal text. If not set, defaults to buffer font family.",
5174                    field: Box::new(SettingField {
5175                        json_path: Some("terminal.font_family"),
5176                        pick: |settings_content| {
5177                            settings_content
5178                                .terminal
5179                                .as_ref()
5180                                .and_then(|terminal| terminal.font_family.as_ref())
5181                                .or(settings_content.theme.buffer_font_family.as_ref())
5182                        },
5183                        write: |settings_content, value| {
5184                            settings_content
5185                                .terminal
5186                                .get_or_insert_default()
5187                                .font_family = value;
5188                        },
5189                    }),
5190                    metadata: None,
5191                    files: USER,
5192                }),
5193                SettingsPageItem::SettingItem(SettingItem {
5194                    title: "Font Fallbacks",
5195                    description: "Font fallbacks for terminal text. If not set, defaults to buffer font fallbacks.",
5196                    field: Box::new(
5197                        SettingField {
5198                            json_path: Some("terminal.font_fallbacks"),
5199                            pick: |settings_content| {
5200                                settings_content
5201                                    .terminal
5202                                    .as_ref()
5203                                    .and_then(|terminal| terminal.font_fallbacks.as_ref())
5204                                    .or(settings_content.theme.buffer_font_fallbacks.as_ref())
5205                            },
5206                            write: |settings_content, value| {
5207                                settings_content
5208                                    .terminal
5209                                    .get_or_insert_default()
5210                                    .font_fallbacks = value;
5211                            },
5212                        }
5213                        .unimplemented(),
5214                    ),
5215                    metadata: None,
5216                    files: USER,
5217                }),
5218                SettingsPageItem::SettingItem(SettingItem {
5219                    title: "Font Weight",
5220                    description: "Font weight for terminal text in CSS weight units (100-900).",
5221                    field: Box::new(SettingField {
5222                        json_path: Some("terminal.font_weight"),
5223                        pick: |settings_content| {
5224                            settings_content.terminal.as_ref()?.font_weight.as_ref()
5225                        },
5226                        write: |settings_content, value| {
5227                            settings_content
5228                                .terminal
5229                                .get_or_insert_default()
5230                                .font_weight = value;
5231                        },
5232                    }),
5233                    metadata: None,
5234                    files: USER,
5235                }),
5236                SettingsPageItem::SettingItem(SettingItem {
5237                    title: "Font Features",
5238                    description: "Font features for terminal text.",
5239                    field: Box::new(
5240                        SettingField {
5241                            json_path: Some("terminal.font_features"),
5242                            pick: |settings_content| {
5243                                settings_content
5244                                    .terminal
5245                                    .as_ref()
5246                                    .and_then(|terminal| terminal.font_features.as_ref())
5247                                    .or(settings_content.theme.buffer_font_features.as_ref())
5248                            },
5249                            write: |settings_content, value| {
5250                                settings_content
5251                                    .terminal
5252                                    .get_or_insert_default()
5253                                    .font_features = value;
5254                            },
5255                        }
5256                        .unimplemented(),
5257                    ),
5258                    metadata: None,
5259                    files: USER,
5260                }),
5261                SettingsPageItem::SectionHeader("Display Settings"),
5262                SettingsPageItem::SettingItem(SettingItem {
5263                    title: "Line Height",
5264                    description: "Line height for terminal text.",
5265                    field: Box::new(
5266                        SettingField {
5267                            json_path: Some("terminal.line_height"),
5268                            pick: |settings_content| {
5269                                settings_content.terminal.as_ref()?.line_height.as_ref()
5270                            },
5271                            write: |settings_content, value| {
5272                                settings_content
5273                                    .terminal
5274                                    .get_or_insert_default()
5275                                    .line_height = value;
5276                            },
5277                        }
5278                        .unimplemented(),
5279                    ),
5280                    metadata: None,
5281                    files: USER,
5282                }),
5283                SettingsPageItem::SettingItem(SettingItem {
5284                    title: "Cursor Shape",
5285                    description: "Default cursor shape for the terminal (bar, block, underline, or hollow).",
5286                    field: Box::new(SettingField {
5287                        json_path: Some("terminal.cursor_shape"),
5288                        pick: |settings_content| {
5289                            settings_content.terminal.as_ref()?.cursor_shape.as_ref()
5290                        },
5291                        write: |settings_content, value| {
5292                            settings_content
5293                                .terminal
5294                                .get_or_insert_default()
5295                                .cursor_shape = value;
5296                        },
5297                    }),
5298                    metadata: None,
5299                    files: USER,
5300                }),
5301                SettingsPageItem::SettingItem(SettingItem {
5302                    title: "Cursor Blinking",
5303                    description: "Sets the cursor blinking behavior in the terminal.",
5304                    field: Box::new(SettingField {
5305                        json_path: Some("terminal.blinking"),
5306                        pick: |settings_content| {
5307                            settings_content.terminal.as_ref()?.blinking.as_ref()
5308                        },
5309                        write: |settings_content, value| {
5310                            settings_content.terminal.get_or_insert_default().blinking = value;
5311                        },
5312                    }),
5313                    metadata: None,
5314                    files: USER,
5315                }),
5316                SettingsPageItem::SettingItem(SettingItem {
5317                    title: "Alternate Scroll",
5318                    description: "Whether alternate scroll mode is active by default (converts mouse scroll to arrow keys in apps like Vim).",
5319                    field: Box::new(SettingField {
5320                        json_path: Some("terminal.alternate_scroll"),
5321                        pick: |settings_content| {
5322                            settings_content
5323                                .terminal
5324                                .as_ref()?
5325                                .alternate_scroll
5326                                .as_ref()
5327                        },
5328                        write: |settings_content, value| {
5329                            settings_content
5330                                .terminal
5331                                .get_or_insert_default()
5332                                .alternate_scroll = value;
5333                        },
5334                    }),
5335                    metadata: None,
5336                    files: USER,
5337                }),
5338                SettingsPageItem::SettingItem(SettingItem {
5339                    title: "Minimum Contrast",
5340                    description: "The minimum APCA perceptual contrast between foreground and background colors (0-106).",
5341                    field: Box::new(SettingField {
5342                        json_path: Some("terminal.minimum_contrast"),
5343                        pick: |settings_content| {
5344                            settings_content
5345                                .terminal
5346                                .as_ref()?
5347                                .minimum_contrast
5348                                .as_ref()
5349                        },
5350                        write: |settings_content, value| {
5351                            settings_content
5352                                .terminal
5353                                .get_or_insert_default()
5354                                .minimum_contrast = value;
5355                        },
5356                    }),
5357                    metadata: None,
5358                    files: USER,
5359                }),
5360                SettingsPageItem::SectionHeader("Behavior Settings"),
5361                SettingsPageItem::SettingItem(SettingItem {
5362                    title: "Option As Meta",
5363                    description: "Whether the option key behaves as the meta key.",
5364                    field: Box::new(SettingField {
5365                        json_path: Some("terminal.option_as_meta"),
5366                        pick: |settings_content| {
5367                            settings_content.terminal.as_ref()?.option_as_meta.as_ref()
5368                        },
5369                        write: |settings_content, value| {
5370                            settings_content
5371                                .terminal
5372                                .get_or_insert_default()
5373                                .option_as_meta = value;
5374                        },
5375                    }),
5376                    metadata: None,
5377                    files: USER,
5378                }),
5379                SettingsPageItem::SettingItem(SettingItem {
5380                    title: "Copy On Select",
5381                    description: "Whether selecting text in the terminal automatically copies to the system clipboard.",
5382                    field: Box::new(SettingField {
5383                        json_path: Some("terminal.copy_on_select"),
5384                        pick: |settings_content| {
5385                            settings_content.terminal.as_ref()?.copy_on_select.as_ref()
5386                        },
5387                        write: |settings_content, value| {
5388                            settings_content
5389                                .terminal
5390                                .get_or_insert_default()
5391                                .copy_on_select = value;
5392                        },
5393                    }),
5394                    metadata: None,
5395                    files: USER,
5396                }),
5397                SettingsPageItem::SettingItem(SettingItem {
5398                    title: "Keep Selection On Copy",
5399                    description: "Whether to keep the text selection after copying it to the clipboard.",
5400                    field: Box::new(SettingField {
5401                        json_path: Some("terminal.keep_selection_on_copy"),
5402                        pick: |settings_content| {
5403                            settings_content
5404                                .terminal
5405                                .as_ref()?
5406                                .keep_selection_on_copy
5407                                .as_ref()
5408                        },
5409                        write: |settings_content, value| {
5410                            settings_content
5411                                .terminal
5412                                .get_or_insert_default()
5413                                .keep_selection_on_copy = value;
5414                        },
5415                    }),
5416                    metadata: None,
5417                    files: USER,
5418                }),
5419                SettingsPageItem::SectionHeader("Layout Settings"),
5420                SettingsPageItem::SettingItem(SettingItem {
5421                    title: "Default Width",
5422                    description: "Default width when the terminal is docked to the left or right (in pixels).",
5423                    field: Box::new(SettingField {
5424                        json_path: Some("terminal.default_width"),
5425                        pick: |settings_content| {
5426                            settings_content.terminal.as_ref()?.default_width.as_ref()
5427                        },
5428                        write: |settings_content, value| {
5429                            settings_content
5430                                .terminal
5431                                .get_or_insert_default()
5432                                .default_width = value;
5433                        },
5434                    }),
5435                    metadata: None,
5436                    files: USER,
5437                }),
5438                SettingsPageItem::SettingItem(SettingItem {
5439                    title: "Default Height",
5440                    description: "Default height when the terminal is docked to the bottom (in pixels).",
5441                    field: Box::new(SettingField {
5442                        json_path: Some("terminal.default_height"),
5443                        pick: |settings_content| {
5444                            settings_content.terminal.as_ref()?.default_height.as_ref()
5445                        },
5446                        write: |settings_content, value| {
5447                            settings_content
5448                                .terminal
5449                                .get_or_insert_default()
5450                                .default_height = value;
5451                        },
5452                    }),
5453                    metadata: None,
5454                    files: USER,
5455                }),
5456                SettingsPageItem::SectionHeader("Advanced Settings"),
5457                SettingsPageItem::SettingItem(SettingItem {
5458                    title: "Max Scroll History Lines",
5459                    description: "Maximum number of lines to keep in scrollback history (max: 100,000; 0 disables scrolling).",
5460                    field: Box::new(SettingField {
5461                        json_path: Some("terminal.max_scroll_history_lines"),
5462                        pick: |settings_content| {
5463                            settings_content
5464                                .terminal
5465                                .as_ref()?
5466                                .max_scroll_history_lines
5467                                .as_ref()
5468                        },
5469                        write: |settings_content, value| {
5470                            settings_content
5471                                .terminal
5472                                .get_or_insert_default()
5473                                .max_scroll_history_lines = value;
5474                        },
5475                    }),
5476                    metadata: None,
5477                    files: USER,
5478                }),
5479                SettingsPageItem::SettingItem(SettingItem {
5480                    title: "Scroll Multiplier",
5481                    description: "The multiplier for scrolling in the terminal with the mouse wheel",
5482                    field: Box::new(SettingField {
5483                        json_path: Some("terminal.scroll_multiplier"),
5484                        pick: |settings_content| {
5485                            settings_content.terminal.as_ref()?.scroll_multiplier.as_ref()
5486                        },
5487                        write: |settings_content, value| {
5488                            settings_content
5489                                .terminal
5490                                .get_or_insert_default()
5491                                .scroll_multiplier = value;
5492                        },
5493                    }),
5494                    metadata: None,
5495                    files: USER,
5496                }),
5497                SettingsPageItem::SectionHeader("Toolbar"),
5498                SettingsPageItem::SettingItem(SettingItem {
5499                    title: "Breadcrumbs",
5500                    description: "Display the terminal title in breadcrumbs inside the terminal pane.",
5501                    field: Box::new(SettingField {
5502                        json_path: Some("terminal.toolbar.breadcrumbs"),
5503                        pick: |settings_content| {
5504                            settings_content
5505                                .terminal
5506                                .as_ref()?
5507                                .toolbar
5508                                .as_ref()?
5509                                .breadcrumbs
5510                                .as_ref()
5511                        },
5512                        write: |settings_content, value| {
5513                            settings_content
5514                                .terminal
5515                                .get_or_insert_default()
5516                                .toolbar
5517                                .get_or_insert_default()
5518                                .breadcrumbs = value;
5519                        },
5520                    }),
5521                    metadata: None,
5522                    files: USER,
5523                }),
5524                SettingsPageItem::SectionHeader("Scrollbar"),
5525                SettingsPageItem::SettingItem(SettingItem {
5526                    title: "Show Scrollbar",
5527                    description: "When to show the scrollbar in the terminal.",
5528                    field: Box::new(SettingField {
5529                        json_path: Some("terminal.scrollbar.show"),
5530                        pick: |settings_content| {
5531                            show_scrollbar_or_editor(settings_content, |settings_content| {
5532                                settings_content
5533                                    .terminal
5534                                    .as_ref()?
5535                                    .scrollbar
5536                                    .as_ref()?
5537                                    .show
5538                                    .as_ref()
5539                            })
5540                        },
5541                        write: |settings_content, value| {
5542                            settings_content
5543                                .terminal
5544                                .get_or_insert_default()
5545                                .scrollbar
5546                                .get_or_insert_default()
5547                                .show = value;
5548                        },
5549                    }),
5550                    metadata: None,
5551                    files: USER,
5552                }),
5553            ],
5554        },
5555        SettingsPage {
5556            title: "Version Control",
5557            items: vec![
5558                SettingsPageItem::SectionHeader("Git Integration"),
5559                SettingsPageItem::DynamicItem(DynamicItem {
5560                    discriminant: SettingItem {
5561                        files: USER,
5562                        title: "Disable Git Integration",
5563                        description: "Disable all Git integration features in Zed.",
5564                        field: Box::new(SettingField::<bool> {
5565                            json_path: Some("git.disable_git"),
5566                            pick: |settings_content| {
5567                                settings_content
5568                                    .git
5569                                    .as_ref()?
5570                                    .enabled
5571                                    .as_ref()?
5572                                    .disable_git
5573                                    .as_ref()
5574                            },
5575                            write: |settings_content, value| {
5576                                settings_content
5577                                    .git
5578                                    .get_or_insert_default()
5579                                    .enabled
5580                                    .get_or_insert_default()
5581                                    .disable_git = value;
5582                            },
5583                        }),
5584                        metadata: None,
5585                    },
5586                    pick_discriminant: |settings_content| {
5587                        let disabled = settings_content
5588                            .git
5589                            .as_ref()?
5590                            .enabled
5591                            .as_ref()?
5592                            .disable_git
5593                            .unwrap_or(false);
5594                        Some(if disabled { 0 } else { 1 })
5595                    },
5596                    fields: vec![
5597                        vec![],
5598                        vec![
5599                            SettingItem {
5600                                files: USER,
5601                                title: "Enable Git Status",
5602                                description: "Show Git status information in the editor.",
5603                                field: Box::new(SettingField::<bool> {
5604                                    json_path: Some("git.enable_status"),
5605                                    pick: |settings_content| {
5606                                        settings_content
5607                                            .git
5608                                            .as_ref()?
5609                                            .enabled
5610                                            .as_ref()?
5611                                            .enable_status
5612                                            .as_ref()
5613                                    },
5614                                    write: |settings_content, value| {
5615                                        settings_content
5616                                            .git
5617                                            .get_or_insert_default()
5618                                            .enabled
5619                                            .get_or_insert_default()
5620                                            .enable_status = value;
5621                                    },
5622                                }),
5623                                metadata: None,
5624                            },
5625                            SettingItem {
5626                                files: USER,
5627                                title: "Enable Git Diff",
5628                                description: "Show Git diff information in the editor.",
5629                                field: Box::new(SettingField::<bool> {
5630                                    json_path: Some("git.enable_diff"),
5631                                    pick: |settings_content| {
5632                                        settings_content
5633                                            .git
5634                                            .as_ref()?
5635                                            .enabled
5636                                            .as_ref()?
5637                                            .enable_diff
5638                                            .as_ref()
5639                                    },
5640                                    write: |settings_content, value| {
5641                                        settings_content
5642                                            .git
5643                                            .get_or_insert_default()
5644                                            .enabled
5645                                            .get_or_insert_default()
5646                                            .enable_diff = value;
5647                                    },
5648                                }),
5649                                metadata: None,
5650                            },
5651                        ],
5652                    ],
5653                }),
5654                SettingsPageItem::SectionHeader("Git Gutter"),
5655                SettingsPageItem::SettingItem(SettingItem {
5656                    title: "Visibility",
5657                    description: "Control whether Git status is shown in the editor's gutter.",
5658                    field: Box::new(SettingField {
5659                        json_path: Some("git.git_gutter"),
5660                        pick: |settings_content| settings_content.git.as_ref()?.git_gutter.as_ref(),
5661                        write: |settings_content, value| {
5662                            settings_content.git.get_or_insert_default().git_gutter = value;
5663                        },
5664                    }),
5665                    metadata: None,
5666                    files: USER,
5667                }),
5668                // todo(settings_ui): Figure out the right default for this value in default.json
5669                SettingsPageItem::SettingItem(SettingItem {
5670                    title: "Debounce",
5671                    description: "Debounce threshold in milliseconds after which changes are reflected in the Git gutter.",
5672                    field: Box::new(SettingField {
5673                        json_path: Some("git.gutter_debounce"),
5674                        pick: |settings_content| {
5675                            settings_content.git.as_ref()?.gutter_debounce.as_ref()
5676                        },
5677                        write: |settings_content, value| {
5678                            settings_content.git.get_or_insert_default().gutter_debounce = value;
5679                        },
5680                    }),
5681                    metadata: None,
5682                    files: USER,
5683                }),
5684                SettingsPageItem::SectionHeader("Inline Git Blame"),
5685                SettingsPageItem::SettingItem(SettingItem {
5686                    title: "Enabled",
5687                    description: "Whether or not to show Git blame data inline in the currently focused line.",
5688                    field: Box::new(SettingField {
5689                        json_path: Some("git.inline_blame.enabled"),
5690                        pick: |settings_content| {
5691                            settings_content
5692                                .git
5693                                .as_ref()?
5694                                .inline_blame
5695                                .as_ref()?
5696                                .enabled
5697                                .as_ref()
5698                        },
5699                        write: |settings_content, value| {
5700                            settings_content
5701                                .git
5702                                .get_or_insert_default()
5703                                .inline_blame
5704                                .get_or_insert_default()
5705                                .enabled = value;
5706                        },
5707                    }),
5708                    metadata: None,
5709                    files: USER,
5710                }),
5711                SettingsPageItem::SettingItem(SettingItem {
5712                    title: "Delay",
5713                    description: "The delay after which the inline blame information is shown.",
5714                    field: Box::new(SettingField {
5715                        json_path: Some("git.inline_blame.delay_ms"),
5716                        pick: |settings_content| {
5717                            settings_content
5718                                .git
5719                                .as_ref()?
5720                                .inline_blame
5721                                .as_ref()?
5722                                .delay_ms
5723                                .as_ref()
5724                        },
5725                        write: |settings_content, value| {
5726                            settings_content
5727                                .git
5728                                .get_or_insert_default()
5729                                .inline_blame
5730                                .get_or_insert_default()
5731                                .delay_ms = value;
5732                        },
5733                    }),
5734                    metadata: None,
5735                    files: USER,
5736                }),
5737                SettingsPageItem::SettingItem(SettingItem {
5738                    title: "Padding",
5739                    description: "Padding between the end of the source line and the start of the inline blame in columns.",
5740                    field: Box::new(SettingField {
5741                        json_path: Some("git.inline_blame.padding"),
5742                        pick: |settings_content| {
5743                            settings_content
5744                                .git
5745                                .as_ref()?
5746                                .inline_blame
5747                                .as_ref()?
5748                                .padding
5749                                .as_ref()
5750                        },
5751                        write: |settings_content, value| {
5752                            settings_content
5753                                .git
5754                                .get_or_insert_default()
5755                                .inline_blame
5756                                .get_or_insert_default()
5757                                .padding = value;
5758                        },
5759                    }),
5760                    metadata: None,
5761                    files: USER,
5762                }),
5763                SettingsPageItem::SettingItem(SettingItem {
5764                    title: "Minimum Column",
5765                    description: "The minimum column number at which to show the inline blame information.",
5766                    field: Box::new(SettingField {
5767                        json_path: Some("git.inline_blame.min_column"),
5768                        pick: |settings_content| {
5769                            settings_content
5770                                .git
5771                                .as_ref()?
5772                                .inline_blame
5773                                .as_ref()?
5774                                .min_column
5775                                .as_ref()
5776                        },
5777                        write: |settings_content, value| {
5778                            settings_content
5779                                .git
5780                                .get_or_insert_default()
5781                                .inline_blame
5782                                .get_or_insert_default()
5783                                .min_column = value;
5784                        },
5785                    }),
5786                    metadata: None,
5787                    files: USER,
5788                }),
5789                SettingsPageItem::SettingItem(SettingItem {
5790                    title: "Show Commit Summary",
5791                    description: "Show commit summary as part of the inline blame.",
5792                    field: Box::new(SettingField {
5793                        json_path: Some("git.inline_blame.show_commit_summary"),
5794                        pick: |settings_content| {
5795                            settings_content
5796                                .git
5797                                .as_ref()?
5798                                .inline_blame
5799                                .as_ref()?
5800                                .show_commit_summary
5801                                .as_ref()
5802                        },
5803                        write: |settings_content, value| {
5804                            settings_content
5805                                .git
5806                                .get_or_insert_default()
5807                                .inline_blame
5808                                .get_or_insert_default()
5809                                .show_commit_summary = value;
5810                        },
5811                    }),
5812                    metadata: None,
5813                    files: USER,
5814                }),
5815                SettingsPageItem::SectionHeader("Git Blame View"),
5816                SettingsPageItem::SettingItem(SettingItem {
5817                    title: "Show Avatar",
5818                    description: "Show the avatar of the author of the commit.",
5819                    field: Box::new(SettingField {
5820                        json_path: Some("git.blame.show_avatar"),
5821                        pick: |settings_content| {
5822                            settings_content
5823                                .git
5824                                .as_ref()?
5825                                .blame
5826                                .as_ref()?
5827                                .show_avatar
5828                                .as_ref()
5829                        },
5830                        write: |settings_content, value| {
5831                            settings_content
5832                                .git
5833                                .get_or_insert_default()
5834                                .blame
5835                                .get_or_insert_default()
5836                                .show_avatar = value;
5837                        },
5838                    }),
5839                    metadata: None,
5840                    files: USER,
5841                }),
5842                SettingsPageItem::SectionHeader("Branch Picker"),
5843                SettingsPageItem::SettingItem(SettingItem {
5844                    title: "Show Author Name",
5845                    description: "Show author name as part of the commit information in branch picker.",
5846                    field: Box::new(SettingField {
5847                        json_path: Some("git.branch_picker.show_author_name"),
5848                        pick: |settings_content| {
5849                            settings_content
5850                                .git
5851                                .as_ref()?
5852                                .branch_picker
5853                                .as_ref()?
5854                                .show_author_name
5855                                .as_ref()
5856                        },
5857                        write: |settings_content, value| {
5858                            settings_content
5859                                .git
5860                                .get_or_insert_default()
5861                                .branch_picker
5862                                .get_or_insert_default()
5863                                .show_author_name = value;
5864                        },
5865                    }),
5866                    metadata: None,
5867                    files: USER,
5868                }),
5869                SettingsPageItem::SectionHeader("Git Hunks"),
5870                SettingsPageItem::SettingItem(SettingItem {
5871                    title: "Hunk Style",
5872                    description: "How Git hunks are displayed visually in the editor.",
5873                    field: Box::new(SettingField {
5874                        json_path: Some("git.hunk_style"),
5875                        pick: |settings_content| settings_content.git.as_ref()?.hunk_style.as_ref(),
5876                        write: |settings_content, value| {
5877                            settings_content.git.get_or_insert_default().hunk_style = value;
5878                        },
5879                    }),
5880                    metadata: None,
5881                    files: USER,
5882                }),
5883                SettingsPageItem::SettingItem(SettingItem {
5884                    title: "Path Style",
5885                    description: "Should the name or path be displayed first in the git view.",
5886                    field: Box::new(SettingField {
5887                        json_path: Some("git.path_style"),
5888                        pick: |settings_content| settings_content.git.as_ref()?.path_style.as_ref(),
5889                        write: |settings_content, value| {
5890                            settings_content.git.get_or_insert_default().path_style = value;
5891                        },
5892                    }),
5893                    metadata: None,
5894                    files: USER,
5895                }),
5896            ],
5897        },
5898        SettingsPage {
5899            title: "Collaboration",
5900            items: vec![
5901                SettingsPageItem::SectionHeader("Calls"),
5902                SettingsPageItem::SettingItem(SettingItem {
5903                    title: "Mute On Join",
5904                    description: "Whether the microphone should be muted when joining a channel or a call.",
5905                    field: Box::new(SettingField {
5906                        json_path: Some("calls.mute_on_join"),
5907                        pick: |settings_content| {
5908                            settings_content.calls.as_ref()?.mute_on_join.as_ref()
5909                        },
5910                        write: |settings_content, value| {
5911                            settings_content.calls.get_or_insert_default().mute_on_join = value;
5912                        },
5913                    }),
5914                    metadata: None,
5915                    files: USER,
5916                }),
5917                SettingsPageItem::SettingItem(SettingItem {
5918                    title: "Share On Join",
5919                    description: "Whether your current project should be shared when joining an empty channel.",
5920                    field: Box::new(SettingField {
5921                        json_path: Some("calls.share_on_join"),
5922                        pick: |settings_content| {
5923                            settings_content.calls.as_ref()?.share_on_join.as_ref()
5924                        },
5925                        write: |settings_content, value| {
5926                            settings_content.calls.get_or_insert_default().share_on_join = value;
5927                        },
5928                    }),
5929                    metadata: None,
5930                    files: USER,
5931                }),
5932                SettingsPageItem::SectionHeader("Experimental"),
5933                SettingsPageItem::SettingItem(SettingItem {
5934                    title: "Rodio Audio",
5935                    description: "Opt into the new audio system.",
5936                    field: Box::new(SettingField {
5937                        json_path: Some("audio.experimental.rodio_audio"),
5938                        pick: |settings_content| {
5939                            settings_content.audio.as_ref()?.rodio_audio.as_ref()
5940                        },
5941                        write: |settings_content, value| {
5942                            settings_content.audio.get_or_insert_default().rodio_audio = value;
5943                        },
5944                    }),
5945                    metadata: None,
5946                    files: USER,
5947                }),
5948                SettingsPageItem::SettingItem(SettingItem {
5949                    title: "Auto Microphone Volume",
5950                    description: "Automatically adjust microphone volume (requires rodio audio).",
5951                    field: Box::new(SettingField {
5952                        json_path: Some("audio.experimental.auto_microphone_volume"),
5953                        pick: |settings_content| {
5954                            settings_content
5955                                .audio
5956                                .as_ref()?
5957                                .auto_microphone_volume
5958                                .as_ref()
5959                        },
5960                        write: |settings_content, value| {
5961                            settings_content
5962                                .audio
5963                                .get_or_insert_default()
5964                                .auto_microphone_volume = value;
5965                        },
5966                    }),
5967                    metadata: None,
5968                    files: USER,
5969                }),
5970                SettingsPageItem::SettingItem(SettingItem {
5971                    title: "Auto Speaker Volume",
5972                    description: "Automatically adjust volume of other call members (requires rodio audio).",
5973                    field: Box::new(SettingField {
5974                        json_path: Some("audio.experimental.auto_speaker_volume"),
5975                        pick: |settings_content| {
5976                            settings_content
5977                                .audio
5978                                .as_ref()?
5979                                .auto_speaker_volume
5980                                .as_ref()
5981                        },
5982                        write: |settings_content, value| {
5983                            settings_content
5984                                .audio
5985                                .get_or_insert_default()
5986                                .auto_speaker_volume = value;
5987                        },
5988                    }),
5989                    metadata: None,
5990                    files: USER,
5991                }),
5992                SettingsPageItem::SettingItem(SettingItem {
5993                    title: "Denoise",
5994                    description: "Remove background noises (requires rodio audio).",
5995                    field: Box::new(SettingField {
5996                        json_path: Some("audio.experimental.denoise"),
5997                        pick: |settings_content| settings_content.audio.as_ref()?.denoise.as_ref(),
5998                        write: |settings_content, value| {
5999                            settings_content.audio.get_or_insert_default().denoise = value;
6000                        },
6001                    }),
6002                    metadata: None,
6003                    files: USER,
6004                }),
6005                SettingsPageItem::SettingItem(SettingItem {
6006                    title: "Legacy Audio Compatible",
6007                    description: "Use audio parameters compatible with previous versions (requires rodio audio).",
6008                    field: Box::new(SettingField {
6009                        json_path: Some("audio.experimental.legacy_audio_compatible"),
6010                        pick: |settings_content| {
6011                            settings_content
6012                                .audio
6013                                .as_ref()?
6014                                .legacy_audio_compatible
6015                                .as_ref()
6016                        },
6017                        write: |settings_content, value| {
6018                            settings_content
6019                                .audio
6020                                .get_or_insert_default()
6021                                .legacy_audio_compatible = value;
6022                        },
6023                    }),
6024                    metadata: None,
6025                    files: USER,
6026                }),
6027            ],
6028        },
6029        SettingsPage {
6030            title: "AI",
6031            items: {
6032                let mut items = vec![
6033                    SettingsPageItem::SectionHeader("General"),
6034                    SettingsPageItem::SettingItem(SettingItem {
6035                        title: "Disable AI",
6036                        description: "Whether to disable all AI features in Zed.",
6037                        field: Box::new(SettingField {
6038                            json_path: Some("disable_ai"),
6039                            pick: |settings_content| settings_content.disable_ai.as_ref(),
6040                            write: |settings_content, value| {
6041                                settings_content.disable_ai = value;
6042                            },
6043                        }),
6044                        metadata: None,
6045                        files: USER,
6046                    }),
6047                    SettingsPageItem::SectionHeader("Agent Configuration"),
6048                    SettingsPageItem::SettingItem(SettingItem {
6049                        title: "Always Allow Tool Actions",
6050                        description: "When enabled, the agent can run potentially destructive actions without asking for your confirmation. This setting has no effect on external agents.",
6051                        field: Box::new(SettingField {
6052                            json_path: Some("agent.always_allow_tool_actions"),
6053                            pick: |settings_content| {
6054                                settings_content
6055                                    .agent
6056                                    .as_ref()?
6057                                    .always_allow_tool_actions
6058                                    .as_ref()
6059                            },
6060                            write: |settings_content, value| {
6061                                settings_content
6062                                    .agent
6063                                    .get_or_insert_default()
6064                                    .always_allow_tool_actions = value;
6065                            },
6066                        }),
6067                        metadata: None,
6068                        files: USER,
6069                    }),
6070                    SettingsPageItem::SettingItem(SettingItem {
6071                        title: "Single File Review",
6072                        description: "When enabled, agent edits will also be displayed in single-file buffers for review.",
6073                        field: Box::new(SettingField {
6074                            json_path: Some("agent.single_file_review"),
6075                            pick: |settings_content| {
6076                                settings_content.agent.as_ref()?.single_file_review.as_ref()
6077                            },
6078                            write: |settings_content, value| {
6079                                settings_content
6080                                    .agent
6081                                    .get_or_insert_default()
6082                                    .single_file_review = value;
6083                            },
6084                        }),
6085                        metadata: None,
6086                        files: USER,
6087                    }),
6088                    SettingsPageItem::SettingItem(SettingItem {
6089                        title: "Enable Feedback",
6090                        description: "Show voting thumbs up/down icon buttons for feedback on agent edits.",
6091                        field: Box::new(SettingField {
6092                            json_path: Some("agent.enable_feedback"),
6093                            pick: |settings_content| {
6094                                settings_content.agent.as_ref()?.enable_feedback.as_ref()
6095                            },
6096                            write: |settings_content, value| {
6097                                settings_content
6098                                    .agent
6099                                    .get_or_insert_default()
6100                                    .enable_feedback = value;
6101                            },
6102                        }),
6103                        metadata: None,
6104                        files: USER,
6105                    }),
6106                    SettingsPageItem::SettingItem(SettingItem {
6107                        title: "Notify When Agent Waiting",
6108                        description: "Where to show notifications when the agent has completed its response or needs confirmation before running a tool action.",
6109                        field: Box::new(SettingField {
6110                            json_path: Some("agent.notify_when_agent_waiting"),
6111                            pick: |settings_content| {
6112                                settings_content
6113                                    .agent
6114                                    .as_ref()?
6115                                    .notify_when_agent_waiting
6116                                    .as_ref()
6117                            },
6118                            write: |settings_content, value| {
6119                                settings_content
6120                                    .agent
6121                                    .get_or_insert_default()
6122                                    .notify_when_agent_waiting = value;
6123                            },
6124                        }),
6125                        metadata: None,
6126                        files: USER,
6127                    }),
6128                    SettingsPageItem::SettingItem(SettingItem {
6129                        title: "Play Sound When Agent Done",
6130                        description: "Whether to play a sound when the agent has either completed its response, or needs user input.",
6131                        field: Box::new(SettingField {
6132                            json_path: Some("agent.play_sound_when_agent_done"),
6133                            pick: |settings_content| {
6134                                settings_content
6135                                    .agent
6136                                    .as_ref()?
6137                                    .play_sound_when_agent_done
6138                                    .as_ref()
6139                            },
6140                            write: |settings_content, value| {
6141                                settings_content
6142                                    .agent
6143                                    .get_or_insert_default()
6144                                    .play_sound_when_agent_done = value;
6145                            },
6146                        }),
6147                        metadata: None,
6148                        files: USER,
6149                    }),
6150                    SettingsPageItem::SettingItem(SettingItem {
6151                        title: "Expand Edit Card",
6152                        description: "Whether to have edit cards in the agent panel expanded, showing a Preview of the diff.",
6153                        field: Box::new(SettingField {
6154                            json_path: Some("agent.expand_edit_card"),
6155                            pick: |settings_content| {
6156                                settings_content.agent.as_ref()?.expand_edit_card.as_ref()
6157                            },
6158                            write: |settings_content, value| {
6159                                settings_content
6160                                    .agent
6161                                    .get_or_insert_default()
6162                                    .expand_edit_card = value;
6163                            },
6164                        }),
6165                        metadata: None,
6166                        files: USER,
6167                    }),
6168                    SettingsPageItem::SettingItem(SettingItem {
6169                        title: "Expand Terminal Card",
6170                        description: "Whether to have terminal cards in the agent panel expanded, showing the whole command output.",
6171                        field: Box::new(SettingField {
6172                            json_path: Some("agent.expand_terminal_card"),
6173                            pick: |settings_content| {
6174                                settings_content
6175                                    .agent
6176                                    .as_ref()?
6177                                    .expand_terminal_card
6178                                    .as_ref()
6179                            },
6180                            write: |settings_content, value| {
6181                                settings_content
6182                                    .agent
6183                                    .get_or_insert_default()
6184                                    .expand_terminal_card = value;
6185                            },
6186                        }),
6187                        metadata: None,
6188                        files: USER,
6189                    }),
6190                    SettingsPageItem::SettingItem(SettingItem {
6191                        title: "Use Modifier To Send",
6192                        description: "Whether to always use cmd-enter (or ctrl-enter on Linux or Windows) to send messages.",
6193                        field: Box::new(SettingField {
6194                            json_path: Some("agent.use_modifier_to_send"),
6195                            pick: |settings_content| {
6196                                settings_content
6197                                    .agent
6198                                    .as_ref()?
6199                                    .use_modifier_to_send
6200                                    .as_ref()
6201                            },
6202                            write: |settings_content, value| {
6203                                settings_content
6204                                    .agent
6205                                    .get_or_insert_default()
6206                                    .use_modifier_to_send = value;
6207                            },
6208                        }),
6209                        metadata: None,
6210                        files: USER,
6211                    }),
6212                    SettingsPageItem::SettingItem(SettingItem {
6213                        title: "Message Editor Min Lines",
6214                        description: "Minimum number of lines to display in the agent message editor.",
6215                        field: Box::new(SettingField {
6216                            json_path: Some("agent.message_editor_min_lines"),
6217                            pick: |settings_content| {
6218                                settings_content
6219                                    .agent
6220                                    .as_ref()?
6221                                    .message_editor_min_lines
6222                                    .as_ref()
6223                            },
6224                            write: |settings_content, value| {
6225                                settings_content
6226                                    .agent
6227                                    .get_or_insert_default()
6228                                    .message_editor_min_lines = value;
6229                            },
6230                        }),
6231                        metadata: None,
6232                        files: USER,
6233                    }),
6234                    SettingsPageItem::SectionHeader("Context Servers"),
6235                    SettingsPageItem::SettingItem(SettingItem {
6236                        title: "Context Server Timeout",
6237                        description: "Default timeout in seconds for context server tool calls. Can be overridden per-server in context_servers configuration.",
6238                        field: Box::new(SettingField {
6239                            json_path: Some("context_server_timeout"),
6240                            pick: |settings_content| {
6241                                settings_content.project.context_server_timeout.as_ref()
6242                            },
6243                            write: |settings_content, value| {
6244                                settings_content.project.context_server_timeout = value;
6245                            },
6246                        }),
6247                        metadata: None,
6248                        files: USER | PROJECT,
6249                    }),
6250                ];
6251                items.extend(edit_prediction_language_settings_section());
6252                items.extend(
6253                    [
6254                        SettingsPageItem::SettingItem(SettingItem {
6255                            title: "Display Mode",
6256                            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.",
6257                            field: Box::new(SettingField {
6258                                json_path: Some("edit_prediction.display_mode"),
6259                                pick: |settings_content| {
6260                                    settings_content.project.all_languages.edit_predictions.as_ref()?.mode.as_ref()
6261                                },
6262                                write: |settings_content, value| {
6263                                    settings_content.project.all_languages.edit_predictions.get_or_insert_default().mode = value;
6264                                },
6265                            }),
6266                            metadata: None,
6267                            files: USER,
6268                        }),
6269                        SettingsPageItem::SettingItem(SettingItem {
6270                            title: "Display In Text Threads",
6271                            description: "Whether edit predictions are enabled when editing text threads in the agent panel.",
6272                            field: Box::new(SettingField {
6273                                json_path: Some("edit_prediction.in_text_threads"),
6274                                pick: |settings_content| {
6275                                    settings_content.project.all_languages.edit_predictions.as_ref()?.enabled_in_text_threads.as_ref()
6276                                },
6277                                write: |settings_content, value| {
6278                                    settings_content.project.all_languages.edit_predictions.get_or_insert_default().enabled_in_text_threads = value;
6279                                },
6280                            }),
6281                            metadata: None,
6282                            files: USER,
6283                        }),
6284                    ]
6285                );
6286                items
6287            },
6288        },
6289        SettingsPage {
6290            title: "Network",
6291            items: vec![
6292                SettingsPageItem::SectionHeader("Network"),
6293                SettingsPageItem::SettingItem(SettingItem {
6294                    title: "Proxy",
6295                    description: "The proxy to use for network requests.",
6296                    field: Box::new(SettingField {
6297                        json_path: Some("proxy"),
6298                        pick: |settings_content| settings_content.proxy.as_ref(),
6299                        write: |settings_content, value| {
6300                            settings_content.proxy = value;
6301                        },
6302                    }),
6303                    metadata: Some(Box::new(SettingsFieldMetadata {
6304                        placeholder: Some("socks5h://localhost:10808"),
6305                        ..Default::default()
6306                    })),
6307                    files: USER,
6308                }),
6309                SettingsPageItem::SettingItem(SettingItem {
6310                    title: "Server URL",
6311                    description: "The URL of the Zed server to connect to.",
6312                    field: Box::new(SettingField {
6313                        json_path: Some("server_url"),
6314                        pick: |settings_content| settings_content.server_url.as_ref(),
6315                        write: |settings_content, value| {
6316                            settings_content.server_url = value;
6317                        },
6318                    }),
6319                    metadata: Some(Box::new(SettingsFieldMetadata {
6320                        placeholder: Some("https://zed.dev"),
6321                        ..Default::default()
6322                    })),
6323                    files: USER,
6324                }),
6325            ],
6326        },
6327    ]
6328}
6329
6330const LANGUAGES_SECTION_HEADER: &'static str = "Languages";
6331
6332fn current_language() -> Option<SharedString> {
6333    sub_page_stack().iter().find_map(|page| {
6334        (page.section_header == LANGUAGES_SECTION_HEADER).then(|| page.link.title.clone())
6335    })
6336}
6337
6338fn language_settings_field<T>(
6339    settings_content: &SettingsContent,
6340    get: fn(&LanguageSettingsContent) -> Option<&T>,
6341) -> Option<&T> {
6342    let all_languages = &settings_content.project.all_languages;
6343    if let Some(current_language_name) = current_language() {
6344        if let Some(current_language) = all_languages.languages.0.get(&current_language_name) {
6345            let value = get(current_language);
6346            if value.is_some() {
6347                return value;
6348            }
6349        }
6350    }
6351    let default_value = get(&all_languages.defaults);
6352    return default_value;
6353}
6354
6355fn language_settings_field_mut<T>(
6356    settings_content: &mut SettingsContent,
6357    value: Option<T>,
6358    write: fn(&mut LanguageSettingsContent, Option<T>),
6359) {
6360    let all_languages = &mut settings_content.project.all_languages;
6361    let language_content = if let Some(current_language) = current_language() {
6362        all_languages
6363            .languages
6364            .0
6365            .entry(current_language)
6366            .or_default()
6367    } else {
6368        &mut all_languages.defaults
6369    };
6370    write(language_content, value);
6371}
6372
6373fn language_settings_data() -> Vec<SettingsPageItem> {
6374    let mut items = vec![
6375        SettingsPageItem::SectionHeader("Indentation"),
6376        SettingsPageItem::SettingItem(SettingItem {
6377            title: "Tab Size",
6378            description: "How many columns a tab should occupy.",
6379            field: Box::new(SettingField {
6380                json_path: Some("languages.$(language).tab_size"), // TODO(cameron): not JQ syntax because not URL-safe
6381                pick: |settings_content| {
6382                    language_settings_field(settings_content, |language| language.tab_size.as_ref())
6383                },
6384                write: |settings_content, value| {
6385                    language_settings_field_mut(settings_content, value, |language, value| {
6386                        language.tab_size = value;
6387                    })
6388                },
6389            }),
6390            metadata: None,
6391            files: USER | PROJECT,
6392        }),
6393        SettingsPageItem::SettingItem(SettingItem {
6394            title: "Hard Tabs",
6395            description: "Whether to indent lines using tab characters, as opposed to multiple spaces.",
6396            field: Box::new(SettingField {
6397                json_path: Some("languages.$(language).hard_tabs"),
6398                pick: |settings_content| {
6399                    language_settings_field(settings_content, |language| {
6400                        language.hard_tabs.as_ref()
6401                    })
6402                },
6403                write: |settings_content, value| {
6404                    language_settings_field_mut(settings_content, value, |language, value| {
6405                        language.hard_tabs = value;
6406                    })
6407                },
6408            }),
6409            metadata: None,
6410            files: USER | PROJECT,
6411        }),
6412        SettingsPageItem::SettingItem(SettingItem {
6413            title: "Auto Indent",
6414            description: "Whether indentation should be adjusted based on the context whilst typing.",
6415            field: Box::new(SettingField {
6416                json_path: Some("languages.$(language).auto_indent"),
6417                pick: |settings_content| {
6418                    language_settings_field(settings_content, |language| {
6419                        language.auto_indent.as_ref()
6420                    })
6421                },
6422                write: |settings_content, value| {
6423                    language_settings_field_mut(settings_content, value, |language, value| {
6424                        language.auto_indent = value;
6425                    })
6426                },
6427            }),
6428            metadata: None,
6429            files: USER | PROJECT,
6430        }),
6431        SettingsPageItem::SettingItem(SettingItem {
6432            title: "Auto Indent On Paste",
6433            description: "Whether indentation of pasted content should be adjusted based on the context.",
6434            field: Box::new(SettingField {
6435                json_path: Some("languages.$(language).auto_indent_on_paste"),
6436                pick: |settings_content| {
6437                    language_settings_field(settings_content, |language| {
6438                        language.auto_indent_on_paste.as_ref()
6439                    })
6440                },
6441                write: |settings_content, value| {
6442                    language_settings_field_mut(settings_content, value, |language, value| {
6443                        language.auto_indent_on_paste = value;
6444                    })
6445                },
6446            }),
6447            metadata: None,
6448            files: USER | PROJECT,
6449        }),
6450        SettingsPageItem::SectionHeader("Wrapping"),
6451        SettingsPageItem::SettingItem(SettingItem {
6452            title: "Soft Wrap",
6453            description: "How to soft-wrap long lines of text.",
6454            field: Box::new(SettingField {
6455                json_path: Some("languages.$(language).soft_wrap"),
6456                pick: |settings_content| {
6457                    language_settings_field(settings_content, |language| {
6458                        language.soft_wrap.as_ref()
6459                    })
6460                },
6461                write: |settings_content, value| {
6462                    language_settings_field_mut(settings_content, value, |language, value| {
6463                        language.soft_wrap = value;
6464                    })
6465                },
6466            }),
6467            metadata: None,
6468            files: USER | PROJECT,
6469        }),
6470        SettingsPageItem::SettingItem(SettingItem {
6471            title: "Show Wrap Guides",
6472            description: "Show wrap guides in the editor.",
6473            field: Box::new(SettingField {
6474                json_path: Some("languages.$(language).show_wrap_guides"),
6475                pick: |settings_content| {
6476                    language_settings_field(settings_content, |language| {
6477                        language.show_wrap_guides.as_ref()
6478                    })
6479                },
6480                write: |settings_content, value| {
6481                    language_settings_field_mut(settings_content, value, |language, value| {
6482                        language.show_wrap_guides = value;
6483                    })
6484                },
6485            }),
6486            metadata: None,
6487            files: USER | PROJECT,
6488        }),
6489        SettingsPageItem::SettingItem(SettingItem {
6490            title: "Preferred Line Length",
6491            description: "The column at which to soft-wrap lines, for buffers where soft-wrap is enabled.",
6492            field: Box::new(SettingField {
6493                json_path: Some("languages.$(language).preferred_line_length"),
6494                pick: |settings_content| {
6495                    language_settings_field(settings_content, |language| {
6496                        language.preferred_line_length.as_ref()
6497                    })
6498                },
6499                write: |settings_content, value| {
6500                    language_settings_field_mut(settings_content, value, |language, value| {
6501                        language.preferred_line_length = value;
6502                    })
6503                },
6504            }),
6505            metadata: None,
6506            files: USER | PROJECT,
6507        }),
6508        SettingsPageItem::SettingItem(SettingItem {
6509            title: "Wrap Guides",
6510            description: "Character counts at which to show wrap guides in the editor.",
6511            field: Box::new(
6512                SettingField {
6513                    json_path: Some("languages.$(language).wrap_guides"),
6514                    pick: |settings_content| {
6515                        language_settings_field(settings_content, |language| {
6516                            language.wrap_guides.as_ref()
6517                        })
6518                    },
6519                    write: |settings_content, value| {
6520                        language_settings_field_mut(settings_content, value, |language, value| {
6521                            language.wrap_guides = value;
6522                        })
6523                    },
6524                }
6525                .unimplemented(),
6526            ),
6527            metadata: None,
6528            files: USER | PROJECT,
6529        }),
6530        SettingsPageItem::SettingItem(SettingItem {
6531            title: "Allow Rewrap",
6532            description: "Controls where the `editor::rewrap` action is allowed for this language.",
6533            field: Box::new(SettingField {
6534                json_path: Some("languages.$(language).allow_rewrap"),
6535                pick: |settings_content| {
6536                    language_settings_field(settings_content, |language| {
6537                        language.allow_rewrap.as_ref()
6538                    })
6539                },
6540                write: |settings_content, value| {
6541                    language_settings_field_mut(settings_content, value, |language, value| {
6542                        language.allow_rewrap = value;
6543                    })
6544                },
6545            }),
6546            metadata: None,
6547            files: USER | PROJECT,
6548        }),
6549        SettingsPageItem::SectionHeader("Indent Guides"),
6550        SettingsPageItem::SettingItem(SettingItem {
6551            title: "Enabled",
6552            description: "Display indent guides in the editor.",
6553            field: Box::new(SettingField {
6554                json_path: Some("languages.$(language).indent_guides.enabled"),
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.enabled.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().enabled = value;
6566                    })
6567                },
6568            }),
6569            metadata: None,
6570            files: USER | PROJECT,
6571        }),
6572        SettingsPageItem::SettingItem(SettingItem {
6573            title: "Line Width",
6574            description: "The width of the indent guides in pixels, between 1 and 10.",
6575            field: Box::new(SettingField {
6576                json_path: Some("languages.$(language).indent_guides.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.line_width.as_ref())
6583                    })
6584                },
6585                write: |settings_content, value| {
6586                    language_settings_field_mut(settings_content, value, |language, value| {
6587                        language.indent_guides.get_or_insert_default().line_width = value;
6588                    })
6589                },
6590            }),
6591            metadata: None,
6592            files: USER | PROJECT,
6593        }),
6594        SettingsPageItem::SettingItem(SettingItem {
6595            title: "Active Line Width",
6596            description: "The width of the active indent guide in pixels, between 1 and 10.",
6597            field: Box::new(SettingField {
6598                json_path: Some("languages.$(language).indent_guides.active_line_width"),
6599                pick: |settings_content| {
6600                    language_settings_field(settings_content, |language| {
6601                        language
6602                            .indent_guides
6603                            .as_ref()
6604                            .and_then(|indent_guides| indent_guides.active_line_width.as_ref())
6605                    })
6606                },
6607                write: |settings_content, value| {
6608                    language_settings_field_mut(settings_content, value, |language, value| {
6609                        language
6610                            .indent_guides
6611                            .get_or_insert_default()
6612                            .active_line_width = value;
6613                    })
6614                },
6615            }),
6616            metadata: None,
6617            files: USER | PROJECT,
6618        }),
6619        SettingsPageItem::SettingItem(SettingItem {
6620            title: "Coloring",
6621            description: "Determines how indent guides are colored.",
6622            field: Box::new(SettingField {
6623                json_path: Some("languages.$(language).indent_guides.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.coloring.as_ref())
6630                    })
6631                },
6632                write: |settings_content, value| {
6633                    language_settings_field_mut(settings_content, value, |language, value| {
6634                        language.indent_guides.get_or_insert_default().coloring = value;
6635                    })
6636                },
6637            }),
6638            metadata: None,
6639            files: USER | PROJECT,
6640        }),
6641        SettingsPageItem::SettingItem(SettingItem {
6642            title: "Background Coloring",
6643            description: "Determines how indent guide backgrounds are colored.",
6644            field: Box::new(SettingField {
6645                json_path: Some("languages.$(language).indent_guides.background_coloring"),
6646                pick: |settings_content| {
6647                    language_settings_field(settings_content, |language| {
6648                        language
6649                            .indent_guides
6650                            .as_ref()
6651                            .and_then(|indent_guides| indent_guides.background_coloring.as_ref())
6652                    })
6653                },
6654                write: |settings_content, value| {
6655                    language_settings_field_mut(settings_content, value, |language, value| {
6656                        language
6657                            .indent_guides
6658                            .get_or_insert_default()
6659                            .background_coloring = value;
6660                    })
6661                },
6662            }),
6663            metadata: None,
6664            files: USER | PROJECT,
6665        }),
6666        SettingsPageItem::SectionHeader("Formatting"),
6667        SettingsPageItem::SettingItem(SettingItem {
6668            title: "Format On Save",
6669            description: "Whether or not to perform a buffer format before saving.",
6670            field: Box::new(
6671                // TODO(settings_ui): this setting should just be a bool
6672                SettingField {
6673                    json_path: Some("languages.$(language).format_on_save"),
6674                    pick: |settings_content| {
6675                        language_settings_field(settings_content, |language| {
6676                            language.format_on_save.as_ref()
6677                        })
6678                    },
6679                    write: |settings_content, value| {
6680                        language_settings_field_mut(settings_content, value, |language, value| {
6681                            language.format_on_save = value;
6682                        })
6683                    },
6684                },
6685            ),
6686            metadata: None,
6687            files: USER | PROJECT,
6688        }),
6689        SettingsPageItem::SettingItem(SettingItem {
6690            title: "Remove Trailing Whitespace On Save",
6691            description: "Whether or not to remove any trailing whitespace from lines of a buffer before saving it.",
6692            field: Box::new(SettingField {
6693                json_path: Some("languages.$(language).remove_trailing_whitespace_on_save"),
6694                pick: |settings_content| {
6695                    language_settings_field(settings_content, |language| {
6696                        language.remove_trailing_whitespace_on_save.as_ref()
6697                    })
6698                },
6699                write: |settings_content, value| {
6700                    language_settings_field_mut(settings_content, value, |language, value| {
6701                        language.remove_trailing_whitespace_on_save = value;
6702                    })
6703                },
6704            }),
6705            metadata: None,
6706            files: USER | PROJECT,
6707        }),
6708        SettingsPageItem::SettingItem(SettingItem {
6709            title: "Ensure Final Newline On Save",
6710            description: "Whether or not to ensure there's a single newline at the end of a buffer when saving it.",
6711            field: Box::new(SettingField {
6712                json_path: Some("languages.$(language).ensure_final_newline_on_save"),
6713                pick: |settings_content| {
6714                    language_settings_field(settings_content, |language| {
6715                        language.ensure_final_newline_on_save.as_ref()
6716                    })
6717                },
6718                write: |settings_content, value| {
6719                    language_settings_field_mut(settings_content, value, |language, value| {
6720                        language.ensure_final_newline_on_save = value;
6721                    })
6722                },
6723            }),
6724            metadata: None,
6725            files: USER | PROJECT,
6726        }),
6727        SettingsPageItem::SettingItem(SettingItem {
6728            title: "Formatter",
6729            description: "How to perform a buffer format.",
6730            field: Box::new(
6731                SettingField {
6732                    json_path: Some("languages.$(language).formatter"),
6733                    pick: |settings_content| {
6734                        language_settings_field(settings_content, |language| {
6735                            language.formatter.as_ref()
6736                        })
6737                    },
6738                    write: |settings_content, value| {
6739                        language_settings_field_mut(settings_content, value, |language, value| {
6740                            language.formatter = value;
6741                        })
6742                    },
6743                }
6744                .unimplemented(),
6745            ),
6746            metadata: None,
6747            files: USER | PROJECT,
6748        }),
6749        SettingsPageItem::SettingItem(SettingItem {
6750            title: "Use On Type Format",
6751            description: "Whether to use additional LSP queries to format (and amend) the code after every \"trigger\" symbol input, defined by LSP server capabilities",
6752            field: Box::new(SettingField {
6753                json_path: Some("languages.$(language).use_on_type_format"),
6754                pick: |settings_content| {
6755                    language_settings_field(settings_content, |language| {
6756                        language.use_on_type_format.as_ref()
6757                    })
6758                },
6759                write: |settings_content, value| {
6760                    language_settings_field_mut(settings_content, value, |language, value| {
6761                        language.use_on_type_format = value;
6762                    })
6763                },
6764            }),
6765            metadata: None,
6766            files: USER | PROJECT,
6767        }),
6768        SettingsPageItem::SettingItem(SettingItem {
6769            title: "Code Actions On Format",
6770            description: "Additional code actions to run when formatting.",
6771            field: Box::new(
6772                SettingField {
6773                    json_path: Some("languages.$(language).code_actions_on_format"),
6774                    pick: |settings_content| {
6775                        language_settings_field(settings_content, |language| {
6776                            language.code_actions_on_format.as_ref()
6777                        })
6778                    },
6779                    write: |settings_content, value| {
6780                        language_settings_field_mut(settings_content, value, |language, value| {
6781                            language.code_actions_on_format = value;
6782                        })
6783                    },
6784                }
6785                .unimplemented(),
6786            ),
6787            metadata: None,
6788            files: USER | PROJECT,
6789        }),
6790        SettingsPageItem::SectionHeader("Autoclose"),
6791        SettingsPageItem::SettingItem(SettingItem {
6792            title: "Use Autoclose",
6793            description: "Whether to automatically type closing characters for you. For example, when you type '(', Zed will automatically add a closing ')' at the correct position.",
6794            field: Box::new(SettingField {
6795                json_path: Some("languages.$(language).use_autoclose"),
6796                pick: |settings_content| {
6797                    language_settings_field(settings_content, |language| {
6798                        language.use_autoclose.as_ref()
6799                    })
6800                },
6801                write: |settings_content, value| {
6802                    language_settings_field_mut(settings_content, value, |language, value| {
6803                        language.use_autoclose = value;
6804                    })
6805                },
6806            }),
6807            metadata: None,
6808            files: USER | PROJECT,
6809        }),
6810        SettingsPageItem::SettingItem(SettingItem {
6811            title: "Use Auto Surround",
6812            description: "Whether to automatically surround text with characters for you. For example, when you select text and type '(', Zed will automatically surround text with ().",
6813            field: Box::new(SettingField {
6814                json_path: Some("languages.$(language).use_auto_surround"),
6815                pick: |settings_content| {
6816                    language_settings_field(settings_content, |language| {
6817                        language.use_auto_surround.as_ref()
6818                    })
6819                },
6820                write: |settings_content, value| {
6821                    language_settings_field_mut(settings_content, value, |language, value| {
6822                        language.use_auto_surround = value;
6823                    })
6824                },
6825            }),
6826            metadata: None,
6827            files: USER | PROJECT,
6828        }),
6829        SettingsPageItem::SettingItem(SettingItem {
6830            title: "Always Treat Brackets As Autoclosed",
6831            description: "Controls whether the closing characters are always skipped over and auto-removed no matter how they were inserted.",
6832            field: Box::new(SettingField {
6833                json_path: Some("languages.$(language).always_treat_brackets_as_autoclosed"),
6834                pick: |settings_content| {
6835                    language_settings_field(settings_content, |language| {
6836                        language.always_treat_brackets_as_autoclosed.as_ref()
6837                    })
6838                },
6839                write: |settings_content, value| {
6840                    language_settings_field_mut(settings_content, value, |language, value| {
6841                        language.always_treat_brackets_as_autoclosed = value;
6842                    })
6843                },
6844            }),
6845            metadata: None,
6846            files: USER | PROJECT,
6847        }),
6848        SettingsPageItem::SettingItem(SettingItem {
6849            title: "JSX Tag Auto Close",
6850            description: "Whether to automatically close JSX tags.",
6851            field: Box::new(SettingField {
6852                json_path: Some("languages.$(language).jsx_tag_auto_close"),
6853                // TODO(settings_ui): this setting should just be a bool
6854                pick: |settings_content| {
6855                    language_settings_field(settings_content, |language| {
6856                        language.jsx_tag_auto_close.as_ref()?.enabled.as_ref()
6857                    })
6858                },
6859                write: |settings_content, value| {
6860                    language_settings_field_mut(settings_content, value, |language, value| {
6861                        language.jsx_tag_auto_close.get_or_insert_default().enabled = value;
6862                    })
6863                },
6864            }),
6865            metadata: None,
6866            files: USER | PROJECT,
6867        }),
6868        SettingsPageItem::SectionHeader("Whitespace"),
6869        SettingsPageItem::SettingItem(SettingItem {
6870            title: "Show Whitespaces",
6871            description: "Whether to show tabs and spaces in the editor.",
6872            field: Box::new(SettingField {
6873                json_path: Some("languages.$(language).show_whitespaces"),
6874                pick: |settings_content| {
6875                    language_settings_field(settings_content, |language| {
6876                        language.show_whitespaces.as_ref()
6877                    })
6878                },
6879                write: |settings_content, value| {
6880                    language_settings_field_mut(settings_content, value, |language, value| {
6881                        language.show_whitespaces = value;
6882                    })
6883                },
6884            }),
6885            metadata: None,
6886            files: USER | PROJECT,
6887        }),
6888        SettingsPageItem::SettingItem(SettingItem {
6889            title: "Space Whitespace Indicator",
6890            description: "Visible character used to render space characters when show_whitespaces is enabled (default: \"\")",
6891            field: Box::new(
6892                SettingField {
6893                    json_path: Some("languages.$(language).whitespace_map.space"),
6894                    pick: |settings_content| {
6895                        language_settings_field(settings_content, |language| {
6896                            language.whitespace_map.as_ref()?.space.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().space = value;
6902                        })
6903                    },
6904                }
6905                .unimplemented(),
6906            ),
6907            metadata: None,
6908            files: USER | PROJECT,
6909        }),
6910        SettingsPageItem::SettingItem(SettingItem {
6911            title: "Tab Whitespace Indicator",
6912            description: "Visible character used to render tab characters when show_whitespaces is enabled (default: \"\")",
6913            field: Box::new(
6914                SettingField {
6915                    json_path: Some("languages.$(language).whitespace_map.tab"),
6916                    pick: |settings_content| {
6917                        language_settings_field(settings_content, |language| {
6918                            language.whitespace_map.as_ref()?.tab.as_ref()
6919                        })
6920                    },
6921                    write: |settings_content, value| {
6922                        language_settings_field_mut(settings_content, value, |language, value| {
6923                            language.whitespace_map.get_or_insert_default().tab = value;
6924                        })
6925                    },
6926                }
6927                .unimplemented(),
6928            ),
6929            metadata: None,
6930            files: USER | PROJECT,
6931        }),
6932        SettingsPageItem::SectionHeader("Completions"),
6933        SettingsPageItem::SettingItem(SettingItem {
6934            title: "Show Completions On Input",
6935            description: "Whether to pop the completions menu while typing in an editor without explicitly requesting it.",
6936            field: Box::new(SettingField {
6937                json_path: Some("languages.$(language).show_completions_on_input"),
6938                pick: |settings_content| {
6939                    language_settings_field(settings_content, |language| {
6940                        language.show_completions_on_input.as_ref()
6941                    })
6942                },
6943                write: |settings_content, value| {
6944                    language_settings_field_mut(settings_content, value, |language, value| {
6945                        language.show_completions_on_input = value;
6946                    })
6947                },
6948            }),
6949            metadata: None,
6950            files: USER | PROJECT,
6951        }),
6952        SettingsPageItem::SettingItem(SettingItem {
6953            title: "Show Completion Documentation",
6954            description: "Whether to display inline and alongside documentation for items in the completions menu.",
6955            field: Box::new(SettingField {
6956                json_path: Some("languages.$(language).show_completion_documentation"),
6957                pick: |settings_content| {
6958                    language_settings_field(settings_content, |language| {
6959                        language.show_completion_documentation.as_ref()
6960                    })
6961                },
6962                write: |settings_content, value| {
6963                    language_settings_field_mut(settings_content, value, |language, value| {
6964                        language.show_completion_documentation = value;
6965                    })
6966                },
6967            }),
6968            metadata: None,
6969            files: USER | PROJECT,
6970        }),
6971        SettingsPageItem::SettingItem(SettingItem {
6972            title: "Words",
6973            description: "Controls how words are completed.",
6974            field: Box::new(SettingField {
6975                json_path: Some("languages.$(language).completions.words"),
6976                pick: |settings_content| {
6977                    language_settings_field(settings_content, |language| {
6978                        language.completions.as_ref()?.words.as_ref()
6979                    })
6980                },
6981                write: |settings_content, value| {
6982                    language_settings_field_mut(settings_content, value, |language, value| {
6983                        language.completions.get_or_insert_default().words = value;
6984                    })
6985                },
6986            }),
6987            metadata: None,
6988            files: USER | PROJECT,
6989        }),
6990        SettingsPageItem::SettingItem(SettingItem {
6991            title: "Words Min Length",
6992            description: "How many characters has to be in the completions query to automatically show the words-based completions.",
6993            field: Box::new(SettingField {
6994                json_path: Some("languages.$(language).completions.words_min_length"),
6995                pick: |settings_content| {
6996                    language_settings_field(settings_content, |language| {
6997                        language.completions.as_ref()?.words_min_length.as_ref()
6998                    })
6999                },
7000                write: |settings_content, value| {
7001                    language_settings_field_mut(settings_content, value, |language, value| {
7002                        language
7003                            .completions
7004                            .get_or_insert_default()
7005                            .words_min_length = value;
7006                    })
7007                },
7008            }),
7009            metadata: None,
7010            files: USER | PROJECT,
7011        }),
7012        SettingsPageItem::SettingItem(SettingItem {
7013            title: "Completion Menu Scrollbar",
7014            description: "When to show the scrollbar in the completion menu.",
7015            field: Box::new(SettingField {
7016                json_path: Some("editor.completion_menu_scrollbar"),
7017                pick: |settings_content| settings_content.editor.completion_menu_scrollbar.as_ref(),
7018                write: |settings_content, value| {
7019                    settings_content.editor.completion_menu_scrollbar = value;
7020                },
7021            }),
7022            metadata: None,
7023            files: USER,
7024        }),
7025        SettingsPageItem::SettingItem(SettingItem {
7026            title: "Completion Detail Alignment",
7027            description: "Whether to align detail text in code completions context menus left or right.",
7028            field: Box::new(SettingField {
7029                json_path: Some("editor.completion_detail_alignment"),
7030                pick: |settings_content| {
7031                    settings_content.editor.completion_detail_alignment.as_ref()
7032                },
7033                write: |settings_content, value| {
7034                    settings_content.editor.completion_detail_alignment = value;
7035                },
7036            }),
7037            metadata: None,
7038            files: USER,
7039        }),
7040        SettingsPageItem::SectionHeader("Inlay Hints"),
7041        SettingsPageItem::SettingItem(SettingItem {
7042            title: "Enabled",
7043            description: "Global switch to toggle hints on and off.",
7044            field: Box::new(SettingField {
7045                json_path: Some("languages.$(language).inlay_hints.enabled"),
7046                pick: |settings_content| {
7047                    language_settings_field(settings_content, |language| {
7048                        language.inlay_hints.as_ref()?.enabled.as_ref()
7049                    })
7050                },
7051                write: |settings_content, value| {
7052                    language_settings_field_mut(settings_content, value, |language, value| {
7053                        language.inlay_hints.get_or_insert_default().enabled = value;
7054                    })
7055                },
7056            }),
7057            metadata: None,
7058            files: USER | PROJECT,
7059        }),
7060        SettingsPageItem::SettingItem(SettingItem {
7061            title: "Show Value Hints",
7062            description: "Global switch to toggle inline values on and off when debugging.",
7063            field: Box::new(SettingField {
7064                json_path: Some("languages.$(language).inlay_hints.show_value_hints"),
7065                pick: |settings_content| {
7066                    language_settings_field(settings_content, |language| {
7067                        language.inlay_hints.as_ref()?.show_value_hints.as_ref()
7068                    })
7069                },
7070                write: |settings_content, value| {
7071                    language_settings_field_mut(settings_content, value, |language, value| {
7072                        language
7073                            .inlay_hints
7074                            .get_or_insert_default()
7075                            .show_value_hints = value;
7076                    })
7077                },
7078            }),
7079            metadata: None,
7080            files: USER | PROJECT,
7081        }),
7082        SettingsPageItem::SettingItem(SettingItem {
7083            title: "Show Type Hints",
7084            description: "Whether type hints should be shown.",
7085            field: Box::new(SettingField {
7086                json_path: Some("languages.$(language).inlay_hints.show_type_hints"),
7087                pick: |settings_content| {
7088                    language_settings_field(settings_content, |language| {
7089                        language.inlay_hints.as_ref()?.show_type_hints.as_ref()
7090                    })
7091                },
7092                write: |settings_content, value| {
7093                    language_settings_field_mut(settings_content, value, |language, value| {
7094                        language.inlay_hints.get_or_insert_default().show_type_hints = value;
7095                    })
7096                },
7097            }),
7098            metadata: None,
7099            files: USER | PROJECT,
7100        }),
7101        SettingsPageItem::SettingItem(SettingItem {
7102            title: "Show Parameter Hints",
7103            description: "Whether parameter hints should be shown.",
7104            field: Box::new(SettingField {
7105                json_path: Some("languages.$(language).inlay_hints.show_parameter_hints"),
7106                pick: |settings_content| {
7107                    language_settings_field(settings_content, |language| {
7108                        language.inlay_hints.as_ref()?.show_parameter_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_parameter_hints = value;
7117                    })
7118                },
7119            }),
7120            metadata: None,
7121            files: USER | PROJECT,
7122        }),
7123        SettingsPageItem::SettingItem(SettingItem {
7124            title: "Show Other Hints",
7125            description: "Whether other hints should be shown.",
7126            field: Box::new(SettingField {
7127                json_path: Some("languages.$(language).inlay_hints.show_other_hints"),
7128                pick: |settings_content| {
7129                    language_settings_field(settings_content, |language| {
7130                        language.inlay_hints.as_ref()?.show_other_hints.as_ref()
7131                    })
7132                },
7133                write: |settings_content, value| {
7134                    language_settings_field_mut(settings_content, value, |language, value| {
7135                        language
7136                            .inlay_hints
7137                            .get_or_insert_default()
7138                            .show_other_hints = value;
7139                    })
7140                },
7141            }),
7142            metadata: None,
7143            files: USER | PROJECT,
7144        }),
7145        SettingsPageItem::SettingItem(SettingItem {
7146            title: "Show Background",
7147            description: "Show a background for inlay hints.",
7148            field: Box::new(SettingField {
7149                json_path: Some("languages.$(language).inlay_hints.show_background"),
7150                pick: |settings_content| {
7151                    language_settings_field(settings_content, |language| {
7152                        language.inlay_hints.as_ref()?.show_background.as_ref()
7153                    })
7154                },
7155                write: |settings_content, value| {
7156                    language_settings_field_mut(settings_content, value, |language, value| {
7157                        language.inlay_hints.get_or_insert_default().show_background = value;
7158                    })
7159                },
7160            }),
7161            metadata: None,
7162            files: USER | PROJECT,
7163        }),
7164        SettingsPageItem::SettingItem(SettingItem {
7165            title: "Edit Debounce Ms",
7166            description: "Whether or not to debounce inlay hints updates after buffer edits (set to 0 to disable debouncing).",
7167            field: Box::new(SettingField {
7168                json_path: Some("languages.$(language).inlay_hints.edit_debounce_ms"),
7169                pick: |settings_content| {
7170                    language_settings_field(settings_content, |language| {
7171                        language.inlay_hints.as_ref()?.edit_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                            .edit_debounce_ms = value;
7180                    })
7181                },
7182            }),
7183            metadata: None,
7184            files: USER | PROJECT,
7185        }),
7186        SettingsPageItem::SettingItem(SettingItem {
7187            title: "Scroll Debounce Ms",
7188            description: "Whether or not to debounce inlay hints updates after buffer scrolls (set to 0 to disable debouncing).",
7189            field: Box::new(SettingField {
7190                json_path: Some("languages.$(language).inlay_hints.scroll_debounce_ms"),
7191                pick: |settings_content| {
7192                    language_settings_field(settings_content, |language| {
7193                        language.inlay_hints.as_ref()?.scroll_debounce_ms.as_ref()
7194                    })
7195                },
7196                write: |settings_content, value| {
7197                    language_settings_field_mut(settings_content, value, |language, value| {
7198                        language
7199                            .inlay_hints
7200                            .get_or_insert_default()
7201                            .scroll_debounce_ms = value;
7202                    })
7203                },
7204            }),
7205            metadata: None,
7206            files: USER | PROJECT,
7207        }),
7208        SettingsPageItem::SettingItem(SettingItem {
7209            title: "Toggle On Modifiers Press",
7210            description: "Toggles inlay hints (hides or shows) when the user presses the modifiers specified.",
7211            field: Box::new(
7212                SettingField {
7213                    json_path: Some("languages.$(language).inlay_hints.toggle_on_modifiers_press"),
7214                    pick: |settings_content| {
7215                        language_settings_field(settings_content, |language| {
7216                            language
7217                                .inlay_hints
7218                                .as_ref()?
7219                                .toggle_on_modifiers_press
7220                                .as_ref()
7221                        })
7222                    },
7223                    write: |settings_content, value| {
7224                        language_settings_field_mut(settings_content, value, |language, value| {
7225                            language
7226                                .inlay_hints
7227                                .get_or_insert_default()
7228                                .toggle_on_modifiers_press = value;
7229                        })
7230                    },
7231                }
7232                .unimplemented(),
7233            ),
7234            metadata: None,
7235            files: USER | PROJECT,
7236        }),
7237    ];
7238    if current_language().is_none() {
7239        items.push(SettingsPageItem::SettingItem(SettingItem {
7240            title: "LSP Document Colors",
7241            description: "How to render LSP color previews in the editor.",
7242            field: Box::new(SettingField {
7243                json_path: Some("lsp_document_colors"),
7244                pick: |settings_content| settings_content.editor.lsp_document_colors.as_ref(),
7245                write: |settings_content, value| {
7246                    settings_content.editor.lsp_document_colors = value;
7247                },
7248            }),
7249            metadata: None,
7250            files: USER,
7251        }))
7252    }
7253    items.extend([
7254        SettingsPageItem::SectionHeader("Tasks"),
7255        SettingsPageItem::SettingItem(SettingItem {
7256            title: "Enabled",
7257            description: "Whether tasks are enabled for this language.",
7258            field: Box::new(SettingField {
7259                json_path: Some("languages.$(language).tasks.enabled"),
7260                pick: |settings_content| {
7261                    language_settings_field(settings_content, |language| {
7262                        language.tasks.as_ref()?.enabled.as_ref()
7263                    })
7264                },
7265                write: |settings_content, value| {
7266                    language_settings_field_mut(settings_content, value, |language, value| {
7267                        language.tasks.get_or_insert_default().enabled = value;
7268
7269                    })
7270                },
7271            }),
7272            metadata: None,
7273            files: USER | PROJECT,
7274        }),
7275        SettingsPageItem::SettingItem(SettingItem {
7276            title: "Variables",
7277            description: "Extra task variables to set for a particular language.",
7278            field: Box::new(
7279                SettingField {
7280                    json_path: Some("languages.$(language).tasks.variables"),
7281                    pick: |settings_content| {
7282                        language_settings_field(settings_content, |language| {
7283                            language.tasks.as_ref()?.variables.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().variables = value;
7289
7290                        })
7291                    },
7292                }
7293                .unimplemented(),
7294            ),
7295            metadata: None,
7296            files: USER | PROJECT,
7297        }),
7298        SettingsPageItem::SettingItem(SettingItem {
7299            title: "Prefer LSP",
7300            description: "Use LSP tasks over Zed language extension tasks.",
7301            field: Box::new(SettingField {
7302                json_path: Some("languages.$(language).tasks.prefer_lsp"),
7303                pick: |settings_content| {
7304                    language_settings_field(settings_content, |language| {
7305                        language.tasks.as_ref()?.prefer_lsp.as_ref()
7306                    })
7307                },
7308                write: |settings_content, value| {
7309                    language_settings_field_mut(settings_content, value, |language, value| {
7310                        language.tasks.get_or_insert_default().prefer_lsp = value;
7311
7312                    })
7313                },
7314            }),
7315            metadata: None,
7316            files: USER | PROJECT,
7317        }),
7318        SettingsPageItem::SectionHeader("Miscellaneous"),
7319        SettingsPageItem::SettingItem(SettingItem {
7320            title: "Word Diff Enabled",
7321            description: "Whether to enable word diff highlighting in the editor. When enabled, changed words within modified lines are highlighted to show exactly what changed.",
7322            field: Box::new(SettingField {
7323                json_path: Some("languages.$(language).word_diff_enabled"),
7324                pick: |settings_content| {
7325                    language_settings_field(settings_content, |language| {
7326                        language.word_diff_enabled.as_ref()
7327                    })
7328                },
7329                write: |settings_content, value| {
7330                    language_settings_field_mut(settings_content, value, |language, value| {
7331                        language.word_diff_enabled = value;
7332                    })
7333                },
7334            }),
7335            metadata: None,
7336            files: USER | PROJECT,
7337        }),
7338        SettingsPageItem::SettingItem(SettingItem {
7339            title: "Debuggers",
7340            description: "Preferred debuggers for this language.",
7341            field: Box::new(
7342                SettingField {
7343                    json_path: Some("languages.$(language).debuggers"),
7344                    pick: |settings_content| {
7345                        language_settings_field(settings_content, |language| language.debuggers.as_ref())
7346                    },
7347                    write: |settings_content, value| {
7348                        language_settings_field_mut(settings_content, value, |language, value| {
7349                            language.debuggers = value;
7350
7351                        })
7352                    },
7353                }
7354                .unimplemented(),
7355            ),
7356            metadata: None,
7357            files: USER | PROJECT,
7358        }),
7359        SettingsPageItem::SettingItem(SettingItem {
7360            title: "Middle Click Paste",
7361            description: "Enable middle-click paste on Linux.",
7362            field: Box::new(SettingField {
7363                json_path: Some("languages.$(language).editor.middle_click_paste"),
7364                pick: |settings_content| settings_content.editor.middle_click_paste.as_ref(),
7365                write: |settings_content, value| {settings_content.editor.middle_click_paste = value;},
7366            }),
7367            metadata: None,
7368            files: USER,
7369        }),
7370        SettingsPageItem::SettingItem(SettingItem {
7371            title: "Extend Comment On Newline",
7372            description: "Whether to start a new line with a comment when a previous line is a comment as well.",
7373            field: Box::new(SettingField {
7374                json_path: Some("languages.$(language).extend_comment_on_newline"),
7375                pick: |settings_content| {
7376                    language_settings_field(settings_content, |language| {
7377                        language.extend_comment_on_newline.as_ref()
7378                    })
7379                },
7380                write: |settings_content, value| {
7381                    language_settings_field_mut(settings_content, value, |language, value| {
7382                        language.extend_comment_on_newline = value;
7383
7384                    })
7385                },
7386            }),
7387            metadata: None,
7388            files: USER | PROJECT,
7389        }),
7390        SettingsPageItem::SettingItem(SettingItem {
7391            title: "Colorize Brackets",
7392            description: "Whether to colorize brackets in the editor.",
7393            field: Box::new(SettingField {
7394                json_path: Some("languages.$(language).colorize_brackets"),
7395                pick: |settings_content| {
7396                    language_settings_field(settings_content, |language| {
7397                        language.colorize_brackets.as_ref()
7398                    })
7399                },
7400                write: |settings_content, value| {
7401                    language_settings_field_mut(settings_content, value, |language, value| {
7402                        language.colorize_brackets = value;
7403                    })
7404                },
7405            }),
7406            metadata: None,
7407            files: USER | PROJECT,
7408        }),
7409    ]);
7410
7411    if current_language().is_none() {
7412        items.extend([
7413            SettingsPageItem::SettingItem(SettingItem {
7414                title: "Image Viewer",
7415                description: "The unit for image file sizes.",
7416                field: Box::new(SettingField {
7417                    json_path: Some("image_viewer.unit"),
7418                    pick: |settings_content| {
7419                        settings_content.image_viewer.as_ref().and_then(|image_viewer| image_viewer.unit.as_ref())
7420                    },
7421                    write: |settings_content, value| {
7422                        settings_content.image_viewer.get_or_insert_default().unit = value;
7423
7424                    },
7425                }),
7426                metadata: None,
7427                files: USER,
7428            }),
7429            SettingsPageItem::SettingItem(SettingItem {
7430                title: "Auto Replace Emoji Shortcode",
7431                description: "Whether to automatically replace emoji shortcodes with emoji characters.",
7432                field: Box::new(SettingField {
7433                    json_path: Some("message_editor.auto_replace_emoji_shortcode"),
7434                    pick: |settings_content| {
7435                        settings_content.message_editor.as_ref().and_then(|message_editor| message_editor.auto_replace_emoji_shortcode.as_ref())
7436                    },
7437                    write: |settings_content, value| {
7438                        settings_content.message_editor.get_or_insert_default().auto_replace_emoji_shortcode = value;
7439
7440                    },
7441                }),
7442                metadata: None,
7443                files: USER,
7444            }),
7445            SettingsPageItem::SettingItem(SettingItem {
7446                title: "Drop Size Target",
7447                description: "Relative size of the drop target in the editor that will open dropped file as a split pane.",
7448                field: Box::new(SettingField {
7449                    json_path: Some("drop_target_size"),
7450                    pick: |settings_content| {
7451                        settings_content.workspace.drop_target_size.as_ref()
7452                    },
7453                    write: |settings_content, value| {
7454                        settings_content.workspace.drop_target_size = value;
7455
7456                    },
7457                }),
7458                metadata: None,
7459                files: USER,
7460            }),
7461        ]);
7462    }
7463    items
7464}
7465
7466/// LanguageSettings items that should be included in the "Languages & Tools" page
7467/// not the "Editor" page
7468fn non_editor_language_settings_data() -> Vec<SettingsPageItem> {
7469    vec![
7470        SettingsPageItem::SectionHeader("LSP"),
7471        SettingsPageItem::SettingItem(SettingItem {
7472            title: "Enable Language Server",
7473            description: "Whether to use language servers to provide code intelligence.",
7474            field: Box::new(SettingField {
7475                json_path: Some("languages.$(language).enable_language_server"),
7476                pick: |settings_content| {
7477                    language_settings_field(settings_content, |language| {
7478                        language.enable_language_server.as_ref()
7479                    })
7480                },
7481                write: |settings_content, value| {
7482                    language_settings_field_mut(settings_content, value, |language, value| {
7483                        language.enable_language_server = value;
7484                    })
7485                },
7486            }),
7487            metadata: None,
7488            files: USER | PROJECT,
7489        }),
7490        SettingsPageItem::SettingItem(SettingItem {
7491            title: "Language Servers",
7492            description: "The list of language servers to use (or disable) for this language.",
7493            field: Box::new(
7494                SettingField {
7495                    json_path: Some("languages.$(language).language_servers"),
7496                    pick: |settings_content| {
7497                        language_settings_field(settings_content, |language| {
7498                            language.language_servers.as_ref()
7499                        })
7500                    },
7501                    write: |settings_content, value| {
7502                        language_settings_field_mut(settings_content, value, |language, value| {
7503                            language.language_servers = value;
7504                        })
7505                    },
7506                }
7507                .unimplemented(),
7508            ),
7509            metadata: None,
7510            files: USER | PROJECT,
7511        }),
7512        SettingsPageItem::SettingItem(SettingItem {
7513            title: "Linked Edits",
7514            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.",
7515            field: Box::new(SettingField {
7516                json_path: Some("languages.$(language).linked_edits"),
7517                pick: |settings_content| {
7518                    language_settings_field(settings_content, |language| {
7519                        language.linked_edits.as_ref()
7520                    })
7521                },
7522                write: |settings_content, value| {
7523                    language_settings_field_mut(settings_content, value, |language, value| {
7524                        language.linked_edits = value;
7525                    })
7526                },
7527            }),
7528            metadata: None,
7529            files: USER | PROJECT,
7530        }),
7531        SettingsPageItem::SettingItem(SettingItem {
7532            title: "Go To Definition Fallback",
7533            description: "Whether to follow-up empty Go to definition responses from the language server.",
7534            field: Box::new(SettingField {
7535                json_path: Some("go_to_definition_fallback"),
7536                pick: |settings_content| settings_content.editor.go_to_definition_fallback.as_ref(),
7537                write: |settings_content, value| {
7538                    settings_content.editor.go_to_definition_fallback = value;
7539                },
7540            }),
7541            metadata: None,
7542            files: USER,
7543        }),
7544        SettingsPageItem::SectionHeader("LSP Completions"),
7545        SettingsPageItem::SettingItem(SettingItem {
7546            title: "Enabled",
7547            description: "Whether to fetch LSP completions or not.",
7548            field: Box::new(SettingField {
7549                json_path: Some("languages.$(language).completions.lsp"),
7550                pick: |settings_content| {
7551                    language_settings_field(settings_content, |language| {
7552                        language.completions.as_ref()?.lsp.as_ref()
7553                    })
7554                },
7555                write: |settings_content, value| {
7556                    language_settings_field_mut(settings_content, value, |language, value| {
7557                        language.completions.get_or_insert_default().lsp = value;
7558                    })
7559                },
7560            }),
7561            metadata: None,
7562            files: USER | PROJECT,
7563        }),
7564        SettingsPageItem::SettingItem(SettingItem {
7565            title: "Fetch Timeout (milliseconds)",
7566            description: "When fetching LSP completions, determines how long to wait for a response of a particular server (set to 0 to wait indefinitely).",
7567            field: Box::new(SettingField {
7568                json_path: Some("languages.$(language).completions.lsp_fetch_timeout_ms"),
7569                pick: |settings_content| {
7570                    language_settings_field(settings_content, |language| {
7571                        language.completions.as_ref()?.lsp_fetch_timeout_ms.as_ref()
7572                    })
7573                },
7574                write: |settings_content, value| {
7575                    language_settings_field_mut(settings_content, value, |language, value| {
7576                        language
7577                            .completions
7578                            .get_or_insert_default()
7579                            .lsp_fetch_timeout_ms = value;
7580                    })
7581                },
7582            }),
7583            metadata: None,
7584            files: USER | PROJECT,
7585        }),
7586        SettingsPageItem::SettingItem(SettingItem {
7587            title: "Insert Mode",
7588            description: "Controls how LSP completions are inserted.",
7589            field: Box::new(SettingField {
7590                json_path: Some("languages.$(language).completions.lsp_insert_mode"),
7591                pick: |settings_content| {
7592                    language_settings_field(settings_content, |language| {
7593                        language.completions.as_ref()?.lsp_insert_mode.as_ref()
7594                    })
7595                },
7596                write: |settings_content, value| {
7597                    language_settings_field_mut(settings_content, value, |language, value| {
7598                        language.completions.get_or_insert_default().lsp_insert_mode = value;
7599                    })
7600                },
7601            }),
7602            metadata: None,
7603            files: USER | PROJECT,
7604        }),
7605        SettingsPageItem::SectionHeader("Debuggers"),
7606        SettingsPageItem::SettingItem(SettingItem {
7607            title: "Debuggers",
7608            description: "Preferred debuggers for this language.",
7609            field: Box::new(
7610                SettingField {
7611                    json_path: Some("languages.$(language).debuggers"),
7612                    pick: |settings_content| {
7613                        language_settings_field(settings_content, |language| {
7614                            language.debuggers.as_ref()
7615                        })
7616                    },
7617                    write: |settings_content, value| {
7618                        language_settings_field_mut(settings_content, value, |language, value| {
7619                            language.debuggers = value;
7620                        })
7621                    },
7622                }
7623                .unimplemented(),
7624            ),
7625            metadata: None,
7626            files: USER | PROJECT,
7627        }),
7628        SettingsPageItem::SectionHeader("Prettier"),
7629        SettingsPageItem::SettingItem(SettingItem {
7630            title: "Allowed",
7631            description: "Enables or disables formatting with Prettier for a given language.",
7632            field: Box::new(SettingField {
7633                json_path: Some("languages.$(language).prettier.allowed"),
7634                pick: |settings_content| {
7635                    language_settings_field(settings_content, |language| {
7636                        language.prettier.as_ref()?.allowed.as_ref()
7637                    })
7638                },
7639                write: |settings_content, value| {
7640                    language_settings_field_mut(settings_content, value, |language, value| {
7641                        language.prettier.get_or_insert_default().allowed = value;
7642                    })
7643                },
7644            }),
7645            metadata: None,
7646            files: USER | PROJECT,
7647        }),
7648        SettingsPageItem::SettingItem(SettingItem {
7649            title: "Parser",
7650            description: "Forces Prettier integration to use a specific parser name when formatting files with the language.",
7651            field: Box::new(SettingField {
7652                json_path: Some("languages.$(language).prettier.parser"),
7653                pick: |settings_content| {
7654                    language_settings_field(settings_content, |language| {
7655                        language.prettier.as_ref()?.parser.as_ref()
7656                    })
7657                },
7658                write: |settings_content, value| {
7659                    language_settings_field_mut(settings_content, value, |language, value| {
7660                        language.prettier.get_or_insert_default().parser = value;
7661                    })
7662                },
7663            }),
7664            metadata: None,
7665            files: USER | PROJECT,
7666        }),
7667        SettingsPageItem::SettingItem(SettingItem {
7668            title: "Plugins",
7669            description: "Forces Prettier integration to use specific plugins when formatting files with the language.",
7670            field: Box::new(
7671                SettingField {
7672                    json_path: Some("languages.$(language).prettier.plugins"),
7673                    pick: |settings_content| {
7674                        language_settings_field(settings_content, |language| {
7675                            language.prettier.as_ref()?.plugins.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().plugins = value;
7681                        })
7682                    },
7683                }
7684                .unimplemented(),
7685            ),
7686            metadata: None,
7687            files: USER | PROJECT,
7688        }),
7689        SettingsPageItem::SettingItem(SettingItem {
7690            title: "Options",
7691            description: "Default Prettier options, in the format as in package.json section for Prettier.",
7692            field: Box::new(
7693                SettingField {
7694                    json_path: Some("languages.$(language).prettier.options"),
7695                    pick: |settings_content| {
7696                        language_settings_field(settings_content, |language| {
7697                            language.prettier.as_ref()?.options.as_ref()
7698                        })
7699                    },
7700                    write: |settings_content, value| {
7701                        language_settings_field_mut(settings_content, value, |language, value| {
7702                            language.prettier.get_or_insert_default().options = value;
7703                        })
7704                    },
7705                }
7706                .unimplemented(),
7707            ),
7708            metadata: None,
7709            files: USER | PROJECT,
7710        }),
7711    ]
7712}
7713
7714fn edit_prediction_language_settings_section() -> Vec<SettingsPageItem> {
7715    vec![
7716        SettingsPageItem::SectionHeader("Edit Predictions"),
7717        SettingsPageItem::SubPageLink(SubPageLink {
7718            title: "Configure Providers".into(),
7719            json_path: Some("edit_predictions.providers"),
7720            description: Some("Set up different edit prediction providers in complement to Zed's built-in Zeta model.".into()),
7721            in_json: false,
7722            files: USER,
7723            render: Arc::new(|_, window, cx| {
7724                let settings_window = cx.entity();
7725                let page = window.use_state(cx, |_, _| {
7726                    crate::pages::EditPredictionSetupPage::new(settings_window)
7727                });
7728                page.into_any_element()
7729            }),
7730        }),
7731        SettingsPageItem::SettingItem(SettingItem {
7732            title: "Show Edit Predictions",
7733            description: "Controls whether edit predictions are shown immediately or manually.",
7734            field: Box::new(SettingField {
7735                json_path: Some("languages.$(language).show_edit_predictions"),
7736                pick: |settings_content| {
7737                    language_settings_field(settings_content, |language| {
7738                        language.show_edit_predictions.as_ref()
7739                    })
7740                },
7741                write: |settings_content, value| {
7742                    language_settings_field_mut(settings_content, value, |language, value| {
7743                        language.show_edit_predictions = value;
7744                    })
7745                },
7746            }),
7747            metadata: None,
7748            files: USER | PROJECT,
7749        }),
7750        SettingsPageItem::SettingItem(SettingItem {
7751            title: "Disable in Language Scopes",
7752            description: "Controls whether edit predictions are shown in the given language scopes.",
7753            field: Box::new(
7754                SettingField {
7755                    json_path: Some("languages.$(language).edit_predictions_disabled_in"),
7756                    pick: |settings_content| {
7757                        language_settings_field(settings_content, |language| {
7758                            language.edit_predictions_disabled_in.as_ref()
7759                        })
7760                    },
7761                    write: |settings_content, value| {
7762                        language_settings_field_mut(settings_content, value, |language, value| {
7763                            language.edit_predictions_disabled_in = value;
7764                        })
7765                    },
7766                }
7767                .unimplemented(),
7768            ),
7769            metadata: None,
7770            files: USER | PROJECT,
7771        }),
7772    ]
7773}
7774
7775fn show_scrollbar_or_editor(
7776    settings_content: &SettingsContent,
7777    show: fn(&SettingsContent) -> Option<&settings::ShowScrollbar>,
7778) -> Option<&settings::ShowScrollbar> {
7779    show(settings_content).or(settings_content
7780        .editor
7781        .scrollbar
7782        .as_ref()
7783        .and_then(|scrollbar| scrollbar.show.as_ref()))
7784}
7785
7786fn dynamic_variants<T>() -> &'static [T::Discriminant]
7787where
7788    T: strum::IntoDiscriminant,
7789    T::Discriminant: strum::VariantArray,
7790{
7791    <<T as strum::IntoDiscriminant>::Discriminant as strum::VariantArray>::VARIANTS
7792}