editor: Add support for no scroll margin in full mode (#41838)

Noticed this whilst testing the Docker debugger. I randomly scrolled the
console off screen and was confused briefly as to why this was the case.

Release Notes:

- The debugger query console will no longer needlessly overscroll.
This commit is contained in:
Finn Evers
2025-11-03 20:47:39 +01:00
committed by GitHub
parent 4da5675920
commit 08daedd014
7 changed files with 42 additions and 17 deletions
+2 -2
View File
@@ -4,7 +4,7 @@ use acp_thread::{AcpThread, AgentThreadEntry};
use agent::HistoryStore; use agent::HistoryStore;
use agent_client_protocol::{self as acp, ToolCallId}; use agent_client_protocol::{self as acp, ToolCallId};
use collections::HashMap; use collections::HashMap;
use editor::{Editor, EditorMode, MinimapVisibility}; use editor::{Editor, EditorMode, MinimapVisibility, SizingBehavior};
use gpui::{ use gpui::{
AnyEntity, App, AppContext as _, Entity, EntityId, EventEmitter, FocusHandle, Focusable, AnyEntity, App, AppContext as _, Entity, EntityId, EventEmitter, FocusHandle, Focusable,
ScrollHandle, SharedString, TextStyleRefinement, WeakEntity, Window, ScrollHandle, SharedString, TextStyleRefinement, WeakEntity, Window,
@@ -357,7 +357,7 @@ fn create_editor_diff(
EditorMode::Full { EditorMode::Full {
scale_ui_elements_with_buffer_font_size: false, scale_ui_elements_with_buffer_font_size: false,
show_active_line_background: false, show_active_line_background: false,
sized_by_content: true, sizing_behavior: SizingBehavior::SizeByContent,
}, },
diff.read(cx).multibuffer().clone(), diff.read(cx).multibuffer().clone(),
None, None,
+4 -2
View File
@@ -17,7 +17,9 @@ use client::zed_urls;
use cloud_llm_client::PlanV1; use cloud_llm_client::PlanV1;
use collections::{HashMap, HashSet}; use collections::{HashMap, HashSet};
use editor::scroll::Autoscroll; use editor::scroll::Autoscroll;
use editor::{Editor, EditorEvent, EditorMode, MultiBuffer, PathKey, SelectionEffects}; use editor::{
Editor, EditorEvent, EditorMode, MultiBuffer, PathKey, SelectionEffects, SizingBehavior,
};
use file_icons::FileIcons; use file_icons::FileIcons;
use fs::Fs; use fs::Fs;
use futures::FutureExt as _; use futures::FutureExt as _;
@@ -893,7 +895,7 @@ impl AcpThreadView {
EditorMode::Full { EditorMode::Full {
scale_ui_elements_with_buffer_font_size: false, scale_ui_elements_with_buffer_font_size: false,
show_active_line_background: false, show_active_line_background: false,
sized_by_content: false, sizing_behavior: SizingBehavior::ExcludeOverscrollMargin,
}, },
cx, cx,
) )
@@ -6,7 +6,10 @@ use alacritty_terminal::vte::ansi;
use anyhow::Result; use anyhow::Result;
use collections::HashMap; use collections::HashMap;
use dap::{CompletionItem, CompletionItemType, OutputEvent}; use dap::{CompletionItem, CompletionItemType, OutputEvent};
use editor::{Bias, CompletionProvider, Editor, EditorElement, EditorStyle, ExcerptId}; use editor::{
Bias, CompletionProvider, Editor, EditorElement, EditorMode, EditorStyle, ExcerptId,
SizingBehavior,
};
use fuzzy::StringMatchCandidate; use fuzzy::StringMatchCandidate;
use gpui::{ use gpui::{
Action as _, AppContext, Context, Corner, Entity, FocusHandle, Focusable, HighlightStyle, Hsla, Action as _, AppContext, Context, Corner, Entity, FocusHandle, Focusable, HighlightStyle, Hsla,
@@ -59,6 +62,11 @@ impl Console {
) -> Self { ) -> Self {
let console = cx.new(|cx| { let console = cx.new(|cx| {
let mut editor = Editor::multi_line(window, cx); let mut editor = Editor::multi_line(window, cx);
editor.set_mode(EditorMode::Full {
scale_ui_elements_with_buffer_font_size: true,
show_active_line_background: true,
sizing_behavior: SizingBehavior::ExcludeOverscrollMargin,
});
editor.move_to_end(&editor::actions::MoveToEnd, window, cx); editor.move_to_end(&editor::actions::MoveToEnd, window, cx);
editor.set_read_only(true); editor.set_read_only(true);
editor.disable_scrollbars_and_minimap(window, cx); editor.disable_scrollbars_and_minimap(window, cx);
+17 -3
View File
@@ -452,6 +452,20 @@ pub enum SelectMode {
All, All,
} }
#[derive(Copy, Clone, Default, PartialEq, Eq, Debug)]
pub enum SizingBehavior {
/// The editor will layout itself using `size_full` and will include the vertical
/// scroll margin as requested by user settings.
#[default]
Default,
/// The editor will layout itself using `size_full`, but will not have any
/// vertical overscroll.
ExcludeOverscrollMargin,
/// The editor will request a vertical size according to its content and will be
/// layouted without a vertical scroll margin.
SizeByContent,
}
#[derive(Clone, PartialEq, Eq, Debug)] #[derive(Clone, PartialEq, Eq, Debug)]
pub enum EditorMode { pub enum EditorMode {
SingleLine, SingleLine,
@@ -464,8 +478,8 @@ pub enum EditorMode {
scale_ui_elements_with_buffer_font_size: bool, scale_ui_elements_with_buffer_font_size: bool,
/// When set to `true`, the editor will render a background for the active line. /// When set to `true`, the editor will render a background for the active line.
show_active_line_background: bool, show_active_line_background: bool,
/// When set to `true`, the editor's height will be determined by its content. /// Determines the sizing behavior for this editor
sized_by_content: bool, sizing_behavior: SizingBehavior,
}, },
Minimap { Minimap {
parent: WeakEntity<Editor>, parent: WeakEntity<Editor>,
@@ -477,7 +491,7 @@ impl EditorMode {
Self::Full { Self::Full {
scale_ui_elements_with_buffer_font_size: true, scale_ui_elements_with_buffer_font_size: true,
show_active_line_background: true, show_active_line_background: true,
sized_by_content: false, sizing_behavior: SizingBehavior::Default,
} }
} }
+1 -1
View File
@@ -14217,7 +14217,7 @@ async fn test_completion_in_multibuffer_with_replace_range(cx: &mut TestAppConte
EditorMode::Full { EditorMode::Full {
scale_ui_elements_with_buffer_font_size: false, scale_ui_elements_with_buffer_font_size: false,
show_active_line_background: false, show_active_line_background: false,
sized_by_content: false, sizing_behavior: SizingBehavior::Default,
}, },
multi_buffer.clone(), multi_buffer.clone(),
Some(project.clone()), Some(project.clone()),
+6 -5
View File
@@ -8,8 +8,8 @@ use crate::{
HandleInput, HoveredCursor, InlayHintRefreshReason, JumpData, LineDown, LineHighlight, LineUp, HandleInput, HoveredCursor, InlayHintRefreshReason, JumpData, LineDown, LineHighlight, LineUp,
MAX_LINE_LEN, MINIMAP_FONT_SIZE, MULTI_BUFFER_EXCERPT_HEADER_HEIGHT, OpenExcerpts, PageDown, MAX_LINE_LEN, MINIMAP_FONT_SIZE, MULTI_BUFFER_EXCERPT_HEADER_HEIGHT, OpenExcerpts, PageDown,
PageUp, PhantomBreakpointIndicator, Point, RowExt, RowRangeExt, SelectPhase, PageUp, PhantomBreakpointIndicator, Point, RowExt, RowRangeExt, SelectPhase,
SelectedTextHighlight, Selection, SelectionDragState, SoftWrap, StickyHeaderExcerpt, ToPoint, SelectedTextHighlight, Selection, SelectionDragState, SizingBehavior, SoftWrap,
ToggleFold, ToggleFoldAll, StickyHeaderExcerpt, ToPoint, ToggleFold, ToggleFoldAll,
code_context_menus::{CodeActionsMenu, MENU_ASIDE_MAX_WIDTH, MENU_ASIDE_MIN_WIDTH, MENU_GAP}, code_context_menus::{CodeActionsMenu, MENU_ASIDE_MAX_WIDTH, MENU_ASIDE_MIN_WIDTH, MENU_GAP},
display_map::{ display_map::{
Block, BlockContext, BlockStyle, ChunkRendererId, DisplaySnapshot, EditorMargins, Block, BlockContext, BlockStyle, ChunkRendererId, DisplaySnapshot, EditorMargins,
@@ -8441,11 +8441,11 @@ impl Element for EditorElement {
window.request_layout(style, None, cx) window.request_layout(style, None, cx)
} }
EditorMode::Full { EditorMode::Full {
sized_by_content, .. sizing_behavior, ..
} => { } => {
let mut style = Style::default(); let mut style = Style::default();
style.size.width = relative(1.).into(); style.size.width = relative(1.).into();
if sized_by_content { if sizing_behavior == SizingBehavior::SizeByContent {
let snapshot = editor.snapshot(window, cx); let snapshot = editor.snapshot(window, cx);
let line_height = let line_height =
self.style.text.line_height_in_pixels(window.rem_size()); self.style.text.line_height_in_pixels(window.rem_size());
@@ -8609,7 +8609,8 @@ impl Element for EditorElement {
EditorMode::SingleLine EditorMode::SingleLine
| EditorMode::AutoHeight { .. } | EditorMode::AutoHeight { .. }
| EditorMode::Full { | EditorMode::Full {
sized_by_content: true, sizing_behavior: SizingBehavior::ExcludeOverscrollMargin
| SizingBehavior::SizeByContent,
.. ..
} }
) { ) {
+3 -3
View File
@@ -11,7 +11,7 @@ mod ui_components;
use anyhow::{Context as _, anyhow}; use anyhow::{Context as _, anyhow};
use collections::{HashMap, HashSet}; use collections::{HashMap, HashSet};
use editor::{CompletionProvider, Editor, EditorEvent}; use editor::{CompletionProvider, Editor, EditorEvent, EditorMode, SizingBehavior};
use fs::Fs; use fs::Fs;
use fuzzy::{StringMatch, StringMatchCandidate}; use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::{ use gpui::{
@@ -2788,10 +2788,10 @@ impl ActionArgumentsEditor {
let editor = cx.new_window_entity(|window, cx| { let editor = cx.new_window_entity(|window, cx| {
let multi_buffer = cx.new(|cx| editor::MultiBuffer::singleton(buffer, cx)); let multi_buffer = cx.new(|cx| editor::MultiBuffer::singleton(buffer, cx));
let mut editor = Editor::new( let mut editor = Editor::new(
editor::EditorMode::Full { EditorMode::Full {
scale_ui_elements_with_buffer_font_size: true, scale_ui_elements_with_buffer_font_size: true,
show_active_line_background: false, show_active_line_background: false,
sized_by_content: true, sizing_behavior: SizingBehavior::SizeByContent,
}, },
multi_buffer, multi_buffer,
project.upgrade(), project.upgrade(),