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