diff --git a/crates/assistant_context_editor/src/context_editor.rs b/crates/assistant_context_editor/src/context_editor.rs index 8fc2433476..214001d13f 100644 --- a/crates/assistant_context_editor/src/context_editor.rs +++ b/crates/assistant_context_editor/src/context_editor.rs @@ -13,7 +13,7 @@ use editor::{ BlockContext, BlockId, BlockPlacement, BlockProperties, BlockStyle, Crease, CreaseMetadata, CustomBlockId, FoldId, RenderBlock, ToDisplayPoint, }, - scroll::{Autoscroll, AutoscrollStrategy}, + scroll::Autoscroll, Anchor, Editor, EditorEvent, MenuInlineCompletionsPolicy, ProposedChangeLocation, ProposedChangesEditor, RowExt, ToOffset as _, ToPoint, }; @@ -414,12 +414,9 @@ impl ContextEditor { cursor..cursor }; self.editor.update(cx, |editor, cx| { - editor.change_selections( - Some(Autoscroll::Strategy(AutoscrollStrategy::Fit)), - window, - cx, - |selections| selections.select_ranges([new_selection]), - ); + editor.change_selections(Some(Autoscroll::fit()), window, cx, |selections| { + selections.select_ranges([new_selection]) + }); }); // Avoid scrolling to the new cursor position so the assistant's output is stable. cx.defer_in(window, |this, _, _| this.scroll_position = None); diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 15670720bb..c4828cc7d3 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -12644,15 +12644,14 @@ impl Editor { let start = snapshot.buffer_snapshot.anchor_before(start); let end = snapshot.buffer_snapshot.anchor_before(end); - self.clear_row_highlights::(); self.highlight_rows::( start..end, highlight_color .unwrap_or_else(|| cx.theme().colors().editor_highlighted_line_background), - true, + false, cx, ); - self.request_autoscroll(Autoscroll::center(), cx); + self.request_autoscroll(Autoscroll::center().for_anchor(start), cx); } pub fn go_to_definition( diff --git a/crates/editor/src/scroll/autoscroll.rs b/crates/editor/src/scroll/autoscroll.rs index f0cfb3a3c6..eae2706a38 100644 --- a/crates/editor/src/scroll/autoscroll.rs +++ b/crates/editor/src/scroll/autoscroll.rs @@ -3,54 +3,66 @@ use crate::{ }; use gpui::{px, Bounds, Context, Pixels, Window}; use language::Point; +use multi_buffer::Anchor; use std::{cmp, f32}; #[derive(PartialEq, Eq, Clone, Copy)] pub enum Autoscroll { Next, - Strategy(AutoscrollStrategy), + Strategy(AutoscrollStrategy, Option), } impl Autoscroll { /// scrolls the minimal amount to (try) and fit all cursors onscreen pub fn fit() -> Self { - Self::Strategy(AutoscrollStrategy::Fit) + Self::Strategy(AutoscrollStrategy::Fit, None) } /// scrolls the minimal amount to fit the newest cursor pub fn newest() -> Self { - Self::Strategy(AutoscrollStrategy::Newest) + Self::Strategy(AutoscrollStrategy::Newest, None) } /// scrolls so the newest cursor is vertically centered pub fn center() -> Self { - Self::Strategy(AutoscrollStrategy::Center) + Self::Strategy(AutoscrollStrategy::Center, None) } /// scrolls so the newest cursor is near the top /// (offset by vertical_scroll_margin) pub fn focused() -> Self { - Self::Strategy(AutoscrollStrategy::Focused) + Self::Strategy(AutoscrollStrategy::Focused, None) } /// Scrolls so that the newest cursor is roughly an n-th line from the top. pub fn top_relative(n: usize) -> Self { - Self::Strategy(AutoscrollStrategy::TopRelative(n)) + Self::Strategy(AutoscrollStrategy::TopRelative(n), None) } /// Scrolls so that the newest cursor is at the top. pub fn top() -> Self { - Self::Strategy(AutoscrollStrategy::Top) + Self::Strategy(AutoscrollStrategy::Top, None) } /// Scrolls so that the newest cursor is roughly an n-th line from the bottom. pub fn bottom_relative(n: usize) -> Self { - Self::Strategy(AutoscrollStrategy::BottomRelative(n)) + Self::Strategy(AutoscrollStrategy::BottomRelative(n), None) } /// Scrolls so that the newest cursor is at the bottom. pub fn bottom() -> Self { - Self::Strategy(AutoscrollStrategy::Bottom) + Self::Strategy(AutoscrollStrategy::Bottom, None) + } + + /// Applies a given auto-scroll strategy to a given anchor instead of a cursor. + /// E.G: Autoscroll::center().for_anchor(...) results in the anchor being at the center of the screen. + pub fn for_anchor(self, anchor: Anchor) -> Self { + match self { + Autoscroll::Next => self, + Autoscroll::Strategy(autoscroll_strategy, _) => { + Self::Strategy(autoscroll_strategy, Some(anchor)) + } + } } } @@ -142,8 +154,11 @@ impl Editor { .as_f32(); let selections_fit = target_bottom - target_top <= visible_lines; - if autoscroll == Autoscroll::newest() - || (autoscroll == Autoscroll::fit() && !selections_fit) + if matches!( + autoscroll, + Autoscroll::Strategy(AutoscrollStrategy::Newest, _) + ) || (matches!(autoscroll, Autoscroll::Strategy(AutoscrollStrategy::Fit, _)) + && !selections_fit) { let newest_selection_top = selections .iter() @@ -165,7 +180,7 @@ impl Editor { }; let strategy = match autoscroll { - Autoscroll::Strategy(strategy) => strategy, + Autoscroll::Strategy(strategy, _) => strategy, Autoscroll::Next => { let last_autoscroll = &self.scroll_manager.last_autoscroll; if let Some(last_autoscroll) = last_autoscroll { @@ -182,6 +197,10 @@ impl Editor { } } }; + if let Autoscroll::Strategy(_, Some(anchor)) = autoscroll { + target_top = anchor.to_display_point(&display_map).row().as_f32(); + target_bottom = target_top + 1.; + } match strategy { AutoscrollStrategy::Fit | AutoscrollStrategy::Newest => { diff --git a/crates/markdown_preview/src/markdown_preview_view.rs b/crates/markdown_preview/src/markdown_preview_view.rs index 13fee8737c..ae62ea3d62 100644 --- a/crates/markdown_preview/src/markdown_preview_view.rs +++ b/crates/markdown_preview/src/markdown_preview_view.rs @@ -3,7 +3,7 @@ use std::time::Duration; use std::{ops::Range, path::PathBuf}; use anyhow::Result; -use editor::scroll::{Autoscroll, AutoscrollStrategy}; +use editor::scroll::Autoscroll; use editor::{Editor, EditorEvent}; use gpui::{ list, App, ClickEvent, Context, Entity, EventEmitter, FocusHandle, Focusable, @@ -408,12 +408,9 @@ impl MarkdownPreviewView { ) { if let Some(state) = &self.active_editor { state.editor.update(cx, |editor, cx| { - editor.change_selections( - Some(Autoscroll::Strategy(AutoscrollStrategy::Center)), - window, - cx, - |selections| selections.select_ranges(vec![selection]), - ); + editor.change_selections(Some(Autoscroll::center()), window, cx, |selections| { + selections.select_ranges(vec![selection]) + }); window.focus(&editor.focus_handle(cx)); }); } diff --git a/crates/outline_panel/src/outline_panel.rs b/crates/outline_panel/src/outline_panel.rs index 5530f745f9..45b47d323c 100644 --- a/crates/outline_panel/src/outline_panel.rs +++ b/crates/outline_panel/src/outline_panel.rs @@ -1067,7 +1067,7 @@ impl OutlinePanel { if change_selection { active_editor.update(cx, |editor, cx| { editor.change_selections( - Some(Autoscroll::Strategy(AutoscrollStrategy::Center)), + Some(Autoscroll::Strategy(AutoscrollStrategy::Center, None)), window, cx, |s| s.select_ranges(Some(anchor..anchor)),