diff --git a/Cargo.lock b/Cargo.lock index db61ba7b121773c6e6941dd940201ec0a9e82f73..933663474f4d8f1909c0747b6f4c94fde95f57fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14884,6 +14884,7 @@ dependencies = [ "serde_json", "serde_json_lenient", "serde_path_to_error", + "serde_repr", "settings_ui_macros", "smallvec", "tree-sitter", diff --git a/crates/settings/Cargo.toml b/crates/settings/Cargo.toml index 4748644604ace11febddd5dcf34b43954dc361c6..4ff12f017f4a379efce7e2054c9c0217db082831 100644 --- a/crates/settings/Cargo.toml +++ b/crates/settings/Cargo.toml @@ -32,6 +32,7 @@ serde.workspace = true serde_json.workspace = true settings_ui_macros.workspace = true serde_json_lenient.workspace = true +serde_repr.workspace = true serde_path_to_error.workspace = true smallvec.workspace = true tree-sitter-json.workspace = true diff --git a/crates/settings/src/settings_content.rs b/crates/settings/src/settings_content.rs index 03510564d117d73db97b32d30b634c9f6c253b71..ef01d7692a00f3a140d6cde676d47b2b293ea945 100644 --- a/crates/settings/src/settings_content.rs +++ b/crates/settings/src/settings_content.rs @@ -1,3 +1,8 @@ +mod language; +mod theme; +pub use language::*; +pub use theme::*; + use std::borrow::Cow; use std::env; use std::num::NonZeroU32; @@ -111,871 +116,6 @@ pub struct ProjectSettingsContent { pub(crate) all_languages: AllLanguageSettingsContent, } -#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize, JsonSchema)] -pub struct AllLanguageSettingsContent { - /// The settings for enabling/disabling features. - #[serde(default)] - pub features: Option, - /// The edit prediction settings. - #[serde(default)] - pub edit_predictions: Option, - /// The default language settings. - #[serde(flatten)] - pub defaults: LanguageSettingsContent, - /// The settings for individual languages. - #[serde(default)] - pub languages: LanguageToSettingsMap, - /// Settings for associating file extensions and filenames - /// with languages. - #[serde(default)] - pub file_types: HashMap>, -} - -/// The settings for enabling/disabling features. -#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub struct FeaturesContent { - /// Determines which edit prediction provider to use. - pub edit_prediction_provider: Option, -} - -/// The provider that supplies edit predictions. -#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum EditPredictionProviderContent { - None, - #[default] - Copilot, - Supermaven, - Zed, -} - -/// The contents of the edit prediction settings. -#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq)] -pub struct EditPredictionSettingsContent { - /// A list of globs representing files that edit predictions should be disabled for. - /// This list adds to a pre-existing, sensible default set of globs. - /// Any additional ones you add are combined with them. - #[serde(default)] - pub disabled_globs: Option>, - /// The mode used to display edit predictions in the buffer. - /// Provider support required. - #[serde(default)] - pub mode: EditPredictionsModeContent, - /// Settings specific to GitHub Copilot. - #[serde(default)] - pub copilot: CopilotSettingsContent, - /// Whether edit predictions are enabled in the assistant prompt editor. - /// This has no effect if globally disabled. - #[serde(default = "default_true")] - pub enabled_in_text_threads: bool, -} - -#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq)] -pub struct CopilotSettingsContent { - /// HTTP/HTTPS proxy to use for Copilot. - /// - /// Default: none - #[serde(default)] - pub proxy: Option, - /// Disable certificate verification for the proxy (not recommended). - /// - /// Default: false - #[serde(default)] - pub proxy_no_verify: Option, - /// Enterprise URI for Copilot. - /// - /// Default: none - #[serde(default)] - pub enterprise_uri: Option, -} - -/// The mode in which edit predictions should be displayed. -#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum EditPredictionsModeContent { - /// If provider supports it, display inline when holding modifier key (e.g., alt). - /// Otherwise, eager preview is used. - #[serde(alias = "auto")] - Subtle, - /// Display inline when there are no language server completions available. - #[default] - #[serde(alias = "eager_preview")] - Eager, -} - -/// Controls the soft-wrapping behavior in the editor. -#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum SoftWrapContent { - /// Prefer a single line generally, unless an overly long line is encountered. - None, - /// Deprecated: use None instead. Left to avoid breaking existing users' configs. - /// Prefer a single line generally, unless an overly long line is encountered. - PreferLine, - /// Soft wrap lines that exceed the editor width. - EditorWidth, - /// Soft wrap lines at the preferred line length. - PreferredLineLength, - /// Soft wrap line at the preferred line length or the editor width (whichever is smaller). - Bounded, -} - -/// The settings for a particular language. -#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize, JsonSchema)] -pub struct LanguageSettingsContent { - /// How many columns a tab should occupy. - /// - /// Default: 4 - #[serde(default)] - pub tab_size: Option, - /// Whether to indent lines using tab characters, as opposed to multiple - /// spaces. - /// - /// Default: false - #[serde(default)] - pub hard_tabs: Option, - /// How to soft-wrap long lines of text. - /// - /// Default: none - #[serde(default)] - pub soft_wrap: Option, - /// The column at which to soft-wrap lines, for buffers where soft-wrap - /// is enabled. - /// - /// Default: 80 - #[serde(default)] - pub preferred_line_length: Option, - /// Whether to show wrap guides in the editor. Setting this to true will - /// show a guide at the 'preferred_line_length' value if softwrap is set to - /// 'preferred_line_length', and will show any additional guides as specified - /// by the 'wrap_guides' setting. - /// - /// Default: true - #[serde(default)] - pub show_wrap_guides: Option, - /// Character counts at which to show wrap guides in the editor. - /// - /// Default: [] - #[serde(default)] - pub wrap_guides: Option>, - /// Indent guide related settings. - #[serde(default)] - pub indent_guides: Option, - /// Whether or not to perform a buffer format before saving. - /// - /// Default: on - #[serde(default)] - pub format_on_save: Option, - /// Whether or not to remove any trailing whitespace from lines of a buffer - /// before saving it. - /// - /// Default: true - #[serde(default)] - pub remove_trailing_whitespace_on_save: Option, - /// Whether or not to ensure there's a single newline at the end of a buffer - /// when saving it. - /// - /// Default: true - #[serde(default)] - pub ensure_final_newline_on_save: Option, - /// How to perform a buffer format. - /// - /// Default: auto - #[serde(default)] - pub formatter: Option, - /// Zed's Prettier integration settings. - /// Allows to enable/disable formatting with Prettier - /// and configure default Prettier, used when no project-level Prettier installation is found. - /// - /// Default: off - #[serde(default)] - pub prettier: Option, - /// Whether to automatically close JSX tags. - #[serde(default)] - pub jsx_tag_auto_close: Option, - /// Whether to use language servers to provide code intelligence. - /// - /// Default: true - #[serde(default)] - pub enable_language_server: Option, - /// The list of language servers to use (or disable) for this language. - /// - /// This array should consist of language server IDs, as well as the following - /// special tokens: - /// - `"!"` - A language server ID prefixed with a `!` will be disabled. - /// - `"..."` - A placeholder to refer to the **rest** of the registered language servers for this language. - /// - /// Default: ["..."] - #[serde(default)] - pub language_servers: Option>, - /// Controls where the `editor::Rewrap` action is allowed for this language. - /// - /// Note: This setting has no effect in Vim mode, as rewrap is already - /// allowed everywhere. - /// - /// Default: "in_comments" - #[serde(default)] - pub allow_rewrap: Option, - /// Controls whether edit predictions are shown immediately (true) - /// or manually by triggering `editor::ShowEditPrediction` (false). - /// - /// Default: true - #[serde(default)] - pub show_edit_predictions: Option, - /// Controls whether edit predictions are shown in the given language - /// scopes. - /// - /// Example: ["string", "comment"] - /// - /// Default: [] - #[serde(default)] - pub edit_predictions_disabled_in: Option>, - /// Whether to show tabs and spaces in the editor. - #[serde(default)] - pub show_whitespaces: Option, - /// Visible characters used to render whitespace when show_whitespaces is enabled. - /// - /// Default: "•" for spaces, "→" for tabs. - #[serde(default)] - pub whitespace_map: Option, - /// Whether to start a new line with a comment when a previous line is a comment as well. - /// - /// Default: true - #[serde(default)] - pub extend_comment_on_newline: Option, - /// Inlay hint related settings. - #[serde(default)] - pub inlay_hints: Option, - /// Whether to automatically type closing characters for you. For example, - /// when you type (, Zed will automatically add a closing ) at the correct position. - /// - /// Default: true - pub use_autoclose: Option, - /// Whether to automatically surround text with characters for you. For example, - /// when you select text and type (, Zed will automatically surround text with (). - /// - /// Default: true - pub use_auto_surround: Option, - /// Controls how the editor handles the autoclosed characters. - /// When set to `false`(default), skipping over and auto-removing of the closing characters - /// happen only for auto-inserted characters. - /// Otherwise(when `true`), the closing characters are always skipped over and auto-removed - /// no matter how they were inserted. - /// - /// Default: false - pub always_treat_brackets_as_autoclosed: Option, - /// Whether to use additional LSP queries to format (and amend) the code after - /// every "trigger" symbol input, defined by LSP server capabilities. - /// - /// Default: true - pub use_on_type_format: Option, - /// Which code actions to run on save after the formatter. - /// These are not run if formatting is off. - /// - /// Default: {} (or {"source.organizeImports": true} for Go). - pub code_actions_on_format: Option>, - /// Whether to perform linked edits of associated ranges, if the language server supports it. - /// For example, when editing opening tag, the contents of the closing tag will be edited as well. - /// - /// Default: true - pub linked_edits: Option, - /// Whether indentation should be adjusted based on the context whilst typing. - /// - /// Default: true - pub auto_indent: Option, - /// Whether indentation of pasted content should be adjusted based on the context. - /// - /// Default: true - pub auto_indent_on_paste: Option, - /// Task configuration for this language. - /// - /// Default: {} - pub tasks: Option, - /// Whether to pop the completions menu while typing in an editor without - /// explicitly requesting it. - /// - /// Default: true - pub show_completions_on_input: Option, - /// Whether to display inline and alongside documentation for items in the - /// completions menu. - /// - /// Default: true - pub show_completion_documentation: Option, - /// Controls how completions are processed for this language. - pub completions: Option, - /// Preferred debuggers for this language. - /// - /// Default: [] - pub debuggers: Option>, -} - -/// Controls how whitespace should be displayedin the editor. -#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum ShowWhitespaceSetting { - /// Draw whitespace only for the selected text. - Selection, - /// Do not draw any tabs or spaces. - None, - /// Draw all invisible symbols. - All, - /// Draw whitespaces at boundaries only. - /// - /// For a whitespace to be on a boundary, any of the following conditions need to be met: - /// - It is a tab - /// - It is adjacent to an edge (start or end) - /// - It is adjacent to a whitespace (left or right) - Boundary, - /// Draw whitespaces only after non-whitespace characters. - Trailing, -} - -#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq)] -pub struct WhitespaceMap { - #[serde(default)] - pub space: Option, - #[serde(default)] - pub tab: Option, -} - -impl WhitespaceMap { - pub fn space(&self) -> SharedString { - self.space - .as_ref() - .map_or_else(|| SharedString::from("•"), |s| SharedString::from(s)) - } - - pub fn tab(&self) -> SharedString { - self.tab - .as_ref() - .map_or_else(|| SharedString::from("→"), |s| SharedString::from(s)) - } -} - -/// The behavior of `editor::Rewrap`. -#[derive(Debug, PartialEq, Clone, Copy, Default, Serialize, Deserialize, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum RewrapBehavior { - /// Only rewrap within comments. - #[default] - InComments, - /// Only rewrap within the current selection(s). - InSelections, - /// Allow rewrapping anywhere. - Anywhere, -} - -#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] -pub struct JsxTagAutoCloseSettings { - /// Enables or disables auto-closing of JSX tags. - #[serde(default)] - pub enabled: bool, -} - -/// The settings for inlay hints. -#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] -pub struct InlayHintSettings { - /// Global switch to toggle hints on and off. - /// - /// Default: false - #[serde(default)] - pub enabled: bool, - /// Global switch to toggle inline values on and off when debugging. - /// - /// Default: true - #[serde(default = "default_true")] - pub show_value_hints: bool, - /// Whether type hints should be shown. - /// - /// Default: true - #[serde(default = "default_true")] - pub show_type_hints: bool, - /// Whether parameter hints should be shown. - /// - /// Default: true - #[serde(default = "default_true")] - pub show_parameter_hints: bool, - /// Whether other hints should be shown. - /// - /// Default: true - #[serde(default = "default_true")] - pub show_other_hints: bool, - /// Whether to show a background for inlay hints. - /// - /// If set to `true`, the background will use the `hint.background` color - /// from the current theme. - /// - /// Default: false - #[serde(default)] - pub show_background: bool, - /// Whether or not to debounce inlay hints updates after buffer edits. - /// - /// Set to 0 to disable debouncing. - /// - /// Default: 700 - #[serde(default = "edit_debounce_ms")] - pub edit_debounce_ms: u64, - /// Whether or not to debounce inlay hints updates after buffer scrolls. - /// - /// Set to 0 to disable debouncing. - /// - /// Default: 50 - #[serde(default = "scroll_debounce_ms")] - pub scroll_debounce_ms: u64, - /// Toggles inlay hints (hides or shows) when the user presses the modifiers specified. - /// If only a subset of the modifiers specified is pressed, hints are not toggled. - /// If no modifiers are specified, this is equivalent to `None`. - /// - /// Default: None - #[serde(default)] - pub toggle_on_modifiers_press: Option, -} - -fn edit_debounce_ms() -> u64 { - 700 -} - -fn scroll_debounce_ms() -> u64 { - 50 -} - -/// Controls how completions are processed for this language. -#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub struct CompletionSettings { - /// Controls how words are completed. - /// For large documents, not all words may be fetched for completion. - /// - /// Default: `fallback` - #[serde(default = "default_words_completion_mode")] - pub words: WordsCompletionMode, - /// How many characters has to be in the completions query to automatically show the words-based completions. - /// Before that value, it's still possible to trigger the words-based completion manually with the corresponding editor command. - /// - /// Default: 3 - #[serde(default = "default_3")] - pub words_min_length: usize, - /// Whether to fetch LSP completions or not. - /// - /// Default: true - #[serde(default = "default_true")] - pub lsp: bool, - /// When fetching LSP completions, determines how long to wait for a response of a particular server. - /// When set to 0, waits indefinitely. - /// - /// Default: 0 - #[serde(default)] - pub lsp_fetch_timeout_ms: u64, - /// Controls how LSP completions are inserted. - /// - /// Default: "replace_suffix" - #[serde(default = "default_lsp_insert_mode")] - pub lsp_insert_mode: LspInsertMode, -} - -#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum LspInsertMode { - /// Replaces text before the cursor, using the `insert` range described in the LSP specification. - Insert, - /// Replaces text before and after the cursor, using the `replace` range described in the LSP specification. - Replace, - /// Behaves like `"replace"` if the text that would be replaced is a subsequence of the completion text, - /// and like `"insert"` otherwise. - ReplaceSubsequence, - /// Behaves like `"replace"` if the text after the cursor is a suffix of the completion, and like - /// `"insert"` otherwise. - ReplaceSuffix, -} - -/// Controls how document's words are completed. -#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum WordsCompletionMode { - /// Always fetch document's words for completions along with LSP completions. - Enabled, - /// Only if LSP response errors or times out, - /// use document's words to show completions. - Fallback, - /// Never fetch or complete document's words for completions. - /// (Word-based completions can still be queried via a separate action) - Disabled, -} - -fn default_words_completion_mode() -> WordsCompletionMode { - WordsCompletionMode::Fallback -} - -fn default_lsp_insert_mode() -> LspInsertMode { - LspInsertMode::ReplaceSuffix -} - -fn default_3() -> usize { - 3 -} - -/// Allows to enable/disable formatting with Prettier -/// and configure default Prettier, used when no project-level Prettier installation is found. -/// Prettier formatting is disabled by default. -#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] -pub struct PrettierSettings { - /// Enables or disables formatting with Prettier for a given language. - #[serde(default)] - pub allowed: bool, - - /// Forces Prettier integration to use a specific parser name when formatting files with the language. - #[serde(default)] - pub parser: Option, - - /// Forces Prettier integration to use specific plugins when formatting files with the language. - /// The default Prettier will be installed with these plugins. - #[serde(default)] - pub plugins: HashSet, - - /// Default Prettier options, in the format as in package.json section for Prettier. - /// If project installs Prettier via its package.json, these options will be ignored. - #[serde(flatten)] - pub options: HashMap, -} -/// Controls the behavior of formatting files when they are saved. -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum FormatOnSave { - /// Files should be formatted on save. - On, - /// Files should not be formatted on save. - Off, - List(FormatterList), -} - -impl JsonSchema for FormatOnSave { - fn schema_name() -> Cow<'static, str> { - "OnSaveFormatter".into() - } - - fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema { - let formatter_schema = Formatter::json_schema(generator); - - json_schema!({ - "oneOf": [ - { - "type": "array", - "items": formatter_schema - }, - { - "type": "string", - "enum": ["on", "off", "language_server"] - }, - formatter_schema - ] - }) - } -} - -impl Serialize for FormatOnSave { - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - match self { - Self::On => serializer.serialize_str("on"), - Self::Off => serializer.serialize_str("off"), - Self::List(list) => list.serialize(serializer), - } - } -} - -impl<'de> Deserialize<'de> for FormatOnSave { - fn deserialize(deserializer: D) -> std::result::Result - where - D: Deserializer<'de>, - { - struct FormatDeserializer; - - impl<'d> Visitor<'d> for FormatDeserializer { - type Value = FormatOnSave; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("a valid on-save formatter kind") - } - fn visit_str(self, v: &str) -> std::result::Result - where - E: serde::de::Error, - { - if v == "on" { - Ok(Self::Value::On) - } else if v == "off" { - Ok(Self::Value::Off) - } else if v == "language_server" { - Ok(Self::Value::List(FormatterList::Single( - Formatter::LanguageServer { name: None }, - ))) - } else { - let ret: Result = - Deserialize::deserialize(v.into_deserializer()); - ret.map(Self::Value::List) - } - } - fn visit_map(self, map: A) -> Result - where - A: MapAccess<'d>, - { - let ret: Result = - Deserialize::deserialize(de::value::MapAccessDeserializer::new(map)); - ret.map(Self::Value::List) - } - fn visit_seq(self, map: A) -> Result - where - A: SeqAccess<'d>, - { - let ret: Result = - Deserialize::deserialize(de::value::SeqAccessDeserializer::new(map)); - ret.map(Self::Value::List) - } - } - deserializer.deserialize_any(FormatDeserializer) - } -} - -/// Controls which formatter should be used when formatting code. -#[derive(Clone, Debug, Default, PartialEq, Eq)] -pub enum SelectedFormatter { - /// Format files using Zed's Prettier integration (if applicable), - /// or falling back to formatting via language server. - #[default] - Auto, - List(FormatterList), -} - -impl JsonSchema for SelectedFormatter { - fn schema_name() -> Cow<'static, str> { - "Formatter".into() - } - - fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema { - let formatter_schema = Formatter::json_schema(generator); - - json_schema!({ - "oneOf": [ - { - "type": "array", - "items": formatter_schema - }, - { - "type": "string", - "enum": ["auto", "language_server"] - }, - formatter_schema - ] - }) - } -} - -impl Serialize for SelectedFormatter { - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - match self { - SelectedFormatter::Auto => serializer.serialize_str("auto"), - SelectedFormatter::List(list) => list.serialize(serializer), - } - } -} - -impl<'de> Deserialize<'de> for SelectedFormatter { - fn deserialize(deserializer: D) -> std::result::Result - where - D: Deserializer<'de>, - { - struct FormatDeserializer; - - impl<'d> Visitor<'d> for FormatDeserializer { - type Value = SelectedFormatter; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("a valid formatter kind") - } - fn visit_str(self, v: &str) -> std::result::Result - where - E: serde::de::Error, - { - if v == "auto" { - Ok(Self::Value::Auto) - } else if v == "language_server" { - Ok(Self::Value::List(FormatterList::Single( - Formatter::LanguageServer { name: None }, - ))) - } else { - let ret: Result = - Deserialize::deserialize(v.into_deserializer()); - ret.map(SelectedFormatter::List) - } - } - fn visit_map(self, map: A) -> Result - where - A: MapAccess<'d>, - { - let ret: Result = - Deserialize::deserialize(de::value::MapAccessDeserializer::new(map)); - ret.map(SelectedFormatter::List) - } - fn visit_seq(self, map: A) -> Result - where - A: SeqAccess<'d>, - { - let ret: Result = - Deserialize::deserialize(de::value::SeqAccessDeserializer::new(map)); - ret.map(SelectedFormatter::List) - } - } - deserializer.deserialize_any(FormatDeserializer) - } -} - -/// Controls which formatters should be used when formatting code. -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] -#[serde(untagged)] -pub enum FormatterList { - Single(Formatter), - Vec(Vec), -} - -impl Default for FormatterList { - fn default() -> Self { - Self::Single(Formatter::default()) - } -} - -/// Controls which formatter should be used when formatting code. If there are multiple formatters, they are executed in the order of declaration. -#[derive(Clone, Default, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum Formatter { - /// Format code using the current language server. - LanguageServer { name: Option }, - /// Format code using Zed's Prettier integration. - #[default] - Prettier, - /// Format code using an external command. - External { - /// The external program to run. - command: Arc, - /// The arguments to pass to the program. - arguments: Option>, - }, - /// Files should be formatted using code actions executed by language servers. - CodeActions(HashMap), -} - -/// The settings for indent guides. -#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] -pub struct IndentGuideSettingsContent { - /// Whether to display indent guides in the editor. - /// - /// Default: true - #[serde(default = "default_true")] - pub enabled: bool, - /// The width of the indent guides in pixels, between 1 and 10. - /// - /// Default: 1 - #[serde(default = "line_width")] - pub line_width: u32, - /// The width of the active indent guide in pixels, between 1 and 10. - /// - /// Default: 1 - #[serde(default = "active_line_width")] - pub active_line_width: u32, - /// Determines how indent guides are colored. - /// - /// Default: Fixed - #[serde(default)] - pub coloring: IndentGuideColoring, - /// Determines how indent guide backgrounds are colored. - /// - /// Default: Disabled - #[serde(default)] - pub background_coloring: IndentGuideBackgroundColoring, -} - -fn line_width() -> u32 { - 1 -} - -fn active_line_width() -> u32 { - line_width() -} - -/// The task settings for a particular language. -#[derive(Debug, Clone, Deserialize, PartialEq, Serialize, JsonSchema)] -pub struct LanguageTaskConfig { - /// Extra task variables to set for a particular language. - #[serde(default)] - pub variables: HashMap, - #[serde(default = "default_true")] - pub enabled: bool, - /// Use LSP tasks over Zed language extension ones. - /// If no LSP tasks are returned due to error/timeout or regular execution, - /// Zed language extension tasks will be used instead. - /// - /// Other Zed tasks will still be shown: - /// * Zed task from either of the task config file - /// * Zed task from history (e.g. one-off task was spawned before) - #[serde(default = "default_true")] - pub prefer_lsp: bool, -} - -/// Map from language name to settings. Its `ParameterizedJsonSchema` allows only known language -/// names in the keys. -#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize, JsonSchema)] -pub struct LanguageToSettingsMap(pub HashMap); - -inventory::submit! { - ParameterizedJsonSchema { - add_and_get_ref: |generator, params, _cx| { - let language_settings_content_ref = generator - .subschema_for::() - .to_value(); - replace_subschema::(generator, || json_schema!({ - "type": "object", - "properties": params - .language_names - .iter() - .map(|name| { - ( - name.clone(), - language_settings_content_ref.clone(), - ) - }) - .collect::>() - })) - } - } -} - -/// Determines how indent guides are colored. -#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum IndentGuideColoring { - /// Do not render any lines for indent guides. - Disabled, - /// Use the same color for all indentation levels. - #[default] - Fixed, - /// Use a different color for each indentation level. - IndentAware, -} - -/// Determines how indent guide backgrounds are colored. -#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum IndentGuideBackgroundColoring { - /// Do not render any background for indent guides. - #[default] - Disabled, - /// Use a different color for each indentation level. - IndentAware, -} - #[derive(Copy, Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema, Debug)] pub struct TitleBarSettingsContent { /// Controls when the title bar is visible: "always" | "never" | "hide_in_full_screen". @@ -1019,317 +159,3 @@ pub enum TitleBarVisibilityContent { Never, HideInFullScreen, } - -/// Settings for rendering text in UI and text buffers. -#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)] -pub struct ThemeSettingsContent { - /// The default font size for text in the UI. - #[serde(default)] - pub ui_font_size: Option, - /// The name of a font to use for rendering in the UI. - #[serde(default)] - pub ui_font_family: Option, - /// The font fallbacks to use for rendering in the UI. - #[serde(default)] - #[schemars(default = "default_font_fallbacks")] - #[schemars(extend("uniqueItems" = true))] - pub ui_font_fallbacks: Option>, - /// The OpenType features to enable for text in the UI. - #[serde(default)] - #[schemars(default = "default_font_features")] - pub ui_font_features: Option, - /// The weight of the UI font in CSS units from 100 to 900. - #[serde(default)] - pub ui_font_weight: Option, - /// The name of a font to use for rendering in text buffers. - #[serde(default)] - pub buffer_font_family: Option, - /// The font fallbacks to use for rendering in text buffers. - #[serde(default)] - #[schemars(extend("uniqueItems" = true))] - pub buffer_font_fallbacks: Option>, - /// The default font size for rendering in text buffers. - #[serde(default)] - pub buffer_font_size: Option, - /// The weight of the editor font in CSS units from 100 to 900. - #[serde(default)] - pub buffer_font_weight: Option, - /// The buffer's line height. - #[serde(default)] - pub buffer_line_height: Option, - /// The OpenType features to enable for rendering in text buffers. - #[serde(default)] - #[schemars(default = "default_font_features")] - pub buffer_font_features: Option, - /// The font size for the agent panel. Falls back to the UI font size if unset. - #[serde(default)] - pub agent_font_size: Option>, - /// The name of the Zed theme to use. - #[serde(default)] - pub theme: Option, - /// The name of the icon theme to use. - #[serde(default)] - pub icon_theme: Option, - - /// UNSTABLE: Expect many elements to be broken. - /// - // Controls the density of the UI. - #[serde(rename = "unstable.ui_density", default)] - pub ui_density: Option, - - /// How much to fade out unused code. - #[serde(default)] - pub unnecessary_code_fade: Option, - - /// EXPERIMENTAL: Overrides for the current theme. - /// - /// These values will override the ones on the current theme specified in `theme`. - #[serde(rename = "experimental.theme_overrides", default)] - pub experimental_theme_overrides: Option, - - /// Overrides per theme - /// - /// These values will override the ones on the specified theme - #[serde(default)] - pub theme_overrides: HashMap, -} - -fn default_font_features() -> Option { - Some(FontFeatures::default()) -} - -fn default_font_fallbacks() -> Option { - Some(FontFallbacks::default()) -} - -/// Represents the selection of a theme, which can be either static or dynamic. -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] -#[serde(untagged)] -pub enum ThemeSelection { - /// A static theme selection, represented by a single theme name. - Static(ThemeName), - /// A dynamic theme selection, which can change based the [ThemeMode]. - Dynamic { - /// The mode used to determine which theme to use. - #[serde(default)] - mode: ThemeMode, - /// The theme to use for light mode. - light: ThemeName, - /// The theme to use for dark mode. - dark: ThemeName, - }, -} - -/// Represents the selection of an icon theme, which can be either static or dynamic. -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] -#[serde(untagged)] -pub enum IconThemeSelection { - /// A static icon theme selection, represented by a single icon theme name. - Static(IconThemeName), - /// A dynamic icon theme selection, which can change based on the [`ThemeMode`]. - Dynamic { - /// The mode used to determine which theme to use. - #[serde(default)] - mode: ThemeMode, - /// The icon theme to use for light mode. - light: IconThemeName, - /// The icon theme to use for dark mode. - dark: IconThemeName, - }, -} - -// TODO: Rename ThemeMode -> ThemeAppearanceMode -/// The mode use to select a theme. -/// -/// `Light` and `Dark` will select their respective themes. -/// -/// `System` will select the theme based on the system's appearance. -#[derive(Debug, PartialEq, Eq, Clone, Copy, Default, Serialize, Deserialize, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum ThemeMode { - /// Use the specified `light` theme. - Light, - - /// Use the specified `dark` theme. - Dark, - - /// Use the theme based on the system's appearance. - #[default] - System, -} - -/// Specifies the density of the UI. -/// Note: This setting is still experimental. See [this tracking issue](https://github.com/zed-industries/zed/issues/18078) -#[derive( - Debug, - Default, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - Clone, - Copy, - Serialize, - Deserialize, - JsonSchema, -)] -#[serde(rename_all = "snake_case")] -pub enum UiDensity { - /// A denser UI with tighter spacing and smaller elements. - #[serde(alias = "compact")] - Compact, - #[default] - #[serde(alias = "default")] - /// The default UI density. - Default, - #[serde(alias = "comfortable")] - /// A looser UI with more spacing and larger elements. - Comfortable, -} - -impl UiDensity { - /// The spacing ratio of a given density. - /// TODO: Standardize usage throughout the app or remove - pub fn spacing_ratio(self) -> f32 { - match self { - UiDensity::Compact => 0.75, - UiDensity::Default => 1.0, - UiDensity::Comfortable => 1.25, - } - } -} - -/// Newtype for font family name. Its `ParameterizedJsonSchema` lists the font families known at -/// runtime. -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] -#[serde(transparent)] -pub struct FontFamilyName(pub Arc); - -inventory::submit! { - ParameterizedJsonSchema { - add_and_get_ref: |generator, params, _cx| { - replace_subschema::(generator, || { - json_schema!({ - "type": "string", - "enum": params.font_names, - }) - }) - } - } -} - -/// The buffer's line height. -#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, JsonSchema, Default)] -#[serde(rename_all = "snake_case")] -pub enum BufferLineHeight { - /// A less dense line height. - #[default] - Comfortable, - /// The default line height. - Standard, - /// A custom line height, where 1.0 is the font's height. Must be at least 1.0. - Custom(#[serde(deserialize_with = "deserialize_line_height")] f32), -} - -fn deserialize_line_height<'de, D>(deserializer: D) -> Result -where - D: serde::Deserializer<'de>, -{ - let value = f32::deserialize(deserializer)?; - if value < 1.0 { - return Err(serde::de::Error::custom( - "buffer_line_height.custom must be at least 1.0", - )); - } - - Ok(value) -} - -/// The content of a serialized theme. -#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema, PartialEq)] -#[serde(default)] -pub struct ThemeStyleContent { - #[serde(default, rename = "background.appearance")] - pub window_background_appearance: Option, - - #[serde(default)] - pub accents: Vec, - - #[serde(flatten, default)] - pub colors: ThemeColorsContent, - - #[serde(flatten, default)] - pub status: StatusColorsContent, - - #[serde(default)] - pub players: Vec, - - /// The styles for syntax nodes. - #[serde(default)] - pub syntax: IndexMap, -} - -#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)] -pub struct AccentContent(pub Option); - -#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)] -pub struct PlayerColorContent { - pub cursor: Option, - pub background: Option, - pub selection: Option, -} - -pub(crate) fn try_parse_color(color: &str) -> Result { - let rgba = gpui::Rgba::try_from(color)?; - let rgba = palette::rgb::Srgba::from_components((rgba.r, rgba.g, rgba.b, rgba.a)); - let hsla = palette::Hsla::from_color(rgba); - - let hsla = gpui::hsla( - hsla.hue.into_positive_degrees() / 360., - hsla.saturation, - hsla.lightness, - hsla.alpha, - ); - - Ok(hsla) -} - -/// Newtype for a theme name. Its `ParameterizedJsonSchema` lists the theme names known at runtime. -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] -#[serde(transparent)] -pub struct ThemeName(pub Arc); - -inventory::submit! { - ParameterizedJsonSchema { - add_and_get_ref: |generator, _params, cx| { - todo!() - // replace_subschema::(generator, || json_schema!({ - // "type": "string", - // "enum": ThemeRegistry::global(cx).list_names(), - // })) - } - } -} - -/// Newtype for a icon theme name. Its `ParameterizedJsonSchema` lists the icon theme names known at -/// runtime. -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] -#[serde(transparent)] -pub struct IconThemeName(pub Arc); - -inventory::submit! { - ParameterizedJsonSchema { - add_and_get_ref: |generator, _params, cx| { - todo!() - // replace_subschema::(generator, || json_schema!({ - // "type": "string", - // "enum": ThemeRegistry::global(cx) - // .list_icon_themes() - // .into_iter() - // .map(|icon_theme| icon_theme.name) - // .collect::>(), - // })) - } - } -} diff --git a/crates/settings/src/settings_content/language.rs b/crates/settings/src/settings_content/language.rs new file mode 100644 index 0000000000000000000000000000000000000000..5d58618f2ac590cbc3f7ac62642f55b2f3d6d81c --- /dev/null +++ b/crates/settings/src/settings_content/language.rs @@ -0,0 +1,882 @@ +use std::{borrow::Cow, num::NonZeroU32}; + +use collections::{HashMap, HashSet}; +use gpui::{Modifiers, SharedString}; +use schemars::{JsonSchema, json_schema}; +use serde::{ + Deserialize, Deserializer, Serialize, + de::{self, IntoDeserializer, MapAccess, SeqAccess, Visitor}, +}; +use std::sync::Arc; +use util::schemars::replace_subschema; + +use crate::ParameterizedJsonSchema; + +#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize, JsonSchema)] +pub struct AllLanguageSettingsContent { + /// The settings for enabling/disabling features. + #[serde(default)] + pub features: Option, + /// The edit prediction settings. + #[serde(default)] + pub edit_predictions: Option, + /// The default language settings. + #[serde(flatten)] + pub defaults: LanguageSettingsContent, + /// The settings for individual languages. + #[serde(default)] + pub languages: LanguageToSettingsMap, + /// Settings for associating file extensions and filenames + /// with languages. + #[serde(default)] + pub file_types: HashMap>, +} + +/// The settings for enabling/disabling features. +#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub struct FeaturesContent { + /// Determines which edit prediction provider to use. + pub edit_prediction_provider: Option, +} + +/// The provider that supplies edit predictions. +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum EditPredictionProviderContent { + None, + #[default] + Copilot, + Supermaven, + Zed, +} + +/// The contents of the edit prediction settings. +#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq)] +pub struct EditPredictionSettingsContent { + /// A list of globs representing files that edit predictions should be disabled for. + /// This list adds to a pre-existing, sensible default set of globs. + /// Any additional ones you add are combined with them. + #[serde(default)] + pub disabled_globs: Option>, + /// The mode used to display edit predictions in the buffer. + /// Provider support required. + #[serde(default)] + pub mode: EditPredictionsModeContent, + /// Settings specific to GitHub Copilot. + #[serde(default)] + pub copilot: CopilotSettingsContent, + /// Whether edit predictions are enabled in the assistant prompt editor. + /// This has no effect if globally disabled. + #[serde(default = "default_true")] + pub enabled_in_text_threads: bool, +} + +fn default_true() -> bool { + true +} + +#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq)] +pub struct CopilotSettingsContent { + /// HTTP/HTTPS proxy to use for Copilot. + /// + /// Default: none + #[serde(default)] + pub proxy: Option, + /// Disable certificate verification for the proxy (not recommended). + /// + /// Default: false + #[serde(default)] + pub proxy_no_verify: Option, + /// Enterprise URI for Copilot. + /// + /// Default: none + #[serde(default)] + pub enterprise_uri: Option, +} + +/// The mode in which edit predictions should be displayed. +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum EditPredictionsModeContent { + /// If provider supports it, display inline when holding modifier key (e.g., alt). + /// Otherwise, eager preview is used. + #[serde(alias = "auto")] + Subtle, + /// Display inline when there are no language server completions available. + #[default] + #[serde(alias = "eager_preview")] + Eager, +} + +/// Controls the soft-wrapping behavior in the editor. +#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum SoftWrapContent { + /// Prefer a single line generally, unless an overly long line is encountered. + None, + /// Deprecated: use None instead. Left to avoid breaking existing users' configs. + /// Prefer a single line generally, unless an overly long line is encountered. + PreferLine, + /// Soft wrap lines that exceed the editor width. + EditorWidth, + /// Soft wrap lines at the preferred line length. + PreferredLineLength, + /// Soft wrap line at the preferred line length or the editor width (whichever is smaller). + Bounded, +} + +/// The settings for a particular language. +#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize, JsonSchema)] +pub struct LanguageSettingsContent { + /// How many columns a tab should occupy. + /// + /// Default: 4 + #[serde(default)] + pub tab_size: Option, + /// Whether to indent lines using tab characters, as opposed to multiple + /// spaces. + /// + /// Default: false + #[serde(default)] + pub hard_tabs: Option, + /// How to soft-wrap long lines of text. + /// + /// Default: none + #[serde(default)] + pub soft_wrap: Option, + /// The column at which to soft-wrap lines, for buffers where soft-wrap + /// is enabled. + /// + /// Default: 80 + #[serde(default)] + pub preferred_line_length: Option, + /// Whether to show wrap guides in the editor. Setting this to true will + /// show a guide at the 'preferred_line_length' value if softwrap is set to + /// 'preferred_line_length', and will show any additional guides as specified + /// by the 'wrap_guides' setting. + /// + /// Default: true + #[serde(default)] + pub show_wrap_guides: Option, + /// Character counts at which to show wrap guides in the editor. + /// + /// Default: [] + #[serde(default)] + pub wrap_guides: Option>, + /// Indent guide related settings. + #[serde(default)] + pub indent_guides: Option, + /// Whether or not to perform a buffer format before saving. + /// + /// Default: on + #[serde(default)] + pub format_on_save: Option, + /// Whether or not to remove any trailing whitespace from lines of a buffer + /// before saving it. + /// + /// Default: true + #[serde(default)] + pub remove_trailing_whitespace_on_save: Option, + /// Whether or not to ensure there's a single newline at the end of a buffer + /// when saving it. + /// + /// Default: true + #[serde(default)] + pub ensure_final_newline_on_save: Option, + /// How to perform a buffer format. + /// + /// Default: auto + #[serde(default)] + pub formatter: Option, + /// Zed's Prettier integration settings. + /// Allows to enable/disable formatting with Prettier + /// and configure default Prettier, used when no project-level Prettier installation is found. + /// + /// Default: off + #[serde(default)] + pub prettier: Option, + /// Whether to automatically close JSX tags. + #[serde(default)] + pub jsx_tag_auto_close: Option, + /// Whether to use language servers to provide code intelligence. + /// + /// Default: true + #[serde(default)] + pub enable_language_server: Option, + /// The list of language servers to use (or disable) for this language. + /// + /// This array should consist of language server IDs, as well as the following + /// special tokens: + /// - `"!"` - A language server ID prefixed with a `!` will be disabled. + /// - `"..."` - A placeholder to refer to the **rest** of the registered language servers for this language. + /// + /// Default: ["..."] + #[serde(default)] + pub language_servers: Option>, + /// Controls where the `editor::Rewrap` action is allowed for this language. + /// + /// Note: This setting has no effect in Vim mode, as rewrap is already + /// allowed everywhere. + /// + /// Default: "in_comments" + #[serde(default)] + pub allow_rewrap: Option, + /// Controls whether edit predictions are shown immediately (true) + /// or manually by triggering `editor::ShowEditPrediction` (false). + /// + /// Default: true + #[serde(default)] + pub show_edit_predictions: Option, + /// Controls whether edit predictions are shown in the given language + /// scopes. + /// + /// Example: ["string", "comment"] + /// + /// Default: [] + #[serde(default)] + pub edit_predictions_disabled_in: Option>, + /// Whether to show tabs and spaces in the editor. + #[serde(default)] + pub show_whitespaces: Option, + /// Visible characters used to render whitespace when show_whitespaces is enabled. + /// + /// Default: "•" for spaces, "→" for tabs. + #[serde(default)] + pub whitespace_map: Option, + /// Whether to start a new line with a comment when a previous line is a comment as well. + /// + /// Default: true + #[serde(default)] + pub extend_comment_on_newline: Option, + /// Inlay hint related settings. + #[serde(default)] + pub inlay_hints: Option, + /// Whether to automatically type closing characters for you. For example, + /// when you type (, Zed will automatically add a closing ) at the correct position. + /// + /// Default: true + pub use_autoclose: Option, + /// Whether to automatically surround text with characters for you. For example, + /// when you select text and type (, Zed will automatically surround text with (). + /// + /// Default: true + pub use_auto_surround: Option, + /// Controls how the editor handles the autoclosed characters. + /// When set to `false`(default), skipping over and auto-removing of the closing characters + /// happen only for auto-inserted characters. + /// Otherwise(when `true`), the closing characters are always skipped over and auto-removed + /// no matter how they were inserted. + /// + /// Default: false + pub always_treat_brackets_as_autoclosed: Option, + /// Whether to use additional LSP queries to format (and amend) the code after + /// every "trigger" symbol input, defined by LSP server capabilities. + /// + /// Default: true + pub use_on_type_format: Option, + /// Which code actions to run on save after the formatter. + /// These are not run if formatting is off. + /// + /// Default: {} (or {"source.organizeImports": true} for Go). + pub code_actions_on_format: Option>, + /// Whether to perform linked edits of associated ranges, if the language server supports it. + /// For example, when editing opening tag, the contents of the closing tag will be edited as well. + /// + /// Default: true + pub linked_edits: Option, + /// Whether indentation should be adjusted based on the context whilst typing. + /// + /// Default: true + pub auto_indent: Option, + /// Whether indentation of pasted content should be adjusted based on the context. + /// + /// Default: true + pub auto_indent_on_paste: Option, + /// Task configuration for this language. + /// + /// Default: {} + pub tasks: Option, + /// Whether to pop the completions menu while typing in an editor without + /// explicitly requesting it. + /// + /// Default: true + pub show_completions_on_input: Option, + /// Whether to display inline and alongside documentation for items in the + /// completions menu. + /// + /// Default: true + pub show_completion_documentation: Option, + /// Controls how completions are processed for this language. + pub completions: Option, + /// Preferred debuggers for this language. + /// + /// Default: [] + pub debuggers: Option>, +} + +/// Controls how whitespace should be displayedin the editor. +#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum ShowWhitespaceSetting { + /// Draw whitespace only for the selected text. + Selection, + /// Do not draw any tabs or spaces. + None, + /// Draw all invisible symbols. + All, + /// Draw whitespaces at boundaries only. + /// + /// For a whitespace to be on a boundary, any of the following conditions need to be met: + /// - It is a tab + /// - It is adjacent to an edge (start or end) + /// - It is adjacent to a whitespace (left or right) + Boundary, + /// Draw whitespaces only after non-whitespace characters. + Trailing, +} + +#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq)] +pub struct WhitespaceMap { + #[serde(default)] + pub space: Option, + #[serde(default)] + pub tab: Option, +} + +impl WhitespaceMap { + pub fn space(&self) -> SharedString { + self.space + .as_ref() + .map_or_else(|| SharedString::from("•"), |s| SharedString::from(s)) + } + + pub fn tab(&self) -> SharedString { + self.tab + .as_ref() + .map_or_else(|| SharedString::from("→"), |s| SharedString::from(s)) + } +} + +/// The behavior of `editor::Rewrap`. +#[derive(Debug, PartialEq, Clone, Copy, Default, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum RewrapBehavior { + /// Only rewrap within comments. + #[default] + InComments, + /// Only rewrap within the current selection(s). + InSelections, + /// Allow rewrapping anywhere. + Anywhere, +} + +#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +pub struct JsxTagAutoCloseSettings { + /// Enables or disables auto-closing of JSX tags. + #[serde(default)] + pub enabled: bool, +} + +/// The settings for inlay hints. +#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +pub struct InlayHintSettings { + /// Global switch to toggle hints on and off. + /// + /// Default: false + #[serde(default)] + pub enabled: bool, + /// Global switch to toggle inline values on and off when debugging. + /// + /// Default: true + #[serde(default = "default_true")] + pub show_value_hints: bool, + /// Whether type hints should be shown. + /// + /// Default: true + #[serde(default = "default_true")] + pub show_type_hints: bool, + /// Whether parameter hints should be shown. + /// + /// Default: true + #[serde(default = "default_true")] + pub show_parameter_hints: bool, + /// Whether other hints should be shown. + /// + /// Default: true + #[serde(default = "default_true")] + pub show_other_hints: bool, + /// Whether to show a background for inlay hints. + /// + /// If set to `true`, the background will use the `hint.background` color + /// from the current theme. + /// + /// Default: false + #[serde(default)] + pub show_background: bool, + /// Whether or not to debounce inlay hints updates after buffer edits. + /// + /// Set to 0 to disable debouncing. + /// + /// Default: 700 + #[serde(default = "edit_debounce_ms")] + pub edit_debounce_ms: u64, + /// Whether or not to debounce inlay hints updates after buffer scrolls. + /// + /// Set to 0 to disable debouncing. + /// + /// Default: 50 + #[serde(default = "scroll_debounce_ms")] + pub scroll_debounce_ms: u64, + /// Toggles inlay hints (hides or shows) when the user presses the modifiers specified. + /// If only a subset of the modifiers specified is pressed, hints are not toggled. + /// If no modifiers are specified, this is equivalent to `None`. + /// + /// Default: None + #[serde(default)] + pub toggle_on_modifiers_press: Option, +} + +fn edit_debounce_ms() -> u64 { + 700 +} + +fn scroll_debounce_ms() -> u64 { + 50 +} + +/// Controls how completions are processed for this language. +#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub struct CompletionSettings { + /// Controls how words are completed. + /// For large documents, not all words may be fetched for completion. + /// + /// Default: `fallback` + #[serde(default = "default_words_completion_mode")] + pub words: WordsCompletionMode, + /// How many characters has to be in the completions query to automatically show the words-based completions. + /// Before that value, it's still possible to trigger the words-based completion manually with the corresponding editor command. + /// + /// Default: 3 + #[serde(default = "default_3")] + pub words_min_length: usize, + /// Whether to fetch LSP completions or not. + /// + /// Default: true + #[serde(default = "default_true")] + pub lsp: bool, + /// When fetching LSP completions, determines how long to wait for a response of a particular server. + /// When set to 0, waits indefinitely. + /// + /// Default: 0 + #[serde(default)] + pub lsp_fetch_timeout_ms: u64, + /// Controls how LSP completions are inserted. + /// + /// Default: "replace_suffix" + #[serde(default = "default_lsp_insert_mode")] + pub lsp_insert_mode: LspInsertMode, +} + +#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum LspInsertMode { + /// Replaces text before the cursor, using the `insert` range described in the LSP specification. + Insert, + /// Replaces text before and after the cursor, using the `replace` range described in the LSP specification. + Replace, + /// Behaves like `"replace"` if the text that would be replaced is a subsequence of the completion text, + /// and like `"insert"` otherwise. + ReplaceSubsequence, + /// Behaves like `"replace"` if the text after the cursor is a suffix of the completion, and like + /// `"insert"` otherwise. + ReplaceSuffix, +} + +/// Controls how document's words are completed. +#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum WordsCompletionMode { + /// Always fetch document's words for completions along with LSP completions. + Enabled, + /// Only if LSP response errors or times out, + /// use document's words to show completions. + Fallback, + /// Never fetch or complete document's words for completions. + /// (Word-based completions can still be queried via a separate action) + Disabled, +} + +fn default_words_completion_mode() -> WordsCompletionMode { + WordsCompletionMode::Fallback +} + +fn default_lsp_insert_mode() -> LspInsertMode { + LspInsertMode::ReplaceSuffix +} + +fn default_3() -> usize { + 3 +} + +/// Allows to enable/disable formatting with Prettier +/// and configure default Prettier, used when no project-level Prettier installation is found. +/// Prettier formatting is disabled by default. +#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +pub struct PrettierSettings { + /// Enables or disables formatting with Prettier for a given language. + #[serde(default)] + pub allowed: bool, + + /// Forces Prettier integration to use a specific parser name when formatting files with the language. + #[serde(default)] + pub parser: Option, + + /// Forces Prettier integration to use specific plugins when formatting files with the language. + /// The default Prettier will be installed with these plugins. + #[serde(default)] + pub plugins: HashSet, + + /// Default Prettier options, in the format as in package.json section for Prettier. + /// If project installs Prettier via its package.json, these options will be ignored. + #[serde(flatten)] + pub options: HashMap, +} +/// Controls the behavior of formatting files when they are saved. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum FormatOnSave { + /// Files should be formatted on save. + On, + /// Files should not be formatted on save. + Off, + List(FormatterList), +} + +impl JsonSchema for FormatOnSave { + fn schema_name() -> Cow<'static, str> { + "OnSaveFormatter".into() + } + + fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema { + let formatter_schema = Formatter::json_schema(generator); + + json_schema!({ + "oneOf": [ + { + "type": "array", + "items": formatter_schema + }, + { + "type": "string", + "enum": ["on", "off", "language_server"] + }, + formatter_schema + ] + }) + } +} + +impl Serialize for FormatOnSave { + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + match self { + Self::On => serializer.serialize_str("on"), + Self::Off => serializer.serialize_str("off"), + Self::List(list) => list.serialize(serializer), + } + } +} + +impl<'de> Deserialize<'de> for FormatOnSave { + fn deserialize(deserializer: D) -> std::result::Result + where + D: Deserializer<'de>, + { + struct FormatDeserializer; + + impl<'d> Visitor<'d> for FormatDeserializer { + type Value = FormatOnSave; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a valid on-save formatter kind") + } + fn visit_str(self, v: &str) -> std::result::Result + where + E: serde::de::Error, + { + if v == "on" { + Ok(Self::Value::On) + } else if v == "off" { + Ok(Self::Value::Off) + } else if v == "language_server" { + Ok(Self::Value::List(FormatterList::Single( + Formatter::LanguageServer { name: None }, + ))) + } else { + let ret: Result = + Deserialize::deserialize(v.into_deserializer()); + ret.map(Self::Value::List) + } + } + fn visit_map(self, map: A) -> Result + where + A: MapAccess<'d>, + { + let ret: Result = + Deserialize::deserialize(de::value::MapAccessDeserializer::new(map)); + ret.map(Self::Value::List) + } + fn visit_seq(self, map: A) -> Result + where + A: SeqAccess<'d>, + { + let ret: Result = + Deserialize::deserialize(de::value::SeqAccessDeserializer::new(map)); + ret.map(Self::Value::List) + } + } + deserializer.deserialize_any(FormatDeserializer) + } +} + +/// Controls which formatter should be used when formatting code. +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub enum SelectedFormatter { + /// Format files using Zed's Prettier integration (if applicable), + /// or falling back to formatting via language server. + #[default] + Auto, + List(FormatterList), +} + +impl JsonSchema for SelectedFormatter { + fn schema_name() -> Cow<'static, str> { + "Formatter".into() + } + + fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema { + let formatter_schema = Formatter::json_schema(generator); + + json_schema!({ + "oneOf": [ + { + "type": "array", + "items": formatter_schema + }, + { + "type": "string", + "enum": ["auto", "language_server"] + }, + formatter_schema + ] + }) + } +} + +impl Serialize for SelectedFormatter { + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + match self { + SelectedFormatter::Auto => serializer.serialize_str("auto"), + SelectedFormatter::List(list) => list.serialize(serializer), + } + } +} + +impl<'de> Deserialize<'de> for SelectedFormatter { + fn deserialize(deserializer: D) -> std::result::Result + where + D: Deserializer<'de>, + { + struct FormatDeserializer; + + impl<'d> Visitor<'d> for FormatDeserializer { + type Value = SelectedFormatter; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a valid formatter kind") + } + fn visit_str(self, v: &str) -> std::result::Result + where + E: serde::de::Error, + { + if v == "auto" { + Ok(Self::Value::Auto) + } else if v == "language_server" { + Ok(Self::Value::List(FormatterList::Single( + Formatter::LanguageServer { name: None }, + ))) + } else { + let ret: Result = + Deserialize::deserialize(v.into_deserializer()); + ret.map(SelectedFormatter::List) + } + } + fn visit_map(self, map: A) -> Result + where + A: MapAccess<'d>, + { + let ret: Result = + Deserialize::deserialize(de::value::MapAccessDeserializer::new(map)); + ret.map(SelectedFormatter::List) + } + fn visit_seq(self, map: A) -> Result + where + A: SeqAccess<'d>, + { + let ret: Result = + Deserialize::deserialize(de::value::SeqAccessDeserializer::new(map)); + ret.map(SelectedFormatter::List) + } + } + deserializer.deserialize_any(FormatDeserializer) + } +} + +/// Controls which formatters should be used when formatting code. +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[serde(untagged)] +pub enum FormatterList { + Single(Formatter), + Vec(Vec), +} + +impl Default for FormatterList { + fn default() -> Self { + Self::Single(Formatter::default()) + } +} + +/// Controls which formatter should be used when formatting code. If there are multiple formatters, they are executed in the order of declaration. +#[derive(Clone, Default, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum Formatter { + /// Format code using the current language server. + LanguageServer { name: Option }, + /// Format code using Zed's Prettier integration. + #[default] + Prettier, + /// Format code using an external command. + External { + /// The external program to run. + command: Arc, + /// The arguments to pass to the program. + arguments: Option>, + }, + /// Files should be formatted using code actions executed by language servers. + CodeActions(HashMap), +} + +/// The settings for indent guides. +#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +pub struct IndentGuideSettingsContent { + /// Whether to display indent guides in the editor. + /// + /// Default: true + #[serde(default = "default_true")] + pub enabled: bool, + /// The width of the indent guides in pixels, between 1 and 10. + /// + /// Default: 1 + #[serde(default = "line_width")] + pub line_width: u32, + /// The width of the active indent guide in pixels, between 1 and 10. + /// + /// Default: 1 + #[serde(default = "active_line_width")] + pub active_line_width: u32, + /// Determines how indent guides are colored. + /// + /// Default: Fixed + #[serde(default)] + pub coloring: IndentGuideColoring, + /// Determines how indent guide backgrounds are colored. + /// + /// Default: Disabled + #[serde(default)] + pub background_coloring: IndentGuideBackgroundColoring, +} + +fn line_width() -> u32 { + 1 +} + +fn active_line_width() -> u32 { + line_width() +} + +/// The task settings for a particular language. +#[derive(Debug, Clone, Deserialize, PartialEq, Serialize, JsonSchema)] +pub struct LanguageTaskConfig { + /// Extra task variables to set for a particular language. + #[serde(default)] + pub variables: HashMap, + #[serde(default = "default_true")] + pub enabled: bool, + /// Use LSP tasks over Zed language extension ones. + /// If no LSP tasks are returned due to error/timeout or regular execution, + /// Zed language extension tasks will be used instead. + /// + /// Other Zed tasks will still be shown: + /// * Zed task from either of the task config file + /// * Zed task from history (e.g. one-off task was spawned before) + #[serde(default = "default_true")] + pub prefer_lsp: bool, +} + +/// Map from language name to settings. Its `ParameterizedJsonSchema` allows only known language +/// names in the keys. +#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize, JsonSchema)] +pub struct LanguageToSettingsMap(pub HashMap); + +inventory::submit! { + ParameterizedJsonSchema { + add_and_get_ref: |generator, params, _cx| { + let language_settings_content_ref = generator + .subschema_for::() + .to_value(); + replace_subschema::(generator, || json_schema!({ + "type": "object", + "properties": params + .language_names + .iter() + .map(|name| { + ( + name.clone(), + language_settings_content_ref.clone(), + ) + }) + .collect::>() + })) + } + } +} + +/// Determines how indent guides are colored. +#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum IndentGuideColoring { + /// Do not render any lines for indent guides. + Disabled, + /// Use the same color for all indentation levels. + #[default] + Fixed, + /// Use a different color for each indentation level. + IndentAware, +} + +/// Determines how indent guide backgrounds are colored. +#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum IndentGuideBackgroundColoring { + /// Do not render any background for indent guides. + #[default] + Disabled, + /// Use a different color for each indentation level. + IndentAware, +} diff --git a/crates/settings/src/settings_content/theme.rs b/crates/settings/src/settings_content/theme.rs new file mode 100644 index 0000000000000000000000000000000000000000..e32f39469ef763448ba2da9ecbb88cab06d1ff95 --- /dev/null +++ b/crates/settings/src/settings_content/theme.rs @@ -0,0 +1,1022 @@ +use collections::{HashMap, IndexMap}; +use gpui::{FontFallbacks, FontFeatures}; +use schemars::{JsonSchema, JsonSchema_repr, json_schema}; +use serde::{Deserialize, Deserializer, Serialize}; +use serde_json::Value; +use serde_repr::{Deserialize_repr, Serialize_repr}; +use std::sync::Arc; +use util::schemars::replace_subschema; + +use crate::ParameterizedJsonSchema; + +/// Settings for rendering text in UI and text buffers. +#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)] +pub struct ThemeSettingsContent { + /// The default font size for text in the UI. + #[serde(default)] + pub ui_font_size: Option, + /// The name of a font to use for rendering in the UI. + #[serde(default)] + pub ui_font_family: Option, + /// The font fallbacks to use for rendering in the UI. + #[serde(default)] + #[schemars(default = "default_font_fallbacks")] + #[schemars(extend("uniqueItems" = true))] + pub ui_font_fallbacks: Option>, + /// The OpenType features to enable for text in the UI. + #[serde(default)] + #[schemars(default = "default_font_features")] + pub ui_font_features: Option, + /// The weight of the UI font in CSS units from 100 to 900. + #[serde(default)] + pub ui_font_weight: Option, + /// The name of a font to use for rendering in text buffers. + #[serde(default)] + pub buffer_font_family: Option, + /// The font fallbacks to use for rendering in text buffers. + #[serde(default)] + #[schemars(extend("uniqueItems" = true))] + pub buffer_font_fallbacks: Option>, + /// The default font size for rendering in text buffers. + #[serde(default)] + pub buffer_font_size: Option, + /// The weight of the editor font in CSS units from 100 to 900. + #[serde(default)] + pub buffer_font_weight: Option, + /// The buffer's line height. + #[serde(default)] + pub buffer_line_height: Option, + /// The OpenType features to enable for rendering in text buffers. + #[serde(default)] + #[schemars(default = "default_font_features")] + pub buffer_font_features: Option, + /// The font size for the agent panel. Falls back to the UI font size if unset. + #[serde(default)] + pub agent_font_size: Option>, + /// The name of the Zed theme to use. + #[serde(default)] + pub theme: Option, + /// The name of the icon theme to use. + #[serde(default)] + pub icon_theme: Option, + + /// UNSTABLE: Expect many elements to be broken. + /// + // Controls the density of the UI. + #[serde(rename = "unstable.ui_density", default)] + pub ui_density: Option, + + /// How much to fade out unused code. + #[serde(default)] + pub unnecessary_code_fade: Option, + + /// EXPERIMENTAL: Overrides for the current theme. + /// + /// These values will override the ones on the current theme specified in `theme`. + #[serde(rename = "experimental.theme_overrides", default)] + pub experimental_theme_overrides: Option, + + /// Overrides per theme + /// + /// These values will override the ones on the specified theme + #[serde(default)] + pub theme_overrides: HashMap, +} + +fn default_font_features() -> Option { + Some(FontFeatures::default()) +} + +fn default_font_fallbacks() -> Option { + Some(FontFallbacks::default()) +} + +/// Represents the selection of a theme, which can be either static or dynamic. +#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +#[serde(untagged)] +pub enum ThemeSelection { + /// A static theme selection, represented by a single theme name. + Static(ThemeName), + /// A dynamic theme selection, which can change based the [ThemeMode]. + Dynamic { + /// The mode used to determine which theme to use. + #[serde(default)] + mode: ThemeMode, + /// The theme to use for light mode. + light: ThemeName, + /// The theme to use for dark mode. + dark: ThemeName, + }, +} + +/// Represents the selection of an icon theme, which can be either static or dynamic. +#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +#[serde(untagged)] +pub enum IconThemeSelection { + /// A static icon theme selection, represented by a single icon theme name. + Static(IconThemeName), + /// A dynamic icon theme selection, which can change based on the [`ThemeMode`]. + Dynamic { + /// The mode used to determine which theme to use. + #[serde(default)] + mode: ThemeMode, + /// The icon theme to use for light mode. + light: IconThemeName, + /// The icon theme to use for dark mode. + dark: IconThemeName, + }, +} + +// TODO: Rename ThemeMode -> ThemeAppearanceMode +/// The mode use to select a theme. +/// +/// `Light` and `Dark` will select their respective themes. +/// +/// `System` will select the theme based on the system's appearance. +#[derive(Debug, PartialEq, Eq, Clone, Copy, Default, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum ThemeMode { + /// Use the specified `light` theme. + Light, + + /// Use the specified `dark` theme. + Dark, + + /// Use the theme based on the system's appearance. + #[default] + System, +} + +/// Specifies the density of the UI. +/// Note: This setting is still experimental. See [this tracking issue](https://github.com/zed-industries/zed/issues/18078) +#[derive( + Debug, + Default, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + Clone, + Copy, + Serialize, + Deserialize, + JsonSchema, +)] +#[serde(rename_all = "snake_case")] +pub enum UiDensity { + /// A denser UI with tighter spacing and smaller elements. + #[serde(alias = "compact")] + Compact, + #[default] + #[serde(alias = "default")] + /// The default UI density. + Default, + #[serde(alias = "comfortable")] + /// A looser UI with more spacing and larger elements. + Comfortable, +} + +impl UiDensity { + /// The spacing ratio of a given density. + /// TODO: Standardize usage throughout the app or remove + pub fn spacing_ratio(self) -> f32 { + match self { + UiDensity::Compact => 0.75, + UiDensity::Default => 1.0, + UiDensity::Comfortable => 1.25, + } + } +} + +/// Newtype for font family name. Its `ParameterizedJsonSchema` lists the font families known at +/// runtime. +#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +#[serde(transparent)] +pub struct FontFamilyName(pub Arc); + +inventory::submit! { + ParameterizedJsonSchema { + add_and_get_ref: |generator, params, _cx| { + replace_subschema::(generator, || { + json_schema!({ + "type": "string", + "enum": params.font_names, + }) + }) + } + } +} + +/// The buffer's line height. +#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, JsonSchema, Default)] +#[serde(rename_all = "snake_case")] +pub enum BufferLineHeight { + /// A less dense line height. + #[default] + Comfortable, + /// The default line height. + Standard, + /// A custom line height, where 1.0 is the font's height. Must be at least 1.0. + Custom(#[serde(deserialize_with = "deserialize_line_height")] f32), +} + +fn deserialize_line_height<'de, D>(deserializer: D) -> Result +where + D: serde::Deserializer<'de>, +{ + let value = f32::deserialize(deserializer)?; + if value < 1.0 { + return Err(serde::de::Error::custom( + "buffer_line_height.custom must be at least 1.0", + )); + } + + Ok(value) +} + +/// The content of a serialized theme. +#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema, PartialEq)] +#[serde(default)] +pub struct ThemeStyleContent { + #[serde(default, rename = "background.appearance")] + pub window_background_appearance: Option, + + #[serde(default)] + pub accents: Vec, + + #[serde(flatten, default)] + pub colors: ThemeColorsContent, + + #[serde(flatten, default)] + pub status: StatusColorsContent, + + #[serde(default)] + pub players: Vec, + + /// The styles for syntax nodes. + #[serde(default)] + pub syntax: IndexMap, +} + +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)] +pub struct AccentContent(pub Option); + +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)] +pub struct PlayerColorContent { + pub cursor: Option, + pub background: Option, + pub selection: Option, +} + +/// Newtype for a theme name. Its `ParameterizedJsonSchema` lists the theme names known at runtime. +#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +#[serde(transparent)] +pub struct ThemeName(pub Arc); + +inventory::submit! { + ParameterizedJsonSchema { + add_and_get_ref: |generator, _params, cx| { + todo!() + // replace_subschema::(generator, || json_schema!({ + // "type": "string", + // "enum": ThemeRegistry::global(cx).list_names(), + // })) + } + } +} + +/// Newtype for a icon theme name. Its `ParameterizedJsonSchema` lists the icon theme names known at +/// runtime. +#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] +#[serde(transparent)] +pub struct IconThemeName(pub Arc); + +inventory::submit! { + ParameterizedJsonSchema { + add_and_get_ref: |generator, _params, cx| { + todo!() + // replace_subschema::(generator, || json_schema!({ + // "type": "string", + // "enum": ThemeRegistry::global(cx) + // .list_icon_themes() + // .into_iter() + // .map(|icon_theme| icon_theme.name) + // .collect::>(), + // })) + } + } +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema, PartialEq)] +#[serde(default)] +pub struct ThemeColorsContent { + /// Border color. Used for most borders, is usually a high contrast color. + #[serde(rename = "border")] + pub border: Option, + + /// Border color. Used for deemphasized borders, like a visual divider between two sections + #[serde(rename = "border.variant")] + pub border_variant: Option, + + /// Border color. Used for focused elements, like keyboard focused list item. + #[serde(rename = "border.focused")] + pub border_focused: Option, + + /// Border color. Used for selected elements, like an active search filter or selected checkbox. + #[serde(rename = "border.selected")] + pub border_selected: Option, + + /// Border color. Used for transparent borders. Used for placeholder borders when an element gains a border on state change. + #[serde(rename = "border.transparent")] + pub border_transparent: Option, + + /// Border color. Used for disabled elements, like a disabled input or button. + #[serde(rename = "border.disabled")] + pub border_disabled: Option, + + /// Background color. Used for elevated surfaces, like a context menu, popup, or dialog. + #[serde(rename = "elevated_surface.background")] + pub elevated_surface_background: Option, + + /// Background Color. Used for grounded surfaces like a panel or tab. + #[serde(rename = "surface.background")] + pub surface_background: Option, + + /// Background Color. Used for the app background and blank panels or windows. + #[serde(rename = "background")] + pub background: Option, + + /// Background Color. Used for the background of an element that should have a different background than the surface it's on. + /// + /// Elements might include: Buttons, Inputs, Checkboxes, Radio Buttons... + /// + /// For an element that should have the same background as the surface it's on, use `ghost_element_background`. + #[serde(rename = "element.background")] + pub element_background: Option, + + /// Background Color. Used for the hover state of an element that should have a different background than the surface it's on. + /// + /// Hover states are triggered by the mouse entering an element, or a finger touching an element on a touch screen. + #[serde(rename = "element.hover")] + pub element_hover: Option, + + /// Background Color. Used for the active state of an element that should have a different background than the surface it's on. + /// + /// Active states are triggered by the mouse button being pressed down on an element, or the Return button or other activator being pressed. + #[serde(rename = "element.active")] + pub element_active: Option, + + /// Background Color. Used for the selected state of an element that should have a different background than the surface it's on. + /// + /// Selected states are triggered by the element being selected (or "activated") by the user. + /// + /// This could include a selected checkbox, a toggleable button that is toggled on, etc. + #[serde(rename = "element.selected")] + pub element_selected: Option, + + /// Background Color. Used for the disabled state of an element that should have a different background than the surface it's on. + /// + /// Disabled states are shown when a user cannot interact with an element, like a disabled button or input. + #[serde(rename = "element.disabled")] + pub element_disabled: Option, + + /// Background Color. Used for the background of selections in a UI element. + #[serde(rename = "element.selection_background")] + pub element_selection_background: Option, + + /// Background Color. Used for the area that shows where a dragged element will be dropped. + #[serde(rename = "drop_target.background")] + pub drop_target_background: Option, + + /// Border Color. Used for the border that shows where a dragged element will be dropped. + #[serde(rename = "drop_target.border")] + pub drop_target_border: Option, + + /// Used for the background of a ghost element that should have the same background as the surface it's on. + /// + /// Elements might include: Buttons, Inputs, Checkboxes, Radio Buttons... + /// + /// For an element that should have a different background than the surface it's on, use `element_background`. + #[serde(rename = "ghost_element.background")] + pub ghost_element_background: Option, + + /// Background Color. Used for the hover state of a ghost element that should have the same background as the surface it's on. + /// + /// Hover states are triggered by the mouse entering an element, or a finger touching an element on a touch screen. + #[serde(rename = "ghost_element.hover")] + pub ghost_element_hover: Option, + + /// Background Color. Used for the active state of a ghost element that should have the same background as the surface it's on. + /// + /// Active states are triggered by the mouse button being pressed down on an element, or the Return button or other activator being pressed. + #[serde(rename = "ghost_element.active")] + pub ghost_element_active: Option, + + /// Background Color. Used for the selected state of a ghost element that should have the same background as the surface it's on. + /// + /// Selected states are triggered by the element being selected (or "activated") by the user. + /// + /// This could include a selected checkbox, a toggleable button that is toggled on, etc. + #[serde(rename = "ghost_element.selected")] + pub ghost_element_selected: Option, + + /// Background Color. Used for the disabled state of a ghost element that should have the same background as the surface it's on. + /// + /// Disabled states are shown when a user cannot interact with an element, like a disabled button or input. + #[serde(rename = "ghost_element.disabled")] + pub ghost_element_disabled: Option, + + /// Text Color. Default text color used for most text. + #[serde(rename = "text")] + pub text: Option, + + /// Text Color. Color of muted or deemphasized text. It is a subdued version of the standard text color. + #[serde(rename = "text.muted")] + pub text_muted: Option, + + /// Text Color. Color of the placeholder text typically shown in input fields to guide the user to enter valid data. + #[serde(rename = "text.placeholder")] + pub text_placeholder: Option, + + /// Text Color. Color used for text denoting disabled elements. Typically, the color is faded or grayed out to emphasize the disabled state. + #[serde(rename = "text.disabled")] + pub text_disabled: Option, + + /// Text Color. Color used for emphasis or highlighting certain text, like an active filter or a matched character in a search. + #[serde(rename = "text.accent")] + pub text_accent: Option, + + /// Fill Color. Used for the default fill color of an icon. + #[serde(rename = "icon")] + pub icon: Option, + + /// Fill Color. Used for the muted or deemphasized fill color of an icon. + /// + /// This might be used to show an icon in an inactive pane, or to deemphasize a series of icons to give them less visual weight. + #[serde(rename = "icon.muted")] + pub icon_muted: Option, + + /// Fill Color. Used for the disabled fill color of an icon. + /// + /// Disabled states are shown when a user cannot interact with an element, like a icon button. + #[serde(rename = "icon.disabled")] + pub icon_disabled: Option, + + /// Fill Color. Used for the placeholder fill color of an icon. + /// + /// This might be used to show an icon in an input that disappears when the user enters text. + #[serde(rename = "icon.placeholder")] + pub icon_placeholder: Option, + + /// Fill Color. Used for the accent fill color of an icon. + /// + /// This might be used to show when a toggleable icon button is selected. + #[serde(rename = "icon.accent")] + pub icon_accent: Option, + + /// Color used to accent some of the debuggers elements + /// Only accent breakpoint & breakpoint related symbols right now + #[serde(rename = "debugger.accent")] + pub debugger_accent: Option, + + #[serde(rename = "status_bar.background")] + pub status_bar_background: Option, + + #[serde(rename = "title_bar.background")] + pub title_bar_background: Option, + + #[serde(rename = "title_bar.inactive_background")] + pub title_bar_inactive_background: Option, + + #[serde(rename = "toolbar.background")] + pub toolbar_background: Option, + + #[serde(rename = "tab_bar.background")] + pub tab_bar_background: Option, + + #[serde(rename = "tab.inactive_background")] + pub tab_inactive_background: Option, + + #[serde(rename = "tab.active_background")] + pub tab_active_background: Option, + + #[serde(rename = "search.match_background")] + pub search_match_background: Option, + + #[serde(rename = "panel.background")] + pub panel_background: Option, + + #[serde(rename = "panel.focused_border")] + pub panel_focused_border: Option, + + #[serde(rename = "panel.indent_guide")] + pub panel_indent_guide: Option, + + #[serde(rename = "panel.indent_guide_hover")] + pub panel_indent_guide_hover: Option, + + #[serde(rename = "panel.indent_guide_active")] + pub panel_indent_guide_active: Option, + + #[serde(rename = "panel.overlay_background")] + pub panel_overlay_background: Option, + + #[serde(rename = "panel.overlay_hover")] + pub panel_overlay_hover: Option, + + #[serde(rename = "pane.focused_border")] + pub pane_focused_border: Option, + + #[serde(rename = "pane_group.border")] + pub pane_group_border: Option, + + /// The deprecated version of `scrollbar.thumb.background`. + /// + /// Don't use this field. + #[serde(rename = "scrollbar_thumb.background", skip_serializing)] + #[schemars(skip)] + pub deprecated_scrollbar_thumb_background: Option, + + /// The color of the scrollbar thumb. + #[serde(rename = "scrollbar.thumb.background")] + pub scrollbar_thumb_background: Option, + + /// The color of the scrollbar thumb when hovered over. + #[serde(rename = "scrollbar.thumb.hover_background")] + pub scrollbar_thumb_hover_background: Option, + + /// The color of the scrollbar thumb whilst being actively dragged. + #[serde(rename = "scrollbar.thumb.active_background")] + pub scrollbar_thumb_active_background: Option, + + /// The border color of the scrollbar thumb. + #[serde(rename = "scrollbar.thumb.border")] + pub scrollbar_thumb_border: Option, + + /// The background color of the scrollbar track. + #[serde(rename = "scrollbar.track.background")] + pub scrollbar_track_background: Option, + + /// The border color of the scrollbar track. + #[serde(rename = "scrollbar.track.border")] + pub scrollbar_track_border: Option, + + /// The color of the minimap thumb. + #[serde(rename = "minimap.thumb.background")] + pub minimap_thumb_background: Option, + + /// The color of the minimap thumb when hovered over. + #[serde(rename = "minimap.thumb.hover_background")] + pub minimap_thumb_hover_background: Option, + + /// The color of the minimap thumb whilst being actively dragged. + #[serde(rename = "minimap.thumb.active_background")] + pub minimap_thumb_active_background: Option, + + /// The border color of the minimap thumb. + #[serde(rename = "minimap.thumb.border")] + pub minimap_thumb_border: Option, + + #[serde(rename = "editor.foreground")] + pub editor_foreground: Option, + + #[serde(rename = "editor.background")] + pub editor_background: Option, + + #[serde(rename = "editor.gutter.background")] + pub editor_gutter_background: Option, + + #[serde(rename = "editor.subheader.background")] + pub editor_subheader_background: Option, + + #[serde(rename = "editor.active_line.background")] + pub editor_active_line_background: Option, + + #[serde(rename = "editor.highlighted_line.background")] + pub editor_highlighted_line_background: Option, + + /// Background of active line of debugger + #[serde(rename = "editor.debugger_active_line.background")] + pub editor_debugger_active_line_background: Option, + + /// Text Color. Used for the text of the line number in the editor gutter. + #[serde(rename = "editor.line_number")] + pub editor_line_number: Option, + + /// Text Color. Used for the text of the line number in the editor gutter when the line is highlighted. + #[serde(rename = "editor.active_line_number")] + pub editor_active_line_number: Option, + + /// Text Color. Used for the text of the line number in the editor gutter when the line is hovered over. + #[serde(rename = "editor.hover_line_number")] + pub editor_hover_line_number: Option, + + /// Text Color. Used to mark invisible characters in the editor. + /// + /// Example: spaces, tabs, carriage returns, etc. + #[serde(rename = "editor.invisible")] + pub editor_invisible: Option, + + #[serde(rename = "editor.wrap_guide")] + pub editor_wrap_guide: Option, + + #[serde(rename = "editor.active_wrap_guide")] + pub editor_active_wrap_guide: Option, + + #[serde(rename = "editor.indent_guide")] + pub editor_indent_guide: Option, + + #[serde(rename = "editor.indent_guide_active")] + pub editor_indent_guide_active: Option, + + /// Read-access of a symbol, like reading a variable. + /// + /// A document highlight is a range inside a text document which deserves + /// special attention. Usually a document highlight is visualized by changing + /// the background color of its range. + #[serde(rename = "editor.document_highlight.read_background")] + pub editor_document_highlight_read_background: Option, + + /// Read-access of a symbol, like reading a variable. + /// + /// A document highlight is a range inside a text document which deserves + /// special attention. Usually a document highlight is visualized by changing + /// the background color of its range. + #[serde(rename = "editor.document_highlight.write_background")] + pub editor_document_highlight_write_background: Option, + + /// Highlighted brackets background color. + /// + /// Matching brackets in the cursor scope are highlighted with this background color. + #[serde(rename = "editor.document_highlight.bracket_background")] + pub editor_document_highlight_bracket_background: Option, + + /// Terminal background color. + #[serde(rename = "terminal.background")] + pub terminal_background: Option, + + /// Terminal foreground color. + #[serde(rename = "terminal.foreground")] + pub terminal_foreground: Option, + + /// Terminal ANSI background color. + #[serde(rename = "terminal.ansi.background")] + pub terminal_ansi_background: Option, + + /// Bright terminal foreground color. + #[serde(rename = "terminal.bright_foreground")] + pub terminal_bright_foreground: Option, + + /// Dim terminal foreground color. + #[serde(rename = "terminal.dim_foreground")] + pub terminal_dim_foreground: Option, + + /// Black ANSI terminal color. + #[serde(rename = "terminal.ansi.black")] + pub terminal_ansi_black: Option, + + /// Bright black ANSI terminal color. + #[serde(rename = "terminal.ansi.bright_black")] + pub terminal_ansi_bright_black: Option, + + /// Dim black ANSI terminal color. + #[serde(rename = "terminal.ansi.dim_black")] + pub terminal_ansi_dim_black: Option, + + /// Red ANSI terminal color. + #[serde(rename = "terminal.ansi.red")] + pub terminal_ansi_red: Option, + + /// Bright red ANSI terminal color. + #[serde(rename = "terminal.ansi.bright_red")] + pub terminal_ansi_bright_red: Option, + + /// Dim red ANSI terminal color. + #[serde(rename = "terminal.ansi.dim_red")] + pub terminal_ansi_dim_red: Option, + + /// Green ANSI terminal color. + #[serde(rename = "terminal.ansi.green")] + pub terminal_ansi_green: Option, + + /// Bright green ANSI terminal color. + #[serde(rename = "terminal.ansi.bright_green")] + pub terminal_ansi_bright_green: Option, + + /// Dim green ANSI terminal color. + #[serde(rename = "terminal.ansi.dim_green")] + pub terminal_ansi_dim_green: Option, + + /// Yellow ANSI terminal color. + #[serde(rename = "terminal.ansi.yellow")] + pub terminal_ansi_yellow: Option, + + /// Bright yellow ANSI terminal color. + #[serde(rename = "terminal.ansi.bright_yellow")] + pub terminal_ansi_bright_yellow: Option, + + /// Dim yellow ANSI terminal color. + #[serde(rename = "terminal.ansi.dim_yellow")] + pub terminal_ansi_dim_yellow: Option, + + /// Blue ANSI terminal color. + #[serde(rename = "terminal.ansi.blue")] + pub terminal_ansi_blue: Option, + + /// Bright blue ANSI terminal color. + #[serde(rename = "terminal.ansi.bright_blue")] + pub terminal_ansi_bright_blue: Option, + + /// Dim blue ANSI terminal color. + #[serde(rename = "terminal.ansi.dim_blue")] + pub terminal_ansi_dim_blue: Option, + + /// Magenta ANSI terminal color. + #[serde(rename = "terminal.ansi.magenta")] + pub terminal_ansi_magenta: Option, + + /// Bright magenta ANSI terminal color. + #[serde(rename = "terminal.ansi.bright_magenta")] + pub terminal_ansi_bright_magenta: Option, + + /// Dim magenta ANSI terminal color. + #[serde(rename = "terminal.ansi.dim_magenta")] + pub terminal_ansi_dim_magenta: Option, + + /// Cyan ANSI terminal color. + #[serde(rename = "terminal.ansi.cyan")] + pub terminal_ansi_cyan: Option, + + /// Bright cyan ANSI terminal color. + #[serde(rename = "terminal.ansi.bright_cyan")] + pub terminal_ansi_bright_cyan: Option, + + /// Dim cyan ANSI terminal color. + #[serde(rename = "terminal.ansi.dim_cyan")] + pub terminal_ansi_dim_cyan: Option, + + /// White ANSI terminal color. + #[serde(rename = "terminal.ansi.white")] + pub terminal_ansi_white: Option, + + /// Bright white ANSI terminal color. + #[serde(rename = "terminal.ansi.bright_white")] + pub terminal_ansi_bright_white: Option, + + /// Dim white ANSI terminal color. + #[serde(rename = "terminal.ansi.dim_white")] + pub terminal_ansi_dim_white: Option, + + #[serde(rename = "link_text.hover")] + pub link_text_hover: Option, + + /// Added version control color. + #[serde(rename = "version_control.added")] + pub version_control_added: Option, + + /// Deleted version control color. + #[serde(rename = "version_control.deleted")] + pub version_control_deleted: Option, + + /// Modified version control color. + #[serde(rename = "version_control.modified")] + pub version_control_modified: Option, + + /// Renamed version control color. + #[serde(rename = "version_control.renamed")] + pub version_control_renamed: Option, + + /// Conflict version control color. + #[serde(rename = "version_control.conflict")] + pub version_control_conflict: Option, + + /// Ignored version control color. + #[serde(rename = "version_control.ignored")] + pub version_control_ignored: Option, + + /// Background color for row highlights of "ours" regions in merge conflicts. + #[serde(rename = "version_control.conflict_marker.ours")] + pub version_control_conflict_marker_ours: Option, + + /// Background color for row highlights of "theirs" regions in merge conflicts. + #[serde(rename = "version_control.conflict_marker.theirs")] + pub version_control_conflict_marker_theirs: Option, + + /// Deprecated in favor of `version_control_conflict_marker_ours`. + #[deprecated] + pub version_control_conflict_ours_background: Option, + + /// Deprecated in favor of `version_control_conflict_marker_theirs`. + #[deprecated] + pub version_control_conflict_theirs_background: Option, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema, PartialEq)] +#[serde(default)] +pub struct HighlightStyleContent { + pub color: Option, + + #[serde(deserialize_with = "treat_error_as_none")] + pub background_color: Option, + + #[serde(deserialize_with = "treat_error_as_none")] + pub font_style: Option, + + #[serde(deserialize_with = "treat_error_as_none")] + pub font_weight: Option, +} + +impl HighlightStyleContent { + pub fn is_empty(&self) -> bool { + self.color.is_none() + && self.background_color.is_none() + && self.font_style.is_none() + && self.font_weight.is_none() + } +} + +fn treat_error_as_none<'de, T, D>(deserializer: D) -> Result, D::Error> +where + T: Deserialize<'de>, + D: Deserializer<'de>, +{ + let value: Value = Deserialize::deserialize(deserializer)?; + Ok(T::deserialize(value).ok()) +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema, PartialEq)] +#[serde(default)] +pub struct StatusColorsContent { + /// Indicates some kind of conflict, like a file changed on disk while it was open, or + /// merge conflicts in a Git repository. + #[serde(rename = "conflict")] + pub conflict: Option, + + #[serde(rename = "conflict.background")] + pub conflict_background: Option, + + #[serde(rename = "conflict.border")] + pub conflict_border: Option, + + /// Indicates something new, like a new file added to a Git repository. + #[serde(rename = "created")] + pub created: Option, + + #[serde(rename = "created.background")] + pub created_background: Option, + + #[serde(rename = "created.border")] + pub created_border: Option, + + /// Indicates that something no longer exists, like a deleted file. + #[serde(rename = "deleted")] + pub deleted: Option, + + #[serde(rename = "deleted.background")] + pub deleted_background: Option, + + #[serde(rename = "deleted.border")] + pub deleted_border: Option, + + /// Indicates a system error, a failed operation or a diagnostic error. + #[serde(rename = "error")] + pub error: Option, + + #[serde(rename = "error.background")] + pub error_background: Option, + + #[serde(rename = "error.border")] + pub error_border: Option, + + /// Represents a hidden status, such as a file being hidden in a file tree. + #[serde(rename = "hidden")] + pub hidden: Option, + + #[serde(rename = "hidden.background")] + pub hidden_background: Option, + + #[serde(rename = "hidden.border")] + pub hidden_border: Option, + + /// Indicates a hint or some kind of additional information. + #[serde(rename = "hint")] + pub hint: Option, + + #[serde(rename = "hint.background")] + pub hint_background: Option, + + #[serde(rename = "hint.border")] + pub hint_border: Option, + + /// Indicates that something is deliberately ignored, such as a file or operation ignored by Git. + #[serde(rename = "ignored")] + pub ignored: Option, + + #[serde(rename = "ignored.background")] + pub ignored_background: Option, + + #[serde(rename = "ignored.border")] + pub ignored_border: Option, + + /// Represents informational status updates or messages. + #[serde(rename = "info")] + pub info: Option, + + #[serde(rename = "info.background")] + pub info_background: Option, + + #[serde(rename = "info.border")] + pub info_border: Option, + + /// Indicates a changed or altered status, like a file that has been edited. + #[serde(rename = "modified")] + pub modified: Option, + + #[serde(rename = "modified.background")] + pub modified_background: Option, + + #[serde(rename = "modified.border")] + pub modified_border: Option, + + /// Indicates something that is predicted, like automatic code completion, or generated code. + #[serde(rename = "predictive")] + pub predictive: Option, + + #[serde(rename = "predictive.background")] + pub predictive_background: Option, + + #[serde(rename = "predictive.border")] + pub predictive_border: Option, + + /// Represents a renamed status, such as a file that has been renamed. + #[serde(rename = "renamed")] + pub renamed: Option, + + #[serde(rename = "renamed.background")] + pub renamed_background: Option, + + #[serde(rename = "renamed.border")] + pub renamed_border: Option, + + /// Indicates a successful operation or task completion. + #[serde(rename = "success")] + pub success: Option, + + #[serde(rename = "success.background")] + pub success_background: Option, + + #[serde(rename = "success.border")] + pub success_border: Option, + + /// Indicates some kind of unreachable status, like a block of code that can never be reached. + #[serde(rename = "unreachable")] + pub unreachable: Option, + + #[serde(rename = "unreachable.background")] + pub unreachable_background: Option, + + #[serde(rename = "unreachable.border")] + pub unreachable_border: Option, + + /// Represents a warning status, like an operation that is about to fail. + #[serde(rename = "warning")] + pub warning: Option, + + #[serde(rename = "warning.background")] + pub warning_background: Option, + + #[serde(rename = "warning.border")] + pub warning_border: Option, +} + +/// The background appearance of the window. +#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum WindowBackgroundContent { + Opaque, + Transparent, + Blurred, +} + +#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq)] +#[serde(rename_all = "snake_case")] +pub enum FontStyleContent { + Normal, + Italic, + Oblique, +} + +#[derive(Debug, Clone, Copy, Serialize_repr, Deserialize_repr, JsonSchema_repr, PartialEq)] +#[repr(u16)] +pub enum FontWeightContent { + Thin = 100, + ExtraLight = 200, + Light = 300, + Normal = 400, + Medium = 500, + Semibold = 600, + Bold = 700, + ExtraBold = 800, + Black = 900, +} diff --git a/crates/settings/src/settings_store.rs b/crates/settings/src/settings_store.rs index 551a3fb31bceb7e924e6685dd51016dae4c00593..e78c341bd7e3b337f1690cd637271e296028b025 100644 --- a/crates/settings/src/settings_store.rs +++ b/crates/settings/src/settings_store.rs @@ -1398,24 +1398,14 @@ mod tests { #[gpui::test] fn test_settings_store_basic(cx: &mut App) { - let mut store = SettingsStore::new( - cx, - r#"{ - "auto_update": false, - "user": { - "name": "John Doe", - "age": 30, - "staff": false - } - }"#, - ); + let mut store = SettingsStore::new(cx, &default_settings()); store.register_setting::(cx); store.register_setting::(cx); // store.register_setting::(cx); assert_eq!( store.get::(None), - &AutoUpdateSetting { auto_update: false } + &AutoUpdateSetting { auto_update: true } ); // assert_eq!( // store.get::(None), @@ -1436,9 +1426,7 @@ mod tests { store .set_user_settings( r#"{ - "auto_update": true, - "user": { "age": 31 }, - "key1": "a" + "auto_update": false, }"#, cx, ) @@ -1446,7 +1434,7 @@ mod tests { assert_eq!( store.get::(None), - &AutoUpdateSetting { auto_update: true } + &AutoUpdateSetting { auto_update: false } ); // assert_eq!( // store.get::(None), diff --git a/crates/theme/src/schema.rs b/crates/theme/src/schema.rs index d2bdbb616a5b6f65f905375769e14dd2a2312ea9..2e8445a7917aa52f8c99d7356bcc5d7623d8faa9 100644 --- a/crates/theme/src/schema.rs +++ b/crates/theme/src/schema.rs @@ -148,508 +148,19 @@ impl ThemeStyleContent { } } -#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema, PartialEq)] -#[serde(default)] -pub struct ThemeColorsContent { - /// Border color. Used for most borders, is usually a high contrast color. - #[serde(rename = "border")] - pub border: Option, - - /// Border color. Used for deemphasized borders, like a visual divider between two sections - #[serde(rename = "border.variant")] - pub border_variant: Option, - - /// Border color. Used for focused elements, like keyboard focused list item. - #[serde(rename = "border.focused")] - pub border_focused: Option, - - /// Border color. Used for selected elements, like an active search filter or selected checkbox. - #[serde(rename = "border.selected")] - pub border_selected: Option, - - /// Border color. Used for transparent borders. Used for placeholder borders when an element gains a border on state change. - #[serde(rename = "border.transparent")] - pub border_transparent: Option, - - /// Border color. Used for disabled elements, like a disabled input or button. - #[serde(rename = "border.disabled")] - pub border_disabled: Option, - - /// Background color. Used for elevated surfaces, like a context menu, popup, or dialog. - #[serde(rename = "elevated_surface.background")] - pub elevated_surface_background: Option, - - /// Background Color. Used for grounded surfaces like a panel or tab. - #[serde(rename = "surface.background")] - pub surface_background: Option, - - /// Background Color. Used for the app background and blank panels or windows. - #[serde(rename = "background")] - pub background: Option, - - /// Background Color. Used for the background of an element that should have a different background than the surface it's on. - /// - /// Elements might include: Buttons, Inputs, Checkboxes, Radio Buttons... - /// - /// For an element that should have the same background as the surface it's on, use `ghost_element_background`. - #[serde(rename = "element.background")] - pub element_background: Option, - - /// Background Color. Used for the hover state of an element that should have a different background than the surface it's on. - /// - /// Hover states are triggered by the mouse entering an element, or a finger touching an element on a touch screen. - #[serde(rename = "element.hover")] - pub element_hover: Option, - - /// Background Color. Used for the active state of an element that should have a different background than the surface it's on. - /// - /// Active states are triggered by the mouse button being pressed down on an element, or the Return button or other activator being pressed. - #[serde(rename = "element.active")] - pub element_active: Option, - - /// Background Color. Used for the selected state of an element that should have a different background than the surface it's on. - /// - /// Selected states are triggered by the element being selected (or "activated") by the user. - /// - /// This could include a selected checkbox, a toggleable button that is toggled on, etc. - #[serde(rename = "element.selected")] - pub element_selected: Option, - - /// Background Color. Used for the disabled state of an element that should have a different background than the surface it's on. - /// - /// Disabled states are shown when a user cannot interact with an element, like a disabled button or input. - #[serde(rename = "element.disabled")] - pub element_disabled: Option, - - /// Background Color. Used for the background of selections in a UI element. - #[serde(rename = "element.selection_background")] - pub element_selection_background: Option, - - /// Background Color. Used for the area that shows where a dragged element will be dropped. - #[serde(rename = "drop_target.background")] - pub drop_target_background: Option, - - /// Border Color. Used for the border that shows where a dragged element will be dropped. - #[serde(rename = "drop_target.border")] - pub drop_target_border: Option, - - /// Used for the background of a ghost element that should have the same background as the surface it's on. - /// - /// Elements might include: Buttons, Inputs, Checkboxes, Radio Buttons... - /// - /// For an element that should have a different background than the surface it's on, use `element_background`. - #[serde(rename = "ghost_element.background")] - pub ghost_element_background: Option, - - /// Background Color. Used for the hover state of a ghost element that should have the same background as the surface it's on. - /// - /// Hover states are triggered by the mouse entering an element, or a finger touching an element on a touch screen. - #[serde(rename = "ghost_element.hover")] - pub ghost_element_hover: Option, - - /// Background Color. Used for the active state of a ghost element that should have the same background as the surface it's on. - /// - /// Active states are triggered by the mouse button being pressed down on an element, or the Return button or other activator being pressed. - #[serde(rename = "ghost_element.active")] - pub ghost_element_active: Option, - - /// Background Color. Used for the selected state of a ghost element that should have the same background as the surface it's on. - /// - /// Selected states are triggered by the element being selected (or "activated") by the user. - /// - /// This could include a selected checkbox, a toggleable button that is toggled on, etc. - #[serde(rename = "ghost_element.selected")] - pub ghost_element_selected: Option, - - /// Background Color. Used for the disabled state of a ghost element that should have the same background as the surface it's on. - /// - /// Disabled states are shown when a user cannot interact with an element, like a disabled button or input. - #[serde(rename = "ghost_element.disabled")] - pub ghost_element_disabled: Option, - - /// Text Color. Default text color used for most text. - #[serde(rename = "text")] - pub text: Option, - - /// Text Color. Color of muted or deemphasized text. It is a subdued version of the standard text color. - #[serde(rename = "text.muted")] - pub text_muted: Option, - - /// Text Color. Color of the placeholder text typically shown in input fields to guide the user to enter valid data. - #[serde(rename = "text.placeholder")] - pub text_placeholder: Option, - - /// Text Color. Color used for text denoting disabled elements. Typically, the color is faded or grayed out to emphasize the disabled state. - #[serde(rename = "text.disabled")] - pub text_disabled: Option, - - /// Text Color. Color used for emphasis or highlighting certain text, like an active filter or a matched character in a search. - #[serde(rename = "text.accent")] - pub text_accent: Option, - - /// Fill Color. Used for the default fill color of an icon. - #[serde(rename = "icon")] - pub icon: Option, - - /// Fill Color. Used for the muted or deemphasized fill color of an icon. - /// - /// This might be used to show an icon in an inactive pane, or to deemphasize a series of icons to give them less visual weight. - #[serde(rename = "icon.muted")] - pub icon_muted: Option, - - /// Fill Color. Used for the disabled fill color of an icon. - /// - /// Disabled states are shown when a user cannot interact with an element, like a icon button. - #[serde(rename = "icon.disabled")] - pub icon_disabled: Option, - - /// Fill Color. Used for the placeholder fill color of an icon. - /// - /// This might be used to show an icon in an input that disappears when the user enters text. - #[serde(rename = "icon.placeholder")] - pub icon_placeholder: Option, - - /// Fill Color. Used for the accent fill color of an icon. - /// - /// This might be used to show when a toggleable icon button is selected. - #[serde(rename = "icon.accent")] - pub icon_accent: Option, - - /// Color used to accent some of the debuggers elements - /// Only accent breakpoint & breakpoint related symbols right now - #[serde(rename = "debugger.accent")] - pub debugger_accent: Option, - - #[serde(rename = "status_bar.background")] - pub status_bar_background: Option, - - #[serde(rename = "title_bar.background")] - pub title_bar_background: Option, - - #[serde(rename = "title_bar.inactive_background")] - pub title_bar_inactive_background: Option, - - #[serde(rename = "toolbar.background")] - pub toolbar_background: Option, - - #[serde(rename = "tab_bar.background")] - pub tab_bar_background: Option, - - #[serde(rename = "tab.inactive_background")] - pub tab_inactive_background: Option, - - #[serde(rename = "tab.active_background")] - pub tab_active_background: Option, - - #[serde(rename = "search.match_background")] - pub search_match_background: Option, - - #[serde(rename = "panel.background")] - pub panel_background: Option, - - #[serde(rename = "panel.focused_border")] - pub panel_focused_border: Option, - - #[serde(rename = "panel.indent_guide")] - pub panel_indent_guide: Option, - - #[serde(rename = "panel.indent_guide_hover")] - pub panel_indent_guide_hover: Option, - - #[serde(rename = "panel.indent_guide_active")] - pub panel_indent_guide_active: Option, - - #[serde(rename = "panel.overlay_background")] - pub panel_overlay_background: Option, - - #[serde(rename = "panel.overlay_hover")] - pub panel_overlay_hover: Option, - - #[serde(rename = "pane.focused_border")] - pub pane_focused_border: Option, - - #[serde(rename = "pane_group.border")] - pub pane_group_border: Option, - - /// The deprecated version of `scrollbar.thumb.background`. - /// - /// Don't use this field. - #[serde(rename = "scrollbar_thumb.background", skip_serializing)] - #[schemars(skip)] - pub deprecated_scrollbar_thumb_background: Option, - - /// The color of the scrollbar thumb. - #[serde(rename = "scrollbar.thumb.background")] - pub scrollbar_thumb_background: Option, - - /// The color of the scrollbar thumb when hovered over. - #[serde(rename = "scrollbar.thumb.hover_background")] - pub scrollbar_thumb_hover_background: Option, - - /// The color of the scrollbar thumb whilst being actively dragged. - #[serde(rename = "scrollbar.thumb.active_background")] - pub scrollbar_thumb_active_background: Option, - - /// The border color of the scrollbar thumb. - #[serde(rename = "scrollbar.thumb.border")] - pub scrollbar_thumb_border: Option, - - /// The background color of the scrollbar track. - #[serde(rename = "scrollbar.track.background")] - pub scrollbar_track_background: Option, - - /// The border color of the scrollbar track. - #[serde(rename = "scrollbar.track.border")] - pub scrollbar_track_border: Option, - - /// The color of the minimap thumb. - #[serde(rename = "minimap.thumb.background")] - pub minimap_thumb_background: Option, - - /// The color of the minimap thumb when hovered over. - #[serde(rename = "minimap.thumb.hover_background")] - pub minimap_thumb_hover_background: Option, - - /// The color of the minimap thumb whilst being actively dragged. - #[serde(rename = "minimap.thumb.active_background")] - pub minimap_thumb_active_background: Option, - - /// The border color of the minimap thumb. - #[serde(rename = "minimap.thumb.border")] - pub minimap_thumb_border: Option, - - #[serde(rename = "editor.foreground")] - pub editor_foreground: Option, - - #[serde(rename = "editor.background")] - pub editor_background: Option, - - #[serde(rename = "editor.gutter.background")] - pub editor_gutter_background: Option, - - #[serde(rename = "editor.subheader.background")] - pub editor_subheader_background: Option, - - #[serde(rename = "editor.active_line.background")] - pub editor_active_line_background: Option, - - #[serde(rename = "editor.highlighted_line.background")] - pub editor_highlighted_line_background: Option, - - /// Background of active line of debugger - #[serde(rename = "editor.debugger_active_line.background")] - pub editor_debugger_active_line_background: Option, - - /// Text Color. Used for the text of the line number in the editor gutter. - #[serde(rename = "editor.line_number")] - pub editor_line_number: Option, - - /// Text Color. Used for the text of the line number in the editor gutter when the line is highlighted. - #[serde(rename = "editor.active_line_number")] - pub editor_active_line_number: Option, - - /// Text Color. Used for the text of the line number in the editor gutter when the line is hovered over. - #[serde(rename = "editor.hover_line_number")] - pub editor_hover_line_number: Option, - - /// Text Color. Used to mark invisible characters in the editor. - /// - /// Example: spaces, tabs, carriage returns, etc. - #[serde(rename = "editor.invisible")] - pub editor_invisible: Option, - - #[serde(rename = "editor.wrap_guide")] - pub editor_wrap_guide: Option, - - #[serde(rename = "editor.active_wrap_guide")] - pub editor_active_wrap_guide: Option, - - #[serde(rename = "editor.indent_guide")] - pub editor_indent_guide: Option, - - #[serde(rename = "editor.indent_guide_active")] - pub editor_indent_guide_active: Option, - - /// Read-access of a symbol, like reading a variable. - /// - /// A document highlight is a range inside a text document which deserves - /// special attention. Usually a document highlight is visualized by changing - /// the background color of its range. - #[serde(rename = "editor.document_highlight.read_background")] - pub editor_document_highlight_read_background: Option, - - /// Read-access of a symbol, like reading a variable. - /// - /// A document highlight is a range inside a text document which deserves - /// special attention. Usually a document highlight is visualized by changing - /// the background color of its range. - #[serde(rename = "editor.document_highlight.write_background")] - pub editor_document_highlight_write_background: Option, - - /// Highlighted brackets background color. - /// - /// Matching brackets in the cursor scope are highlighted with this background color. - #[serde(rename = "editor.document_highlight.bracket_background")] - pub editor_document_highlight_bracket_background: Option, - - /// Terminal background color. - #[serde(rename = "terminal.background")] - pub terminal_background: Option, - - /// Terminal foreground color. - #[serde(rename = "terminal.foreground")] - pub terminal_foreground: Option, - - /// Terminal ANSI background color. - #[serde(rename = "terminal.ansi.background")] - pub terminal_ansi_background: Option, - - /// Bright terminal foreground color. - #[serde(rename = "terminal.bright_foreground")] - pub terminal_bright_foreground: Option, - - /// Dim terminal foreground color. - #[serde(rename = "terminal.dim_foreground")] - pub terminal_dim_foreground: Option, - - /// Black ANSI terminal color. - #[serde(rename = "terminal.ansi.black")] - pub terminal_ansi_black: Option, - - /// Bright black ANSI terminal color. - #[serde(rename = "terminal.ansi.bright_black")] - pub terminal_ansi_bright_black: Option, - - /// Dim black ANSI terminal color. - #[serde(rename = "terminal.ansi.dim_black")] - pub terminal_ansi_dim_black: Option, - - /// Red ANSI terminal color. - #[serde(rename = "terminal.ansi.red")] - pub terminal_ansi_red: Option, - - /// Bright red ANSI terminal color. - #[serde(rename = "terminal.ansi.bright_red")] - pub terminal_ansi_bright_red: Option, - - /// Dim red ANSI terminal color. - #[serde(rename = "terminal.ansi.dim_red")] - pub terminal_ansi_dim_red: Option, - - /// Green ANSI terminal color. - #[serde(rename = "terminal.ansi.green")] - pub terminal_ansi_green: Option, - - /// Bright green ANSI terminal color. - #[serde(rename = "terminal.ansi.bright_green")] - pub terminal_ansi_bright_green: Option, - - /// Dim green ANSI terminal color. - #[serde(rename = "terminal.ansi.dim_green")] - pub terminal_ansi_dim_green: Option, - - /// Yellow ANSI terminal color. - #[serde(rename = "terminal.ansi.yellow")] - pub terminal_ansi_yellow: Option, - - /// Bright yellow ANSI terminal color. - #[serde(rename = "terminal.ansi.bright_yellow")] - pub terminal_ansi_bright_yellow: Option, - - /// Dim yellow ANSI terminal color. - #[serde(rename = "terminal.ansi.dim_yellow")] - pub terminal_ansi_dim_yellow: Option, - - /// Blue ANSI terminal color. - #[serde(rename = "terminal.ansi.blue")] - pub terminal_ansi_blue: Option, - - /// Bright blue ANSI terminal color. - #[serde(rename = "terminal.ansi.bright_blue")] - pub terminal_ansi_bright_blue: Option, - - /// Dim blue ANSI terminal color. - #[serde(rename = "terminal.ansi.dim_blue")] - pub terminal_ansi_dim_blue: Option, - - /// Magenta ANSI terminal color. - #[serde(rename = "terminal.ansi.magenta")] - pub terminal_ansi_magenta: Option, - - /// Bright magenta ANSI terminal color. - #[serde(rename = "terminal.ansi.bright_magenta")] - pub terminal_ansi_bright_magenta: Option, - - /// Dim magenta ANSI terminal color. - #[serde(rename = "terminal.ansi.dim_magenta")] - pub terminal_ansi_dim_magenta: Option, - - /// Cyan ANSI terminal color. - #[serde(rename = "terminal.ansi.cyan")] - pub terminal_ansi_cyan: Option, - - /// Bright cyan ANSI terminal color. - #[serde(rename = "terminal.ansi.bright_cyan")] - pub terminal_ansi_bright_cyan: Option, - - /// Dim cyan ANSI terminal color. - #[serde(rename = "terminal.ansi.dim_cyan")] - pub terminal_ansi_dim_cyan: Option, - - /// White ANSI terminal color. - #[serde(rename = "terminal.ansi.white")] - pub terminal_ansi_white: Option, - - /// Bright white ANSI terminal color. - #[serde(rename = "terminal.ansi.bright_white")] - pub terminal_ansi_bright_white: Option, - - /// Dim white ANSI terminal color. - #[serde(rename = "terminal.ansi.dim_white")] - pub terminal_ansi_dim_white: Option, - - #[serde(rename = "link_text.hover")] - pub link_text_hover: Option, - - /// Added version control color. - #[serde(rename = "version_control.added")] - pub version_control_added: Option, - - /// Deleted version control color. - #[serde(rename = "version_control.deleted")] - pub version_control_deleted: Option, - - /// Modified version control color. - #[serde(rename = "version_control.modified")] - pub version_control_modified: Option, - - /// Renamed version control color. - #[serde(rename = "version_control.renamed")] - pub version_control_renamed: Option, - - /// Conflict version control color. - #[serde(rename = "version_control.conflict")] - pub version_control_conflict: Option, - - /// Ignored version control color. - #[serde(rename = "version_control.ignored")] - pub version_control_ignored: Option, - - /// Background color for row highlights of "ours" regions in merge conflicts. - #[serde(rename = "version_control.conflict_marker.ours")] - pub version_control_conflict_marker_ours: Option, - - /// Background color for row highlights of "theirs" regions in merge conflicts. - #[serde(rename = "version_control.conflict_marker.theirs")] - pub version_control_conflict_marker_theirs: Option, +pub(crate) fn try_parse_color(color: &str) -> Result { + let rgba = gpui::Rgba::try_from(color)?; + let rgba = palette::rgb::Srgba::from_components((rgba.r, rgba.g, rgba.b, rgba.a)); + let hsla = palette::Hsla::from_color(rgba); - /// Deprecated in favor of `version_control_conflict_marker_ours`. - #[deprecated] - pub version_control_conflict_ours_background: Option, + let hsla = gpui::hsla( + hsla.hue.into_positive_degrees() / 360., + hsla.saturation, + hsla.lightness, + hsla.alpha, + ); - /// Deprecated in favor of `version_control_conflict_marker_theirs`. - #[deprecated] - pub version_control_conflict_theirs_background: Option, + Ok(hsla) } impl ThemeColorsContent { @@ -1547,36 +1058,3 @@ impl From for FontWeight { } } } - -#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema, PartialEq)] -#[serde(default)] -pub struct HighlightStyleContent { - pub color: Option, - - #[serde(deserialize_with = "treat_error_as_none")] - pub background_color: Option, - - #[serde(deserialize_with = "treat_error_as_none")] - pub font_style: Option, - - #[serde(deserialize_with = "treat_error_as_none")] - pub font_weight: Option, -} - -impl HighlightStyleContent { - pub fn is_empty(&self) -> bool { - self.color.is_none() - && self.background_color.is_none() - && self.font_style.is_none() - && self.font_weight.is_none() - } -} - -fn treat_error_as_none<'de, T, D>(deserializer: D) -> Result, D::Error> -where - T: Deserialize<'de>, - D: Deserializer<'de>, -{ - let value: Value = Deserialize::deserialize(deserializer)?; - Ok(T::deserialize(value).ok()) -}