settings_content.rs

   1use std::borrow::Cow;
   2use std::env;
   3use std::num::NonZeroU32;
   4use std::sync::Arc;
   5
   6use anyhow::Result;
   7use collections::{HashMap, HashSet};
   8use gpui::{App, FontFallbacks, FontFeatures, HighlightStyle, Hsla, Modifiers, SharedString};
   9use release_channel::ReleaseChannel;
  10use schemars::{JsonSchema, json_schema};
  11use serde::de::{self, IntoDeserializer, MapAccess, SeqAccess, Visitor};
  12use serde::{Deserialize, Deserializer, Serialize};
  13use util::schemars::replace_subschema;
  14use util::serde::default_true;
  15
  16use crate::{ActiveSettingsProfileName, ParameterizedJsonSchema, Settings};
  17
  18#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)]
  19pub struct SettingsContent {
  20    #[serde(flatten)]
  21    pub project: ProjectSettingsContent,
  22
  23    pub base_keymap: Option<BaseKeymapContent>,
  24
  25    pub auto_update: Option<bool>,
  26
  27    pub title_bar: Option<TitleBarSettingsContent>,
  28}
  29
  30impl SettingsContent {
  31    pub fn languages_mut(&mut self) -> &mut HashMap<SharedString, LanguageSettingsContent> {
  32        &mut self.project.all_languages.languages.0
  33    }
  34}
  35
  36// todo!() what should this be?
  37#[derive(Debug, Default, Serialize, Deserialize, JsonSchema)]
  38pub struct ServerSettingsContent {
  39    #[serde(flatten)]
  40    pub project: ProjectSettingsContent,
  41}
  42
  43#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)]
  44pub(crate) struct UserSettingsContent {
  45    #[serde(flatten)]
  46    pub(crate) content: SettingsContent,
  47
  48    pub(crate) dev: Option<SettingsContent>,
  49    pub(crate) nightly: Option<SettingsContent>,
  50    pub(crate) preview: Option<SettingsContent>,
  51    pub(crate) stable: Option<SettingsContent>,
  52
  53    pub(crate) macos: Option<SettingsContent>,
  54    pub(crate) windows: Option<SettingsContent>,
  55    pub(crate) linux: Option<SettingsContent>,
  56
  57    #[serde(default)]
  58    pub(crate) profiles: HashMap<String, SettingsContent>,
  59}
  60
  61pub struct ExtensionsSettingsContent {
  62    pub(crate) all_languages: AllLanguageSettingsContent,
  63}
  64
  65impl UserSettingsContent {
  66    pub(crate) fn for_release_channel(&self) -> Option<&SettingsContent> {
  67        match *release_channel::RELEASE_CHANNEL {
  68            ReleaseChannel::Dev => self.dev.as_ref(),
  69            ReleaseChannel::Nightly => self.nightly.as_ref(),
  70            ReleaseChannel::Preview => self.preview.as_ref(),
  71            ReleaseChannel::Stable => self.stable.as_ref(),
  72        }
  73    }
  74
  75    pub(crate) fn for_os(&self) -> Option<&SettingsContent> {
  76        match env::consts::OS {
  77            "macos" => self.macos.as_ref(),
  78            "linux" => self.linux.as_ref(),
  79            "windows" => self.windows.as_ref(),
  80            _ => None,
  81        }
  82    }
  83
  84    pub(crate) fn for_profile(&self, cx: &App) -> Option<&SettingsContent> {
  85        let Some(active_profile) = cx.try_global::<ActiveSettingsProfileName>() else {
  86            return None;
  87        };
  88        self.profiles.get(&active_profile.0)
  89    }
  90}
  91
  92/// Base key bindings scheme. Base keymaps can be overridden with user keymaps.
  93///
  94/// Default: VSCode
  95#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Default)]
  96pub enum BaseKeymapContent {
  97    #[default]
  98    VSCode,
  99    JetBrains,
 100    SublimeText,
 101    Atom,
 102    TextMate,
 103    Emacs,
 104    Cursor,
 105    None,
 106}
 107
 108#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
 109pub struct ProjectSettingsContent {
 110    #[serde(flatten)]
 111    pub(crate) all_languages: AllLanguageSettingsContent,
 112}
 113
 114#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
 115pub struct AllLanguageSettingsContent {
 116    /// The settings for enabling/disabling features.
 117    #[serde(default)]
 118    pub features: Option<FeaturesContent>,
 119    /// The edit prediction settings.
 120    #[serde(default)]
 121    pub edit_predictions: Option<EditPredictionSettingsContent>,
 122    /// The default language settings.
 123    #[serde(flatten)]
 124    pub defaults: LanguageSettingsContent,
 125    /// The settings for individual languages.
 126    #[serde(default)]
 127    pub languages: LanguageToSettingsMap,
 128    /// Settings for associating file extensions and filenames
 129    /// with languages.
 130    #[serde(default)]
 131    pub file_types: HashMap<SharedString, Vec<String>>,
 132}
 133
 134/// The settings for enabling/disabling features.
 135#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema)]
 136#[serde(rename_all = "snake_case")]
 137pub struct FeaturesContent {
 138    /// Determines which edit prediction provider to use.
 139    pub edit_prediction_provider: Option<EditPredictionProviderContent>,
 140}
 141
 142/// The provider that supplies edit predictions.
 143#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
 144#[serde(rename_all = "snake_case")]
 145pub enum EditPredictionProviderContent {
 146    None,
 147    #[default]
 148    Copilot,
 149    Supermaven,
 150    Zed,
 151}
 152
 153/// The contents of the edit prediction settings.
 154#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq)]
 155pub struct EditPredictionSettingsContent {
 156    /// A list of globs representing files that edit predictions should be disabled for.
 157    /// This list adds to a pre-existing, sensible default set of globs.
 158    /// Any additional ones you add are combined with them.
 159    #[serde(default)]
 160    pub disabled_globs: Option<Vec<String>>,
 161    /// The mode used to display edit predictions in the buffer.
 162    /// Provider support required.
 163    #[serde(default)]
 164    pub mode: EditPredictionsModeContent,
 165    /// Settings specific to GitHub Copilot.
 166    #[serde(default)]
 167    pub copilot: CopilotSettingsContent,
 168    /// Whether edit predictions are enabled in the assistant prompt editor.
 169    /// This has no effect if globally disabled.
 170    #[serde(default = "default_true")]
 171    pub enabled_in_text_threads: bool,
 172}
 173
 174#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq)]
 175pub struct CopilotSettingsContent {
 176    /// HTTP/HTTPS proxy to use for Copilot.
 177    ///
 178    /// Default: none
 179    #[serde(default)]
 180    pub proxy: Option<String>,
 181    /// Disable certificate verification for the proxy (not recommended).
 182    ///
 183    /// Default: false
 184    #[serde(default)]
 185    pub proxy_no_verify: Option<bool>,
 186    /// Enterprise URI for Copilot.
 187    ///
 188    /// Default: none
 189    #[serde(default)]
 190    pub enterprise_uri: Option<String>,
 191}
 192
 193/// The mode in which edit predictions should be displayed.
 194#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
 195#[serde(rename_all = "snake_case")]
 196pub enum EditPredictionsModeContent {
 197    /// If provider supports it, display inline when holding modifier key (e.g., alt).
 198    /// Otherwise, eager preview is used.
 199    #[serde(alias = "auto")]
 200    Subtle,
 201    /// Display inline when there are no language server completions available.
 202    #[default]
 203    #[serde(alias = "eager_preview")]
 204    Eager,
 205}
 206
 207/// Controls the soft-wrapping behavior in the editor.
 208#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
 209#[serde(rename_all = "snake_case")]
 210pub enum SoftWrapContent {
 211    /// Prefer a single line generally, unless an overly long line is encountered.
 212    None,
 213    /// Deprecated: use None instead. Left to avoid breaking existing users' configs.
 214    /// Prefer a single line generally, unless an overly long line is encountered.
 215    PreferLine,
 216    /// Soft wrap lines that exceed the editor width.
 217    EditorWidth,
 218    /// Soft wrap lines at the preferred line length.
 219    PreferredLineLength,
 220    /// Soft wrap line at the preferred line length or the editor width (whichever is smaller).
 221    Bounded,
 222}
 223
 224/// The settings for a particular language.
 225#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
 226pub struct LanguageSettingsContent {
 227    /// How many columns a tab should occupy.
 228    ///
 229    /// Default: 4
 230    #[serde(default)]
 231    pub tab_size: Option<NonZeroU32>,
 232    /// Whether to indent lines using tab characters, as opposed to multiple
 233    /// spaces.
 234    ///
 235    /// Default: false
 236    #[serde(default)]
 237    pub hard_tabs: Option<bool>,
 238    /// How to soft-wrap long lines of text.
 239    ///
 240    /// Default: none
 241    #[serde(default)]
 242    pub soft_wrap: Option<SoftWrapContent>,
 243    /// The column at which to soft-wrap lines, for buffers where soft-wrap
 244    /// is enabled.
 245    ///
 246    /// Default: 80
 247    #[serde(default)]
 248    pub preferred_line_length: Option<u32>,
 249    /// Whether to show wrap guides in the editor. Setting this to true will
 250    /// show a guide at the 'preferred_line_length' value if softwrap is set to
 251    /// 'preferred_line_length', and will show any additional guides as specified
 252    /// by the 'wrap_guides' setting.
 253    ///
 254    /// Default: true
 255    #[serde(default)]
 256    pub show_wrap_guides: Option<bool>,
 257    /// Character counts at which to show wrap guides in the editor.
 258    ///
 259    /// Default: []
 260    #[serde(default)]
 261    pub wrap_guides: Option<Vec<usize>>,
 262    /// Indent guide related settings.
 263    #[serde(default)]
 264    pub indent_guides: Option<IndentGuideSettingsContent>,
 265    /// Whether or not to perform a buffer format before saving.
 266    ///
 267    /// Default: on
 268    #[serde(default)]
 269    pub format_on_save: Option<FormatOnSave>,
 270    /// Whether or not to remove any trailing whitespace from lines of a buffer
 271    /// before saving it.
 272    ///
 273    /// Default: true
 274    #[serde(default)]
 275    pub remove_trailing_whitespace_on_save: Option<bool>,
 276    /// Whether or not to ensure there's a single newline at the end of a buffer
 277    /// when saving it.
 278    ///
 279    /// Default: true
 280    #[serde(default)]
 281    pub ensure_final_newline_on_save: Option<bool>,
 282    /// How to perform a buffer format.
 283    ///
 284    /// Default: auto
 285    #[serde(default)]
 286    pub formatter: Option<SelectedFormatter>,
 287    /// Zed's Prettier integration settings.
 288    /// Allows to enable/disable formatting with Prettier
 289    /// and configure default Prettier, used when no project-level Prettier installation is found.
 290    ///
 291    /// Default: off
 292    #[serde(default)]
 293    pub prettier: Option<PrettierSettings>,
 294    /// Whether to automatically close JSX tags.
 295    #[serde(default)]
 296    pub jsx_tag_auto_close: Option<JsxTagAutoCloseSettings>,
 297    /// Whether to use language servers to provide code intelligence.
 298    ///
 299    /// Default: true
 300    #[serde(default)]
 301    pub enable_language_server: Option<bool>,
 302    /// The list of language servers to use (or disable) for this language.
 303    ///
 304    /// This array should consist of language server IDs, as well as the following
 305    /// special tokens:
 306    /// - `"!<language_server_id>"` - A language server ID prefixed with a `!` will be disabled.
 307    /// - `"..."` - A placeholder to refer to the **rest** of the registered language servers for this language.
 308    ///
 309    /// Default: ["..."]
 310    #[serde(default)]
 311    pub language_servers: Option<Vec<String>>,
 312    /// Controls where the `editor::Rewrap` action is allowed for this language.
 313    ///
 314    /// Note: This setting has no effect in Vim mode, as rewrap is already
 315    /// allowed everywhere.
 316    ///
 317    /// Default: "in_comments"
 318    #[serde(default)]
 319    pub allow_rewrap: Option<RewrapBehavior>,
 320    /// Controls whether edit predictions are shown immediately (true)
 321    /// or manually by triggering `editor::ShowEditPrediction` (false).
 322    ///
 323    /// Default: true
 324    #[serde(default)]
 325    pub show_edit_predictions: Option<bool>,
 326    /// Controls whether edit predictions are shown in the given language
 327    /// scopes.
 328    ///
 329    /// Example: ["string", "comment"]
 330    ///
 331    /// Default: []
 332    #[serde(default)]
 333    pub edit_predictions_disabled_in: Option<Vec<String>>,
 334    /// Whether to show tabs and spaces in the editor.
 335    #[serde(default)]
 336    pub show_whitespaces: Option<ShowWhitespaceSetting>,
 337    /// Visible characters used to render whitespace when show_whitespaces is enabled.
 338    ///
 339    /// Default: "•" for spaces, "→" for tabs.
 340    #[serde(default)]
 341    pub whitespace_map: Option<WhitespaceMap>,
 342    /// Whether to start a new line with a comment when a previous line is a comment as well.
 343    ///
 344    /// Default: true
 345    #[serde(default)]
 346    pub extend_comment_on_newline: Option<bool>,
 347    /// Inlay hint related settings.
 348    #[serde(default)]
 349    pub inlay_hints: Option<InlayHintSettings>,
 350    /// Whether to automatically type closing characters for you. For example,
 351    /// when you type (, Zed will automatically add a closing ) at the correct position.
 352    ///
 353    /// Default: true
 354    pub use_autoclose: Option<bool>,
 355    /// Whether to automatically surround text with characters for you. For example,
 356    /// when you select text and type (, Zed will automatically surround text with ().
 357    ///
 358    /// Default: true
 359    pub use_auto_surround: Option<bool>,
 360    /// Controls how the editor handles the autoclosed characters.
 361    /// When set to `false`(default), skipping over and auto-removing of the closing characters
 362    /// happen only for auto-inserted characters.
 363    /// Otherwise(when `true`), the closing characters are always skipped over and auto-removed
 364    /// no matter how they were inserted.
 365    ///
 366    /// Default: false
 367    pub always_treat_brackets_as_autoclosed: Option<bool>,
 368    /// Whether to use additional LSP queries to format (and amend) the code after
 369    /// every "trigger" symbol input, defined by LSP server capabilities.
 370    ///
 371    /// Default: true
 372    pub use_on_type_format: Option<bool>,
 373    /// Which code actions to run on save after the formatter.
 374    /// These are not run if formatting is off.
 375    ///
 376    /// Default: {} (or {"source.organizeImports": true} for Go).
 377    pub code_actions_on_format: Option<HashMap<String, bool>>,
 378    /// Whether to perform linked edits of associated ranges, if the language server supports it.
 379    /// For example, when editing opening <html> tag, the contents of the closing </html> tag will be edited as well.
 380    ///
 381    /// Default: true
 382    pub linked_edits: Option<bool>,
 383    /// Whether indentation should be adjusted based on the context whilst typing.
 384    ///
 385    /// Default: true
 386    pub auto_indent: Option<bool>,
 387    /// Whether indentation of pasted content should be adjusted based on the context.
 388    ///
 389    /// Default: true
 390    pub auto_indent_on_paste: Option<bool>,
 391    /// Task configuration for this language.
 392    ///
 393    /// Default: {}
 394    pub tasks: Option<LanguageTaskConfig>,
 395    /// Whether to pop the completions menu while typing in an editor without
 396    /// explicitly requesting it.
 397    ///
 398    /// Default: true
 399    pub show_completions_on_input: Option<bool>,
 400    /// Whether to display inline and alongside documentation for items in the
 401    /// completions menu.
 402    ///
 403    /// Default: true
 404    pub show_completion_documentation: Option<bool>,
 405    /// Controls how completions are processed for this language.
 406    pub completions: Option<CompletionSettings>,
 407    /// Preferred debuggers for this language.
 408    ///
 409    /// Default: []
 410    pub debuggers: Option<Vec<String>>,
 411}
 412
 413/// Controls how whitespace should be displayedin the editor.
 414#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
 415#[serde(rename_all = "snake_case")]
 416pub enum ShowWhitespaceSetting {
 417    /// Draw whitespace only for the selected text.
 418    Selection,
 419    /// Do not draw any tabs or spaces.
 420    None,
 421    /// Draw all invisible symbols.
 422    All,
 423    /// Draw whitespaces at boundaries only.
 424    ///
 425    /// For a whitespace to be on a boundary, any of the following conditions need to be met:
 426    /// - It is a tab
 427    /// - It is adjacent to an edge (start or end)
 428    /// - It is adjacent to a whitespace (left or right)
 429    Boundary,
 430    /// Draw whitespaces only after non-whitespace characters.
 431    Trailing,
 432}
 433
 434#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq)]
 435pub struct WhitespaceMap {
 436    #[serde(default)]
 437    pub space: Option<String>,
 438    #[serde(default)]
 439    pub tab: Option<String>,
 440}
 441
 442impl WhitespaceMap {
 443    pub fn space(&self) -> SharedString {
 444        self.space
 445            .as_ref()
 446            .map_or_else(|| SharedString::from(""), |s| SharedString::from(s))
 447    }
 448
 449    pub fn tab(&self) -> SharedString {
 450        self.tab
 451            .as_ref()
 452            .map_or_else(|| SharedString::from(""), |s| SharedString::from(s))
 453    }
 454}
 455
 456/// The behavior of `editor::Rewrap`.
 457#[derive(Debug, PartialEq, Clone, Copy, Default, Serialize, Deserialize, JsonSchema)]
 458#[serde(rename_all = "snake_case")]
 459pub enum RewrapBehavior {
 460    /// Only rewrap within comments.
 461    #[default]
 462    InComments,
 463    /// Only rewrap within the current selection(s).
 464    InSelections,
 465    /// Allow rewrapping anywhere.
 466    Anywhere,
 467}
 468
 469#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
 470pub struct JsxTagAutoCloseSettings {
 471    /// Enables or disables auto-closing of JSX tags.
 472    #[serde(default)]
 473    pub enabled: bool,
 474}
 475
 476/// The settings for inlay hints.
 477#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
 478pub struct InlayHintSettings {
 479    /// Global switch to toggle hints on and off.
 480    ///
 481    /// Default: false
 482    #[serde(default)]
 483    pub enabled: bool,
 484    /// Global switch to toggle inline values on and off when debugging.
 485    ///
 486    /// Default: true
 487    #[serde(default = "default_true")]
 488    pub show_value_hints: bool,
 489    /// Whether type hints should be shown.
 490    ///
 491    /// Default: true
 492    #[serde(default = "default_true")]
 493    pub show_type_hints: bool,
 494    /// Whether parameter hints should be shown.
 495    ///
 496    /// Default: true
 497    #[serde(default = "default_true")]
 498    pub show_parameter_hints: bool,
 499    /// Whether other hints should be shown.
 500    ///
 501    /// Default: true
 502    #[serde(default = "default_true")]
 503    pub show_other_hints: bool,
 504    /// Whether to show a background for inlay hints.
 505    ///
 506    /// If set to `true`, the background will use the `hint.background` color
 507    /// from the current theme.
 508    ///
 509    /// Default: false
 510    #[serde(default)]
 511    pub show_background: bool,
 512    /// Whether or not to debounce inlay hints updates after buffer edits.
 513    ///
 514    /// Set to 0 to disable debouncing.
 515    ///
 516    /// Default: 700
 517    #[serde(default = "edit_debounce_ms")]
 518    pub edit_debounce_ms: u64,
 519    /// Whether or not to debounce inlay hints updates after buffer scrolls.
 520    ///
 521    /// Set to 0 to disable debouncing.
 522    ///
 523    /// Default: 50
 524    #[serde(default = "scroll_debounce_ms")]
 525    pub scroll_debounce_ms: u64,
 526    /// Toggles inlay hints (hides or shows) when the user presses the modifiers specified.
 527    /// If only a subset of the modifiers specified is pressed, hints are not toggled.
 528    /// If no modifiers are specified, this is equivalent to `None`.
 529    ///
 530    /// Default: None
 531    #[serde(default)]
 532    pub toggle_on_modifiers_press: Option<Modifiers>,
 533}
 534
 535fn edit_debounce_ms() -> u64 {
 536    700
 537}
 538
 539fn scroll_debounce_ms() -> u64 {
 540    50
 541}
 542
 543/// Controls how completions are processed for this language.
 544#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
 545#[serde(rename_all = "snake_case")]
 546pub struct CompletionSettings {
 547    /// Controls how words are completed.
 548    /// For large documents, not all words may be fetched for completion.
 549    ///
 550    /// Default: `fallback`
 551    #[serde(default = "default_words_completion_mode")]
 552    pub words: WordsCompletionMode,
 553    /// How many characters has to be in the completions query to automatically show the words-based completions.
 554    /// Before that value, it's still possible to trigger the words-based completion manually with the corresponding editor command.
 555    ///
 556    /// Default: 3
 557    #[serde(default = "default_3")]
 558    pub words_min_length: usize,
 559    /// Whether to fetch LSP completions or not.
 560    ///
 561    /// Default: true
 562    #[serde(default = "default_true")]
 563    pub lsp: bool,
 564    /// When fetching LSP completions, determines how long to wait for a response of a particular server.
 565    /// When set to 0, waits indefinitely.
 566    ///
 567    /// Default: 0
 568    #[serde(default)]
 569    pub lsp_fetch_timeout_ms: u64,
 570    /// Controls how LSP completions are inserted.
 571    ///
 572    /// Default: "replace_suffix"
 573    #[serde(default = "default_lsp_insert_mode")]
 574    pub lsp_insert_mode: LspInsertMode,
 575}
 576
 577#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
 578#[serde(rename_all = "snake_case")]
 579pub enum LspInsertMode {
 580    /// Replaces text before the cursor, using the `insert` range described in the LSP specification.
 581    Insert,
 582    /// Replaces text before and after the cursor, using the `replace` range described in the LSP specification.
 583    Replace,
 584    /// Behaves like `"replace"` if the text that would be replaced is a subsequence of the completion text,
 585    /// and like `"insert"` otherwise.
 586    ReplaceSubsequence,
 587    /// Behaves like `"replace"` if the text after the cursor is a suffix of the completion, and like
 588    /// `"insert"` otherwise.
 589    ReplaceSuffix,
 590}
 591
 592/// Controls how document's words are completed.
 593#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
 594#[serde(rename_all = "snake_case")]
 595pub enum WordsCompletionMode {
 596    /// Always fetch document's words for completions along with LSP completions.
 597    Enabled,
 598    /// Only if LSP response errors or times out,
 599    /// use document's words to show completions.
 600    Fallback,
 601    /// Never fetch or complete document's words for completions.
 602    /// (Word-based completions can still be queried via a separate action)
 603    Disabled,
 604}
 605
 606fn default_words_completion_mode() -> WordsCompletionMode {
 607    WordsCompletionMode::Fallback
 608}
 609
 610fn default_lsp_insert_mode() -> LspInsertMode {
 611    LspInsertMode::ReplaceSuffix
 612}
 613
 614fn default_3() -> usize {
 615    3
 616}
 617
 618/// Allows to enable/disable formatting with Prettier
 619/// and configure default Prettier, used when no project-level Prettier installation is found.
 620/// Prettier formatting is disabled by default.
 621#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
 622pub struct PrettierSettings {
 623    /// Enables or disables formatting with Prettier for a given language.
 624    #[serde(default)]
 625    pub allowed: bool,
 626
 627    /// Forces Prettier integration to use a specific parser name when formatting files with the language.
 628    #[serde(default)]
 629    pub parser: Option<String>,
 630
 631    /// Forces Prettier integration to use specific plugins when formatting files with the language.
 632    /// The default Prettier will be installed with these plugins.
 633    #[serde(default)]
 634    pub plugins: HashSet<String>,
 635
 636    /// Default Prettier options, in the format as in package.json section for Prettier.
 637    /// If project installs Prettier via its package.json, these options will be ignored.
 638    #[serde(flatten)]
 639    pub options: HashMap<String, serde_json::Value>,
 640}
 641/// Controls the behavior of formatting files when they are saved.
 642#[derive(Debug, Clone, PartialEq, Eq)]
 643pub enum FormatOnSave {
 644    /// Files should be formatted on save.
 645    On,
 646    /// Files should not be formatted on save.
 647    Off,
 648    List(FormatterList),
 649}
 650
 651impl JsonSchema for FormatOnSave {
 652    fn schema_name() -> Cow<'static, str> {
 653        "OnSaveFormatter".into()
 654    }
 655
 656    fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
 657        let formatter_schema = Formatter::json_schema(generator);
 658
 659        json_schema!({
 660            "oneOf": [
 661                {
 662                    "type": "array",
 663                    "items": formatter_schema
 664                },
 665                {
 666                    "type": "string",
 667                    "enum": ["on", "off", "language_server"]
 668                },
 669                formatter_schema
 670            ]
 671        })
 672    }
 673}
 674
 675impl Serialize for FormatOnSave {
 676    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
 677    where
 678        S: serde::Serializer,
 679    {
 680        match self {
 681            Self::On => serializer.serialize_str("on"),
 682            Self::Off => serializer.serialize_str("off"),
 683            Self::List(list) => list.serialize(serializer),
 684        }
 685    }
 686}
 687
 688impl<'de> Deserialize<'de> for FormatOnSave {
 689    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
 690    where
 691        D: Deserializer<'de>,
 692    {
 693        struct FormatDeserializer;
 694
 695        impl<'d> Visitor<'d> for FormatDeserializer {
 696            type Value = FormatOnSave;
 697
 698            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
 699                formatter.write_str("a valid on-save formatter kind")
 700            }
 701            fn visit_str<E>(self, v: &str) -> std::result::Result<Self::Value, E>
 702            where
 703                E: serde::de::Error,
 704            {
 705                if v == "on" {
 706                    Ok(Self::Value::On)
 707                } else if v == "off" {
 708                    Ok(Self::Value::Off)
 709                } else if v == "language_server" {
 710                    Ok(Self::Value::List(FormatterList::Single(
 711                        Formatter::LanguageServer { name: None },
 712                    )))
 713                } else {
 714                    let ret: Result<FormatterList, _> =
 715                        Deserialize::deserialize(v.into_deserializer());
 716                    ret.map(Self::Value::List)
 717                }
 718            }
 719            fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
 720            where
 721                A: MapAccess<'d>,
 722            {
 723                let ret: Result<FormatterList, _> =
 724                    Deserialize::deserialize(de::value::MapAccessDeserializer::new(map));
 725                ret.map(Self::Value::List)
 726            }
 727            fn visit_seq<A>(self, map: A) -> Result<Self::Value, A::Error>
 728            where
 729                A: SeqAccess<'d>,
 730            {
 731                let ret: Result<FormatterList, _> =
 732                    Deserialize::deserialize(de::value::SeqAccessDeserializer::new(map));
 733                ret.map(Self::Value::List)
 734            }
 735        }
 736        deserializer.deserialize_any(FormatDeserializer)
 737    }
 738}
 739
 740/// Controls which formatter should be used when formatting code.
 741#[derive(Clone, Debug, Default, PartialEq, Eq)]
 742pub enum SelectedFormatter {
 743    /// Format files using Zed's Prettier integration (if applicable),
 744    /// or falling back to formatting via language server.
 745    #[default]
 746    Auto,
 747    List(FormatterList),
 748}
 749
 750impl JsonSchema for SelectedFormatter {
 751    fn schema_name() -> Cow<'static, str> {
 752        "Formatter".into()
 753    }
 754
 755    fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
 756        let formatter_schema = Formatter::json_schema(generator);
 757
 758        json_schema!({
 759            "oneOf": [
 760                {
 761                    "type": "array",
 762                    "items": formatter_schema
 763                },
 764                {
 765                    "type": "string",
 766                    "enum": ["auto", "language_server"]
 767                },
 768                formatter_schema
 769            ]
 770        })
 771    }
 772}
 773
 774impl Serialize for SelectedFormatter {
 775    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
 776    where
 777        S: serde::Serializer,
 778    {
 779        match self {
 780            SelectedFormatter::Auto => serializer.serialize_str("auto"),
 781            SelectedFormatter::List(list) => list.serialize(serializer),
 782        }
 783    }
 784}
 785
 786impl<'de> Deserialize<'de> for SelectedFormatter {
 787    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
 788    where
 789        D: Deserializer<'de>,
 790    {
 791        struct FormatDeserializer;
 792
 793        impl<'d> Visitor<'d> for FormatDeserializer {
 794            type Value = SelectedFormatter;
 795
 796            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
 797                formatter.write_str("a valid formatter kind")
 798            }
 799            fn visit_str<E>(self, v: &str) -> std::result::Result<Self::Value, E>
 800            where
 801                E: serde::de::Error,
 802            {
 803                if v == "auto" {
 804                    Ok(Self::Value::Auto)
 805                } else if v == "language_server" {
 806                    Ok(Self::Value::List(FormatterList::Single(
 807                        Formatter::LanguageServer { name: None },
 808                    )))
 809                } else {
 810                    let ret: Result<FormatterList, _> =
 811                        Deserialize::deserialize(v.into_deserializer());
 812                    ret.map(SelectedFormatter::List)
 813                }
 814            }
 815            fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
 816            where
 817                A: MapAccess<'d>,
 818            {
 819                let ret: Result<FormatterList, _> =
 820                    Deserialize::deserialize(de::value::MapAccessDeserializer::new(map));
 821                ret.map(SelectedFormatter::List)
 822            }
 823            fn visit_seq<A>(self, map: A) -> Result<Self::Value, A::Error>
 824            where
 825                A: SeqAccess<'d>,
 826            {
 827                let ret: Result<FormatterList, _> =
 828                    Deserialize::deserialize(de::value::SeqAccessDeserializer::new(map));
 829                ret.map(SelectedFormatter::List)
 830            }
 831        }
 832        deserializer.deserialize_any(FormatDeserializer)
 833    }
 834}
 835
 836/// Controls which formatters should be used when formatting code.
 837#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
 838#[serde(untagged)]
 839pub enum FormatterList {
 840    Single(Formatter),
 841    Vec(Vec<Formatter>),
 842}
 843
 844impl Default for FormatterList {
 845    fn default() -> Self {
 846        Self::Single(Formatter::default())
 847    }
 848}
 849
 850/// Controls which formatter should be used when formatting code. If there are multiple formatters, they are executed in the order of declaration.
 851#[derive(Clone, Default, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
 852#[serde(rename_all = "snake_case")]
 853pub enum Formatter {
 854    /// Format code using the current language server.
 855    LanguageServer { name: Option<String> },
 856    /// Format code using Zed's Prettier integration.
 857    #[default]
 858    Prettier,
 859    /// Format code using an external command.
 860    External {
 861        /// The external program to run.
 862        command: Arc<str>,
 863        /// The arguments to pass to the program.
 864        arguments: Option<Arc<[String]>>,
 865    },
 866    /// Files should be formatted using code actions executed by language servers.
 867    CodeActions(HashMap<String, bool>),
 868}
 869
 870/// The settings for indent guides.
 871#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
 872pub struct IndentGuideSettingsContent {
 873    /// Whether to display indent guides in the editor.
 874    ///
 875    /// Default: true
 876    #[serde(default = "default_true")]
 877    pub enabled: bool,
 878    /// The width of the indent guides in pixels, between 1 and 10.
 879    ///
 880    /// Default: 1
 881    #[serde(default = "line_width")]
 882    pub line_width: u32,
 883    /// The width of the active indent guide in pixels, between 1 and 10.
 884    ///
 885    /// Default: 1
 886    #[serde(default = "active_line_width")]
 887    pub active_line_width: u32,
 888    /// Determines how indent guides are colored.
 889    ///
 890    /// Default: Fixed
 891    #[serde(default)]
 892    pub coloring: IndentGuideColoring,
 893    /// Determines how indent guide backgrounds are colored.
 894    ///
 895    /// Default: Disabled
 896    #[serde(default)]
 897    pub background_coloring: IndentGuideBackgroundColoring,
 898}
 899
 900fn line_width() -> u32 {
 901    1
 902}
 903
 904fn active_line_width() -> u32 {
 905    line_width()
 906}
 907
 908/// The task settings for a particular language.
 909#[derive(Debug, Clone, Deserialize, PartialEq, Serialize, JsonSchema)]
 910pub struct LanguageTaskConfig {
 911    /// Extra task variables to set for a particular language.
 912    #[serde(default)]
 913    pub variables: HashMap<String, String>,
 914    #[serde(default = "default_true")]
 915    pub enabled: bool,
 916    /// Use LSP tasks over Zed language extension ones.
 917    /// If no LSP tasks are returned due to error/timeout or regular execution,
 918    /// Zed language extension tasks will be used instead.
 919    ///
 920    /// Other Zed tasks will still be shown:
 921    /// * Zed task from either of the task config file
 922    /// * Zed task from history (e.g. one-off task was spawned before)
 923    #[serde(default = "default_true")]
 924    pub prefer_lsp: bool,
 925}
 926
 927/// Map from language name to settings. Its `ParameterizedJsonSchema` allows only known language
 928/// names in the keys.
 929#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
 930pub struct LanguageToSettingsMap(pub HashMap<SharedString, LanguageSettingsContent>);
 931
 932inventory::submit! {
 933    ParameterizedJsonSchema {
 934        add_and_get_ref: |generator, params, _cx| {
 935            let language_settings_content_ref = generator
 936                .subschema_for::<LanguageSettingsContent>()
 937                .to_value();
 938            replace_subschema::<LanguageToSettingsMap>(generator, || json_schema!({
 939                "type": "object",
 940                "properties": params
 941                    .language_names
 942                    .iter()
 943                    .map(|name| {
 944                        (
 945                            name.clone(),
 946                            language_settings_content_ref.clone(),
 947                        )
 948                    })
 949                    .collect::<serde_json::Map<_, _>>()
 950            }))
 951        }
 952    }
 953}
 954
 955/// Determines how indent guides are colored.
 956#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
 957#[serde(rename_all = "snake_case")]
 958pub enum IndentGuideColoring {
 959    /// Do not render any lines for indent guides.
 960    Disabled,
 961    /// Use the same color for all indentation levels.
 962    #[default]
 963    Fixed,
 964    /// Use a different color for each indentation level.
 965    IndentAware,
 966}
 967
 968/// Determines how indent guide backgrounds are colored.
 969#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
 970#[serde(rename_all = "snake_case")]
 971pub enum IndentGuideBackgroundColoring {
 972    /// Do not render any background for indent guides.
 973    #[default]
 974    Disabled,
 975    /// Use a different color for each indentation level.
 976    IndentAware,
 977}
 978
 979#[derive(Copy, Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, Debug)]
 980pub struct TitleBarSettingsContent {
 981    /// Controls when the title bar is visible: "always" | "never" | "hide_in_full_screen".
 982    ///
 983    /// Default: "always"
 984    pub show: Option<TitleBarVisibilityContent>,
 985    /// Whether to show the branch icon beside branch switcher in the title bar.
 986    ///
 987    /// Default: false
 988    pub show_branch_icon: Option<bool>,
 989    /// Whether to show onboarding banners in the title bar.
 990    ///
 991    /// Default: true
 992    pub show_onboarding_banner: Option<bool>,
 993    /// Whether to show user avatar in the title bar.
 994    ///
 995    /// Default: true
 996    pub show_user_picture: Option<bool>,
 997    /// Whether to show the branch name button in the titlebar.
 998    ///
 999    /// Default: true
1000    pub show_branch_name: Option<bool>,
1001    /// Whether to show the project host and name in the titlebar.
1002    ///
1003    /// Default: true
1004    pub show_project_items: Option<bool>,
1005    /// Whether to show the sign in button in the title bar.
1006    ///
1007    /// Default: true
1008    pub show_sign_in: Option<bool>,
1009    /// Whether to show the menus in the title bar.
1010    ///
1011    /// Default: false
1012    pub show_menus: Option<bool>,
1013}
1014
1015#[derive(Copy, Clone, PartialEq, Serialize, Deserialize, JsonSchema, Debug)]
1016#[serde(rename_all = "snake_case")]
1017pub enum TitleBarVisibilityContent {
1018    Always,
1019    Never,
1020    HideInFullScreen,
1021}
1022
1023/// Settings for rendering text in UI and text buffers.
1024#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
1025pub struct ThemeSettingsContent {
1026    /// The default font size for text in the UI.
1027    #[serde(default)]
1028    pub ui_font_size: Option<f32>,
1029    /// The name of a font to use for rendering in the UI.
1030    #[serde(default)]
1031    pub ui_font_family: Option<FontFamilyName>,
1032    /// The font fallbacks to use for rendering in the UI.
1033    #[serde(default)]
1034    #[schemars(default = "default_font_fallbacks")]
1035    #[schemars(extend("uniqueItems" = true))]
1036    pub ui_font_fallbacks: Option<Vec<FontFamilyName>>,
1037    /// The OpenType features to enable for text in the UI.
1038    #[serde(default)]
1039    #[schemars(default = "default_font_features")]
1040    pub ui_font_features: Option<FontFeatures>,
1041    /// The weight of the UI font in CSS units from 100 to 900.
1042    #[serde(default)]
1043    pub ui_font_weight: Option<f32>,
1044    /// The name of a font to use for rendering in text buffers.
1045    #[serde(default)]
1046    pub buffer_font_family: Option<FontFamilyName>,
1047    /// The font fallbacks to use for rendering in text buffers.
1048    #[serde(default)]
1049    #[schemars(extend("uniqueItems" = true))]
1050    pub buffer_font_fallbacks: Option<Vec<FontFamilyName>>,
1051    /// The default font size for rendering in text buffers.
1052    #[serde(default)]
1053    pub buffer_font_size: Option<f32>,
1054    /// The weight of the editor font in CSS units from 100 to 900.
1055    #[serde(default)]
1056    pub buffer_font_weight: Option<f32>,
1057    /// The buffer's line height.
1058    #[serde(default)]
1059    pub buffer_line_height: Option<BufferLineHeight>,
1060    /// The OpenType features to enable for rendering in text buffers.
1061    #[serde(default)]
1062    #[schemars(default = "default_font_features")]
1063    pub buffer_font_features: Option<FontFeatures>,
1064    /// The font size for the agent panel. Falls back to the UI font size if unset.
1065    #[serde(default)]
1066    pub agent_font_size: Option<Option<f32>>,
1067    /// The name of the Zed theme to use.
1068    #[serde(default)]
1069    pub theme: Option<ThemeSelection>,
1070    /// The name of the icon theme to use.
1071    #[serde(default)]
1072    pub icon_theme: Option<IconThemeSelection>,
1073
1074    /// UNSTABLE: Expect many elements to be broken.
1075    ///
1076    // Controls the density of the UI.
1077    #[serde(rename = "unstable.ui_density", default)]
1078    pub ui_density: Option<UiDensity>,
1079
1080    /// How much to fade out unused code.
1081    #[serde(default)]
1082    pub unnecessary_code_fade: Option<f32>,
1083
1084    /// EXPERIMENTAL: Overrides for the current theme.
1085    ///
1086    /// These values will override the ones on the current theme specified in `theme`.
1087    #[serde(rename = "experimental.theme_overrides", default)]
1088    pub experimental_theme_overrides: Option<ThemeStyleContent>,
1089
1090    /// Overrides per theme
1091    ///
1092    /// These values will override the ones on the specified theme
1093    #[serde(default)]
1094    pub theme_overrides: HashMap<String, ThemeStyleContent>,
1095}
1096
1097fn default_font_features() -> Option<FontFeatures> {
1098    Some(FontFeatures::default())
1099}
1100
1101fn default_font_fallbacks() -> Option<FontFallbacks> {
1102    Some(FontFallbacks::default())
1103}
1104
1105/// Represents the selection of a theme, which can be either static or dynamic.
1106#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1107#[serde(untagged)]
1108pub enum ThemeSelection {
1109    /// A static theme selection, represented by a single theme name.
1110    Static(ThemeName),
1111    /// A dynamic theme selection, which can change based the [ThemeMode].
1112    Dynamic {
1113        /// The mode used to determine which theme to use.
1114        #[serde(default)]
1115        mode: ThemeMode,
1116        /// The theme to use for light mode.
1117        light: ThemeName,
1118        /// The theme to use for dark mode.
1119        dark: ThemeName,
1120    },
1121}
1122
1123/// Represents the selection of an icon theme, which can be either static or dynamic.
1124#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1125#[serde(untagged)]
1126pub enum IconThemeSelection {
1127    /// A static icon theme selection, represented by a single icon theme name.
1128    Static(IconThemeName),
1129    /// A dynamic icon theme selection, which can change based on the [`ThemeMode`].
1130    Dynamic {
1131        /// The mode used to determine which theme to use.
1132        #[serde(default)]
1133        mode: ThemeMode,
1134        /// The icon theme to use for light mode.
1135        light: IconThemeName,
1136        /// The icon theme to use for dark mode.
1137        dark: IconThemeName,
1138    },
1139}
1140
1141// TODO: Rename ThemeMode -> ThemeAppearanceMode
1142/// The mode use to select a theme.
1143///
1144/// `Light` and `Dark` will select their respective themes.
1145///
1146/// `System` will select the theme based on the system's appearance.
1147#[derive(Debug, PartialEq, Eq, Clone, Copy, Default, Serialize, Deserialize, JsonSchema)]
1148#[serde(rename_all = "snake_case")]
1149pub enum ThemeMode {
1150    /// Use the specified `light` theme.
1151    Light,
1152
1153    /// Use the specified `dark` theme.
1154    Dark,
1155
1156    /// Use the theme based on the system's appearance.
1157    #[default]
1158    System,
1159}
1160
1161/// Specifies the density of the UI.
1162/// Note: This setting is still experimental. See [this tracking issue](https://github.com/zed-industries/zed/issues/18078)
1163#[derive(
1164    Debug,
1165    Default,
1166    PartialEq,
1167    Eq,
1168    PartialOrd,
1169    Ord,
1170    Hash,
1171    Clone,
1172    Copy,
1173    Serialize,
1174    Deserialize,
1175    JsonSchema,
1176)]
1177#[serde(rename_all = "snake_case")]
1178pub enum UiDensity {
1179    /// A denser UI with tighter spacing and smaller elements.
1180    #[serde(alias = "compact")]
1181    Compact,
1182    #[default]
1183    #[serde(alias = "default")]
1184    /// The default UI density.
1185    Default,
1186    #[serde(alias = "comfortable")]
1187    /// A looser UI with more spacing and larger elements.
1188    Comfortable,
1189}
1190
1191impl UiDensity {
1192    /// The spacing ratio of a given density.
1193    /// TODO: Standardize usage throughout the app or remove
1194    pub fn spacing_ratio(self) -> f32 {
1195        match self {
1196            UiDensity::Compact => 0.75,
1197            UiDensity::Default => 1.0,
1198            UiDensity::Comfortable => 1.25,
1199        }
1200    }
1201}
1202
1203/// Newtype for font family name. Its `ParameterizedJsonSchema` lists the font families known at
1204/// runtime.
1205#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1206#[serde(transparent)]
1207pub struct FontFamilyName(pub Arc<str>);
1208
1209inventory::submit! {
1210    ParameterizedJsonSchema {
1211        add_and_get_ref: |generator, params, _cx| {
1212            replace_subschema::<FontFamilyName>(generator, || {
1213                json_schema!({
1214                    "type": "string",
1215                    "enum": params.font_names,
1216                })
1217            })
1218        }
1219    }
1220}
1221
1222/// The buffer's line height.
1223#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, JsonSchema, Default)]
1224#[serde(rename_all = "snake_case")]
1225pub enum BufferLineHeight {
1226    /// A less dense line height.
1227    #[default]
1228    Comfortable,
1229    /// The default line height.
1230    Standard,
1231    /// A custom line height, where 1.0 is the font's height. Must be at least 1.0.
1232    Custom(#[serde(deserialize_with = "deserialize_line_height")] f32),
1233}
1234
1235fn deserialize_line_height<'de, D>(deserializer: D) -> Result<f32, D::Error>
1236where
1237    D: serde::Deserializer<'de>,
1238{
1239    let value = f32::deserialize(deserializer)?;
1240    if value < 1.0 {
1241        return Err(serde::de::Error::custom(
1242            "buffer_line_height.custom must be at least 1.0",
1243        ));
1244    }
1245
1246    Ok(value)
1247}
1248
1249/// The content of a serialized theme.
1250#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema, PartialEq)]
1251#[serde(default)]
1252pub struct ThemeStyleContent {
1253    #[serde(default, rename = "background.appearance")]
1254    pub window_background_appearance: Option<WindowBackgroundContent>,
1255
1256    #[serde(default)]
1257    pub accents: Vec<AccentContent>,
1258
1259    #[serde(flatten, default)]
1260    pub colors: ThemeColorsContent,
1261
1262    #[serde(flatten, default)]
1263    pub status: StatusColorsContent,
1264
1265    #[serde(default)]
1266    pub players: Vec<PlayerColorContent>,
1267
1268    /// The styles for syntax nodes.
1269    #[serde(default)]
1270    pub syntax: IndexMap<String, HighlightStyleContent>,
1271}
1272
1273#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
1274pub struct AccentContent(pub Option<String>);
1275
1276#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
1277pub struct PlayerColorContent {
1278    pub cursor: Option<String>,
1279    pub background: Option<String>,
1280    pub selection: Option<String>,
1281}
1282
1283pub(crate) fn try_parse_color(color: &str) -> Result<Hsla> {
1284    let rgba = gpui::Rgba::try_from(color)?;
1285    let rgba = palette::rgb::Srgba::from_components((rgba.r, rgba.g, rgba.b, rgba.a));
1286    let hsla = palette::Hsla::from_color(rgba);
1287
1288    let hsla = gpui::hsla(
1289        hsla.hue.into_positive_degrees() / 360.,
1290        hsla.saturation,
1291        hsla.lightness,
1292        hsla.alpha,
1293    );
1294
1295    Ok(hsla)
1296}
1297
1298/// Newtype for a theme name. Its `ParameterizedJsonSchema` lists the theme names known at runtime.
1299#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1300#[serde(transparent)]
1301pub struct ThemeName(pub Arc<str>);
1302
1303inventory::submit! {
1304    ParameterizedJsonSchema {
1305        add_and_get_ref: |generator, _params, cx| {
1306            todo!()
1307            // replace_subschema::<ThemeName>(generator, || json_schema!({
1308            //     "type": "string",
1309            //     "enum": ThemeRegistry::global(cx).list_names(),
1310            // }))
1311        }
1312    }
1313}
1314
1315/// Newtype for a icon theme name. Its `ParameterizedJsonSchema` lists the icon theme names known at
1316/// runtime.
1317#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1318#[serde(transparent)]
1319pub struct IconThemeName(pub Arc<str>);
1320
1321inventory::submit! {
1322    ParameterizedJsonSchema {
1323        add_and_get_ref: |generator, _params, cx| {
1324            todo!()
1325            // replace_subschema::<IconThemeName>(generator, || json_schema!({
1326            //     "type": "string",
1327            //     "enum": ThemeRegistry::global(cx)
1328            //         .list_icon_themes()
1329            //         .into_iter()
1330            //         .map(|icon_theme| icon_theme.name)
1331            //         .collect::<Vec<SharedString>>(),
1332            // }))
1333        }
1334    }
1335}