page_data.rs

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