editor: Add configurable git gutter width setting (#61304)
## Summary
Adds a `gutter.git_gutter_width` setting that lets users pin the width,
in pixels, of the git diff hunk indicators in the editor gutter.
Previously the width was always derived from the buffer font size
(`floor(0.275 * line_height)`), which can render too thin or too thick
depending on font family and display pixel density. This adds an
optional override:
```json
{
"gutter": {
"git_gutter_width": 6
}
}
```
When the setting is unset (`null`, the default), the width continues to
scale with the buffer font size, so existing behavior is unchanged.
## Motivation
Requested in [discussion
#27799](https://github.com/zed-industries/zed/discussions/27799). Beyond
the width itself, participants noted the git hunk hit target is
extremely narrow and hard to click. Because the hunk hitbox reuses the
painted strip bounds, setting a wider `git_gutter_width` also widens the
clickable area, addressing that complaint with the same setting.
## Changes
- `settings_content`: new `git_gutter_width: Option<f32>` on
`GutterContent`.
- `editor`: mirror field on the resolved `Gutter`; `gutter_strip_width`
now consults the setting, and the value flows through `diff_hunk_bounds`
(including the deleted-hunk marker) and the gutter layout anchors for
line numbers, folds, and expand toggles.
- `settings` (VS Code import): pass through the new field.
- Docs + `default.json`: document the new setting.
## Notes
- `Eq` was dropped from `GutterContent`/`Gutter` because `f32` is not
`Eq`; this matches the existing `EditorSettingsContent` convention for
float-bearing settings.
Release Notes:
- Added a `gutter.git_gutter_width` setting to configure the width of
git diff indicators in the editor gutter
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
077311366d
commit
3b56897a51
7 files changed
+57
-11
No files matched your search
@@ -695,6 +695,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,
|
||||
},
|
||||
"indent_guides": {
|
||||
// Whether to show indent guides in the editor.
|
||||
|
||||
@@ -141,7 +141,7 @@ impl Minimap {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub struct Gutter {
|
||||
pub min_line_number_digits: usize,
|
||||
pub line_numbers: bool,
|
||||
@@ -149,6 +149,7 @@ pub struct Gutter {
|
||||
pub breakpoints: bool,
|
||||
pub bookmarks: bool,
|
||||
pub folds: bool,
|
||||
pub git_gutter_width: Option<f32>,
|
||||
}
|
||||
|
||||
/// Forcefully enable or disable the scrollbar for each axis
|
||||
@@ -267,6 +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,
|
||||
},
|
||||
scroll_beyond_last_line: editor.scroll_beyond_last_line.unwrap(),
|
||||
vertical_scroll_margin: editor.vertical_scroll_margin.unwrap() as f64,
|
||||
|
||||
@@ -1676,6 +1676,7 @@ impl EditorElement {
|
||||
gutter_hitbox.bounds,
|
||||
hunk,
|
||||
snapshot,
|
||||
cx,
|
||||
);
|
||||
*hitbox = Some(window.insert_hitbox(hunk_bounds, HitboxBehavior::BlockMouse));
|
||||
}
|
||||
@@ -2669,7 +2670,7 @@ impl EditorElement {
|
||||
.ilog10()
|
||||
+ 1;
|
||||
|
||||
let git_gutter_width = Self::gutter_strip_width(line_height)
|
||||
let git_gutter_width = Self::gutter_strip_width(line_height, cx)
|
||||
+ gutter_dimensions
|
||||
.git_blame_entries_width
|
||||
.unwrap_or_default();
|
||||
@@ -5228,6 +5229,7 @@ impl EditorElement {
|
||||
layout.gutter_hitbox.bounds,
|
||||
hunk,
|
||||
&layout.position_map.snapshot,
|
||||
cx,
|
||||
);
|
||||
Some((
|
||||
hunk_bounds,
|
||||
@@ -5313,8 +5315,11 @@ impl EditorElement {
|
||||
});
|
||||
}
|
||||
|
||||
fn gutter_strip_width(line_height: Pixels) -> Pixels {
|
||||
(0.275 * line_height).floor()
|
||||
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(),
|
||||
}
|
||||
}
|
||||
|
||||
fn diff_hunk_bounds(
|
||||
@@ -5323,9 +5328,10 @@ impl EditorElement {
|
||||
gutter_bounds: Bounds<Pixels>,
|
||||
hunk: &DisplayDiffHunk,
|
||||
snapshot: &EditorSnapshot,
|
||||
cx: &App,
|
||||
) -> Bounds<Pixels> {
|
||||
let scroll_top = scroll_position.y * ScrollPixelOffset::from(line_height);
|
||||
let gutter_strip_width = Self::gutter_strip_width(line_height);
|
||||
let gutter_strip_width = Self::gutter_strip_width(line_height, cx);
|
||||
|
||||
match hunk {
|
||||
DisplayDiffHunk::Folded { display_row, .. } => {
|
||||
@@ -5351,7 +5357,10 @@ impl EditorElement {
|
||||
.into();
|
||||
let end_y = start_y + line_height;
|
||||
|
||||
let width = (0.35 * line_height).floor();
|
||||
let width = match EditorSettings::get_global(cx).gutter.git_gutter_width {
|
||||
Some(width) => px(width),
|
||||
None => (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);
|
||||
Bounds::new(highlight_origin, highlight_size)
|
||||
@@ -6720,7 +6729,7 @@ impl Gutter<'_> {
|
||||
AvailableSpace::Definite(self.line_height),
|
||||
);
|
||||
let indicator_size = button.layout_as_root(available_space, window, cx);
|
||||
let git_gutter_width = EditorElement::gutter_strip_width(self.line_height)
|
||||
let git_gutter_width = EditorElement::gutter_strip_width(self.line_height, cx)
|
||||
+ self.dimensions.git_blame_entries_width.unwrap_or_default();
|
||||
|
||||
let x = git_gutter_width + px(2.);
|
||||
@@ -9148,7 +9157,7 @@ impl Element for EditorElement {
|
||||
);
|
||||
}
|
||||
|
||||
let git_gutter_width = Self::gutter_strip_width(line_height)
|
||||
let git_gutter_width = Self::gutter_strip_width(line_height, cx)
|
||||
+ gutter_dimensions
|
||||
.git_blame_entries_width
|
||||
.unwrap_or_default();
|
||||
|
||||
@@ -350,6 +350,7 @@ impl VsCodeSettings {
|
||||
"never" => Some(false),
|
||||
_ => None,
|
||||
}),
|
||||
git_gutter_width: None,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -483,7 +483,7 @@ pub struct ScrollbarAxesContent {
|
||||
|
||||
/// Gutter related settings
|
||||
#[with_fallible_options]
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq)]
|
||||
pub struct GutterContent {
|
||||
/// Whether to show line numbers in the gutter.
|
||||
///
|
||||
@@ -509,6 +509,11 @@ pub struct GutterContent {
|
||||
///
|
||||
/// Default: true
|
||||
pub folds: Option<bool>,
|
||||
/// The width, in pixels, of the git diff hunk indicators in the gutter.
|
||||
/// When unset, the width scales with the buffer font size.
|
||||
///
|
||||
/// Default: null
|
||||
pub git_gutter_width: Option<f32>,
|
||||
}
|
||||
|
||||
/// Whether to display code lenses from language servers above code elements.
|
||||
|
||||
@@ -2182,7 +2182,7 @@ fn editor_page() -> SettingsPage {
|
||||
]
|
||||
}
|
||||
|
||||
fn gutter_section() -> [SettingsPageItem; 9] {
|
||||
fn gutter_section() -> [SettingsPageItem; 10] {
|
||||
[
|
||||
SettingsPageItem::SectionHeader("Gutter"),
|
||||
SettingsPageItem::SettingItem(SettingItem {
|
||||
@@ -2339,6 +2339,30 @@ 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| {
|
||||
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,
|
||||
}),
|
||||
SettingsPageItem::SettingItem(SettingItem {
|
||||
title: "Inline Code Actions",
|
||||
description: "Show code action button at start of buffer line.",
|
||||
|
||||
@@ -838,7 +838,8 @@ List of `string` values
|
||||
"runnables": true,
|
||||
"breakpoints": true,
|
||||
"folds": true,
|
||||
"min_line_number_digits": 4
|
||||
"min_line_number_digits": 4,
|
||||
"git_gutter_width": null
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -850,6 +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
|
||||
|
||||
## Hide Mouse
|
||||
|
||||
|
||||
Reference in new issue
Block a user