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