project_settings.rs

  1use collections::HashMap;
  2use gpui::AppContext;
  3use schemars::JsonSchema;
  4use serde::{Deserialize, Serialize};
  5use settings::{Settings, SettingsSources};
  6use std::{sync::Arc, time::Duration};
  7
  8#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
  9pub struct ProjectSettings {
 10    /// Configuration for language servers.
 11    ///
 12    /// The following settings can be overridden for specific language servers:
 13    /// - initialization_options
 14    /// To override settings for a language, add an entry for that language server's
 15    /// name to the lsp value.
 16    /// Default: null
 17    #[serde(default)]
 18    pub lsp: HashMap<Arc<str>, LspSettings>,
 19
 20    /// Configuration for Git-related features
 21    #[serde(default)]
 22    pub git: GitSettings,
 23
 24    /// Configuration for how direnv configuration should be loaded
 25    #[serde(default)]
 26    pub load_direnv: DirenvSettings,
 27}
 28
 29#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
 30#[serde(rename_all = "snake_case")]
 31pub enum DirenvSettings {
 32    /// Load direnv configuration through a shell hook
 33    #[default]
 34    ShellHook,
 35    /// Load direnv configuration directly using `direnv export json`
 36    ///
 37    /// Warning: This option is experimental and might cause some inconsistent behaviour compared to using the shell hook.
 38    /// If it does, please report it to GitHub
 39    Direct,
 40}
 41
 42#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
 43pub struct GitSettings {
 44    /// Whether or not to show the git gutter.
 45    ///
 46    /// Default: tracked_files
 47    pub git_gutter: Option<GitGutterSetting>,
 48    pub gutter_debounce: Option<u64>,
 49    /// Whether or not to show git blame data inline in
 50    /// the currently focused line.
 51    ///
 52    /// Default: on
 53    pub inline_blame: Option<InlineBlameSettings>,
 54}
 55
 56impl GitSettings {
 57    pub fn inline_blame_enabled(&self) -> bool {
 58        #[allow(unknown_lints, clippy::manual_unwrap_or_default)]
 59        match self.inline_blame {
 60            Some(InlineBlameSettings { enabled, .. }) => enabled,
 61            _ => false,
 62        }
 63    }
 64
 65    pub fn inline_blame_delay(&self) -> Option<Duration> {
 66        match self.inline_blame {
 67            Some(InlineBlameSettings {
 68                delay_ms: Some(delay_ms),
 69                ..
 70            }) if delay_ms > 0 => Some(Duration::from_millis(delay_ms)),
 71            _ => None,
 72        }
 73    }
 74}
 75
 76#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, JsonSchema)]
 77#[serde(rename_all = "snake_case")]
 78pub enum GitGutterSetting {
 79    /// Show git gutter in tracked files.
 80    #[default]
 81    TrackedFiles,
 82    /// Hide git gutter
 83    Hide,
 84}
 85
 86#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, JsonSchema)]
 87#[serde(rename_all = "snake_case")]
 88pub struct InlineBlameSettings {
 89    /// Whether or not to show git blame data inline in
 90    /// the currently focused line.
 91    ///
 92    /// Default: true
 93    #[serde(default = "true_value")]
 94    pub enabled: bool,
 95    /// Whether to only show the inline blame information
 96    /// after a delay once the cursor stops moving.
 97    ///
 98    /// Default: 0
 99    pub delay_ms: Option<u64>,
100    /// The minimum column number to show the inline blame information at
101    ///
102    /// Default: 0
103    pub min_column: Option<u32>,
104}
105
106const fn true_value() -> bool {
107    true
108}
109
110#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
111pub struct BinarySettings {
112    pub path: Option<String>,
113    pub arguments: Option<Vec<String>>,
114    pub path_lookup: Option<bool>,
115}
116
117#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
118#[serde(rename_all = "snake_case")]
119pub struct LspSettings {
120    pub binary: Option<BinarySettings>,
121    pub initialization_options: Option<serde_json::Value>,
122    pub settings: Option<serde_json::Value>,
123}
124
125impl Settings for ProjectSettings {
126    const KEY: Option<&'static str> = None;
127
128    type FileContent = Self;
129
130    fn load(
131        sources: SettingsSources<Self::FileContent>,
132        _: &mut AppContext,
133    ) -> anyhow::Result<Self> {
134        sources.json_merge()
135    }
136}