use anyhow::Context as _;use collections::HashMap;use context_server::ContextServerCommand;use dap::adapters::DebugAdapterName;use fs::Fs;use futures::StreamExt as _;use git::repository::DEFAULT_WORKTREE_DIRECTORY;use gpui::{AsyncApp, BorrowAppContext, Context, Entity, EventEmitter, Subscription, Task};use lsp::{DEFAULT_LSP_REQUEST_TIMEOUT_SECS, LanguageServerName};use paths::{ EDITORCONFIG_NAME, local_debug_file_relative_path, local_settings_file_relative_path, local_tasks_file_relative_path, local_vscode_launch_file_relative_path, local_vscode_tasks_file_relative_path, task_file_name,};use rpc::{ AnyProtoClient, TypedEnvelope, proto::{self, REMOTE_SERVER_PROJECT_ID},};use schemars::JsonSchema;use serde::{Deserialize, Serialize};pub use settings::BinarySettings;pub use settings::DirenvSettings;pub use settings::LspSettings;use settings::{ DapSettingsContent, EditorconfigEvent, InvalidSettingsError, LocalSettingsKind, LocalSettingsPath, RegisterSetting, SemanticTokenRules, Settings, SettingsLocation, SettingsStore, parse_json_with_comments, watch_config_file,};use std::{cell::OnceCell, collections::BTreeMap, path::PathBuf, sync::Arc, time::Duration};use task::{DebugTaskFile, TaskTemplates, VsCodeDebugTaskFile, VsCodeTaskFile};use util::{ResultExt, rel_path::RelPath, serde::default_true};use worktree::{PathChange, UpdatedEntriesSet, Worktree, WorktreeId}; use crate::{ task_store::{TaskSettingsLocation, TaskStore}, trusted_worktrees::{PathTrust, TrustedWorktrees, TrustedWorktreesEvent}, worktree_store::{WorktreeStore, WorktreeStoreEvent},}; #[derive(Debug, Clone, RegisterSetting)]pub struct ProjectSettings { /// Configuration for language servers. /// /// The following settings can be overridden for specific language servers: /// - initialization_options /// /// To override settings for a language, add an entry for that language server's /// name to the lsp value. /// Default: null // todo(settings-follow-up) // We should change to use a non content type (settings::LspSettings is a content type) // Note: Will either require merging with defaults, which also requires deciding where the defaults come from, // or case by case deciding which fields are optional and which are actually required. pub lsp: HashMap<LanguageServerName, settings::LspSettings>, /// Common language server settings. pub global_lsp_settings: GlobalLspSettings, /// Configuration for Debugger-related features pub dap: HashMap<DebugAdapterName, DapSettings>, /// Settings for context servers used for AI-related features. pub context_servers: HashMap<Arc<str>, ContextServerSettings>, /// Default timeout for context server requests in seconds. pub context_server_timeout: u64, /// Configuration for Diagnostics-related features. pub diagnostics: DiagnosticsSettings, /// Configuration for Git-related features pub git: GitSettings, /// Configuration for Node-related features pub node: NodeBinarySettings, /// Configuration for how direnv configuration should be loaded pub load_direnv: DirenvSettings, /// Configuration for session-related features pub session: SessionSettings,} #[derive(Copy, Clone, Debug)]pub struct SessionSettings { /// Whether or not to restore unsaved buffers on restart. /// /// If this is true, user won't be prompted whether to save/discard /// dirty files when closing the application. /// /// Default: true pub restore_unsaved_buffers: bool, /// Whether or not to skip worktree trust checks. /// When trusted, project settings are synchronized automatically, /// language and MCP servers are downloaded and started automatically. /// /// Default: false pub trust_all_worktrees: bool,} #[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize, JsonSchema)]pub struct NodeBinarySettings { /// The path to the Node binary. pub path: Option<String>, /// The path to the npm binary Zed should use (defaults to `.path/../npm`). pub npm_path: Option<String>, /// If enabled, Zed will download its own copy of Node. pub ignore_system_version: bool,} impl From<settings::NodeBinarySettings> for NodeBinarySettings { fn from(settings: settings::NodeBinarySettings) -> Self { Self { path: settings.path, npm_path: settings.npm_path, ignore_system_version: settings.ignore_system_version.unwrap_or(false), } }} /// Common language server settings.#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]#[serde(default)]pub struct GlobalLspSettings { /// Whether to show the LSP servers button in the status bar. /// /// Default: `true` pub button: bool, /// The maximum amount of time to wait for responses from language servers, in seconds. /// A value of `0` will result in no timeout being applied (causing all LSP responses to wait /// indefinitely until completed). /// This should not be used outside of serialization/de-serialization in favor of get_request_timeout. /// /// Default: `120` pub request_timeout: u64, /// The maximum line length a buffer may contain before language server features are disabled for the entire buffer. /// /// Default: `20000` pub max_buffer_line_length: u32, pub notifications: LspNotificationSettings, /// Rules for highlighting semantic tokens. pub semantic_token_rules: SemanticTokenRules,} impl Default for GlobalLspSettings { fn default() -> Self { Self { button: true, request_timeout: DEFAULT_LSP_REQUEST_TIMEOUT_SECS, max_buffer_line_length: 20_000, notifications: LspNotificationSettings::default(), semantic_token_rules: SemanticTokenRules::default(), } }} impl GlobalLspSettings { /// Returns the timeout duration for LSP-related interactions, or Duration::ZERO if no timeout should be applied. /// Zero durations are treated as no timeout by language servers, so code using this in an async context can /// simply call unwrap_or_default. pub const fn get_request_timeout(&self) -> Duration { Duration::from_secs(self.request_timeout) }} #[derive(Deserialize, Serialize, Clone, PartialEq, Eq, JsonSchema, Debug)]#[serde(tag = "source", rename_all = "snake_case")]pub struct LspNotificationSettings { /// Timeout in milliseconds for automatically dismissing language server notifications. /// Set to 0 to disable auto-dismiss. /// /// Default: 5000 pub dismiss_timeout_ms: Option<u64>,} impl Default for LspNotificationSettings { fn default() -> Self { Self { dismiss_timeout_ms: Some(5000), } }} #[derive(Deserialize, Serialize, Clone, PartialEq, Eq, JsonSchema, Debug)]#[serde(tag = "source", rename_all = "snake_case")]pub enum ContextServerSettings { Stdio { /// Whether the context server is enabled. #[serde(default = "default_true")] enabled: bool, /// If true, run this server on the remote server when using remote development. #[serde(default)] remote: bool, #[serde(flatten)] command: ContextServerCommand, }, Http { /// Whether the context server is enabled. #[serde(default = "default_true")] enabled: bool, /// The URL of the remote context server. url: String, /// Optional authentication configuration for the remote server. #[serde(skip_serializing_if = "HashMap::is_empty", default)] headers: HashMap<String, String>, /// Timeout for tool calls in milliseconds. timeout: Option<u64>, /// Pre-registered OAuth client credentials for authorization servers that /// require out-of-band client registration. #[serde(default, skip_serializing_if = "Option::is_none")] oauth: Option<OAuthClientSettings>, }, Extension { /// Whether the context server is enabled. #[serde(default = "default_true")] enabled: bool, /// If true, run this server on the remote server when using remote development. #[serde(default)] remote: bool, /// The settings for this context server specified by the extension. /// /// Consult the documentation for the context server to see what settings /// are supported. settings: serde_json::Value, },} impl From<settings::ContextServerSettingsContent> for ContextServerSettings { fn from(value: settings::ContextServerSettingsContent) -> Self { match value { settings::ContextServerSettingsContent::Stdio { enabled, remote, command, } => ContextServerSettings::Stdio { enabled, remote, command, }, settings::ContextServerSettingsContent::Extension { enabled, remote, settings, } => ContextServerSettings::Extension { enabled, remote, settings, }, settings::ContextServerSettingsContent::Http { enabled, url, headers, timeout, oauth, } => ContextServerSettings::Http { enabled, url, headers, timeout, oauth: oauth.map(|o| OAuthClientSettings { client_id: o.client_id, client_secret: o.client_secret, }), }, } }}impl Into<settings::ContextServerSettingsContent> for ContextServerSettings { fn into(self) -> settings::ContextServerSettingsContent { match self { ContextServerSettings::Stdio { enabled, remote, command, } => settings::ContextServerSettingsContent::Stdio { enabled, remote, command, }, ContextServerSettings::Extension { enabled, remote, settings, } => settings::ContextServerSettingsContent::Extension { enabled, remote, settings, }, ContextServerSettings::Http { enabled, url, headers, timeout, oauth, } => settings::ContextServerSettingsContent::Http { enabled, url, headers, timeout, oauth: oauth.map(|o| settings::OAuthClientSettings { client_id: o.client_id, client_secret: o.client_secret, }), }, } }} /// Pre-registered OAuth client credentials for MCP servers that don't support/// Dynamic Client Registration.#[derive(Deserialize, Serialize, Clone, PartialEq, Eq, JsonSchema, Debug)]pub struct OAuthClientSettings { /// The OAuth client ID obtained from out-of-band registration with the /// authorization server. pub client_id: String, /// The OAuth client secret, if this is a confidential client. For security, /// prefer providing this interactively; we will prompt and store it in /// the system keychain. #[serde(default, skip_serializing_if = "Option::is_none")] pub client_secret: Option<String>,} impl ContextServerSettings { pub fn default_extension() -> Self { Self::Extension { enabled: true, remote: false, settings: serde_json::json!({}), } } pub fn enabled(&self) -> bool { match self { ContextServerSettings::Stdio { enabled, .. } => *enabled, ContextServerSettings::Http { enabled, .. } => *enabled, ContextServerSettings::Extension { enabled, .. } => *enabled, } } pub fn set_enabled(&mut self, enabled: bool) { match self { ContextServerSettings::Stdio { enabled: e, .. } => *e = enabled, ContextServerSettings::Http { enabled: e, .. } => *e = enabled, ContextServerSettings::Extension { enabled: e, .. } => *e = enabled, } }} #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]pub enum DiagnosticSeverity { // No diagnostics are shown. Off, Error, Warning, Info, Hint,} impl DiagnosticSeverity { pub fn into_lsp(self) -> Option<lsp::DiagnosticSeverity> { match self { DiagnosticSeverity::Off => None, DiagnosticSeverity::Error => Some(lsp::DiagnosticSeverity::ERROR), DiagnosticSeverity::Warning => Some(lsp::DiagnosticSeverity::WARNING), DiagnosticSeverity::Info => Some(lsp::DiagnosticSeverity::INFORMATION), DiagnosticSeverity::Hint => Some(lsp::DiagnosticSeverity::HINT), } }} impl From<settings::DiagnosticSeverityContent> for DiagnosticSeverity { fn from(severity: settings::DiagnosticSeverityContent) -> Self { match severity { settings::DiagnosticSeverityContent::Off => DiagnosticSeverity::Off, settings::DiagnosticSeverityContent::Error => DiagnosticSeverity::Error, settings::DiagnosticSeverityContent::Warning => DiagnosticSeverity::Warning, settings::DiagnosticSeverityContent::Info => DiagnosticSeverity::Info, settings::DiagnosticSeverityContent::Hint => DiagnosticSeverity::Hint, settings::DiagnosticSeverityContent::All => DiagnosticSeverity::Hint, } }} /// Determines the severity of the diagnostic that should be moved to.#[derive(PartialEq, PartialOrd, Clone, Copy, Debug, Eq, Deserialize, JsonSchema)]#[serde(rename_all = "snake_case")]pub enum GoToDiagnosticSeverity { /// Errors Error = 3, /// Warnings Warning = 2, /// Information Information = 1, /// Hints Hint = 0,} impl From<lsp::DiagnosticSeverity> for GoToDiagnosticSeverity { fn from(severity: lsp::DiagnosticSeverity) -> Self { match severity { lsp::DiagnosticSeverity::ERROR => Self::Error, lsp::DiagnosticSeverity::WARNING => Self::Warning, lsp::DiagnosticSeverity::INFORMATION => Self::Information, lsp::DiagnosticSeverity::HINT => Self::Hint, _ => Self::Error, } }} impl GoToDiagnosticSeverity { pub fn min() -> Self { Self::Hint } pub fn max() -> Self { Self::Error }} /// Allows filtering diagnostics that should be moved to.#[derive(PartialEq, Clone, Copy, Debug, Deserialize, JsonSchema)]#[serde(untagged)]pub enum GoToDiagnosticSeverityFilter { /// Move to diagnostics of a specific severity. Only(GoToDiagnosticSeverity), /// Specify a range of severities to include. Range { /// Minimum severity to move to. Defaults no "error". #[serde(default = "GoToDiagnosticSeverity::min")] min: GoToDiagnosticSeverity, /// Maximum severity to move to. Defaults to "hint". #[serde(default = "GoToDiagnosticSeverity::max")] max: GoToDiagnosticSeverity, },} impl Default for GoToDiagnosticSeverityFilter { fn default() -> Self { Self::Range { min: GoToDiagnosticSeverity::min(), max: GoToDiagnosticSeverity::max(), } }} impl GoToDiagnosticSeverityFilter { pub fn matches(&self, severity: lsp::DiagnosticSeverity) -> bool { let severity: GoToDiagnosticSeverity = severity.into(); match self { Self::Only(target) => *target == severity, Self::Range { min, max } => severity >= *min && severity <= *max, } }} #[derive(Clone, Debug)]pub struct GitSettings { /// Whether or not git integration is enabled. /// /// Default: true pub enabled: GitEnabledSettings, /// Whether or not to show the git gutter. /// /// Default: tracked_files pub git_gutter: settings::GitGutterSetting, /// Sets the debounce threshold (in milliseconds) after which changes are reflected in the git gutter. /// /// Default: 0 pub gutter_debounce: u64, /// Whether or not to show git blame data inline in /// the currently focused line. /// /// Default: on pub inline_blame: InlineBlameSettings, /// Git blame settings. pub blame: BlameSettings, /// Which information to show in the branch picker. /// /// Default: on pub branch_picker: BranchPickerSettings, /// How hunks are displayed visually in the editor. /// /// Default: staged_hollow pub hunk_style: settings::GitHunkStyleSetting, /// Which base git features diff against. /// /// Default: head pub diff_base: settings::GitDiffBaseSetting, /// How file paths are displayed in the git gutter. /// /// Default: file_name_first pub path_style: GitPathStyle, /// Whether to show the stage and restore buttons on diff hunks. /// /// Default: true pub show_stage_restore_buttons: bool, /// Directory where git worktrees are created, relative to the repository /// working directory. When the resolved directory is outside the projectLines 1–500 of 1659. Load more
use anyhow::Context as _; use collections::HashMap; use context_server::ContextServerCommand; use dap::adapters::DebugAdapterName; use fs::Fs; use futures::StreamExt as _; use git::repository::DEFAULT_WORKTREE_DIRECTORY; use gpui::{AsyncApp, BorrowAppContext, Context, Entity, EventEmitter, Subscription, Task}; use lsp::{DEFAULT_LSP_REQUEST_TIMEOUT_SECS, LanguageServerName}; use paths::{ EDITORCONFIG_NAME, local_debug_file_relative_path, local_settings_file_relative_path, local_tasks_file_relative_path, local_vscode_launch_file_relative_path, local_vscode_tasks_file_relative_path, task_file_name, }; use rpc::{ AnyProtoClient, TypedEnvelope, proto::{self, REMOTE_SERVER_PROJECT_ID}, }; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; pub use settings::BinarySettings; pub use settings::DirenvSettings; pub use settings::LspSettings; use settings::{ DapSettingsContent, EditorconfigEvent, InvalidSettingsError, LocalSettingsKind, LocalSettingsPath, RegisterSetting, SemanticTokenRules, Settings, SettingsLocation, SettingsStore, parse_json_with_comments, watch_config_file, }; use std::{cell::OnceCell, collections::BTreeMap, path::PathBuf, sync::Arc, time::Duration}; use task::{DebugTaskFile, TaskTemplates, VsCodeDebugTaskFile, VsCodeTaskFile}; use util::{ResultExt, rel_path::RelPath, serde::default_true}; use worktree::{PathChange, UpdatedEntriesSet, Worktree, WorktreeId}; use crate::{ task_store::{TaskSettingsLocation, TaskStore}, trusted_worktrees::{PathTrust, TrustedWorktrees, TrustedWorktreesEvent}, worktree_store::{WorktreeStore, WorktreeStoreEvent}, }; #[derive(Debug, Clone, RegisterSetting)] pub struct ProjectSettings { /// Configuration for language servers. /// /// The following settings can be overridden for specific language servers: /// - initialization_options /// /// To override settings for a language, add an entry for that language server's /// name to the lsp value. /// Default: null // todo(settings-follow-up) // We should change to use a non content type (settings::LspSettings is a content type) // Note: Will either require merging with defaults, which also requires deciding where the defaults come from, // or case by case deciding which fields are optional and which are actually required. pub lsp: HashMap<LanguageServerName, settings::LspSettings>, /// Common language server settings. pub global_lsp_settings: GlobalLspSettings, /// Configuration for Debugger-related features pub dap: HashMap<DebugAdapterName, DapSettings>, /// Settings for context servers used for AI-related features. pub context_servers: HashMap<Arc<str>, ContextServerSettings>, /// Default timeout for context server requests in seconds. pub context_server_timeout: u64, /// Configuration for Diagnostics-related features. pub diagnostics: DiagnosticsSettings, /// Configuration for Git-related features pub git: GitSettings, /// Configuration for Node-related features pub node: NodeBinarySettings, /// Configuration for how direnv configuration should be loaded pub load_direnv: DirenvSettings, /// Configuration for session-related features pub session: SessionSettings, } #[derive(Copy, Clone, Debug)] pub struct SessionSettings { /// Whether or not to restore unsaved buffers on restart. /// /// If this is true, user won't be prompted whether to save/discard /// dirty files when closing the application. /// /// Default: true pub restore_unsaved_buffers: bool, /// Whether or not to skip worktree trust checks. /// When trusted, project settings are synchronized automatically, /// language and MCP servers are downloaded and started automatically. /// /// Default: false pub trust_all_worktrees: bool, } #[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize, JsonSchema)] pub struct NodeBinarySettings { /// The path to the Node binary. pub path: Option<String>, /// The path to the npm binary Zed should use (defaults to `.path/../npm`). pub npm_path: Option<String>, /// If enabled, Zed will download its own copy of Node. pub ignore_system_version: bool, } impl From<settings::NodeBinarySettings> for NodeBinarySettings { fn from(settings: settings::NodeBinarySettings) -> Self { Self { path: settings.path, npm_path: settings.npm_path, ignore_system_version: settings.ignore_system_version.unwrap_or(false), } } } /// Common language server settings. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)] #[serde(default)] pub struct GlobalLspSettings { /// Whether to show the LSP servers button in the status bar. /// /// Default: `true` pub button: bool, /// The maximum amount of time to wait for responses from language servers, in seconds. /// A value of `0` will result in no timeout being applied (causing all LSP responses to wait /// indefinitely until completed). /// This should not be used outside of serialization/de-serialization in favor of get_request_timeout. /// /// Default: `120` pub request_timeout: u64, /// The maximum line length a buffer may contain before language server features are disabled for the entire buffer. /// /// Default: `20000` pub max_buffer_line_length: u32, pub notifications: LspNotificationSettings, /// Rules for highlighting semantic tokens. pub semantic_token_rules: SemanticTokenRules, } impl Default for GlobalLspSettings { fn default() -> Self { Self { button: true, request_timeout: DEFAULT_LSP_REQUEST_TIMEOUT_SECS, max_buffer_line_length: 20_000, notifications: LspNotificationSettings::default(), semantic_token_rules: SemanticTokenRules::default(), } } } impl GlobalLspSettings { /// Returns the timeout duration for LSP-related interactions, or Duration::ZERO if no timeout should be applied. /// Zero durations are treated as no timeout by language servers, so code using this in an async context can /// simply call unwrap_or_default. pub const fn get_request_timeout(&self) -> Duration { Duration::from_secs(self.request_timeout) } } #[derive(Deserialize, Serialize, Clone, PartialEq, Eq, JsonSchema, Debug)] #[serde(tag = "source", rename_all = "snake_case")] pub struct LspNotificationSettings { /// Timeout in milliseconds for automatically dismissing language server notifications. /// Set to 0 to disable auto-dismiss. /// /// Default: 5000 pub dismiss_timeout_ms: Option<u64>, } impl Default for LspNotificationSettings { fn default() -> Self { Self { dismiss_timeout_ms: Some(5000), } } } #[derive(Deserialize, Serialize, Clone, PartialEq, Eq, JsonSchema, Debug)] #[serde(tag = "source", rename_all = "snake_case")] pub enum ContextServerSettings { Stdio { /// Whether the context server is enabled. #[serde(default = "default_true")] enabled: bool, /// If true, run this server on the remote server when using remote development. #[serde(default)] remote: bool, #[serde(flatten)] command: ContextServerCommand, }, Http { /// Whether the context server is enabled. #[serde(default = "default_true")] enabled: bool, /// The URL of the remote context server. url: String, /// Optional authentication configuration for the remote server. #[serde(skip_serializing_if = "HashMap::is_empty", default)] headers: HashMap<String, String>, /// Timeout for tool calls in milliseconds. timeout: Option<u64>, /// Pre-registered OAuth client credentials for authorization servers that /// require out-of-band client registration. #[serde(default, skip_serializing_if = "Option::is_none")] oauth: Option<OAuthClientSettings>, }, Extension { /// Whether the context server is enabled. #[serde(default = "default_true")] enabled: bool, /// If true, run this server on the remote server when using remote development. #[serde(default)] remote: bool, /// The settings for this context server specified by the extension. /// /// Consult the documentation for the context server to see what settings /// are supported. settings: serde_json::Value, }, } impl From<settings::ContextServerSettingsContent> for ContextServerSettings { fn from(value: settings::ContextServerSettingsContent) -> Self { match value { settings::ContextServerSettingsContent::Stdio { enabled, remote, command, } => ContextServerSettings::Stdio { enabled, remote, command, }, settings::ContextServerSettingsContent::Extension { enabled, remote, settings, } => ContextServerSettings::Extension { enabled, remote, settings, }, settings::ContextServerSettingsContent::Http { enabled, url, headers, timeout, oauth, } => ContextServerSettings::Http { enabled, url, headers, timeout, oauth: oauth.map(|o| OAuthClientSettings { client_id: o.client_id, client_secret: o.client_secret, }), }, } } } impl Into<settings::ContextServerSettingsContent> for ContextServerSettings { fn into(self) -> settings::ContextServerSettingsContent { match self { ContextServerSettings::Stdio { enabled, remote, command, } => settings::ContextServerSettingsContent::Stdio { enabled, remote, command, }, ContextServerSettings::Extension { enabled, remote, settings, } => settings::ContextServerSettingsContent::Extension { enabled, remote, settings, }, ContextServerSettings::Http { enabled, url, headers, timeout, oauth, } => settings::ContextServerSettingsContent::Http { enabled, url, headers, timeout, oauth: oauth.map(|o| settings::OAuthClientSettings { client_id: o.client_id, client_secret: o.client_secret, }), }, } } } /// Pre-registered OAuth client credentials for MCP servers that don't support /// Dynamic Client Registration. #[derive(Deserialize, Serialize, Clone, PartialEq, Eq, JsonSchema, Debug)] pub struct OAuthClientSettings { /// The OAuth client ID obtained from out-of-band registration with the /// authorization server. pub client_id: String, /// The OAuth client secret, if this is a confidential client. For security, /// prefer providing this interactively; we will prompt and store it in /// the system keychain. #[serde(default, skip_serializing_if = "Option::is_none")] pub client_secret: Option<String>, } impl ContextServerSettings { pub fn default_extension() -> Self { Self::Extension { enabled: true, remote: false, settings: serde_json::json!({}), } } pub fn enabled(&self) -> bool { match self { ContextServerSettings::Stdio { enabled, .. } => *enabled, ContextServerSettings::Http { enabled, .. } => *enabled, ContextServerSettings::Extension { enabled, .. } => *enabled, } } pub fn set_enabled(&mut self, enabled: bool) { match self { ContextServerSettings::Stdio { enabled: e, .. } => *e = enabled, ContextServerSettings::Http { enabled: e, .. } => *e = enabled, ContextServerSettings::Extension { enabled: e, .. } => *e = enabled, } } } #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)] pub enum DiagnosticSeverity { // No diagnostics are shown. Off, Error, Warning, Info, Hint, } impl DiagnosticSeverity { pub fn into_lsp(self) -> Option<lsp::DiagnosticSeverity> { match self { DiagnosticSeverity::Off => None, DiagnosticSeverity::Error => Some(lsp::DiagnosticSeverity::ERROR), DiagnosticSeverity::Warning => Some(lsp::DiagnosticSeverity::WARNING), DiagnosticSeverity::Info => Some(lsp::DiagnosticSeverity::INFORMATION), DiagnosticSeverity::Hint => Some(lsp::DiagnosticSeverity::HINT), } } } impl From<settings::DiagnosticSeverityContent> for DiagnosticSeverity { fn from(severity: settings::DiagnosticSeverityContent) -> Self { match severity { settings::DiagnosticSeverityContent::Off => DiagnosticSeverity::Off, settings::DiagnosticSeverityContent::Error => DiagnosticSeverity::Error, settings::DiagnosticSeverityContent::Warning => DiagnosticSeverity::Warning, settings::DiagnosticSeverityContent::Info => DiagnosticSeverity::Info, settings::DiagnosticSeverityContent::Hint => DiagnosticSeverity::Hint, settings::DiagnosticSeverityContent::All => DiagnosticSeverity::Hint, } } } /// Determines the severity of the diagnostic that should be moved to. #[derive(PartialEq, PartialOrd, Clone, Copy, Debug, Eq, Deserialize, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum GoToDiagnosticSeverity { /// Errors Error = 3, /// Warnings Warning = 2, /// Information Information = 1, /// Hints Hint = 0, } impl From<lsp::DiagnosticSeverity> for GoToDiagnosticSeverity { fn from(severity: lsp::DiagnosticSeverity) -> Self { match severity { lsp::DiagnosticSeverity::ERROR => Self::Error, lsp::DiagnosticSeverity::WARNING => Self::Warning, lsp::DiagnosticSeverity::INFORMATION => Self::Information, lsp::DiagnosticSeverity::HINT => Self::Hint, _ => Self::Error, } } } impl GoToDiagnosticSeverity { pub fn min() -> Self { Self::Hint } pub fn max() -> Self { Self::Error } } /// Allows filtering diagnostics that should be moved to. #[derive(PartialEq, Clone, Copy, Debug, Deserialize, JsonSchema)] #[serde(untagged)] pub enum GoToDiagnosticSeverityFilter { /// Move to diagnostics of a specific severity. Only(GoToDiagnosticSeverity), /// Specify a range of severities to include. Range { /// Minimum severity to move to. Defaults no "error". #[serde(default = "GoToDiagnosticSeverity::min")] min: GoToDiagnosticSeverity, /// Maximum severity to move to. Defaults to "hint". #[serde(default = "GoToDiagnosticSeverity::max")] max: GoToDiagnosticSeverity, }, } impl Default for GoToDiagnosticSeverityFilter { fn default() -> Self { Self::Range { min: GoToDiagnosticSeverity::min(), max: GoToDiagnosticSeverity::max(), } } } impl GoToDiagnosticSeverityFilter { pub fn matches(&self, severity: lsp::DiagnosticSeverity) -> bool { let severity: GoToDiagnosticSeverity = severity.into(); match self { Self::Only(target) => *target == severity, Self::Range { min, max } => severity >= *min && severity <= *max, } } } #[derive(Clone, Debug)] pub struct GitSettings { /// Whether or not git integration is enabled. /// /// Default: true pub enabled: GitEnabledSettings, /// Whether or not to show the git gutter. /// /// Default: tracked_files pub git_gutter: settings::GitGutterSetting, /// Sets the debounce threshold (in milliseconds) after which changes are reflected in the git gutter. /// /// Default: 0 pub gutter_debounce: u64, /// Whether or not to show git blame data inline in /// the currently focused line. /// /// Default: on pub inline_blame: InlineBlameSettings, /// Git blame settings. pub blame: BlameSettings, /// Which information to show in the branch picker. /// /// Default: on pub branch_picker: BranchPickerSettings, /// How hunks are displayed visually in the editor. /// /// Default: staged_hollow pub hunk_style: settings::GitHunkStyleSetting, /// Which base git features diff against. /// /// Default: head pub diff_base: settings::GitDiffBaseSetting, /// How file paths are displayed in the git gutter. /// /// Default: file_name_first pub path_style: GitPathStyle, /// Whether to show the stage and restore buttons on diff hunks. /// /// Default: true pub show_stage_restore_buttons: bool, /// Directory where git worktrees are created, relative to the repository /// working directory. When the resolved directory is outside the project