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    /// Configuration for session-related features
 29    #[serde(default)]
 30    pub session: SessionSettings,
 31}
 32
 33#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
 34#[serde(rename_all = "snake_case")]
 35pub enum DirenvSettings {
 36    /// Load direnv configuration through a shell hook
 37    #[default]
 38    ShellHook,
 39    /// Load direnv configuration directly using `direnv export json`
 40    ///
 41    /// Warning: This option is experimental and might cause some inconsistent behaviour compared to using the shell hook.
 42    /// If it does, please report it to GitHub
 43    Direct,
 44}
 45
 46#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
 47pub struct GitSettings {
 48    /// Whether or not to show the git gutter.
 49    ///
 50    /// Default: tracked_files
 51    pub git_gutter: Option<GitGutterSetting>,
 52    pub gutter_debounce: Option<u64>,
 53    /// Whether or not to show git blame data inline in
 54    /// the currently focused line.
 55    ///
 56    /// Default: on
 57    pub inline_blame: Option<InlineBlameSettings>,
 58}
 59
 60impl GitSettings {
 61    pub fn inline_blame_enabled(&self) -> bool {
 62        #[allow(unknown_lints, clippy::manual_unwrap_or_default)]
 63        match self.inline_blame {
 64            Some(InlineBlameSettings { enabled, .. }) => enabled,
 65            _ => false,
 66        }
 67    }
 68
 69    pub fn inline_blame_delay(&self) -> Option<Duration> {
 70        match self.inline_blame {
 71            Some(InlineBlameSettings {
 72                delay_ms: Some(delay_ms),
 73                ..
 74            }) if delay_ms > 0 => Some(Duration::from_millis(delay_ms)),
 75            _ => None,
 76        }
 77    }
 78}
 79
 80#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, JsonSchema)]
 81#[serde(rename_all = "snake_case")]
 82pub enum GitGutterSetting {
 83    /// Show git gutter in tracked files.
 84    #[default]
 85    TrackedFiles,
 86    /// Hide git gutter
 87    Hide,
 88}
 89
 90#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, JsonSchema)]
 91#[serde(rename_all = "snake_case")]
 92pub struct InlineBlameSettings {
 93    /// Whether or not to show git blame data inline in
 94    /// the currently focused line.
 95    ///
 96    /// Default: true
 97    #[serde(default = "true_value")]
 98    pub enabled: bool,
 99    /// Whether to only show the inline blame information
100    /// after a delay once the cursor stops moving.
101    ///
102    /// Default: 0
103    pub delay_ms: Option<u64>,
104    /// The minimum column number to show the inline blame information at
105    ///
106    /// Default: 0
107    pub min_column: Option<u32>,
108}
109
110const fn true_value() -> bool {
111    true
112}
113
114#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
115pub struct BinarySettings {
116    pub path: Option<String>,
117    pub arguments: Option<Vec<String>>,
118    pub path_lookup: Option<bool>,
119}
120
121#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
122#[serde(rename_all = "snake_case")]
123pub struct LspSettings {
124    pub binary: Option<BinarySettings>,
125    pub initialization_options: Option<serde_json::Value>,
126    pub settings: Option<serde_json::Value>,
127}
128
129#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema)]
130pub struct SessionSettings {
131    /// Whether or not to restore unsaved buffers on restart.
132    ///
133    /// If this is true, user won't be prompted whether to save/discard
134    /// dirty files when closing the application.
135    ///
136    /// Default: true
137    pub restore_unsaved_buffers: bool,
138}
139
140impl Default for SessionSettings {
141    fn default() -> Self {
142        Self {
143            restore_unsaved_buffers: true,
144        }
145    }
146}
147
148impl Settings for ProjectSettings {
149    const KEY: Option<&'static str> = None;
150
151    type FileContent = Self;
152
153    fn load(
154        sources: SettingsSources<Self::FileContent>,
155        _: &mut AppContext,
156    ) -> anyhow::Result<Self> {
157        sources.json_merge()
158    }
159}