terminal_settings.rs

  1use std::{collections::HashMap, path::PathBuf};
  2
  3use gpui::{fonts, AppContext};
  4use schemars::JsonSchema;
  5use serde_derive::{Deserialize, Serialize};
  6
  7#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
  8#[serde(rename_all = "snake_case")]
  9pub enum TerminalDockPosition {
 10    Left,
 11    Bottom,
 12    Right,
 13}
 14
 15#[derive(Deserialize)]
 16pub struct TerminalSettings {
 17    pub shell: Shell,
 18    pub working_directory: WorkingDirectory,
 19    font_size: Option<f32>,
 20    pub font_family: Option<String>,
 21    pub line_height: TerminalLineHeight,
 22    pub font_features: Option<fonts::Features>,
 23    pub env: HashMap<String, String>,
 24    pub blinking: TerminalBlink,
 25    pub alternate_scroll: AlternateScroll,
 26    pub option_as_meta: bool,
 27    pub copy_on_select: bool,
 28    pub dock: TerminalDockPosition,
 29    pub default_width: f32,
 30    pub default_height: f32,
 31    pub detect_venv: VenvSettings,
 32}
 33
 34#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
 35#[serde(rename_all = "snake_case")]
 36pub enum VenvSettings {
 37    #[default]
 38    Off,
 39    On {
 40        activate_script: Option<ActivateScript>,
 41        directories: Option<Vec<PathBuf>>,
 42    },
 43}
 44
 45pub struct VenvSettingsContent<'a> {
 46    pub activate_script: ActivateScript,
 47    pub directories: &'a [PathBuf],
 48}
 49
 50impl VenvSettings {
 51    pub fn as_option(&self) -> Option<VenvSettingsContent> {
 52        match self {
 53            VenvSettings::Off => None,
 54            VenvSettings::On {
 55                activate_script,
 56                directories,
 57            } => Some(VenvSettingsContent {
 58                activate_script: activate_script.unwrap_or(ActivateScript::Default),
 59                directories: directories.as_deref().unwrap_or(&[]),
 60            }),
 61        }
 62    }
 63}
 64
 65#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, JsonSchema)]
 66#[serde(rename_all = "snake_case")]
 67pub enum ActivateScript {
 68    #[default]
 69    Default,
 70    Csh,
 71    Fish,
 72}
 73
 74#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
 75pub struct TerminalSettingsContent {
 76    pub shell: Option<Shell>,
 77    pub working_directory: Option<WorkingDirectory>,
 78    pub font_size: Option<f32>,
 79    pub font_family: Option<String>,
 80    pub line_height: Option<TerminalLineHeight>,
 81    pub font_features: Option<fonts::Features>,
 82    pub env: Option<HashMap<String, String>>,
 83    pub blinking: Option<TerminalBlink>,
 84    pub alternate_scroll: Option<AlternateScroll>,
 85    pub option_as_meta: Option<bool>,
 86    pub copy_on_select: Option<bool>,
 87    pub dock: Option<TerminalDockPosition>,
 88    pub default_width: Option<f32>,
 89    pub default_height: Option<f32>,
 90    pub detect_venv: Option<VenvSettings>,
 91}
 92
 93impl TerminalSettings {
 94    pub fn font_size(&self, cx: &AppContext) -> Option<f32> {
 95        self.font_size
 96            .map(|size| theme::adjusted_font_size(size, cx))
 97    }
 98}
 99
100impl settings::Setting for TerminalSettings {
101    const KEY: Option<&'static str> = Some("terminal");
102
103    type FileContent = TerminalSettingsContent;
104
105    fn load(
106        default_value: &Self::FileContent,
107        user_values: &[&Self::FileContent],
108        _: &AppContext,
109    ) -> anyhow::Result<Self> {
110        Self::load_via_json_merge(default_value, user_values)
111    }
112}
113
114#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema, Default)]
115#[serde(rename_all = "snake_case")]
116pub enum TerminalLineHeight {
117    #[default]
118    Comfortable,
119    Standard,
120    Custom(f32),
121}
122
123impl TerminalLineHeight {
124    pub fn value(&self) -> f32 {
125        match self {
126            TerminalLineHeight::Comfortable => 1.618,
127            TerminalLineHeight::Standard => 1.3,
128            TerminalLineHeight::Custom(line_height) => f32::max(*line_height, 1.),
129        }
130    }
131}
132
133#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
134#[serde(rename_all = "snake_case")]
135pub enum TerminalBlink {
136    Off,
137    TerminalControlled,
138    On,
139}
140
141#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
142#[serde(rename_all = "snake_case")]
143pub enum Shell {
144    System,
145    Program(String),
146    WithArguments { program: String, args: Vec<String> },
147}
148
149#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
150#[serde(rename_all = "snake_case")]
151pub enum AlternateScroll {
152    On,
153    Off,
154}
155
156#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
157#[serde(rename_all = "snake_case")]
158pub enum WorkingDirectory {
159    CurrentProjectDirectory,
160    FirstProjectDirectory,
161    AlwaysHome,
162    Always { directory: String },
163}