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