Define terminal settings in terminal crate

Max Brunsfeld created

Change summary

Cargo.lock                                    |   1 
crates/diagnostics/src/diagnostics.rs         |   4 
crates/editor/src/editor.rs                   |   6 
crates/project/src/terminals.rs               |  22 +-
crates/settings/src/font_size.rs              |  19 ++
crates/settings/src/settings.rs               | 149 --------------------
crates/terminal/Cargo.toml                    |   2 
crates/terminal/src/terminal.rs               | 118 ++++++++++++++-
crates/terminal_view/src/terminal_element.rs  |  76 ++++------
crates/terminal_view/src/terminal_view.rs     |  44 ++----
crates/theme_testbench/src/theme_testbench.rs |   2 
crates/zed/src/main.rs                        |  12 -
crates/zed/src/zed.rs                         |  26 --
13 files changed, 205 insertions(+), 276 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -6748,6 +6748,7 @@ dependencies = [
  "ordered-float",
  "procinfo",
  "rand 0.8.5",
+ "schemars",
  "serde",
  "serde_derive",
  "settings",

crates/diagnostics/src/diagnostics.rs 🔗

@@ -682,7 +682,9 @@ fn diagnostic_header_renderer(diagnostic: Diagnostic) -> RenderBlock {
         let settings = cx.global::<Settings>();
         let theme = &settings.theme.editor;
         let style = theme.diagnostic_header.clone();
-        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
+        let font_size = (style.text_scale_factor
+            * settings::font_size_for_setting(settings.buffer_font_size, cx))
+        .round();
         let icon_width = cx.em_width * style.icon_width_factor;
         let icon = if diagnostic.severity == DiagnosticSeverity::ERROR {
             Svg::new("icons/circle_x_mark_12.svg")

crates/editor/src/editor.rs 🔗

@@ -7388,7 +7388,7 @@ fn build_style(
         let font_id = font_cache
             .select_font(font_family_id, &font_properties)
             .unwrap();
-        let font_size = settings.buffer_font_size;
+        let font_size = settings::font_size_for_setting(settings.buffer_font_size, cx);
         EditorStyle {
             text: TextStyle {
                 color: settings.theme.editor.text_color,
@@ -7561,7 +7561,9 @@ pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> Rend
         let settings = cx.global::<Settings>();
         let theme = &settings.theme.editor;
         let style = diagnostic_style(diagnostic.severity, is_valid, theme);
-        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
+        let font_size = (style.text_scale_factor
+            * settings::font_size_for_setting(settings.buffer_font_size, cx))
+        .round();
         Flex::column()
             .with_children(highlighted_lines.iter().map(|(line, highlights)| {
                 Label::new(

crates/project/src/terminals.rs 🔗

@@ -1,10 +1,7 @@
-use std::path::PathBuf;
-
-use gpui::{ModelContext, ModelHandle, WeakModelHandle};
-use settings::Settings;
-use terminal::{Terminal, TerminalBuilder};
-
 use crate::Project;
+use gpui::{ModelContext, ModelHandle, WeakModelHandle};
+use std::path::PathBuf;
+use terminal::{Terminal, TerminalBuilder, TerminalSettings};
 
 pub struct Terminals {
     pub(crate) local_handles: Vec<WeakModelHandle<terminal::Terminal>>,
@@ -22,17 +19,14 @@ impl Project {
                 "creating terminals as a guest is not supported yet"
             ));
         } else {
-            let settings = cx.global::<Settings>();
-            let shell = settings.terminal_shell();
-            let envs = settings.terminal_env();
-            let scroll = settings.terminal_scroll();
+            let settings = settings::get_setting::<TerminalSettings>(None, cx);
 
             let terminal = TerminalBuilder::new(
                 working_directory.clone(),
-                shell,
-                envs,
-                settings.terminal_overrides.blinking.clone(),
-                scroll,
+                settings.shell.clone(),
+                settings.env.clone(),
+                Some(settings.blinking.clone()),
+                settings.alternate_scroll,
                 window_id,
             )
             .map(|builder| {

crates/settings/src/font_size.rs 🔗

@@ -0,0 +1,19 @@
+use gpui::AppContext;
+
+#[derive(Default)]
+pub struct FontSizeDelta(pub f32);
+
+pub fn adjust_font_size_delta(cx: &mut AppContext, f: fn(&mut f32, cx: &mut AppContext)) {
+    cx.update_default_global::<FontSizeDelta, _, _>(|size, cx| {
+        f(&mut size.0, cx);
+    });
+    cx.refresh_windows();
+}
+
+pub fn font_size_for_setting(size: f32, cx: &AppContext) -> f32 {
+    if cx.has_global::<FontSizeDelta>() {
+        size + cx.global::<FontSizeDelta>().0
+    } else {
+        size
+    }
+}

crates/settings/src/settings.rs 🔗

@@ -1,3 +1,4 @@
+mod font_size;
 mod keymap_file;
 mod settings_file;
 mod settings_store;
@@ -22,6 +23,7 @@ use std::{borrow::Cow, collections::HashMap, num::NonZeroU32, path::Path, str, s
 use theme::{Theme, ThemeRegistry};
 use util::ResultExt as _;
 
+pub use font_size::{adjust_font_size_delta, font_size_for_setting};
 pub use keymap_file::{keymap_file_json_schema, KeymapFileContent};
 pub use settings_file::*;
 pub use settings_store::{Setting, SettingsJsonSchemaParams, SettingsStore};
@@ -35,7 +37,6 @@ pub struct Settings {
     pub buffer_font_family_name: String,
     pub buffer_font_features: fonts::Features,
     pub buffer_font_family: FamilyId,
-    pub default_buffer_font_size: f32,
     pub buffer_font_size: f32,
     pub active_pane_magnification: f32,
     pub cursor_blink: bool,
@@ -50,8 +51,6 @@ pub struct Settings {
     pub git: GitSettings,
     pub git_overrides: GitSettings,
     pub copilot: CopilotSettings,
-    pub terminal_defaults: TerminalSettings,
-    pub terminal_overrides: TerminalSettings,
     pub language_defaults: HashMap<Arc<str>, EditorSettings>,
     pub language_overrides: HashMap<Arc<str>, EditorSettings>,
     pub lsp: HashMap<Arc<str>, LspSettings>,
@@ -84,7 +83,6 @@ impl Setting for Settings {
             buffer_font_features,
             buffer_font_size: defaults.buffer_font_size.unwrap(),
             active_pane_magnification: defaults.active_pane_magnification.unwrap(),
-            default_buffer_font_size: defaults.buffer_font_size.unwrap(),
             confirm_quit: defaults.confirm_quit.unwrap(),
             cursor_blink: defaults.cursor_blink.unwrap(),
             hover_popover_enabled: defaults.hover_popover_enabled.unwrap(),
@@ -121,8 +119,6 @@ impl Setting for Settings {
             },
             git: defaults.git.unwrap(),
             git_overrides: Default::default(),
-            terminal_defaults: defaults.terminal.clone(),
-            terminal_overrides: Default::default(),
             language_defaults: defaults.languages.clone(),
             language_overrides: Default::default(),
             lsp: defaults.lsp.clone(),
@@ -332,104 +328,6 @@ pub enum Autosave {
     OnWindowChange,
 }
 
-#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
-pub struct TerminalSettings {
-    pub shell: Option<Shell>,
-    pub working_directory: Option<WorkingDirectory>,
-    pub font_size: Option<f32>,
-    pub font_family: Option<String>,
-    pub line_height: Option<TerminalLineHeight>,
-    pub font_features: Option<fonts::Features>,
-    pub env: Option<HashMap<String, String>>,
-    pub blinking: Option<TerminalBlink>,
-    pub alternate_scroll: Option<AlternateScroll>,
-    pub option_as_meta: Option<bool>,
-    pub copy_on_select: Option<bool>,
-}
-
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema, Default)]
-#[serde(rename_all = "snake_case")]
-pub enum TerminalLineHeight {
-    #[default]
-    Comfortable,
-    Standard,
-    Custom(f32),
-}
-
-impl TerminalLineHeight {
-    fn value(&self) -> f32 {
-        match self {
-            TerminalLineHeight::Comfortable => 1.618,
-            TerminalLineHeight::Standard => 1.3,
-            TerminalLineHeight::Custom(line_height) => *line_height,
-        }
-    }
-}
-
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
-#[serde(rename_all = "snake_case")]
-pub enum TerminalBlink {
-    Off,
-    TerminalControlled,
-    On,
-}
-
-impl Default for TerminalBlink {
-    fn default() -> Self {
-        TerminalBlink::TerminalControlled
-    }
-}
-
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
-#[serde(rename_all = "snake_case")]
-pub enum Shell {
-    System,
-    Program(String),
-    WithArguments { program: String, args: Vec<String> },
-}
-
-impl Default for Shell {
-    fn default() -> Self {
-        Shell::System
-    }
-}
-
-#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
-#[serde(rename_all = "snake_case")]
-pub enum AlternateScroll {
-    On,
-    Off,
-}
-
-impl Default for AlternateScroll {
-    fn default() -> Self {
-        AlternateScroll::On
-    }
-}
-
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
-#[serde(rename_all = "snake_case")]
-pub enum WorkingDirectory {
-    CurrentProjectDirectory,
-    FirstProjectDirectory,
-    AlwaysHome,
-    Always { directory: String },
-}
-
-impl Default for WorkingDirectory {
-    fn default() -> Self {
-        Self::CurrentProjectDirectory
-    }
-}
-
-impl TerminalSettings {
-    fn line_height(&self) -> Option<f32> {
-        self.line_height
-            .to_owned()
-            .map(|line_height| line_height.value())
-    }
-}
-
 #[derive(PartialEq, Eq, Debug, Default, Copy, Clone, Hash, Serialize, Deserialize, JsonSchema)]
 #[serde(rename_all = "snake_case")]
 pub enum DockAnchor {
@@ -496,8 +394,6 @@ pub struct SettingsFileContent {
     #[serde(flatten)]
     pub editor: EditorSettings,
     #[serde(default)]
-    pub terminal: TerminalSettings,
-    #[serde(default)]
     pub git: Option<GitSettings>,
     #[serde(default)]
     #[serde(alias = "language_overrides")]
@@ -575,7 +471,6 @@ impl Settings {
             buffer_font_features,
             buffer_font_size: defaults.buffer_font_size.unwrap(),
             active_pane_magnification: defaults.active_pane_magnification.unwrap(),
-            default_buffer_font_size: defaults.buffer_font_size.unwrap(),
             confirm_quit: defaults.confirm_quit.unwrap(),
             cursor_blink: defaults.cursor_blink.unwrap(),
             hover_popover_enabled: defaults.hover_popover_enabled.unwrap(),
@@ -613,8 +508,6 @@ impl Settings {
             },
             git: defaults.git.unwrap(),
             git_overrides: Default::default(),
-            terminal_defaults: defaults.terminal,
-            terminal_overrides: Default::default(),
             language_defaults: defaults.languages,
             language_overrides: Default::default(),
             lsp: defaults.lsp.clone(),
@@ -627,7 +520,7 @@ impl Settings {
     }
 
     // Fill out the overrride and etc. settings from the user's settings.json
-    pub fn set_user_settings(
+    fn set_user_settings(
         &mut self,
         data: SettingsFileContent,
         theme_registry: &ThemeRegistry,
@@ -662,7 +555,6 @@ impl Settings {
             &mut self.active_pane_magnification,
             data.active_pane_magnification,
         );
-        merge(&mut self.default_buffer_font_size, data.buffer_font_size);
         merge(&mut self.cursor_blink, data.cursor_blink);
         merge(&mut self.confirm_quit, data.confirm_quit);
         merge(&mut self.hover_popover_enabled, data.hover_popover_enabled);
@@ -685,9 +577,6 @@ impl Settings {
         }
         self.editor_overrides = data.editor;
         self.git_overrides = data.git.unwrap_or_default();
-        self.terminal_defaults.font_size = data.terminal.font_size;
-        self.terminal_overrides.copy_on_select = data.terminal.copy_on_select;
-        self.terminal_overrides = data.terminal;
         self.language_overrides = data.languages;
         self.lsp = data.lsp;
     }
@@ -799,35 +688,6 @@ impl Settings {
         })
     }
 
-    fn terminal_setting<F, R>(&self, f: F) -> R
-    where
-        F: Fn(&TerminalSettings) -> Option<R>,
-    {
-        None.or_else(|| f(&self.terminal_overrides))
-            .or_else(|| f(&self.terminal_defaults))
-            .expect("missing default")
-    }
-
-    pub fn terminal_line_height(&self) -> f32 {
-        self.terminal_setting(|terminal_setting| terminal_setting.line_height())
-    }
-
-    pub fn terminal_scroll(&self) -> AlternateScroll {
-        self.terminal_setting(|terminal_setting| terminal_setting.alternate_scroll.to_owned())
-    }
-
-    pub fn terminal_shell(&self) -> Shell {
-        self.terminal_setting(|terminal_setting| terminal_setting.shell.to_owned())
-    }
-
-    pub fn terminal_env(&self) -> HashMap<String, String> {
-        self.terminal_setting(|terminal_setting| terminal_setting.env.to_owned())
-    }
-
-    pub fn terminal_strategy(&self) -> WorkingDirectory {
-        self.terminal_setting(|terminal_setting| terminal_setting.working_directory.to_owned())
-    }
-
     #[cfg(any(test, feature = "test-support"))]
     pub fn test(cx: &gpui::AppContext) -> Settings {
         Settings {
@@ -839,7 +699,6 @@ impl Settings {
                 .unwrap(),
             buffer_font_size: 14.,
             active_pane_magnification: 1.,
-            default_buffer_font_size: 14.,
             confirm_quit: false,
             cursor_blink: true,
             hover_popover_enabled: true,
@@ -862,8 +721,6 @@ impl Settings {
             },
             editor_overrides: Default::default(),
             copilot: Default::default(),
-            terminal_defaults: Default::default(),
-            terminal_overrides: Default::default(),
             git: Default::default(),
             git_overrides: Default::default(),
             language_defaults: Default::default(),

crates/terminal/Cargo.toml 🔗

@@ -15,6 +15,7 @@ settings = { path = "../settings" }
 db = { path = "../db" }
 theme = { path = "../theme" }
 util = { path = "../util" }
+
 alacritty_terminal = { git = "https://github.com/zed-industries/alacritty", rev = "a51dbe25d67e84d6ed4261e640d3954fbdd9be45" }
 procinfo = { git = "https://github.com/zed-industries/wezterm", rev = "5cd757e5f2eb039ed0c6bb6512223e69d5efc64d", default-features = false }
 smallvec.workspace = true
@@ -27,6 +28,7 @@ dirs = "4.0.0"
 shellexpand = "2.1.0"
 libc = "0.2"
 anyhow.workspace = true
+schemars.workspace = true
 thiserror.workspace = true
 lazy_static.workspace = true
 serde.workspace = true

crates/terminal/src/terminal.rs 🔗

@@ -31,8 +31,9 @@ use mappings::mouse::{
 };
 
 use procinfo::LocalProcessInfo;
+use schemars::JsonSchema;
 use serde::{Deserialize, Serialize};
-use settings::{AlternateScroll, Settings, Shell, TerminalBlink};
+use settings::Settings;
 use util::truncate_and_trailoff;
 
 use std::{
@@ -48,11 +49,12 @@ use std::{
 use thiserror::Error;
 
 use gpui::{
+    fonts,
     geometry::vector::{vec2f, Vector2F},
     keymap_matcher::Keystroke,
     platform::{MouseButton, MouseMovedEvent, TouchPhase},
     scene::{MouseDown, MouseDrag, MouseScrollWheel, MouseUp},
-    ClipboardItem, Entity, ModelContext, Task,
+    AppContext, ClipboardItem, Entity, ModelContext, Task,
 };
 
 use crate::mappings::{
@@ -114,6 +116,105 @@ impl EventListener for ZedListener {
     }
 }
 
+pub fn init(cx: &mut AppContext) {
+    settings::register_setting::<TerminalSettings>(cx);
+}
+
+#[derive(Deserialize)]
+pub struct TerminalSettings {
+    pub shell: Shell,
+    pub working_directory: WorkingDirectory,
+    pub font_size: Option<f32>,
+    pub font_family: Option<String>,
+    pub line_height: TerminalLineHeight,
+    pub font_features: Option<fonts::Features>,
+    pub env: HashMap<String, String>,
+    pub blinking: TerminalBlink,
+    pub alternate_scroll: AlternateScroll,
+    pub option_as_meta: bool,
+    pub copy_on_select: bool,
+}
+
+#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
+pub struct TerminalSettingsContent {
+    pub shell: Option<Shell>,
+    pub working_directory: Option<WorkingDirectory>,
+    pub font_size: Option<f32>,
+    pub font_family: Option<String>,
+    pub line_height: Option<TerminalLineHeight>,
+    pub font_features: Option<fonts::Features>,
+    pub env: Option<HashMap<String, String>>,
+    pub blinking: Option<TerminalBlink>,
+    pub alternate_scroll: Option<AlternateScroll>,
+    pub option_as_meta: Option<bool>,
+    pub copy_on_select: Option<bool>,
+}
+
+impl settings::Setting for TerminalSettings {
+    const KEY: Option<&'static str> = Some("terminal");
+
+    type FileContent = TerminalSettingsContent;
+
+    fn load(
+        default_value: &Self::FileContent,
+        user_values: &[&Self::FileContent],
+        _: &AppContext,
+    ) -> Self {
+        Self::load_via_json_merge(default_value, user_values)
+    }
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema, Default)]
+#[serde(rename_all = "snake_case")]
+pub enum TerminalLineHeight {
+    #[default]
+    Comfortable,
+    Standard,
+    Custom(f32),
+}
+
+impl TerminalLineHeight {
+    pub fn value(&self) -> f32 {
+        match self {
+            TerminalLineHeight::Comfortable => 1.618,
+            TerminalLineHeight::Standard => 1.3,
+            TerminalLineHeight::Custom(line_height) => *line_height,
+        }
+    }
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
+#[serde(rename_all = "snake_case")]
+pub enum TerminalBlink {
+    Off,
+    TerminalControlled,
+    On,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
+#[serde(rename_all = "snake_case")]
+pub enum Shell {
+    System,
+    Program(String),
+    WithArguments { program: String, args: Vec<String> },
+}
+
+#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
+#[serde(rename_all = "snake_case")]
+pub enum AlternateScroll {
+    On,
+    Off,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
+#[serde(rename_all = "snake_case")]
+pub enum WorkingDirectory {
+    CurrentProjectDirectory,
+    FirstProjectDirectory,
+    AlwaysHome,
+    Always { directory: String },
+}
+
 #[derive(Clone, Copy, Debug, Serialize, Deserialize)]
 pub struct TerminalSize {
     pub cell_width: f32,
@@ -1049,16 +1150,7 @@ impl Terminal {
     }
 
     pub fn mouse_up(&mut self, e: &MouseUp, origin: Vector2F, cx: &mut ModelContext<Self>) {
-        let settings = cx.global::<Settings>();
-        let copy_on_select = settings
-            .terminal_overrides
-            .copy_on_select
-            .unwrap_or_else(|| {
-                settings
-                    .terminal_defaults
-                    .copy_on_select
-                    .expect("Should be set in defaults")
-            });
+        let setting = settings::get_setting::<TerminalSettings>(None, cx);
 
         let position = e.position.sub(origin);
         if self.mouse_mode(e.shift) {
@@ -1072,7 +1164,7 @@ impl Terminal {
                 self.pty_tx.notify(bytes);
             }
         } else {
-            if e.button == MouseButton::Left && copy_on_select {
+            if e.button == MouseButton::Left && setting.copy_on_select {
                 self.copy();
             }
 

crates/terminal_view/src/terminal_element.rs 🔗

@@ -16,7 +16,7 @@ use gpui::{
 use itertools::Itertools;
 use language::CursorShape;
 use ordered_float::OrderedFloat;
-use settings::Settings;
+use settings::{font_size_for_setting, Settings};
 use terminal::{
     alacritty_terminal::{
         ansi::{Color as AnsiColor, Color::Named, CursorShape as AlacCursorShape, NamedColor},
@@ -25,7 +25,7 @@ use terminal::{
         term::{cell::Flags, TermMode},
     },
     mappings::colors::convert_color,
-    IndexedCell, Terminal, TerminalContent, TerminalSize,
+    IndexedCell, Terminal, TerminalContent, TerminalSettings, TerminalSize,
 };
 use theme::TerminalStyle;
 use util::ResultExt;
@@ -510,38 +510,50 @@ impl TerminalElement {
 
         scene.push_mouse_region(region);
     }
+}
+
+impl Element<TerminalView> for TerminalElement {
+    type LayoutState = LayoutState;
+    type PaintState = ();
 
-    ///Configures a text style from the current settings.
-    pub fn make_text_style(font_cache: &FontCache, settings: &Settings) -> TextStyle {
-        let font_family_name = settings
-            .terminal_overrides
+    fn layout(
+        &mut self,
+        constraint: gpui::SizeConstraint,
+        view: &mut TerminalView,
+        cx: &mut LayoutContext<TerminalView>,
+    ) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) {
+        let settings = cx.global::<Settings>();
+        let terminal_settings = settings::get_setting::<TerminalSettings>(None, cx);
+
+        //Setup layout information
+        let terminal_theme = settings.theme.terminal.clone(); //TODO: Try to minimize this clone.
+        let link_style = settings.theme.editor.link_definition;
+        let tooltip_style = settings.theme.tooltip.clone();
+
+        let font_cache = cx.font_cache();
+        let font_size = font_size_for_setting(
+            terminal_settings
+                .font_size
+                .unwrap_or(settings.buffer_font_size),
+            cx,
+        );
+        let font_family_name = terminal_settings
             .font_family
             .as_ref()
-            .or(settings.terminal_defaults.font_family.as_ref())
             .unwrap_or(&settings.buffer_font_family_name);
-        let font_features = settings
-            .terminal_overrides
+        let font_features = terminal_settings
             .font_features
             .as_ref()
-            .or(settings.terminal_defaults.font_features.as_ref())
             .unwrap_or(&settings.buffer_font_features);
-
         let family_id = font_cache
             .load_family(&[font_family_name], &font_features)
             .log_err()
             .unwrap_or(settings.buffer_font_family);
-
-        let font_size = settings
-            .terminal_overrides
-            .font_size
-            .or(settings.terminal_defaults.font_size)
-            .unwrap_or(settings.buffer_font_size);
-
         let font_id = font_cache
             .select_font(family_id, &Default::default())
             .unwrap();
 
-        TextStyle {
+        let text_style = TextStyle {
             color: settings.theme.editor.text_color,
             font_family_id: family_id,
             font_family_name: font_cache.family_name(family_id).unwrap(),
@@ -549,34 +561,12 @@ impl TerminalElement {
             font_size,
             font_properties: Default::default(),
             underline: Default::default(),
-        }
-    }
-}
-
-impl Element<TerminalView> for TerminalElement {
-    type LayoutState = LayoutState;
-    type PaintState = ();
-
-    fn layout(
-        &mut self,
-        constraint: gpui::SizeConstraint,
-        view: &mut TerminalView,
-        cx: &mut LayoutContext<TerminalView>,
-    ) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) {
-        let settings = cx.global::<Settings>();
-        let font_cache = cx.font_cache();
-
-        //Setup layout information
-        let terminal_theme = settings.theme.terminal.clone(); //TODO: Try to minimize this clone.
-        let link_style = settings.theme.editor.link_definition;
-        let tooltip_style = settings.theme.tooltip.clone();
-
-        let text_style = TerminalElement::make_text_style(font_cache, settings);
+        };
         let selection_color = settings.theme.editor.selection.selection;
         let match_color = settings.theme.search.match_background;
         let gutter;
         let dimensions = {
-            let line_height = text_style.font_size * settings.terminal_line_height();
+            let line_height = text_style.font_size * terminal_settings.line_height.value();
             let cell_width = font_cache.em_advance(text_style.font_id, text_style.font_size);
             gutter = cell_width;
 

crates/terminal_view/src/terminal_view.rs 🔗

@@ -2,6 +2,7 @@ mod persistence;
 pub mod terminal_button;
 pub mod terminal_element;
 
+use crate::{persistence::TERMINAL_DB, terminal_element::TerminalElement};
 use context_menu::{ContextMenu, ContextMenuItem};
 use dirs::home_dir;
 use gpui::{
@@ -16,7 +17,6 @@ use gpui::{
 };
 use project::{LocalWorktree, Project};
 use serde::Deserialize;
-use settings::{Settings, TerminalBlink, WorkingDirectory};
 use smallvec::{smallvec, SmallVec};
 use smol::Timer;
 use std::{
@@ -30,7 +30,7 @@ use terminal::{
         index::Point,
         term::{search::RegexSearch, TermMode},
     },
-    Event, Terminal,
+    Event, Terminal, TerminalBlink, WorkingDirectory,
 };
 use util::ResultExt;
 use workspace::{
@@ -41,7 +41,7 @@ use workspace::{
     Pane, ToolbarItemLocation, Workspace, WorkspaceId,
 };
 
-use crate::{persistence::TERMINAL_DB, terminal_element::TerminalElement};
+pub use terminal::TerminalSettings;
 
 const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
 
@@ -63,6 +63,8 @@ actions!(
 impl_actions!(terminal, [SendText, SendKeystroke]);
 
 pub fn init(cx: &mut AppContext) {
+    terminal::init(cx);
+
     cx.add_action(TerminalView::deploy);
 
     register_deserializable_item::<TerminalView>(cx);
@@ -101,9 +103,9 @@ impl TerminalView {
         _: &workspace::NewTerminal,
         cx: &mut ViewContext<Workspace>,
     ) {
-        let strategy = cx.global::<Settings>().terminal_strategy();
-
-        let working_directory = get_working_directory(workspace, cx, strategy);
+        let strategy = settings::get_setting::<TerminalSettings>(None, cx);
+        let working_directory =
+            get_working_directory(workspace, cx, strategy.working_directory.clone());
 
         let window_id = cx.window_id();
         let terminal = workspace
@@ -215,10 +217,7 @@ impl TerminalView {
             self.terminal.update(cx, |term, cx| {
                 term.try_keystroke(
                     &Keystroke::parse("ctrl-cmd-space").unwrap(),
-                    cx.global::<Settings>()
-                        .terminal_overrides
-                        .option_as_meta
-                        .unwrap_or(false),
+                    settings::get_setting::<TerminalSettings>(None, cx).option_as_meta,
                 )
             });
         }
@@ -244,16 +243,7 @@ impl TerminalView {
             return true;
         }
 
-        let setting = {
-            let settings = cx.global::<Settings>();
-            settings
-                .terminal_overrides
-                .blinking
-                .clone()
-                .unwrap_or(TerminalBlink::TerminalControlled)
-        };
-
-        match setting {
+        match settings::get_setting::<TerminalSettings>(None, cx).blinking {
             //If the user requested to never blink, don't blink it.
             TerminalBlink::Off => true,
             //If the terminal is controlling it, check terminal mode
@@ -346,10 +336,7 @@ impl TerminalView {
             self.terminal.update(cx, |term, cx| {
                 term.try_keystroke(
                     &keystroke,
-                    cx.global::<Settings>()
-                        .terminal_overrides
-                        .option_as_meta
-                        .unwrap_or(false),
+                    settings::get_setting::<TerminalSettings>(None, cx).option_as_meta,
                 );
             });
         }
@@ -412,10 +399,7 @@ impl View for TerminalView {
         self.terminal.update(cx, |term, cx| {
             term.try_keystroke(
                 &event.keystroke,
-                cx.global::<Settings>()
-                    .terminal_overrides
-                    .option_as_meta
-                    .unwrap_or(false),
+                settings::get_setting::<TerminalSettings>(None, cx).option_as_meta,
             )
         })
     }
@@ -617,7 +601,9 @@ impl Item for TerminalView {
                 .flatten()
                 .or_else(|| {
                     cx.read(|cx| {
-                        let strategy = cx.global::<Settings>().terminal_strategy();
+                        let strategy = settings::get_setting::<TerminalSettings>(None, cx)
+                            .working_directory
+                            .clone();
                         workspace
                             .upgrade(cx)
                             .map(|workspace| {

crates/theme_testbench/src/theme_testbench.rs 🔗

@@ -223,7 +223,7 @@ impl ThemeTestbench {
         let settings = cx.global::<Settings>();
         let font_cache = cx.font_cache();
         let family_id = settings.buffer_font_family;
-        let font_size = settings.buffer_font_size;
+        let font_size = settings::font_size_for_setting(settings.buffer_font_size, cx);
         let font_id = font_cache
             .select_font(family_id, &Default::default())
             .unwrap();

crates/zed/src/main.rs 🔗

@@ -25,7 +25,7 @@ use project::Fs;
 use serde::{Deserialize, Serialize};
 use settings::{
     default_settings, handle_keymap_file_changes, handle_settings_file_changes, watch_config_file,
-    Settings, SettingsStore, WorkingDirectory,
+    Settings, SettingsStore,
 };
 use simplelog::ConfigBuilder;
 use smol::process::Command;
@@ -42,7 +42,7 @@ use std::{
     thread,
     time::Duration,
 };
-use terminal_view::{get_working_directory, TerminalView};
+use terminal_view::{get_working_directory, TerminalSettings, TerminalView};
 use util::http::{self, HttpClient};
 use welcome::{show_welcome_experience, FIRST_OPEN};
 
@@ -722,13 +722,9 @@ pub fn dock_default_item_factory(
     workspace: &mut Workspace,
     cx: &mut ViewContext<Workspace>,
 ) -> Option<Box<dyn ItemHandle>> {
-    let strategy = cx
-        .global::<Settings>()
-        .terminal_overrides
+    let strategy = settings::get_setting::<TerminalSettings>(None, cx)
         .working_directory
-        .clone()
-        .unwrap_or(WorkingDirectory::CurrentProjectDirectory);
-
+        .clone();
     let working_directory = get_working_directory(workspace, cx, strategy);
 
     let window_id = cx.window_id();

crates/zed/src/zed.rs 🔗

@@ -29,7 +29,7 @@ use project_panel::ProjectPanel;
 use search::{BufferSearchBar, ProjectSearchBar};
 use serde::Deserialize;
 use serde_json::to_string_pretty;
-use settings::{Settings, DEFAULT_SETTINGS_ASSET_PATH};
+use settings::{adjust_font_size_delta, Settings, DEFAULT_SETTINGS_ASSET_PATH};
 use std::{borrow::Cow, str, sync::Arc};
 use terminal_view::terminal_button::TerminalButton;
 use util::{channel::ReleaseChannel, paths, ResultExt};
@@ -117,29 +117,17 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut gpui::AppContext) {
     cx.add_global_action(quit);
     cx.add_global_action(move |action: &OpenBrowser, cx| cx.platform().open_url(&action.url));
     cx.add_global_action(move |_: &IncreaseBufferFontSize, cx| {
-        cx.update_global::<Settings, _, _>(|settings, cx| {
-            settings.buffer_font_size = (settings.buffer_font_size + 1.0).max(MIN_FONT_SIZE);
-            if let Some(terminal_font_size) = settings.terminal_overrides.font_size.as_mut() {
-                *terminal_font_size = (*terminal_font_size + 1.0).max(MIN_FONT_SIZE);
-            }
-            cx.refresh_windows();
-        });
+        adjust_font_size_delta(cx, |size, _| *size += 1.0)
     });
     cx.add_global_action(move |_: &DecreaseBufferFontSize, cx| {
-        cx.update_global::<Settings, _, _>(|settings, cx| {
-            settings.buffer_font_size = (settings.buffer_font_size - 1.0).max(MIN_FONT_SIZE);
-            if let Some(terminal_font_size) = settings.terminal_overrides.font_size.as_mut() {
-                *terminal_font_size = (*terminal_font_size - 1.0).max(MIN_FONT_SIZE);
+        adjust_font_size_delta(cx, |size, cx| {
+            if cx.global::<Settings>().buffer_font_size + *size > MIN_FONT_SIZE {
+                *size -= 1.0;
             }
-            cx.refresh_windows();
-        });
+        })
     });
     cx.add_global_action(move |_: &ResetBufferFontSize, cx| {
-        cx.update_global::<Settings, _, _>(|settings, cx| {
-            settings.buffer_font_size = settings.default_buffer_font_size;
-            settings.terminal_overrides.font_size = settings.terminal_defaults.font_size;
-            cx.refresh_windows();
-        });
+        adjust_font_size_delta(cx, |size, _| *size = 0.0)
     });
     cx.add_global_action(move |_: &install_cli::Install, cx| {
         cx.spawn(|cx| async move {