From a7d74150ac7a663fdaa01ec5177e303baaf6c331 Mon Sep 17 00:00:00 2001 From: afdul <74723091+abdul2801@users.noreply.github.com> Date: Tue, 18 Aug 2026 12:40:18 +0000 Subject: [PATCH] Fix the `git_gutter_width` setting (#62704) # Objective - Fixes #62645 ## Solution Since the default value isnt constant.It now has two options 1) Default 2) custom where user inputs a value. ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [ ] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [ ] Tests cover the new/changed behavior - [ ] Performance impact has been considered and is acceptable ## Showcase Screenshot 2026-08-16 at 4 29 54 PM Screenshot 2026-08-16 at 4 30 13 PM Release Notes: - Added git_gutter_width setting to the Settings UI with default (font-size-scaled) and custom (fixed pixel width) options --------- Co-authored-by: Abdul Rafey Ahmed Co-authored-by: MrSubidubi --- Cargo.toml | 1 + assets/settings/default.json | 6 +- crates/agent_settings/src/agent_settings.rs | 10 +- crates/collab_ui/src/panel_settings.rs | 5 +- crates/editor/src/editor_settings.rs | 6 +- crates/editor/src/element.rs | 12 +- crates/git_ui/src/git_panel_settings.rs | 10 +- .../src/markdown_preview_settings.rs | 6 +- crates/migrator/src/migrations.rs | 6 + .../src/migrations/m_2026_08_17/settings.rs | 32 ++++++ crates/migrator/src/migrator.rs | 59 ++++++++++ .../src/outline_panel_settings.rs | 6 +- .../src/project_panel_settings.rs | 11 +- crates/settings/src/content_into_gpui.rs | 10 +- crates/settings_content/src/agent.rs | 9 +- crates/settings_content/src/editor.rs | 31 ++++- .../settings_content/src/settings_content.rs | 44 +++++-- crates/settings_content/src/terminal.rs | 6 +- crates/settings_content/src/workspace.rs | 9 +- .../src/components/number_field.rs | 3 +- crates/settings_ui/src/page_data.rs | 107 ++++++++++++++---- crates/settings_ui/src/settings_ui.rs | 2 + crates/terminal/src/terminal_settings.rs | 6 +- crates/workspace/src/workspace_settings.rs | 2 +- docs/src/reference/all-settings.md | 4 +- 25 files changed, 307 insertions(+), 96 deletions(-) create mode 100644 crates/migrator/src/migrations/m_2026_08_17/settings.rs diff --git a/Cargo.toml b/Cargo.toml index b49e6de2314..b8d3b8df741 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -598,6 +598,7 @@ derive_more = { version = "2.1.1", features = [ "deref", "deref_mut", "display", + "from", "from_str", "mul", "mul_assign", diff --git a/assets/settings/default.json b/assets/settings/default.json index 40e4c325de8..7e71a8cb0ac 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -703,9 +703,9 @@ "folds": true, // Minimum number of characters to reserve space for in the gutter. "min_line_number_digits": 4, - // The width, in pixels, of the git diff hunk indicators in the gutter. - // When set to null, the width scales with the buffer font size. - "git_gutter_width": null, + // The width of the git diff hunk indicators in the gutter. + // Use "default" to scale with font size, or {"custom": } for a fixed width. + "git_gutter_width": "default", }, "indent_guides": { // Whether to show indent guides in the editor. diff --git a/crates/agent_settings/src/agent_settings.rs b/crates/agent_settings/src/agent_settings.rs index b30751f5db3..875b8fef456 100644 --- a/crates/agent_settings/src/agent_settings.rs +++ b/crates/agent_settings/src/agent_settings.rs @@ -10,13 +10,13 @@ use anyhow::Context as _; use collections::{HashSet, IndexMap}; use fs::Fs; use futures::channel::oneshot; -use gpui::{App, Pixels, SharedString, px}; +use gpui::{App, Pixels, SharedString}; use language_model::LanguageModel; use project::DisableAiSettings; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use settings::{ - DockPosition, DockSide, LanguageModelParameters, LanguageModelSelection, + DockPosition, DockSide, IntoGpui, LanguageModelParameters, LanguageModelSelection, NotifyWhenAgentWaiting, PlaySoundWhenAgentDone, RegisterSetting, Settings, SettingsContent, SettingsStore, SidebarDockPosition, SidebarSide, ThinkingBlockDisplay, ToolPermissionMode, update_settings_file, update_settings_file_with_completion, @@ -759,10 +759,10 @@ impl Settings for AgentSettings { button: agent.button.unwrap(), dock: agent.dock.unwrap(), sidebar_side: agent.sidebar_side.unwrap(), - default_width: px(agent.default_width.unwrap()), - default_height: px(agent.default_height.unwrap()), + default_width: agent.default_width.unwrap().into_gpui(), + default_height: agent.default_height.unwrap().into_gpui(), max_content_width: if agent.limit_content_width.unwrap() { - Some(px(agent.max_content_width.unwrap())) + Some(agent.max_content_width.unwrap().into_gpui()) } else { None }, diff --git a/crates/collab_ui/src/panel_settings.rs b/crates/collab_ui/src/panel_settings.rs index 3d6de1015a3..aa84407b3fc 100644 --- a/crates/collab_ui/src/panel_settings.rs +++ b/crates/collab_ui/src/panel_settings.rs @@ -1,6 +1,5 @@ use gpui::Pixels; -use settings::{RegisterSetting, Settings}; -use ui::px; +use settings::{IntoGpui, RegisterSetting, Settings}; use workspace::dock::DockPosition; #[derive(Debug, RegisterSetting)] @@ -17,7 +16,7 @@ impl Settings for CollaborationPanelSettings { Self { button: panel.button.unwrap(), dock: panel.dock.unwrap().into(), - default_width: panel.default_width.map(px).unwrap(), + default_width: panel.default_width.unwrap().into_gpui(), } } } diff --git a/crates/editor/src/editor_settings.rs b/crates/editor/src/editor_settings.rs index f6fdd6c16d2..394f24892f9 100644 --- a/crates/editor/src/editor_settings.rs +++ b/crates/editor/src/editor_settings.rs @@ -5,7 +5,7 @@ use language::CursorShape; use project::project_settings::DiagnosticSeverity; pub use settings::{ CodeLens, CompletionDetailAlignment, CompletionMenuItemKind, CurrentLineHighlight, DelayMs, - DiffViewStyle, DisplayIn, DocumentColorsRenderMode, DoubleClickInMultibuffer, + DiffViewStyle, DisplayIn, DocumentColorsRenderMode, DoubleClickInMultibuffer, GitGutterWidth, GoToDefinitionFallback, GoToDefinitionScrollStrategy, MinimapThumb, MinimapThumbBorder, MultiCursorModifier, OpenResultsIn, ScrollBeyondLastLine, ScrollbarDiagnostics, SeedQuerySetting, ShowMinimap, SnippetSortOrder, @@ -149,7 +149,7 @@ pub struct Gutter { pub breakpoints: bool, pub bookmarks: bool, pub folds: bool, - pub git_gutter_width: Option, + pub git_gutter_width: settings::GitGutterWidth, } /// Forcefully enable or disable the scrollbar for each axis @@ -268,7 +268,7 @@ impl Settings for EditorSettings { bookmarks: gutter.bookmarks.unwrap(), breakpoints: gutter.breakpoints.unwrap(), folds: gutter.folds.unwrap(), - git_gutter_width: gutter.git_gutter_width, + git_gutter_width: gutter.git_gutter_width.unwrap(), }, scroll_beyond_last_line: editor.scroll_beyond_last_line.unwrap(), vertical_scroll_margin: editor.vertical_scroll_margin.unwrap() as f64, diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 07e81acc821..ac32816a807 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -22,8 +22,8 @@ use crate::{ HighlightKey, HighlightedChunk, ToDisplayPoint, }, editor_settings::{ - CurrentLineHighlight, DocumentColorsRenderMode, Minimap, MinimapThumb, MinimapThumbBorder, - ScrollBeyondLastLine, ScrollbarAxes, ScrollbarDiagnostics, ShowMinimap, + CurrentLineHighlight, DocumentColorsRenderMode, GitGutterWidth, Minimap, MinimapThumb, + MinimapThumbBorder, ScrollBeyondLastLine, ScrollbarAxes, ScrollbarDiagnostics, ShowMinimap, }, git::blame::{BlameRenderer, GitBlame, GlobalBlameRenderer}, hover_popover::{ @@ -5321,8 +5321,8 @@ impl EditorElement { fn gutter_strip_width(line_height: Pixels, cx: &App) -> Pixels { match EditorSettings::get_global(cx).gutter.git_gutter_width { - Some(width) => px(width), - None => (0.275 * line_height).floor(), + GitGutterWidth::Custom(width) => px(*width), + GitGutterWidth::Default => (0.275 * line_height).floor(), } } @@ -5362,8 +5362,8 @@ impl EditorElement { let end_y = start_y + line_height; let width = match EditorSettings::get_global(cx).gutter.git_gutter_width { - Some(width) => px(width), - None => (0.35 * line_height).floor(), + GitGutterWidth::Custom(width) => px(*width), + GitGutterWidth::Default => (0.35 * line_height).floor(), }; let highlight_origin = gutter_bounds.origin + point(px(0.), start_y); let highlight_size = size(width, end_y - start_y); diff --git a/crates/git_ui/src/git_panel_settings.rs b/crates/git_ui/src/git_panel_settings.rs index 0dbde43cfb5..6027c85bdab 100644 --- a/crates/git_ui/src/git_panel_settings.rs +++ b/crates/git_ui/src/git_panel_settings.rs @@ -3,12 +3,10 @@ use gpui::Pixels; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use settings::{ - GitPanelClickBehavior, GitPanelGroupBy, GitPanelSortBy, RegisterSetting, Settings, StatusStyle, -}; -use ui::{ - px, - scrollbars::{ScrollbarVisibility, ShowScrollbar}, + GitPanelClickBehavior, GitPanelGroupBy, GitPanelSortBy, IntoGpui, RegisterSetting, Settings, + StatusStyle, }; +use ui::scrollbars::{ScrollbarVisibility, ShowScrollbar}; use workspace::dock::DockPosition; #[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] @@ -63,7 +61,7 @@ impl Settings for GitPanelSettings { Self { button: git_panel.button.unwrap(), dock: git_panel.dock.unwrap().into(), - default_width: px(git_panel.default_width.unwrap()), + default_width: git_panel.default_width.unwrap().into_gpui(), status_style: git_panel.status_style.unwrap(), file_icons: git_panel.file_icons.unwrap(), folder_icons: git_panel.folder_icons.unwrap(), diff --git a/crates/markdown_preview/src/markdown_preview_settings.rs b/crates/markdown_preview/src/markdown_preview_settings.rs index bb624ad2cb8..94bd4ab597b 100644 --- a/crates/markdown_preview/src/markdown_preview_settings.rs +++ b/crates/markdown_preview/src/markdown_preview_settings.rs @@ -1,5 +1,5 @@ -use gpui::{Pixels, px}; -use settings::{RegisterSetting, Settings}; +use gpui::Pixels; +use settings::{IntoGpui, RegisterSetting, Settings}; /// The settings for the markdown preview. #[derive(Clone, Copy, Debug, Default, RegisterSetting)] @@ -13,7 +13,7 @@ impl Settings for MarkdownPreviewSettings { fn from_settings(content: &settings::SettingsContent) -> Self { let content = content.markdown_preview.clone().unwrap_or_default(); let max_width = if content.limit_content_width.unwrap_or(true) { - content.max_width.map(px) + content.max_width.map(IntoGpui::into_gpui) } else { None }; diff --git a/crates/migrator/src/migrations.rs b/crates/migrator/src/migrations.rs index 394b26f57ab..48588baa576 100644 --- a/crates/migrator/src/migrations.rs +++ b/crates/migrator/src/migrations.rs @@ -364,3 +364,9 @@ pub(crate) mod m_2026_05_04 { pub(crate) use settings::SETTINGS_PATTERNS; } + +pub(crate) mod m_2026_08_17 { + mod settings; + + pub(crate) use settings::make_git_gutter_width_an_enum; +} diff --git a/crates/migrator/src/migrations/m_2026_08_17/settings.rs b/crates/migrator/src/migrations/m_2026_08_17/settings.rs new file mode 100644 index 00000000000..4ec41fba115 --- /dev/null +++ b/crates/migrator/src/migrations/m_2026_08_17/settings.rs @@ -0,0 +1,32 @@ +use anyhow::Result; +use serde_json::Value; + +use crate::migrations::migrate_settings; + +pub fn make_git_gutter_width_an_enum(value: &mut Value) -> Result<()> { + migrate_settings(value, &mut migrate_one) +} + +fn migrate_one(obj: &mut serde_json::Map) -> Result<()> { + let Some(gutter) = obj + .get_mut("gutter") + .and_then(|gutter| gutter.as_object_mut()) + else { + return Ok(()); + }; + + let Some(git_gutter_width) = gutter.get_mut("git_gutter_width") else { + return Ok(()); + }; + + *git_gutter_width = match git_gutter_width { + Value::Number(n) => { + serde_json::json!({ + "custom": n + }) + } + _ => return Ok(()), + }; + + Ok(()) +} diff --git a/crates/migrator/src/migrator.rs b/crates/migrator/src/migrator.rs index e1b15d98ea5..7b2dc972d8a 100644 --- a/crates/migrator/src/migrator.rs +++ b/crates/migrator/src/migrator.rs @@ -257,6 +257,7 @@ pub fn migrate_settings(text: &str) -> Result> { migrations::m_2026_05_04::SETTINGS_PATTERNS, &SETTINGS_QUERY_2026_05_04, ), + MigrationType::Json(migrations::m_2026_08_17::make_git_gutter_width_an_enum), ]; run_migrations(text, migrations) } @@ -5422,4 +5423,62 @@ mod tests { None, ); } + + #[test] + fn test_make_git_gutter_width_an_enum_from_number() { + assert_migrate_settings( + &r#" + { + "gutter": { + "git_gutter_width": 4.0 + } + } + "# + .unindent(), + Some( + &r#" + { + "gutter": { + "git_gutter_width": { + "custom": 4.0 + } + } + } + "# + .unindent(), + ), + ); + } + + #[test] + fn test_make_git_gutter_width_an_enum_no_change_when_already_migrated() { + // already "default" string — no change + assert_migrate_settings( + &r#" + { + "gutter": { + "git_gutter_width": "default" + } + } + "# + .unindent(), + None, + ); + + // already custom object — no change + assert_migrate_settings( + &r#" + { + "gutter": { + "git_gutter_width": { "custom": 4.0 } + } + } + "# + .unindent(), + None, + ); + + // no gutter key — no change + assert_migrate_settings(&r#"{ "theme": "One Dark" }"#.unindent(), None); + } } diff --git a/crates/outline_panel/src/outline_panel_settings.rs b/crates/outline_panel/src/outline_panel_settings.rs index 18f52e512da..660a3562b93 100644 --- a/crates/outline_panel/src/outline_panel_settings.rs +++ b/crates/outline_panel/src/outline_panel_settings.rs @@ -1,7 +1,7 @@ use editor::{EditorSettings, ui_scrollbar_settings_from_raw}; use gpui::{App, Pixels}; -use settings::RegisterSetting; pub use settings::{DockSide, Settings, ShowIndentGuides}; +use settings::{IntoGpui, RegisterSetting}; use ui::scrollbars::{ScrollbarVisibility, ShowScrollbar}; #[derive(Debug, Clone, Copy, PartialEq, RegisterSetting)] @@ -50,7 +50,7 @@ impl Settings for OutlinePanelSettings { let panel = content.outline_panel.as_ref().unwrap(); Self { button: panel.button.unwrap(), - default_width: panel.default_width.map(gpui::px).unwrap(), + default_width: panel.default_width.unwrap().into_gpui(), dock: panel.dock.unwrap(), file_icons: panel.file_icons.unwrap(), folder_icons: panel.folder_icons.unwrap(), @@ -62,7 +62,7 @@ impl Settings for OutlinePanelSettings { .enabled .unwrap() .is_git_status_enabled(), - indent_size: panel.indent_size.unwrap(), + indent_size: *panel.indent_size.unwrap(), indent_guides: IndentGuidesSettings { show: panel.indent_guides.unwrap().show.unwrap(), }, diff --git a/crates/project_panel/src/project_panel_settings.rs b/crates/project_panel/src/project_panel_settings.rs index 8c464d28806..d2972a87f1b 100644 --- a/crates/project_panel/src/project_panel_settings.rs +++ b/crates/project_panel/src/project_panel_settings.rs @@ -3,13 +3,10 @@ use gpui::Pixels; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use settings::{ - DockSide, ProjectPanelEntrySpacing, ProjectPanelSortMode, ProjectPanelSortOrder, + DockSide, IntoGpui, ProjectPanelEntrySpacing, ProjectPanelSortMode, ProjectPanelSortOrder, RegisterSetting, Settings, ShowDiagnostics, ShowIndentGuides, }; -use ui::{ - px, - scrollbars::{ScrollbarVisibility, ShowScrollbar}, -}; +use ui::scrollbars::{ScrollbarVisibility, ShowScrollbar}; #[derive(Deserialize, Debug, Clone, Copy, PartialEq, RegisterSetting)] pub struct ProjectPanelSettings { @@ -100,7 +97,7 @@ impl Settings for ProjectPanelSettings { Self { button: project_panel.button.unwrap(), hide_gitignore: project_panel.hide_gitignore.unwrap(), - default_width: px(project_panel.default_width.unwrap()), + default_width: project_panel.default_width.unwrap().into_gpui(), dock: project_panel.dock.unwrap(), entry_spacing: project_panel.entry_spacing.unwrap(), file_icons: project_panel.file_icons.unwrap(), @@ -113,7 +110,7 @@ impl Settings for ProjectPanelSettings { .enabled .unwrap() .is_git_status_enabled(), - indent_size: project_panel.indent_size.unwrap(), + indent_size: *project_panel.indent_size.unwrap(), indent_guides: IndentGuidesSettings { show: project_panel.indent_guides.unwrap().show.unwrap(), }, diff --git a/crates/settings/src/content_into_gpui.rs b/crates/settings/src/content_into_gpui.rs index 5b358f1156e..fc38b2129ab 100644 --- a/crates/settings/src/content_into_gpui.rs +++ b/crates/settings/src/content_into_gpui.rs @@ -4,7 +4,7 @@ use gpui::{ }; use settings_content::{ FontFamilyName, FontFeaturesContent, FontSize, FontStyleContent, FontWeightContent, - ModifiersContent, WindowBackgroundContent, + ModifiersContent, PixelSetting, WindowBackgroundContent, }; use std::sync::Arc; @@ -76,6 +76,14 @@ impl IntoGpui for FontSize { } } +impl IntoGpui for PixelSetting { + type Output = Pixels; + + fn into_gpui(self) -> Self::Output { + px(self.0) + } +} + impl IntoGpui for FontFamilyName { type Output = SharedString; diff --git a/crates/settings_content/src/agent.rs b/crates/settings_content/src/agent.rs index 1a90e05b675..6b0a47bb80a 100644 --- a/crates/settings_content/src/agent.rs +++ b/crates/settings_content/src/agent.rs @@ -217,13 +217,11 @@ pub struct AgentSettingsContent { /// Default width in pixels when the agent panel is docked to the left or right. /// /// Default: 640 - #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")] - pub default_width: Option, + pub default_width: Option, /// Default height in pixels when the agent panel is docked to the bottom. /// /// Default: 320 - #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")] - pub default_height: Option, + pub default_height: Option, /// Whether to limit the content width in the agent panel. When enabled, /// content will be constrained to `max_content_width` and centered when /// the panel is wider than that value, for optimal readability. @@ -234,8 +232,7 @@ pub struct AgentSettingsContent { /// centered when the panel is wider than this value. /// /// Default: 850 - #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")] - pub max_content_width: Option, + pub max_content_width: Option, /// The default model to use when creating new chats and for other features when a specific model is not specified. pub default_model: Option, /// The model to use for subagents spawned via the `spawn_agent` tool. Defaults to the parent agent's model when not specified. diff --git a/crates/settings_content/src/editor.rs b/crates/settings_content/src/editor.rs index 52ff2fa10e1..6481da236df 100644 --- a/crates/settings_content/src/editor.rs +++ b/crates/settings_content/src/editor.rs @@ -481,6 +481,29 @@ pub struct ScrollbarAxesContent { pub vertical: Option, } +/// Controls the width of the git diff hunk indicators in the gutter. +#[derive( + Clone, + Copy, + Debug, + Default, + Serialize, + Deserialize, + JsonSchema, + MergeFrom, + PartialEq, + strum::EnumDiscriminants, +)] +#[strum_discriminants(derive(strum::VariantArray, strum::VariantNames, strum::FromRepr))] +#[serde(rename_all = "snake_case")] +pub enum GitGutterWidth { + /// Width scales automatically with the buffer font size. + #[default] + Default, + /// A fixed pixel width for the git diff indicators. + Custom(crate::PixelSetting), +} + /// Gutter related settings #[with_fallible_options] #[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq)] @@ -509,11 +532,11 @@ pub struct GutterContent { /// /// Default: true pub folds: Option, - /// The width, in pixels, of the git diff hunk indicators in the gutter. - /// When unset, the width scales with the buffer font size. + /// The width of the git diff hunk indicators in the gutter. + /// Use "default" to scale with the buffer font size, or {"custom": } for a fixed width. /// - /// Default: null - pub git_gutter_width: Option, + /// Default: "default" + pub git_gutter_width: Option, } /// Whether to display code lenses from language servers above code elements. diff --git a/crates/settings_content/src/settings_content.rs b/crates/settings_content/src/settings_content.rs index bb5df9679c0..ee33c90e018 100644 --- a/crates/settings_content/src/settings_content.rs +++ b/crates/settings_content/src/settings_content.rs @@ -37,6 +37,36 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use settings_macros::{MergeFrom, with_fallible_options}; +/// A non-negative size in pixels. +/// +/// Valid range: 0.0 and up +#[derive( + Clone, + Copy, + Debug, + Default, + Serialize, + Deserialize, + JsonSchema, + MergeFrom, + PartialEq, + PartialOrd, + derive_more::FromStr, + derive_more::Deref, + derive_more::From, +)] +#[serde(transparent)] +pub struct PixelSetting( + #[serde(serialize_with = "crate::serialize_f32_with_two_decimal_places")] pub f32, +); + +impl std::fmt::Display for PixelSetting { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let rounded = (self.0 * 100.0).round() / 100.0; + write!(f, "{rounded}") + } +} + /// Defines a settings override struct where each field is /// `Option>`, along with: /// - `OVERRIDE_KEYS`: a `&[&str]` of the field names (the JSON keys) @@ -682,8 +712,7 @@ pub struct GitPanelSettingsContent { /// Default width of the panel in pixels. /// /// Default: 360 - #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")] - pub default_width: Option, + pub default_width: Option, /// How entry statuses are displayed. /// /// Default: icon @@ -868,8 +897,7 @@ pub struct PanelSettingsContent { /// Default width of the panel in pixels. /// /// Default: 240 - #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")] - pub default_width: Option, + pub default_width: Option, } #[with_fallible_options] @@ -1094,8 +1122,7 @@ pub struct OutlinePanelSettingsContent { /// Customize default width (in pixels) taken by outline panel /// /// Default: 240 - #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")] - pub default_width: Option, + pub default_width: Option, /// The position of outline panel /// /// Default: right (Agentic layout), left (Classic layout) @@ -1115,8 +1142,7 @@ pub struct OutlinePanelSettingsContent { /// Amount of indentation (in pixels) for nested items. /// /// Default: 20 - #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")] - pub indent_size: Option, + pub indent_size: Option, /// Whether to reveal it in the outline panel automatically, /// when a corresponding project entry becomes active. /// Gitignored entries are never auto revealed. @@ -1210,7 +1236,7 @@ pub struct MarkdownPreviewSettingsContent { /// `limit_content_width` is enabled. /// /// Default: 800 - pub max_width: Option, + pub max_width: Option, } /// The settings for the image viewer. diff --git a/crates/settings_content/src/terminal.rs b/crates/settings_content/src/terminal.rs index 338cee6d24c..7ac398295f9 100644 --- a/crates/settings_content/src/terminal.rs +++ b/crates/settings_content/src/terminal.rs @@ -148,13 +148,11 @@ pub struct TerminalSettingsContent { /// Default width when the terminal is docked to the left or right. /// /// Default: 640 - #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")] - pub default_width: Option, + pub default_width: Option, /// Default height when the terminal is docked to the bottom. /// /// Default: 320 - #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")] - pub default_height: Option, + pub default_height: Option, /// The maximum number of lines to keep in the scrollback history. /// Maximum allowed value is 100_000, all values above that will be treated as 100_000. /// 0 disables the scrolling. diff --git a/crates/settings_content/src/workspace.rs b/crates/settings_content/src/workspace.rs index 991ed3d14f9..9d3f328928f 100644 --- a/crates/settings_content/src/workspace.rs +++ b/crates/settings_content/src/workspace.rs @@ -304,8 +304,7 @@ pub struct ActivePaneModifiers { /// The border is drawn inset. /// /// Default: `0.0` - #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")] - pub border_size: Option, + pub border_size: Option, /// Opacity of inactive panels. /// When set to 1.0, the inactive panes have the same opacity as the active one. /// If set to 0, the inactive panes content will not be visible at all. @@ -766,8 +765,7 @@ pub struct ProjectPanelSettingsContent { /// Customize default width (in pixels) taken by project panel /// /// Default: 240 - #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")] - pub default_width: Option, + pub default_width: Option, /// The position of project panel /// /// Default: right (Agentic layout), left (Classic layout) @@ -791,8 +789,7 @@ pub struct ProjectPanelSettingsContent { /// Amount of indentation (in pixels) for nested items. /// /// Default: 20 - #[serde(serialize_with = "serialize_optional_f32_with_two_decimal_places")] - pub indent_size: Option, + pub indent_size: Option, /// Whether to reveal it in the project panel automatically, /// when a corresponding project entry becomes active. /// Gitignored entries are never auto revealed. diff --git a/crates/settings_ui/src/components/number_field.rs b/crates/settings_ui/src/components/number_field.rs index 00201047406..614a0830c77 100644 --- a/crates/settings_ui/src/components/number_field.rs +++ b/crates/settings_ui/src/components/number_field.rs @@ -13,7 +13,7 @@ use gpui::{ use settings::{ CenteredPaddingSettings, CodeFade, DelayMs, FontSize, FontWeightContent, InactiveOpacity, - MinimumContrast, + MinimumContrast, PixelSetting, }; use ui::prelude::*; use zed_actions::editor::{MoveDown, MoveUp}; @@ -120,6 +120,7 @@ impl_newtype_numeric_stepper_float!(CodeFade, 0.1, 0.2, 0.05, 0.0, 0.9); impl_newtype_numeric_stepper_float!(FontSize, 1.0, 4.0, 0.5, 6.0, 72.0); impl_newtype_numeric_stepper_float!(InactiveOpacity, 0.1, 0.2, 0.05, 0.0, 1.0); impl_newtype_numeric_stepper_float!(MinimumContrast, 1., 10., 0.5, 0.0, 106.0); +impl_newtype_numeric_stepper_float!(PixelSetting, 1.0, 10.0, 0.5, 0.0, f32::MAX); impl_newtype_numeric_stepper_int!(DelayMs, 100, 500, 10, 0, 2000); impl_newtype_numeric_stepper_float!( CenteredPaddingSettings, diff --git a/crates/settings_ui/src/page_data.rs b/crates/settings_ui/src/page_data.rs index aea8f723289..ead651f5dd0 100644 --- a/crates/settings_ui/src/page_data.rs +++ b/crates/settings_ui/src/page_data.rs @@ -2341,29 +2341,96 @@ fn editor_page() -> SettingsPage { metadata: None, files: USER, }), - SettingsPageItem::SettingItem(SettingItem { - title: "Git Gutter Width", - description: "Width, in pixels, of the git diff indicators in the gutter. When unset, the width scales with the buffer font size.", - field: Box::new(SettingField { - organization_override: None, - json_path: Some("gutter.git_gutter_width"), - pick: |settings_content| { + SettingsPageItem::DynamicItem(DynamicItem { + discriminant: SettingItem { + title: "Git Gutter Width", + description: "Width of the git diff indicators in the gutter. Default scales with the buffer font size.", + field: Box::new(SettingField { + organization_override: None, + json_path: Some("gutter.git_gutter_width$"), + pick: |settings_content| { + Some( + &dynamic_variants::()[settings_content + .editor + .gutter + .as_ref()? + .git_gutter_width + .as_ref()? + .discriminant() + as usize], + ) + }, + write: |settings_content, value, _| { + let gutter = settings_content.editor.gutter.get_or_insert_default(); + gutter.git_gutter_width = value.map(|value| match value { + settings::GitGutterWidthDiscriminants::Default => { + settings::GitGutterWidth::Default + } + settings::GitGutterWidthDiscriminants::Custom => { + let width = match gutter.git_gutter_width { + Some(settings::GitGutterWidth::Custom(width)) => { + settings::PixelSetting(*width) + } + _ => settings::PixelSetting(3.0), + }; + settings::GitGutterWidth::Custom(width) + } + }); + }, + }), + metadata: None, + files: USER, + }, + pick_discriminant: |settings_content| { + Some( settings_content .editor .gutter - .as_ref() - .and_then(|gutter| gutter.git_gutter_width.as_ref()) - }, - write: |settings_content, value, _| { - settings_content - .editor - .gutter - .get_or_insert_default() - .git_gutter_width = value; - }, - }), - metadata: None, - files: USER, + .as_ref()? + .git_gutter_width + .as_ref()? + .discriminant() as usize, + ) + }, + fields: dynamic_variants::() + .into_iter() + .map(|variant| match variant { + settings::GitGutterWidthDiscriminants::Default => vec![], + settings::GitGutterWidthDiscriminants::Custom => vec![SettingItem { + files: USER, + title: "Custom Width", + description: "Width in pixels of the git diff indicators.", + field: Box::new(SettingField { + organization_override: None, + json_path: Some("gutter.git_gutter_width"), + pick: |settings_content| match settings_content + .editor + .gutter + .as_ref() + .and_then(|gutter| gutter.git_gutter_width.as_ref()) + { + Some(settings::GitGutterWidth::Custom(value)) => Some(value), + _ => None, + }, + write: |settings_content, value, _| { + let Some(value) = value else { + return; + }; + if let Some(settings::GitGutterWidth::Custom(width)) = + settings_content + .editor + .gutter + .as_mut() + .and_then(|gutter| gutter.git_gutter_width.as_mut()) + { + *width = value; + } + }, + }), + metadata: None, + }], + }) + .collect(), }), SettingsPageItem::SettingItem(SettingItem { title: "Inline Code Actions", diff --git a/crates/settings_ui/src/settings_ui.rs b/crates/settings_ui/src/settings_ui.rs index 221b0ecea94..223c39f2cdf 100644 --- a/crates/settings_ui/src/settings_ui.rs +++ b/crates/settings_ui/src/settings_ui.rs @@ -600,6 +600,7 @@ fn init_renderers(cx: &mut App) { .add_basic_renderer::(render_editable_number_field) .add_basic_renderer::(render_editable_number_field) .add_basic_renderer::(render_editable_number_field) + .add_basic_renderer::(render_editable_number_field) .add_basic_renderer::(render_editable_number_field) .add_basic_renderer::(render_editable_number_field) .add_basic_renderer::(render_editable_number_field) @@ -633,6 +634,7 @@ fn init_renderers(cx: &mut App) { .add_basic_renderer::(render_dropdown) .add_basic_renderer::(render_icon_theme_picker) .add_basic_renderer::(render_dropdown) + .add_basic_renderer::(render_dropdown) .add_basic_renderer::(render_dropdown) .add_basic_renderer::(render_dropdown) .add_basic_renderer::(render_dropdown) diff --git a/crates/terminal/src/terminal_settings.rs b/crates/terminal/src/terminal_settings.rs index 698f60f68f2..e9ac01b71f7 100644 --- a/crates/terminal/src/terminal_settings.rs +++ b/crates/terminal/src/terminal_settings.rs @@ -1,5 +1,5 @@ use collections::HashMap; -use gpui::{FontFallbacks, FontFeatures, FontWeight, Pixels, px}; +use gpui::{FontFallbacks, FontFeatures, FontWeight, Pixels}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -111,8 +111,8 @@ impl settings::Settings for TerminalSettings { button: user_content.button.unwrap(), dock: user_content.dock.unwrap(), starts_open: user_content.starts_open.unwrap(), - default_width: px(user_content.default_width.unwrap()), - default_height: px(user_content.default_height.unwrap()), + default_width: user_content.default_width.unwrap().into_gpui(), + default_height: user_content.default_height.unwrap().into_gpui(), flexible: user_content.flexible.unwrap(), detect_venv: project_content.detect_venv.unwrap(), scroll_multiplier: user_content.scroll_multiplier.unwrap(), diff --git a/crates/workspace/src/workspace_settings.rs b/crates/workspace/src/workspace_settings.rs index 3df477fb602..698e9ffef43 100644 --- a/crates/workspace/src/workspace_settings.rs +++ b/crates/workspace/src/workspace_settings.rs @@ -83,7 +83,7 @@ impl Settings for WorkspaceSettings { Self { active_pane_modifiers: ActivePanelModifiers { border_size: Some( - workspace + *workspace .active_pane_modifiers .unwrap() .border_size diff --git a/docs/src/reference/all-settings.md b/docs/src/reference/all-settings.md index 94d7fe0c957..8b260f91d63 100644 --- a/docs/src/reference/all-settings.md +++ b/docs/src/reference/all-settings.md @@ -839,7 +839,7 @@ List of `string` values "breakpoints": true, "folds": true, "min_line_number_digits": 4, - "git_gutter_width": null + "git_gutter_width": "default" } } ``` @@ -851,7 +851,7 @@ List of `string` values - `breakpoints`: Whether to show breakpoints in the gutter - `folds`: Whether to show fold buttons in the gutter - `min_line_number_digits`: Minimum number of characters to reserve space for in the gutter -- `git_gutter_width`: The width, in pixels, of the git diff hunk indicators in the gutter. When `null`, the width scales with the buffer font size +- `git_gutter_width`: The width, in pixels, of the git diff hunk indicators in the gutter. When `default`, the width scales with the buffer font size ## Hide Mouse