page_data.rs

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