Add settings to control gutter elements (#7665)

The current gutter was a bit too big for my taste, so I added some
settings to change which visual elements are shown, including being able
to hide the gutter completely.

This should help with the following issues: #4963, #4382, #7422

New settings:
```json5
"gutter": {
    "line_numbers": true, // Whether line numbers are shown
    "buttons": true // Whether the code action/folding buttons are shown
}
```

The existing `git.git_gutter` setting is also taken into account when
calculating the width of the gutter.

We could also separate the display of the code action and folding
buttons into separate settings, let me know if that is desirable.

## Screenshots:

- Everything on (`gutter.line_numbers`, `gutter.buttons`,
`git.git_gutter`):
<img width="434" alt="SCR-20240210-trfb"
src="https://github.com/zed-industries/zed/assets/17355488/bcc55311-6e1d-4c22-8c43-4f364637959b">

- Only line numbers and git gutter (`gutter.line_numbers`,
`git.git_gutter`):
<img width="406" alt="SCR-20240210-trhm"
src="https://github.com/zed-industries/zed/assets/17355488/0a0e074d-64d0-437c-851b-55560d5a6c6b">

- Only git gutter (`git.git_gutter`):
<img width="356" alt="SCR-20240210-trkb"
src="https://github.com/zed-industries/zed/assets/17355488/7ebdb38d-93a5-4e38-b008-beabf355510d">

- Only git gutter and buttons (`git.git_gutter`, `gutter.buttons`):
<img width="356" alt="SCR-20240210-txyo"
src="https://github.com/zed-industries/zed/assets/17355488/e2c92c05-cc30-43bc-9399-09ea5e376e1b">


- Nothing:
<img width="350" alt="SCR-20240210-trne"
src="https://github.com/zed-industries/zed/assets/17355488/e0cd301d-c3e0-4b31-ac69-997515928b5a">



## Release Notes:
- Added settings to control the display of gutter visual elements. `"gutter": {"line_numbers": true,    "code_actions": true,    "folds": true}` ([#8041](https://github.com/zed-industries/zed/issues/8041))  ([#7422](https://github.com/zed-industries/zed/issues/7422))
```

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
This commit is contained in:
Felipe 2024-02-23 00:37:13 -03:00 committed by GitHub
parent 0de8672044
commit a82f4857f4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 175 additions and 81 deletions

View file

@ -140,6 +140,14 @@
// Whether to show diagnostic indicators in the scrollbar. // Whether to show diagnostic indicators in the scrollbar.
"diagnostics": true "diagnostics": true
}, },
"gutter": {
// Whether to show line numbers in the gutter.
"line_numbers": true,
// Whether to show code action buttons in the gutter.
"code_actions": true,
// Whether to show fold buttons in the gutter.
"folds": true
},
// The number of lines to keep above/below the cursor when scrolling. // The number of lines to keep above/below the cursor when scrolling.
"vertical_scroll_margin": 3, "vertical_scroll_margin": 3,
"relative_line_numbers": false, "relative_line_numbers": false,

View file

@ -365,7 +365,7 @@ impl AssistantPanel {
move |cx: &mut BlockContext| { move |cx: &mut BlockContext| {
measurements.set(BlockMeasurements { measurements.set(BlockMeasurements {
anchor_x: cx.anchor_x, anchor_x: cx.anchor_x,
gutter_width: cx.gutter_width, gutter_width: cx.gutter_dimensions.width,
}); });
inline_assistant.clone().into_any_element() inline_assistant.clone().into_any_element()
} }

View file

@ -885,7 +885,7 @@ mod tests {
use super::*; use super::*;
use editor::{ use editor::{
display_map::{BlockContext, TransformBlock}, display_map::{BlockContext, TransformBlock},
DisplayPoint, DisplayPoint, GutterDimensions,
}; };
use gpui::{px, TestAppContext, VisualTestContext, WindowContext}; use gpui::{px, TestAppContext, VisualTestContext, WindowContext};
use language::{Diagnostic, DiagnosticEntry, DiagnosticSeverity, PointUtf16, Unclipped}; use language::{Diagnostic, DiagnosticEntry, DiagnosticSeverity, PointUtf16, Unclipped};
@ -1599,8 +1599,7 @@ mod tests {
.render(&mut BlockContext { .render(&mut BlockContext {
context: cx, context: cx,
anchor_x: px(0.), anchor_x: px(0.),
gutter_padding: px(0.), gutter_dimensions: &GutterDimensions::default(),
gutter_width: px(0.),
line_height: px(0.), line_height: px(0.),
em_width: px(0.), em_width: px(0.),
max_width: px(0.), max_width: px(0.),

View file

@ -2,7 +2,7 @@ use super::{
wrap_map::{self, WrapEdit, WrapPoint, WrapSnapshot}, wrap_map::{self, WrapEdit, WrapPoint, WrapSnapshot},
Highlights, Highlights,
}; };
use crate::{Anchor, Editor, EditorStyle, ExcerptId, ExcerptRange, ToPoint as _}; use crate::{Anchor, Editor, EditorStyle, ExcerptId, ExcerptRange, GutterDimensions, ToPoint as _};
use collections::{Bound, HashMap, HashSet}; use collections::{Bound, HashMap, HashSet};
use gpui::{AnyElement, ElementContext, Pixels, View}; use gpui::{AnyElement, ElementContext, Pixels, View};
use language::{BufferSnapshot, Chunk, Patch, Point}; use language::{BufferSnapshot, Chunk, Patch, Point};
@ -88,8 +88,7 @@ pub struct BlockContext<'a, 'b> {
pub view: View<Editor>, pub view: View<Editor>,
pub anchor_x: Pixels, pub anchor_x: Pixels,
pub max_width: Pixels, pub max_width: Pixels,
pub gutter_width: Pixels, pub gutter_dimensions: &'b GutterDimensions,
pub gutter_padding: Pixels,
pub em_width: Pixels, pub em_width: Pixels,
pub line_height: Pixels, pub line_height: Pixels,
pub block_id: usize, pub block_id: usize,

View file

@ -88,6 +88,7 @@ pub use multi_buffer::{
}; };
use ordered_float::OrderedFloat; use ordered_float::OrderedFloat;
use parking_lot::{Mutex, RwLock}; use parking_lot::{Mutex, RwLock};
use project::project_settings::{GitGutterSetting, ProjectSettings};
use project::{FormatTrigger, Location, Project, ProjectPath, ProjectTransaction}; use project::{FormatTrigger, Location, Project, ProjectPath, ProjectTransaction};
use rand::prelude::*; use rand::prelude::*;
use rpc::proto::*; use rpc::proto::*;
@ -443,7 +444,8 @@ pub struct EditorSnapshot {
} }
pub struct GutterDimensions { pub struct GutterDimensions {
pub padding: Pixels, pub left_padding: Pixels,
pub right_padding: Pixels,
pub width: Pixels, pub width: Pixels,
pub margin: Pixels, pub margin: Pixels,
} }
@ -451,7 +453,8 @@ pub struct GutterDimensions {
impl Default for GutterDimensions { impl Default for GutterDimensions {
fn default() -> Self { fn default() -> Self {
Self { Self {
padding: Pixels::ZERO, left_padding: Pixels::ZERO,
right_padding: Pixels::ZERO,
width: Pixels::ZERO, width: Pixels::ZERO,
margin: Pixels::ZERO, margin: Pixels::ZERO,
} }
@ -4058,7 +4061,8 @@ impl Editor {
if self.available_code_actions.is_some() { if self.available_code_actions.is_some() {
Some( Some(
IconButton::new("code_actions_indicator", ui::IconName::Bolt) IconButton::new("code_actions_indicator", ui::IconName::Bolt)
.icon_size(IconSize::Small) .icon_size(IconSize::XSmall)
.size(ui::ButtonSize::None)
.icon_color(Color::Muted) .icon_color(Color::Muted)
.selected(is_active) .selected(is_active)
.on_click(cx.listener(|editor, _e, cx| { .on_click(cx.listener(|editor, _e, cx| {
@ -9636,23 +9640,50 @@ impl EditorSnapshot {
max_line_number_width: Pixels, max_line_number_width: Pixels,
cx: &AppContext, cx: &AppContext,
) -> GutterDimensions { ) -> GutterDimensions {
if self.show_gutter { if !self.show_gutter {
return GutterDimensions::default();
}
let descent = cx.text_system().descent(font_id, font_size); let descent = cx.text_system().descent(font_id, font_size);
let gutter_padding_factor = 4.0;
let gutter_padding = (em_width * gutter_padding_factor).round(); let show_git_gutter = matches!(
ProjectSettings::get_global(cx).git.git_gutter,
Some(GitGutterSetting::TrackedFiles)
);
let gutter_settings = EditorSettings::get_global(cx).gutter;
let line_gutter_width = if gutter_settings.line_numbers {
// Avoid flicker-like gutter resizes when the line number gains another digit and only resize the gutter on files with N*10^5 lines. // Avoid flicker-like gutter resizes when the line number gains another digit and only resize the gutter on files with N*10^5 lines.
let min_width_for_number_on_gutter = em_width * 4.0; let min_width_for_number_on_gutter = em_width * 4.0;
let gutter_width = max_line_number_width.max(min_width_for_number_on_gutter)
max_line_number_width.max(min_width_for_number_on_gutter) + gutter_padding * 2.0; } else {
let gutter_margin = -descent; 0.0.into()
};
let left_padding = if gutter_settings.code_actions {
em_width * 3.0
} else if show_git_gutter && gutter_settings.line_numbers {
em_width * 2.0
} else if show_git_gutter || gutter_settings.line_numbers {
em_width
} else {
px(0.)
};
let right_padding = if gutter_settings.folds && gutter_settings.line_numbers {
em_width * 4.0
} else if gutter_settings.folds {
em_width * 3.0
} else if gutter_settings.line_numbers {
em_width
} else {
px(0.)
};
GutterDimensions { GutterDimensions {
padding: gutter_padding, left_padding,
width: gutter_width, right_padding,
margin: gutter_margin, width: line_gutter_width + left_padding + right_padding,
} margin: -descent,
} else {
GutterDimensions::default()
} }
} }
} }
@ -10159,9 +10190,14 @@ pub fn diagnostic_block_renderer(diagnostic: Diagnostic, _is_valid: bool) -> Ren
.group(group_id.clone()) .group(group_id.clone())
.relative() .relative()
.size_full() .size_full()
.pl(cx.gutter_width) .pl(cx.gutter_dimensions.width)
.w(cx.max_width + cx.gutter_width) .w(cx.max_width + cx.gutter_dimensions.width)
.child(div().flex().w(cx.anchor_x - cx.gutter_width).flex_shrink()) .child(
div()
.flex()
.w(cx.anchor_x - cx.gutter_dimensions.width)
.flex_shrink(),
)
.child(div().flex().flex_shrink_0().child( .child(div().flex().flex_shrink_0().child(
StyledText::new(text_without_backticks.clone()).with_highlights( StyledText::new(text_without_backticks.clone()).with_highlights(
&text_style, &text_style,

View file

@ -12,6 +12,7 @@ pub struct EditorSettings {
pub use_on_type_format: bool, pub use_on_type_format: bool,
pub toolbar: Toolbar, pub toolbar: Toolbar,
pub scrollbar: Scrollbar, pub scrollbar: Scrollbar,
pub gutter: Gutter,
pub vertical_scroll_margin: f32, pub vertical_scroll_margin: f32,
pub relative_line_numbers: bool, pub relative_line_numbers: bool,
pub seed_search_query_from_cursor: SeedQuerySetting, pub seed_search_query_from_cursor: SeedQuerySetting,
@ -45,6 +46,13 @@ pub struct Scrollbar {
pub diagnostics: bool, pub diagnostics: bool,
} }
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
pub struct Gutter {
pub line_numbers: bool,
pub code_actions: bool,
pub folds: bool,
}
/// When to show the scrollbar in the editor. /// When to show the scrollbar in the editor.
/// ///
/// Default: auto /// Default: auto
@ -97,6 +105,8 @@ pub struct EditorSettingsContent {
pub toolbar: Option<ToolbarContent>, pub toolbar: Option<ToolbarContent>,
/// Scrollbar related settings /// Scrollbar related settings
pub scrollbar: Option<ScrollbarContent>, pub scrollbar: Option<ScrollbarContent>,
/// Gutter related settings
pub gutter: Option<GutterContent>,
/// The number of lines to keep above/below the cursor when auto-scrolling. /// The number of lines to keep above/below the cursor when auto-scrolling.
/// ///
@ -157,6 +167,23 @@ pub struct ScrollbarContent {
pub diagnostics: Option<bool>, pub diagnostics: Option<bool>,
} }
/// Gutter related settings
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
pub struct GutterContent {
/// Whether to show line numbers in the gutter.
///
/// Default: true
pub line_numbers: Option<bool>,
/// Whether to show code action buttons in the gutter.
///
/// Default: true
pub code_actions: Option<bool>,
/// Whether to show fold buttons in the gutter.
///
/// Default: true
pub folds: Option<bool>,
}
impl Settings for EditorSettings { impl Settings for EditorSettings {
const KEY: Option<&'static str> = None; const KEY: Option<&'static str> = None;

View file

@ -12,9 +12,9 @@ use crate::{
mouse_context_menu, mouse_context_menu,
scroll::scroll_amount::ScrollAmount, scroll::scroll_amount::ScrollAmount,
CursorShape, DisplayPoint, DocumentHighlightRead, DocumentHighlightWrite, Editor, EditorMode, CursorShape, DisplayPoint, DocumentHighlightRead, DocumentHighlightWrite, Editor, EditorMode,
EditorSettings, EditorSnapshot, EditorStyle, HalfPageDown, HalfPageUp, HoveredCursor, LineDown, EditorSettings, EditorSnapshot, EditorStyle, GutterDimensions, HalfPageDown, HalfPageUp,
LineUp, OpenExcerpts, PageDown, PageUp, Point, SelectPhase, Selection, SoftWrap, ToPoint, HoveredCursor, LineDown, LineUp, OpenExcerpts, PageDown, PageUp, Point, SelectPhase, Selection,
CURSORS_VISIBLE_FOR, MAX_LINE_LEN, SoftWrap, ToPoint, CURSORS_VISIBLE_FOR, MAX_LINE_LEN,
}; };
use anyhow::Result; use anyhow::Result;
use collections::{BTreeMap, HashMap}; use collections::{BTreeMap, HashMap};
@ -716,20 +716,22 @@ impl EditorElement {
let scroll_position = layout.position_map.snapshot.scroll_position(); let scroll_position = layout.position_map.snapshot.scroll_position();
let scroll_top = scroll_position.y * line_height; let scroll_top = scroll_position.y * line_height;
let show_gutter = matches!( let show_git_gutter = matches!(
ProjectSettings::get_global(cx).git.git_gutter, ProjectSettings::get_global(cx).git.git_gutter,
Some(GitGutterSetting::TrackedFiles) Some(GitGutterSetting::TrackedFiles)
); );
if show_gutter { if show_git_gutter {
Self::paint_diff_hunks(bounds, layout, cx); Self::paint_diff_hunks(bounds, layout, cx);
} }
let gutter_settings = EditorSettings::get_global(cx).gutter;
for (ix, line) in layout.line_numbers.iter().enumerate() { for (ix, line) in layout.line_numbers.iter().enumerate() {
if let Some(line) = line { if let Some(line) = line {
let line_origin = bounds.origin let line_origin = bounds.origin
+ point( + point(
bounds.size.width - line.width - layout.gutter_padding, bounds.size.width - line.width - layout.gutter_dimensions.right_padding,
ix as f32 * line_height - (scroll_top % line_height), ix as f32 * line_height - (scroll_top % line_height),
); );
@ -740,6 +742,7 @@ impl EditorElement {
cx.with_z_index(1, |cx| { cx.with_z_index(1, |cx| {
for (ix, fold_indicator) in layout.fold_indicators.drain(..).enumerate() { for (ix, fold_indicator) in layout.fold_indicators.drain(..).enumerate() {
if let Some(fold_indicator) = fold_indicator { if let Some(fold_indicator) = fold_indicator {
debug_assert!(gutter_settings.folds);
let mut fold_indicator = fold_indicator.into_any_element(); let mut fold_indicator = fold_indicator.into_any_element();
let available_space = size( let available_space = size(
AvailableSpace::MinContent, AvailableSpace::MinContent,
@ -748,11 +751,12 @@ impl EditorElement {
let fold_indicator_size = fold_indicator.measure(available_space, cx); let fold_indicator_size = fold_indicator.measure(available_space, cx);
let position = point( let position = point(
bounds.size.width - layout.gutter_padding, bounds.size.width - layout.gutter_dimensions.right_padding,
ix as f32 * line_height - (scroll_top % line_height), ix as f32 * line_height - (scroll_top % line_height),
); );
let centering_offset = point( let centering_offset = point(
(layout.gutter_padding + layout.gutter_margin - fold_indicator_size.width) (layout.gutter_dimensions.right_padding + layout.gutter_dimensions.margin
- fold_indicator_size.width)
/ 2., / 2.,
(line_height - fold_indicator_size.height) / 2., (line_height - fold_indicator_size.height) / 2.,
); );
@ -762,6 +766,7 @@ impl EditorElement {
} }
if let Some(indicator) = layout.code_actions_indicator.take() { if let Some(indicator) = layout.code_actions_indicator.take() {
debug_assert!(gutter_settings.code_actions);
let mut button = indicator.button.into_any_element(); let mut button = indicator.button.into_any_element();
let available_space = size( let available_space = size(
AvailableSpace::MinContent, AvailableSpace::MinContent,
@ -772,7 +777,9 @@ impl EditorElement {
let mut x = Pixels::ZERO; let mut x = Pixels::ZERO;
let mut y = indicator.row as f32 * line_height - scroll_top; let mut y = indicator.row as f32 * line_height - scroll_top;
// Center indicator. // Center indicator.
x += ((layout.gutter_padding + layout.gutter_margin) - indicator_size.width) / 2.; x += (layout.gutter_dimensions.margin + layout.gutter_dimensions.left_padding
- indicator_size.width)
/ 2.;
y += (line_height - indicator_size.height) / 2.; y += (line_height - indicator_size.height) / 2.;
button.draw(bounds.origin + point(x, y), available_space, cx); button.draw(bounds.origin + point(x, y), available_space, cx);
@ -887,7 +894,8 @@ impl EditorElement {
cx: &mut ElementContext, cx: &mut ElementContext,
) { ) {
let start_row = layout.visible_display_row_range.start; let start_row = layout.visible_display_row_range.start;
let content_origin = text_bounds.origin + point(layout.gutter_margin, Pixels::ZERO); let content_origin =
text_bounds.origin + point(layout.gutter_dimensions.margin, Pixels::ZERO);
let line_end_overshoot = 0.15 * layout.position_map.line_height; let line_end_overshoot = 0.15 * layout.position_map.line_height;
let whitespace_setting = self let whitespace_setting = self
.editor .editor
@ -1156,7 +1164,8 @@ impl EditorElement {
layout: &LayoutState, layout: &LayoutState,
cx: &mut ElementContext, cx: &mut ElementContext,
) { ) {
let content_origin = text_bounds.origin + point(layout.gutter_margin, Pixels::ZERO); let content_origin =
text_bounds.origin + point(layout.gutter_dimensions.margin, Pixels::ZERO);
let line_end_overshoot = layout.line_end_overshoot(); let line_end_overshoot = layout.line_end_overshoot();
// A softer than perfect black // A softer than perfect black
@ -1182,7 +1191,8 @@ impl EditorElement {
layout: &mut LayoutState, layout: &mut LayoutState,
cx: &mut ElementContext, cx: &mut ElementContext,
) { ) {
let content_origin = text_bounds.origin + point(layout.gutter_margin, Pixels::ZERO); let content_origin =
text_bounds.origin + point(layout.gutter_dimensions.margin, Pixels::ZERO);
let start_row = layout.visible_display_row_range.start; let start_row = layout.visible_display_row_range.start;
if let Some((position, mut context_menu)) = layout.context_menu.take() { if let Some((position, mut context_menu)) = layout.context_menu.take() {
let available_space = size(AvailableSpace::MinContent, AvailableSpace::MinContent); let available_space = size(AvailableSpace::MinContent, AvailableSpace::MinContent);
@ -1819,7 +1829,10 @@ impl EditorElement {
Vec<Option<(FoldStatus, BufferRow, bool)>>, Vec<Option<(FoldStatus, BufferRow, bool)>>,
) { ) {
let font_size = self.style.text.font_size.to_pixels(cx.rem_size()); let font_size = self.style.text.font_size.to_pixels(cx.rem_size());
let include_line_numbers = snapshot.mode == EditorMode::Full; let include_line_numbers =
EditorSettings::get_global(cx).gutter.line_numbers && snapshot.mode == EditorMode::Full;
let include_fold_statuses =
EditorSettings::get_global(cx).gutter.folds && snapshot.mode == EditorMode::Full;
let mut shaped_line_numbers = Vec::with_capacity(rows.len()); let mut shaped_line_numbers = Vec::with_capacity(rows.len());
let mut fold_statuses = Vec::with_capacity(rows.len()); let mut fold_statuses = Vec::with_capacity(rows.len());
let mut line_number = String::new(); let mut line_number = String::new();
@ -1864,6 +1877,8 @@ impl EditorElement {
.shape_line(line_number.clone().into(), font_size, &[run]) .shape_line(line_number.clone().into(), font_size, &[run])
.unwrap(); .unwrap();
shaped_line_numbers.push(Some(shaped_line)); shaped_line_numbers.push(Some(shaped_line));
}
if include_fold_statuses {
fold_statuses.push( fold_statuses.push(
is_singleton is_singleton
.then(|| { .then(|| {
@ -1960,7 +1975,13 @@ impl EditorElement {
.unwrap() .unwrap()
.width; .width;
let gutter_dimensions = snapshot.gutter_dimensions(font_id, font_size, em_width, self.max_line_number_width(&snapshot, cx), cx); let gutter_dimensions = snapshot.gutter_dimensions(
font_id,
font_size,
em_width,
self.max_line_number_width(&snapshot, cx),
cx,
);
editor.gutter_width = gutter_dimensions.width; editor.gutter_width = gutter_dimensions.width;
@ -2213,8 +2234,7 @@ impl EditorElement {
bounds.size.width, bounds.size.width,
scroll_width, scroll_width,
text_width, text_width,
gutter_dimensions.padding, &gutter_dimensions,
gutter_dimensions.width,
em_width, em_width,
gutter_dimensions.width + gutter_dimensions.margin, gutter_dimensions.width + gutter_dimensions.margin,
line_height, line_height,
@ -2251,6 +2271,8 @@ impl EditorElement {
snapshot = editor.snapshot(cx); snapshot = editor.snapshot(cx);
} }
let gutter_settings = EditorSettings::get_global(cx).gutter;
let mut context_menu = None; let mut context_menu = None;
let mut code_actions_indicator = None; let mut code_actions_indicator = None;
if let Some(newest_selection_head) = newest_selection_head { if let Some(newest_selection_head) = newest_selection_head {
@ -2272,6 +2294,7 @@ impl EditorElement {
Some(crate::ContextMenu::CodeActions(_)) Some(crate::ContextMenu::CodeActions(_))
); );
if gutter_settings.code_actions {
code_actions_indicator = editor code_actions_indicator = editor
.render_code_actions_indicator(&style, active, cx) .render_code_actions_indicator(&style, active, cx)
.map(|element| CodeActionsIndicator { .map(|element| CodeActionsIndicator {
@ -2280,6 +2303,7 @@ impl EditorElement {
}); });
} }
} }
}
let visible_rows = start_row..start_row + line_layouts.len() as u32; let visible_rows = start_row..start_row + line_layouts.len() as u32;
let max_size = size( let max_size = size(
@ -2305,8 +2329,8 @@ impl EditorElement {
}; };
let editor_view = cx.view().clone(); let editor_view = cx.view().clone();
let fold_indicators = cx.with_element_context(|cx| { let fold_indicators = if gutter_settings.folds {
cx.with_element_context(|cx| {
cx.with_element_id(Some("gutter_fold_indicators"), |_cx| { cx.with_element_id(Some("gutter_fold_indicators"), |_cx| {
editor.render_fold_indicators( editor.render_fold_indicators(
fold_statuses, fold_statuses,
@ -2317,7 +2341,10 @@ impl EditorElement {
editor_view, editor_view,
) )
}) })
}); })
} else {
Vec::new()
};
let invisible_symbol_font_size = font_size / 2.; let invisible_symbol_font_size = font_size / 2.;
let tab_invisible = cx let tab_invisible = cx
@ -2370,13 +2397,12 @@ impl EditorElement {
visible_display_row_range: start_row..end_row, visible_display_row_range: start_row..end_row,
wrap_guides, wrap_guides,
gutter_size, gutter_size,
gutter_padding: gutter_dimensions.padding, gutter_dimensions,
text_size, text_size,
scrollbar_row_range, scrollbar_row_range,
show_scrollbars, show_scrollbars,
is_singleton, is_singleton,
max_row, max_row,
gutter_margin: gutter_dimensions.margin,
active_rows, active_rows,
highlighted_rows, highlighted_rows,
highlighted_ranges, highlighted_ranges,
@ -2403,8 +2429,7 @@ impl EditorElement {
editor_width: Pixels, editor_width: Pixels,
scroll_width: Pixels, scroll_width: Pixels,
text_width: Pixels, text_width: Pixels,
gutter_padding: Pixels, gutter_dimensions: &GutterDimensions,
gutter_width: Pixels,
em_width: Pixels, em_width: Pixels,
text_x: Pixels, text_x: Pixels,
line_height: Pixels, line_height: Pixels,
@ -2447,9 +2472,8 @@ impl EditorElement {
block.render(&mut BlockContext { block.render(&mut BlockContext {
context: cx, context: cx,
anchor_x, anchor_x,
gutter_padding, gutter_dimensions,
line_height, line_height,
gutter_width,
em_width, em_width,
block_id, block_id,
max_width: scroll_width.max(text_width), max_width: scroll_width.max(text_width),
@ -2553,12 +2577,14 @@ impl EditorElement {
h_flex() h_flex()
.id(("collapsed context", block_id)) .id(("collapsed context", block_id))
.size_full() .size_full()
.gap(gutter_padding) .gap(gutter_dimensions.left_padding + gutter_dimensions.right_padding)
.child( .child(
h_flex() h_flex()
.justify_end() .justify_end()
.flex_none() .flex_none()
.w(gutter_width - gutter_padding) .w(gutter_dimensions.width
- (gutter_dimensions.left_padding
+ gutter_dimensions.right_padding))
.h_full() .h_full()
.text_buffer(cx) .text_buffer(cx)
.text_color(cx.theme().colors().editor_line_number) .text_color(cx.theme().colors().editor_line_number)
@ -2619,7 +2645,7 @@ impl EditorElement {
BlockStyle::Sticky => editor_width, BlockStyle::Sticky => editor_width,
BlockStyle::Flex => editor_width BlockStyle::Flex => editor_width
.max(fixed_block_max_width) .max(fixed_block_max_width)
.max(gutter_width + scroll_width), .max(gutter_dimensions.width + scroll_width),
BlockStyle::Fixed => unreachable!(), BlockStyle::Fixed => unreachable!(),
}; };
let available_space = size( let available_space = size(
@ -2636,7 +2662,7 @@ impl EditorElement {
}); });
} }
( (
scroll_width.max(fixed_block_max_width - gutter_width), scroll_width.max(fixed_block_max_width - gutter_dimensions.width),
blocks, blocks,
) )
} }
@ -3153,8 +3179,7 @@ type BufferRow = u32;
pub struct LayoutState { pub struct LayoutState {
position_map: Arc<PositionMap>, position_map: Arc<PositionMap>,
gutter_size: Size<Pixels>, gutter_size: Size<Pixels>,
gutter_padding: Pixels, gutter_dimensions: GutterDimensions,
gutter_margin: Pixels,
text_size: gpui::Size<Pixels>, text_size: gpui::Size<Pixels>,
mode: EditorMode, mode: EditorMode,
wrap_guides: SmallVec<[(Pixels, bool); 2]>, wrap_guides: SmallVec<[(Pixels, bool); 2]>,