page_data.rs

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