mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-29 15:31:38 +03:00
Keep cursor stable as autocompletions are being streamed
This commit is contained in:
parent
75ad76bfb2
commit
f8b9417406
@ -7,11 +7,8 @@ use chrono::{DateTime, Local};
|
|||||||
use collections::{HashMap, HashSet};
|
use collections::{HashMap, HashSet};
|
||||||
use editor::{
|
use editor::{
|
||||||
display_map::{BlockDisposition, BlockId, BlockProperties, BlockStyle, ToDisplayPoint},
|
display_map::{BlockDisposition, BlockId, BlockProperties, BlockStyle, ToDisplayPoint},
|
||||||
scroll::{
|
scroll::autoscroll::{Autoscroll, AutoscrollStrategy},
|
||||||
autoscroll::{Autoscroll, AutoscrollStrategy},
|
Anchor, Editor, ToOffset as _,
|
||||||
ScrollAnchor,
|
|
||||||
},
|
|
||||||
Anchor, DisplayPoint, Editor, ToOffset as _,
|
|
||||||
};
|
};
|
||||||
use fs::Fs;
|
use fs::Fs;
|
||||||
use futures::{io::BufReader, AsyncBufReadExt, AsyncReadExt, Stream, StreamExt};
|
use futures::{io::BufReader, AsyncBufReadExt, AsyncReadExt, Stream, StreamExt};
|
||||||
@ -19,7 +16,7 @@ use gpui::{
|
|||||||
actions,
|
actions,
|
||||||
elements::*,
|
elements::*,
|
||||||
executor::Background,
|
executor::Background,
|
||||||
geometry::vector::vec2f,
|
geometry::vector::{vec2f, Vector2F},
|
||||||
platform::{CursorStyle, MouseButton},
|
platform::{CursorStyle, MouseButton},
|
||||||
Action, AppContext, AsyncAppContext, ClipboardItem, Entity, ModelContext, ModelHandle,
|
Action, AppContext, AsyncAppContext, ClipboardItem, Entity, ModelContext, ModelHandle,
|
||||||
Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle, WindowContext,
|
Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle, WindowContext,
|
||||||
@ -801,11 +798,17 @@ enum AssistantEditorEvent {
|
|||||||
TabContentChanged,
|
TabContentChanged,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
|
struct ScrollPosition {
|
||||||
|
offset_before_cursor: Vector2F,
|
||||||
|
cursor: Anchor,
|
||||||
|
}
|
||||||
|
|
||||||
struct AssistantEditor {
|
struct AssistantEditor {
|
||||||
assistant: ModelHandle<Assistant>,
|
assistant: ModelHandle<Assistant>,
|
||||||
editor: ViewHandle<Editor>,
|
editor: ViewHandle<Editor>,
|
||||||
blocks: HashSet<BlockId>,
|
blocks: HashSet<BlockId>,
|
||||||
scroll_bottom: ScrollAnchor,
|
scroll_position: Option<ScrollPosition>,
|
||||||
_subscriptions: Vec<Subscription>,
|
_subscriptions: Vec<Subscription>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -833,10 +836,7 @@ impl AssistantEditor {
|
|||||||
assistant,
|
assistant,
|
||||||
editor,
|
editor,
|
||||||
blocks: Default::default(),
|
blocks: Default::default(),
|
||||||
scroll_bottom: ScrollAnchor {
|
scroll_position: None,
|
||||||
offset: Default::default(),
|
|
||||||
anchor: Anchor::max(),
|
|
||||||
},
|
|
||||||
_subscriptions,
|
_subscriptions,
|
||||||
};
|
};
|
||||||
this.update_message_headers(cx);
|
this.update_message_headers(cx);
|
||||||
@ -874,7 +874,7 @@ impl AssistantEditor {
|
|||||||
|selections| selections.select_ranges([cursor..cursor]),
|
|selections| selections.select_ranges([cursor..cursor]),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
self.update_scroll_bottom(cx);
|
self.scroll_position = self.cursor_scroll_position(cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -900,18 +900,16 @@ impl AssistantEditor {
|
|||||||
}
|
}
|
||||||
AssistantEvent::StreamedCompletion => {
|
AssistantEvent::StreamedCompletion => {
|
||||||
self.editor.update(cx, |editor, cx| {
|
self.editor.update(cx, |editor, cx| {
|
||||||
let snapshot = editor.snapshot(cx);
|
if let Some(scroll_position) = self.scroll_position {
|
||||||
let scroll_bottom_row = self
|
let snapshot = editor.snapshot(cx);
|
||||||
.scroll_bottom
|
let cursor_point = scroll_position.cursor.to_display_point(&snapshot);
|
||||||
.anchor
|
let scroll_top =
|
||||||
.to_display_point(&snapshot.display_snapshot)
|
cursor_point.row() as f32 - scroll_position.offset_before_cursor.y();
|
||||||
.row();
|
editor.set_scroll_position(
|
||||||
|
vec2f(scroll_position.offset_before_cursor.x(), scroll_top),
|
||||||
let scroll_bottom = scroll_bottom_row as f32 + self.scroll_bottom.offset.y();
|
cx,
|
||||||
let visible_line_count = editor.visible_line_count().unwrap_or(0.);
|
);
|
||||||
let scroll_top = scroll_bottom - visible_line_count;
|
}
|
||||||
editor
|
|
||||||
.set_scroll_position(vec2f(self.scroll_bottom.offset.x(), scroll_top), cx);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -924,11 +922,43 @@ impl AssistantEditor {
|
|||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) {
|
) {
|
||||||
match event {
|
match event {
|
||||||
editor::Event::ScrollPositionChanged { .. } => self.update_scroll_bottom(cx),
|
editor::Event::ScrollPositionChanged { .. } => {
|
||||||
|
if self.cursor_scroll_position(cx) != self.scroll_position {
|
||||||
|
self.scroll_position = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
editor::Event::SelectionsChanged { .. } => {
|
||||||
|
self.scroll_position = self.cursor_scroll_position(cx);
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn cursor_scroll_position(&self, cx: &mut ViewContext<Self>) -> Option<ScrollPosition> {
|
||||||
|
self.editor.update(cx, |editor, cx| {
|
||||||
|
let snapshot = editor.snapshot(cx);
|
||||||
|
let cursor = editor.selections.newest_anchor().head();
|
||||||
|
let cursor_row = cursor.to_display_point(&snapshot.display_snapshot).row() as f32;
|
||||||
|
let scroll_position = editor
|
||||||
|
.scroll_manager
|
||||||
|
.anchor()
|
||||||
|
.scroll_position(&snapshot.display_snapshot);
|
||||||
|
|
||||||
|
let scroll_bottom = scroll_position.y() + editor.visible_line_count().unwrap_or(0.);
|
||||||
|
if (scroll_position.y()..scroll_bottom).contains(&cursor_row) {
|
||||||
|
Some(ScrollPosition {
|
||||||
|
cursor,
|
||||||
|
offset_before_cursor: vec2f(
|
||||||
|
scroll_position.x(),
|
||||||
|
cursor_row - scroll_position.y(),
|
||||||
|
),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn update_message_headers(&mut self, cx: &mut ViewContext<Self>) {
|
fn update_message_headers(&mut self, cx: &mut ViewContext<Self>) {
|
||||||
self.editor.update(cx, |editor, cx| {
|
self.editor.update(cx, |editor, cx| {
|
||||||
let buffer = editor.buffer().read(cx).snapshot(cx);
|
let buffer = editor.buffer().read(cx).snapshot(cx);
|
||||||
@ -1031,32 +1061,6 @@ impl AssistantEditor {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_scroll_bottom(&mut self, cx: &mut ViewContext<Self>) {
|
|
||||||
self.editor.update(cx, |editor, cx| {
|
|
||||||
let snapshot = editor.snapshot(cx);
|
|
||||||
let scroll_position = editor
|
|
||||||
.scroll_manager
|
|
||||||
.anchor()
|
|
||||||
.scroll_position(&snapshot.display_snapshot);
|
|
||||||
let scroll_bottom = scroll_position.y() + editor.visible_line_count().unwrap_or(0.);
|
|
||||||
let scroll_bottom_point = cmp::min(
|
|
||||||
DisplayPoint::new(scroll_bottom.floor() as u32, 0),
|
|
||||||
snapshot.display_snapshot.max_point(),
|
|
||||||
);
|
|
||||||
let scroll_bottom_anchor = snapshot
|
|
||||||
.buffer_snapshot
|
|
||||||
.anchor_after(scroll_bottom_point.to_point(&snapshot.display_snapshot));
|
|
||||||
let scroll_bottom_offset = vec2f(
|
|
||||||
scroll_position.x(),
|
|
||||||
scroll_bottom - scroll_bottom_point.row() as f32,
|
|
||||||
);
|
|
||||||
self.scroll_bottom = ScrollAnchor {
|
|
||||||
anchor: scroll_bottom_anchor,
|
|
||||||
offset: scroll_bottom_offset,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn quote_selection(
|
fn quote_selection(
|
||||||
workspace: &mut Workspace,
|
workspace: &mut Workspace,
|
||||||
_: &QuoteSelection,
|
_: &QuoteSelection,
|
||||||
|
Loading…
Reference in New Issue
Block a user