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