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