Get editor2 compiling with a ton of code commented out

This commit is contained in:
Nathan Sobo 2023-11-02 23:35:20 -06:00
parent f3b8a9d8c2
commit fbee6b5352
12 changed files with 582 additions and 552 deletions

View file

@ -241,7 +241,7 @@ impl DisplayMap {
pub fn set_font(&self, font: Font, font_size: Pixels, cx: &mut ModelContext<Self>) -> bool {
self.wrap_map
.update(cx, |map, cx| map.set_font(font, font_size, cx))
.update(cx, |map, cx| map.set_font_with_size(font, font_size, cx))
}
pub fn set_fold_ellipses_color(&mut self, color: Hsla) -> bool {
@ -1388,7 +1388,7 @@ pub fn next_rows(display_row: u32, display_map: &DisplaySnapshot) -> impl Iterat
// );
// // Re-wrap on font size changes
// map.update(cx, |map, cx| map.set_font(font_id, font_size + 3., cx));
// map.update(cx, |map, cx| map.set_font_with_size(font_id, font_size + 3., cx));
// let snapshot = map.update(cx, |map, cx| map.snapshot(cx));
// assert_eq!(

View file

@ -1629,7 +1629,8 @@ mod tests {
}
fn init_test(cx: &mut gpui::AppContext) {
cx.set_global(SettingsStore::test(cx));
let store = SettingsStore::test(cx);
cx.set_global(store);
}
impl FoldMap {

View file

@ -1889,7 +1889,8 @@ mod tests {
}
fn init_test(cx: &mut AppContext) {
cx.set_global(SettingsStore::test(cx));
let store = SettingsStore::test(cx);
cx.set_global(store);
theme::init(cx);
}
}

View file

@ -23,7 +23,7 @@ pub struct WrapMap {
edits_since_sync: Patch<u32>,
wrap_width: Option<Pixels>,
background_task: Option<Task<()>>,
font: (Font, Pixels),
font_with_size: (Font, Pixels),
}
#[derive(Clone)]
@ -76,7 +76,7 @@ impl WrapMap {
) -> (Model<Self>, WrapSnapshot) {
let handle = cx.build_model(|cx| {
let mut this = Self {
font: (font, font_size),
font_with_size: (font, font_size),
wrap_width: None,
pending_edits: Default::default(),
interpolated_edits: Default::default(),
@ -116,9 +116,16 @@ impl WrapMap {
(self.snapshot.clone(), mem::take(&mut self.edits_since_sync))
}
pub fn set_font(&mut self, font: Font, font_size: Pixels, cx: &mut ModelContext<Self>) -> bool {
if (font, font_size) != self.font {
self.font = (font, font_size);
pub fn set_font_with_size(
&mut self,
font: Font,
font_size: Pixels,
cx: &mut ModelContext<Self>,
) -> bool {
let font_with_size = (font, font_size);
if font_with_size != self.font_with_size {
self.font_with_size = font_with_size;
self.rewrap(cx);
true
} else {
@ -149,10 +156,9 @@ impl WrapMap {
let mut new_snapshot = self.snapshot.clone();
let mut edits = Patch::default();
let text_system = cx.text_system().clone();
let (font_id, font_size) = self.font;
let (font, font_size) = self.font_with_size.clone();
let task = cx.background_executor().spawn(async move {
if let Some(mut line_wrapper) =
text_system.line_wrapper(font_id, font_size).log_err()
if let Some(mut line_wrapper) = text_system.line_wrapper(font, font_size).log_err()
{
let tab_snapshot = new_snapshot.tab_snapshot.clone();
let range = TabPoint::zero()..tab_snapshot.max_point();
@ -236,11 +242,11 @@ impl WrapMap {
let pending_edits = self.pending_edits.clone();
let mut snapshot = self.snapshot.clone();
let text_system = cx.text_system().clone();
let (font_id, font_size) = self.font;
let (font, font_size) = self.font_with_size.clone();
let update_task = cx.background_executor().spawn(async move {
let mut edits = Patch::default();
if let Some(mut line_wrapper) =
text_system.line_wrapper(font_id, font_size).log_err()
text_system.line_wrapper(font, font_size).log_err()
{
for (tab_snapshot, tab_edits) in pending_edits {
let wrap_edits = snapshot

View file

@ -35,8 +35,8 @@ pub use element::{
use futures::FutureExt;
use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::{
AnyElement, AppContext, BackgroundExecutor, Element, EventEmitter, Model, Pixels, Render,
Subscription, Task, TextStyle, View, ViewContext, WeakView, WindowContext,
AnyElement, AppContext, BackgroundExecutor, Context, Element, EventEmitter, Model, Pixels,
Render, Subscription, Task, TextStyle, View, ViewContext, WeakView, WindowContext,
};
use hover_popover::HoverState;
pub use items::MAX_TAB_TITLE_LEN;
@ -64,7 +64,7 @@ use std::{
cmp::Reverse,
ops::{Deref, DerefMut, Range},
sync::Arc,
time::Duration,
time::{Duration, Instant},
};
pub use sum_tree::Bias;
use util::{ResultExt, TryFutureExt};
@ -1810,14 +1810,14 @@ impl Editor {
// )
// }
// pub fn for_buffer(
// buffer: Model<Buffer>,
// project: Option<Model<Project>>,
// cx: &mut ViewContext<Self>,
// ) -> Self {
// let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
// Self::new(EditorMode::Full, buffer, project, None, cx)
// }
pub fn for_buffer(
buffer: Model<Buffer>,
project: Option<Model<Project>>,
cx: &mut ViewContext<Self>,
) -> Self {
let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx));
Self::new(EditorMode::Full, buffer, project, cx)
}
// pub fn for_multibuffer(
// buffer: Model<MultiBuffer>,
@ -1827,171 +1827,175 @@ impl Editor {
// Self::new(EditorMode::Full, buffer, project, None, cx)
// }
// pub fn clone(&self, cx: &mut ViewContext<Self>) -> Self {
// let mut clone = Self::new(
// self.mode,
// self.buffer.clone(),
// self.project.clone(),
// self.get_field_editor_theme.clone(),
pub fn clone(&self, cx: &mut ViewContext<Self>) -> Self {
let mut clone = Self::new(
self.mode,
self.buffer.clone(),
self.project.clone(),
// todo!
// self.get_field_editor_theme.clone(),
cx,
);
self.display_map.update(cx, |display_map, cx| {
let snapshot = display_map.snapshot(cx);
clone.display_map.update(cx, |display_map, cx| {
display_map.set_state(&snapshot, cx);
});
});
clone.selections.clone_state(&self.selections);
clone.scroll_manager.clone_state(&self.scroll_manager);
clone.searchable = self.searchable;
clone
}
fn new(
mode: EditorMode,
buffer: Model<MultiBuffer>,
project: Option<Model<Project>>,
// todo!()
// get_field_editor_theme: Option<Arc<GetFieldEditorTheme>>,
cx: &mut ViewContext<Self>,
) -> Self {
todo!("old version below")
}
// let editor_view_id = cx.view_id();
// let display_map = cx.add_model(|cx| {
// let settings = settings::get::<ThemeSettings>(cx);
// let style = build_style(settings, get_field_editor_theme.as_deref(), None, cx);
// DisplayMap::new(
// buffer.clone(),
// style.text.font_id,
// style.text.font_size,
// None,
// 2,
// 1,
// cx,
// );
// self.display_map.update(cx, |display_map, cx| {
// let snapshot = display_map.snapshot(cx);
// clone.display_map.update(cx, |display_map, cx| {
// display_map.set_state(&snapshot, cx);
// });
// });
// clone.selections.clone_state(&self.selections);
// clone.scroll_manager.clone_state(&self.scroll_manager);
// clone.searchable = self.searchable;
// clone
// }
// )
// });
// fn new(
// mode: EditorMode,
// buffer: Model<MultiBuffer>,
// project: Option<Model<Project>>,
// get_field_editor_theme: Option<Arc<GetFieldEditorTheme>>,
// cx: &mut ViewContext<Self>,
// ) -> Self {
// let editor_view_id = cx.view_id();
// let display_map = cx.add_model(|cx| {
// let settings = settings::get::<ThemeSettings>(cx);
// let style = build_style(settings, get_field_editor_theme.as_deref(), None, cx);
// DisplayMap::new(
// buffer.clone(),
// style.text.font_id,
// style.text.font_size,
// None,
// 2,
// 1,
// cx,
// )
// });
// let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
// let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
// let blink_manager = cx.add_model(|cx| BlinkManager::new(CURSOR_BLINK_INTERVAL, cx));
// let blink_manager = cx.add_model(|cx| BlinkManager::new(CURSOR_BLINK_INTERVAL, cx));
// let soft_wrap_mode_override =
// (mode == EditorMode::SingleLine).then(|| language_settings::SoftWrap::None);
// let soft_wrap_mode_override =
// (mode == EditorMode::SingleLine).then(|| language_settings::SoftWrap::None);
// let mut project_subscriptions = Vec::new();
// if mode == EditorMode::Full {
// if let Some(project) = project.as_ref() {
// if buffer.read(cx).is_singleton() {
// project_subscriptions.push(cx.observe(project, |_, _, cx| {
// cx.emit(Event::TitleChanged);
// }));
// }
// project_subscriptions.push(cx.subscribe(project, |editor, _, event, cx| {
// if let project::Event::RefreshInlayHints = event {
// editor.refresh_inlay_hints(InlayHintRefreshReason::RefreshRequested, cx);
// };
// let mut project_subscriptions = Vec::new();
// if mode == EditorMode::Full {
// if let Some(project) = project.as_ref() {
// if buffer.read(cx).is_singleton() {
// project_subscriptions.push(cx.observe(project, |_, _, cx| {
// cx.emit(Event::TitleChanged);
// }));
// }
// project_subscriptions.push(cx.subscribe(project, |editor, _, event, cx| {
// if let project::Event::RefreshInlayHints = event {
// editor.refresh_inlay_hints(InlayHintRefreshReason::RefreshRequested, cx);
// };
// }));
// }
// let inlay_hint_settings = inlay_hint_settings(
// selections.newest_anchor().head(),
// &buffer.read(cx).snapshot(cx),
// cx,
// );
// let mut this = Self {
// handle: cx.weak_handle(),
// buffer: buffer.clone(),
// display_map: display_map.clone(),
// selections,
// scroll_manager: ScrollManager::new(),
// columnar_selection_tail: None,
// add_selections_state: None,
// select_next_state: None,
// select_prev_state: None,
// selection_history: Default::default(),
// autoclose_regions: Default::default(),
// snippet_stack: Default::default(),
// select_larger_syntax_node_stack: Vec::new(),
// ime_transaction: Default::default(),
// active_diagnostics: None,
// soft_wrap_mode_override,
// get_field_editor_theme,
// collaboration_hub: project.clone().map(|project| Box::new(project) as _),
// project,
// focused: false,
// blink_manager: blink_manager.clone(),
// show_local_selections: true,
// mode,
// show_gutter: mode == EditorMode::Full,
// show_wrap_guides: None,
// placeholder_text: None,
// highlighted_rows: None,
// background_highlights: Default::default(),
// inlay_background_highlights: Default::default(),
// nav_history: None,
// context_menu: RwLock::new(None),
// mouse_context_menu: cx
// .add_view(|cx| context_menu::ContextMenu::new(editor_view_id, cx)),
// completion_tasks: Default::default(),
// next_completion_id: 0,
// next_inlay_id: 0,
// available_code_actions: Default::default(),
// code_actions_task: Default::default(),
// document_highlights_task: Default::default(),
// pending_rename: Default::default(),
// searchable: true,
// override_text_style: None,
// cursor_shape: Default::default(),
// autoindent_mode: Some(AutoindentMode::EachLine),
// collapse_matches: false,
// workspace: None,
// keymap_context_layers: Default::default(),
// input_enabled: true,
// read_only: false,
// leader_peer_id: None,
// remote_id: None,
// hover_state: Default::default(),
// link_go_to_definition_state: Default::default(),
// copilot_state: Default::default(),
// // inlay_hint_cache: InlayHintCache::new(inlay_hint_settings),
// gutter_hovered: false,
// pixel_position_of_newest_cursor: None,
// _subscriptions: vec![
// cx.observe(&buffer, Self::on_buffer_changed),
// cx.subscribe(&buffer, Self::on_buffer_event),
// cx.observe(&display_map, Self::on_display_map_changed),
// cx.observe(&blink_manager, |_, _, cx| cx.notify()),
// cx.observe_global::<SettingsStore, _>(Self::settings_changed),
// cx.observe_window_activation(|editor, active, cx| {
// editor.blink_manager.update(cx, |blink_manager, cx| {
// if active {
// blink_manager.enable(cx);
// } else {
// blink_manager.show_cursor(cx);
// blink_manager.disable(cx);
// }
// });
// }),
// ],
// };
// this._subscriptions.extend(project_subscriptions);
// this.end_selection(cx);
// this.scroll_manager.show_scrollbar(cx);
// let editor_created_event = EditorCreated(cx.handle());
// cx.emit_global(editor_created_event);
// if mode == EditorMode::Full {
// let should_auto_hide_scrollbars = cx.platform().should_auto_hide_scrollbars();
// cx.set_global(ScrollbarAutoHide(should_auto_hide_scrollbars));
// }
// this.report_editor_event("open", None, cx);
// this
// }
// let inlay_hint_settings = inlay_hint_settings(
// selections.newest_anchor().head(),
// &buffer.read(cx).snapshot(cx),
// cx,
// );
// let mut this = Self {
// handle: cx.weak_handle(),
// buffer: buffer.clone(),
// display_map: display_map.clone(),
// selections,
// scroll_manager: ScrollManager::new(),
// columnar_selection_tail: None,
// add_selections_state: None,
// select_next_state: None,
// select_prev_state: None,
// selection_history: Default::default(),
// autoclose_regions: Default::default(),
// snippet_stack: Default::default(),
// select_larger_syntax_node_stack: Vec::new(),
// ime_transaction: Default::default(),
// active_diagnostics: None,
// soft_wrap_mode_override,
// get_field_editor_theme,
// collaboration_hub: project.clone().map(|project| Box::new(project) as _),
// project,
// focused: false,
// blink_manager: blink_manager.clone(),
// show_local_selections: true,
// mode,
// show_gutter: mode == EditorMode::Full,
// show_wrap_guides: None,
// placeholder_text: None,
// highlighted_rows: None,
// background_highlights: Default::default(),
// inlay_background_highlights: Default::default(),
// nav_history: None,
// context_menu: RwLock::new(None),
// mouse_context_menu: cx
// .add_view(|cx| context_menu::ContextMenu::new(editor_view_id, cx)),
// completion_tasks: Default::default(),
// next_completion_id: 0,
// next_inlay_id: 0,
// available_code_actions: Default::default(),
// code_actions_task: Default::default(),
// document_highlights_task: Default::default(),
// pending_rename: Default::default(),
// searchable: true,
// override_text_style: None,
// cursor_shape: Default::default(),
// autoindent_mode: Some(AutoindentMode::EachLine),
// collapse_matches: false,
// workspace: None,
// keymap_context_layers: Default::default(),
// input_enabled: true,
// read_only: false,
// leader_peer_id: None,
// remote_id: None,
// hover_state: Default::default(),
// link_go_to_definition_state: Default::default(),
// copilot_state: Default::default(),
// // inlay_hint_cache: InlayHintCache::new(inlay_hint_settings),
// gutter_hovered: false,
// pixel_position_of_newest_cursor: None,
// _subscriptions: vec![
// cx.observe(&buffer, Self::on_buffer_changed),
// cx.subscribe(&buffer, Self::on_buffer_event),
// cx.observe(&display_map, Self::on_display_map_changed),
// cx.observe(&blink_manager, |_, _, cx| cx.notify()),
// cx.observe_global::<SettingsStore, _>(Self::settings_changed),
// cx.observe_window_activation(|editor, active, cx| {
// editor.blink_manager.update(cx, |blink_manager, cx| {
// if active {
// blink_manager.enable(cx);
// } else {
// blink_manager.show_cursor(cx);
// blink_manager.disable(cx);
// }
// });
// }),
// ],
// };
// this._subscriptions.extend(project_subscriptions);
// this.end_selection(cx);
// this.scroll_manager.show_scrollbar(cx);
// let editor_created_event = EditorCreated(cx.handle());
// cx.emit_global(editor_created_event);
// if mode == EditorMode::Full {
// let should_auto_hide_scrollbars = cx.platform().should_auto_hide_scrollbars();
// cx.set_global(ScrollbarAutoHide(should_auto_hide_scrollbars));
// }
// this.report_editor_event("open", None, cx);
// this
// }
// pub fn new_file(
// workspace: &mut Workspace,
// _: &workspace::NewFile,
@ -2316,19 +2320,19 @@ impl Editor {
// result
// }
// pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
// where
// I: IntoIterator<Item = (Range<S>, T)>,
// S: ToOffset,
// T: Into<Arc<str>>,
// {
// if self.read_only {
// return;
// }
pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
where
I: IntoIterator<Item = (Range<S>, T)>,
S: ToOffset,
T: Into<Arc<str>>,
{
if self.read_only {
return;
}
// self.buffer
// .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
// }
self.buffer
.update(cx, |buffer, cx| buffer.edit(edits, None, cx));
}
// pub fn edit_with_autoindent<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
// where
@ -8058,48 +8062,50 @@ impl Editor {
// });
// }
// pub fn transact(
// &mut self,
// cx: &mut ViewContext<Self>,
// update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
// ) -> Option<TransactionId> {
// self.start_transaction_at(Instant::now(), cx);
// update(self, cx);
// self.end_transaction_at(Instant::now(), cx)
// }
pub fn transact(
&mut self,
cx: &mut ViewContext<Self>,
update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
) -> Option<TransactionId> {
self.start_transaction_at(Instant::now(), cx);
update(self, cx);
self.end_transaction_at(Instant::now(), cx)
}
// fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
// self.end_selection(cx);
// if let Some(tx_id) = self
// .buffer
// .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
// {
// self.selection_history
// .insert_transaction(tx_id, self.selections.disjoint_anchors());
// }
// }
fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
todo!()
// self.end_selection(cx);
// if let Some(tx_id) = self
// .buffer
// .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
// {
// self.selection_history
// .insert_transaction(tx_id, self.selections.disjoint_anchors());
// }
}
// fn end_transaction_at(
// &mut self,
// now: Instant,
// cx: &mut ViewContext<Self>,
// ) -> Option<TransactionId> {
// if let Some(tx_id) = self
// .buffer
// .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
// {
// if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
// *end_selections = Some(self.selections.disjoint_anchors());
// } else {
// error!("unexpectedly ended a transaction that wasn't started by this editor");
// }
fn end_transaction_at(
&mut self,
now: Instant,
cx: &mut ViewContext<Self>,
) -> Option<TransactionId> {
todo!()
// if let Some(tx_id) = self
// .buffer
// .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
// {
// if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
// *end_selections = Some(self.selections.disjoint_anchors());
// } else {
// error!("unexpectedly ended a transaction that wasn't started by this editor");
// }
// cx.emit(Event::Edited);
// Some(tx_id)
// } else {
// None
// }
// }
// cx.emit(Event::Edited);
// Some(tx_id)
// } else {
// None
// }
}
// pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
// let mut fold_ranges = Vec::new();
@ -9304,7 +9310,7 @@ impl Render for Editor {
// let style = self.style(cx);
// let font_changed = self.display_map.update(cx, |map, cx| {
// map.set_fold_ellipses_color(style.folds.ellipses.text_color);
// map.set_font(style.text.font_id, style.text.font_size, cx)
// map.set_font_with_size(style.text.font_id, style.text.font_size, cx)
// });
// if font_changed {

View file

@ -2704,10 +2704,11 @@ impl PositionMap {
let y = position.y.max(px(0.)).min(self.size.width);
let x = position.x + (scroll_position.x * self.em_width);
let row = (f32::from(y / self.line_height) + scroll_position.y) as u32;
let (column, x_overshoot_after_line_end) = if let Some(line) = self
.line_layouts
.get(row as usize - scroll_position.y.into())
.map(|LineWithInvisibles { line, .. }| line)
.get(row as usize - scroll_position.y as usize)
.map(|&LineWithInvisibles { ref line, .. }| line)
{
if let Some(ix) = line.index_for_x(x) {
(ix as u32, px(0.))

View file

@ -3,12 +3,12 @@ use crate::{
movement::surrounding_word, persistence::DB, scroll::ScrollAnchor, Anchor, Autoscroll, Editor,
Event, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, NavigationData, ToPoint as _,
};
use anyhow::{Context, Result};
use anyhow::{anyhow, Context, Result};
use collections::HashSet;
use futures::future::try_join_all;
use gpui::{
point, AnyElement, AppContext, AsyncAppContext, Entity, EntityId, Model, Pixels, SharedString,
Subscription, Task, View, ViewContext, WeakView,
Subscription, Task, View, ViewContext, VisualContext, WeakView,
};
use language::{
proto::serialize_anchor as serialize_text_anchor, Bias, Buffer, OffsetRangeExt, Point,
@ -566,11 +566,9 @@ impl Item for Editor {
Some(file_path.into())
}
fn tab_description<'a>(&'a self, detail: usize, cx: &'a AppContext) -> Option<SharedString> {
match path_for_buffer(&self.buffer, detail, true, cx)? {
Cow::Borrowed(path) => Some(path.to_string_lossy().into()),
Cow::Owned(path) => Some(path.to_string_lossy().to_string().into()),
}
fn tab_description<'a>(&self, detail: usize, cx: &'a AppContext) -> Option<SharedString> {
let path = path_for_buffer(&self.buffer, detail, true, cx)?;
Some(path.to_string_lossy().to_string().into())
}
fn tab_content<T: 'static>(&self, detail: Option<usize>, cx: &AppContext) -> AnyElement<T> {
@ -613,11 +611,11 @@ impl Item for Editor {
&self,
_workspace_id: WorkspaceId,
cx: &mut ViewContext<Self>,
) -> Option<View<Self>>
) -> Option<View<Editor>>
where
Self: Sized,
{
Some(self.clone())
Some(cx.build_view(|cx| self.clone(cx)))
}
fn set_nav_history(&mut self, history: ItemNavHistory, _: &mut ViewContext<Self>) {
@ -706,7 +704,9 @@ impl Item for Editor {
.as_singleton()
.expect("cannot call save_as on an excerpt list");
let file_extension = abs_path.extension().map(|a| a.to_string_lossy.to_string());
let file_extension = abs_path
.extension()
.map(|a| a.to_string_lossy().to_string());
self.report_editor_event("save", file_extension, cx);
project.update(cx, |project, cx| {
@ -807,7 +807,7 @@ impl Item for Editor {
fn added_to_workspace(&mut self, workspace: &mut Workspace, cx: &mut ViewContext<Self>) {
let workspace_id = workspace.database_id();
let item_id = cx.view_id();
let item_id = cx.view().entity_id().as_u64() as ItemId;
self.workspace = Some((workspace.weak_handle(), workspace.database_id()));
fn serialize(
@ -835,7 +835,12 @@ impl Item for Editor {
cx.subscribe(&buffer, |this, buffer, event, cx| {
if let Some((_, workspace_id)) = this.workspace.as_ref() {
if let language::Event::FileHandleChanged = event {
serialize(buffer, *workspace_id, cx.view_id(), cx);
serialize(
buffer,
*workspace_id,
cx.view().entity_id().as_u64() as ItemId,
cx,
);
}
}
})
@ -877,10 +882,11 @@ impl Item for Editor {
let (_, project_item) = project_item.await?;
let buffer = project_item
.downcast::<Buffer>()
.context("Project item at stored path was not a buffer")?;
.map_err(|_| anyhow!("Project item at stored path was not a buffer"))?;
Ok(pane.update(&mut cx, |_, cx| {
cx.add_view(|cx| {
cx.build_view(|cx| {
let mut editor = Editor::for_buffer(buffer, Some(project), cx);
editor.read_scroll_position_from_db(item_id, workspace_id, cx);
editor
})

View file

@ -108,59 +108,61 @@ pub fn update_go_to_definition_link(
shift_held: bool,
cx: &mut ViewContext<Editor>,
) {
let pending_nonempty_selection = editor.has_pending_nonempty_selection();
// Store new mouse point as an anchor
let snapshot = editor.snapshot(cx);
let trigger_point = match origin {
Some(GoToDefinitionTrigger::Text(p)) => {
Some(TriggerPoint::Text(snapshot.buffer_snapshot.anchor_before(
p.to_offset(&snapshot.display_snapshot, Bias::Left),
)))
}
Some(GoToDefinitionTrigger::InlayHint(p, lsp_location, language_server_id)) => {
Some(TriggerPoint::InlayHint(p, lsp_location, language_server_id))
}
None => None,
};
// If the new point is the same as the previously stored one, return early
if let (Some(a), Some(b)) = (
&trigger_point,
&editor.link_go_to_definition_state.last_trigger_point,
) {
match (a, b) {
(TriggerPoint::Text(anchor_a), TriggerPoint::Text(anchor_b)) => {
if anchor_a.cmp(anchor_b, &snapshot.buffer_snapshot).is_eq() {
return;
}
}
(TriggerPoint::InlayHint(range_a, _, _), TriggerPoint::InlayHint(range_b, _, _)) => {
if range_a == range_b {
return;
}
}
_ => {}
}
}
editor.link_go_to_definition_state.last_trigger_point = trigger_point.clone();
if pending_nonempty_selection {
hide_link_definition(editor, cx);
return;
}
if cmd_held {
if let Some(trigger_point) = trigger_point {
let kind = trigger_point.definition_kind(shift_held);
show_link_definition(kind, editor, trigger_point, snapshot, cx);
return;
}
}
hide_link_definition(editor, cx);
todo!("old version below");
}
// let pending_nonempty_selection = editor.has_pending_nonempty_selection();
// // Store new mouse point as an anchor
// let snapshot = editor.snapshot(cx);
// let trigger_point = match origin {
// Some(GoToDefinitionTrigger::Text(p)) => {
// Some(TriggerPoint::Text(snapshot.buffer_snapshot.anchor_before(
// p.to_offset(&snapshot.display_snapshot, Bias::Left),
// )))
// }
// Some(GoToDefinitionTrigger::InlayHint(p, lsp_location, language_server_id)) => {
// Some(TriggerPoint::InlayHint(p, lsp_location, language_server_id))
// }
// None => None,
// };
// // If the new point is the same as the previously stored one, return early
// if let (Some(a), Some(b)) = (
// &trigger_point,
// &editor.link_go_to_definition_state.last_trigger_point,
// ) {
// match (a, b) {
// (TriggerPoint::Text(anchor_a), TriggerPoint::Text(anchor_b)) => {
// if anchor_a.cmp(anchor_b, &snapshot.buffer_snapshot).is_eq() {
// return;
// }
// }
// (TriggerPoint::InlayHint(range_a, _, _), TriggerPoint::InlayHint(range_b, _, _)) => {
// if range_a == range_b {
// return;
// }
// }
// _ => {}
// }
// }
// editor.link_go_to_definition_state.last_trigger_point = trigger_point.clone();
// if pending_nonempty_selection {
// hide_link_definition(editor, cx);
// return;
// }
// if cmd_held {
// if let Some(trigger_point) = trigger_point {
// let kind = trigger_point.definition_kind(shift_held);
// show_link_definition(kind, editor, trigger_point, snapshot, cx);
// return;
// }
// }
// hide_link_definition(editor, cx);
// }
pub fn update_inlay_link_and_hover_points(
snapshot: &DisplaySnapshot,
@ -351,201 +353,204 @@ pub fn show_link_definition(
snapshot: EditorSnapshot,
cx: &mut ViewContext<Editor>,
) {
let same_kind = editor.link_go_to_definition_state.kind == Some(definition_kind);
if !same_kind {
hide_link_definition(editor, cx);
}
if editor.pending_rename.is_some() {
return;
}
let trigger_anchor = trigger_point.anchor();
let (buffer, buffer_position) = if let Some(output) = editor
.buffer
.read(cx)
.text_anchor_for_position(trigger_anchor.clone(), cx)
{
output
} else {
return;
};
let excerpt_id = if let Some((excerpt_id, _, _)) = editor
.buffer()
.read(cx)
.excerpt_containing(trigger_anchor.clone(), cx)
{
excerpt_id
} else {
return;
};
let project = if let Some(project) = editor.project.clone() {
project
} else {
return;
};
// Don't request again if the location is within the symbol region of a previous request with the same kind
if let Some(symbol_range) = &editor.link_go_to_definition_state.symbol_range {
if same_kind && symbol_range.point_within_range(&trigger_point, &snapshot) {
return;
}
}
let task = cx.spawn(|this, mut cx| {
async move {
let result = match &trigger_point {
TriggerPoint::Text(_) => {
// query the LSP for definition info
cx.update(|cx| {
project.update(cx, |project, cx| match definition_kind {
LinkDefinitionKind::Symbol => {
project.definition(&buffer, buffer_position, cx)
}
LinkDefinitionKind::Type => {
project.type_definition(&buffer, buffer_position, cx)
}
})
})
.await
.ok()
.map(|definition_result| {
(
definition_result.iter().find_map(|link| {
link.origin.as_ref().map(|origin| {
let start = snapshot
.buffer_snapshot
.anchor_in_excerpt(excerpt_id.clone(), origin.range.start);
let end = snapshot
.buffer_snapshot
.anchor_in_excerpt(excerpt_id.clone(), origin.range.end);
RangeInEditor::Text(start..end)
})
}),
definition_result
.into_iter()
.map(GoToDefinitionLink::Text)
.collect(),
)
})
}
TriggerPoint::InlayHint(highlight, lsp_location, server_id) => Some((
Some(RangeInEditor::Inlay(highlight.clone())),
vec![GoToDefinitionLink::InlayHint(
lsp_location.clone(),
*server_id,
)],
)),
};
this.update(&mut cx, |this, cx| {
// Clear any existing highlights
this.clear_highlights::<LinkGoToDefinitionState>(cx);
this.link_go_to_definition_state.kind = Some(definition_kind);
this.link_go_to_definition_state.symbol_range = result
.as_ref()
.and_then(|(symbol_range, _)| symbol_range.clone());
if let Some((symbol_range, definitions)) = result {
this.link_go_to_definition_state.definitions = definitions.clone();
let buffer_snapshot = buffer.read(cx).snapshot();
// Only show highlight if there exists a definition to jump to that doesn't contain
// the current location.
let any_definition_does_not_contain_current_location =
definitions.iter().any(|definition| {
match &definition {
GoToDefinitionLink::Text(link) => {
if link.target.buffer == buffer {
let range = &link.target.range;
// Expand range by one character as lsp definition ranges include positions adjacent
// but not contained by the symbol range
let start = buffer_snapshot.clip_offset(
range
.start
.to_offset(&buffer_snapshot)
.saturating_sub(1),
Bias::Left,
);
let end = buffer_snapshot.clip_offset(
range.end.to_offset(&buffer_snapshot) + 1,
Bias::Right,
);
let offset = buffer_position.to_offset(&buffer_snapshot);
!(start <= offset && end >= offset)
} else {
true
}
}
GoToDefinitionLink::InlayHint(_, _) => true,
}
});
if any_definition_does_not_contain_current_location {
// todo!()
// // Highlight symbol using theme link definition highlight style
// let style = theme::current(cx).editor.link_definition;
// let highlight_range =
// symbol_range.unwrap_or_else(|| match &trigger_point {
// TriggerPoint::Text(trigger_anchor) => {
// let snapshot = &snapshot.buffer_snapshot;
// // If no symbol range returned from language server, use the surrounding word.
// let (offset_range, _) =
// snapshot.surrounding_word(*trigger_anchor);
// RangeInEditor::Text(
// snapshot.anchor_before(offset_range.start)
// ..snapshot.anchor_after(offset_range.end),
// )
// }
// TriggerPoint::InlayHint(highlight, _, _) => {
// RangeInEditor::Inlay(highlight.clone())
// }
// });
// match highlight_range {
// RangeInEditor::Text(text_range) => this
// .highlight_text::<LinkGoToDefinitionState>(
// vec![text_range],
// style,
// cx,
// ),
// RangeInEditor::Inlay(highlight) => this
// .highlight_inlays::<LinkGoToDefinitionState>(
// vec![highlight],
// style,
// cx,
// ),
// }
} else {
hide_link_definition(this, cx);
}
}
})?;
Ok::<_, anyhow::Error>(())
}
.log_err()
});
editor.link_go_to_definition_state.task = Some(task);
todo!("old implementation below")
}
// let same_kind = editor.link_go_to_definition_state.kind == Some(definition_kind);
// if !same_kind {
// hide_link_definition(editor, cx);
// }
// if editor.pending_rename.is_some() {
// return;
// }
// let trigger_anchor = trigger_point.anchor();
// let (buffer, buffer_position) = if let Some(output) = editor
// .buffer
// .read(cx)
// .text_anchor_for_position(trigger_anchor.clone(), cx)
// {
// output
// } else {
// return;
// };
// let excerpt_id = if let Some((excerpt_id, _, _)) = editor
// .buffer()
// .read(cx)
// .excerpt_containing(trigger_anchor.clone(), cx)
// {
// excerpt_id
// } else {
// return;
// };
// let project = if let Some(project) = editor.project.clone() {
// project
// } else {
// return;
// };
// // Don't request again if the location is within the symbol region of a previous request with the same kind
// if let Some(symbol_range) = &editor.link_go_to_definition_state.symbol_range {
// if same_kind && symbol_range.point_within_range(&trigger_point, &snapshot) {
// return;
// }
// }
// let task = cx.spawn(|this, mut cx| {
// async move {
// let result = match &trigger_point {
// TriggerPoint::Text(_) => {
// // query the LSP for definition info
// cx.update(|cx| {
// project.update(cx, |project, cx| match definition_kind {
// LinkDefinitionKind::Symbol => {
// project.definition(&buffer, buffer_position, cx)
// }
// LinkDefinitionKind::Type => {
// project.type_definition(&buffer, buffer_position, cx)
// }
// })
// })
// .await
// .ok()
// .map(|definition_result| {
// (
// definition_result.iter().find_map(|link| {
// link.origin.as_ref().map(|origin| {
// let start = snapshot
// .buffer_snapshot
// .anchor_in_excerpt(excerpt_id.clone(), origin.range.start);
// let end = snapshot
// .buffer_snapshot
// .anchor_in_excerpt(excerpt_id.clone(), origin.range.end);
// RangeInEditor::Text(start..end)
// })
// }),
// definition_result
// .into_iter()
// .map(GoToDefinitionLink::Text)
// .collect(),
// )
// })
// }
// TriggerPoint::InlayHint(highlight, lsp_location, server_id) => Some((
// Some(RangeInEditor::Inlay(highlight.clone())),
// vec![GoToDefinitionLink::InlayHint(
// lsp_location.clone(),
// *server_id,
// )],
// )),
// };
// this.update(&mut cx, |this, cx| {
// // Clear any existing highlights
// this.clear_highlights::<LinkGoToDefinitionState>(cx);
// this.link_go_to_definition_state.kind = Some(definition_kind);
// this.link_go_to_definition_state.symbol_range = result
// .as_ref()
// .and_then(|(symbol_range, _)| symbol_range.clone());
// if let Some((symbol_range, definitions)) = result {
// this.link_go_to_definition_state.definitions = definitions.clone();
// let buffer_snapshot = buffer.read(cx).snapshot();
// // Only show highlight if there exists a definition to jump to that doesn't contain
// // the current location.
// let any_definition_does_not_contain_current_location =
// definitions.iter().any(|definition| {
// match &definition {
// GoToDefinitionLink::Text(link) => {
// if link.target.buffer == buffer {
// let range = &link.target.range;
// // Expand range by one character as lsp definition ranges include positions adjacent
// // but not contained by the symbol range
// let start = buffer_snapshot.clip_offset(
// range
// .start
// .to_offset(&buffer_snapshot)
// .saturating_sub(1),
// Bias::Left,
// );
// let end = buffer_snapshot.clip_offset(
// range.end.to_offset(&buffer_snapshot) + 1,
// Bias::Right,
// );
// let offset = buffer_position.to_offset(&buffer_snapshot);
// !(start <= offset && end >= offset)
// } else {
// true
// }
// }
// GoToDefinitionLink::InlayHint(_, _) => true,
// }
// });
// if any_definition_does_not_contain_current_location {
// // todo!()
// // // Highlight symbol using theme link definition highlight style
// // let style = theme::current(cx).editor.link_definition;
// // let highlight_range =
// // symbol_range.unwrap_or_else(|| match &trigger_point {
// // TriggerPoint::Text(trigger_anchor) => {
// // let snapshot = &snapshot.buffer_snapshot;
// // // If no symbol range returned from language server, use the surrounding word.
// // let (offset_range, _) =
// // snapshot.surrounding_word(*trigger_anchor);
// // RangeInEditor::Text(
// // snapshot.anchor_before(offset_range.start)
// // ..snapshot.anchor_after(offset_range.end),
// // )
// // }
// // TriggerPoint::InlayHint(highlight, _, _) => {
// // RangeInEditor::Inlay(highlight.clone())
// // }
// // });
// // match highlight_range {
// // RangeInEditor::Text(text_range) => this
// // .highlight_text::<LinkGoToDefinitionState>(
// // vec![text_range],
// // style,
// // cx,
// // ),
// // RangeInEditor::Inlay(highlight) => this
// // .highlight_inlays::<LinkGoToDefinitionState>(
// // vec![highlight],
// // style,
// // cx,
// // ),
// // }
// } else {
// hide_link_definition(this, cx);
// }
// }
// })?;
// Ok::<_, anyhow::Error>(())
// }
// .log_err()
// });
// editor.link_go_to_definition_state.task = Some(task);
// }
pub fn hide_link_definition(editor: &mut Editor, cx: &mut ViewContext<Editor>) {
if editor.link_go_to_definition_state.symbol_range.is_some()
|| !editor.link_go_to_definition_state.definitions.is_empty()
{
editor.link_go_to_definition_state.symbol_range.take();
editor.link_go_to_definition_state.definitions.clear();
cx.notify();
}
todo!()
// if editor.link_go_to_definition_state.symbol_range.is_some()
// || !editor.link_go_to_definition_state.definitions.is_empty()
// {
// editor.link_go_to_definition_state.symbol_range.take();
// editor.link_go_to_definition_state.definitions.clear();
// cx.notify();
// }
editor.link_go_to_definition_state.task = None;
// editor.link_go_to_definition_state.task = None;
editor.clear_highlights::<LinkGoToDefinitionState>(cx);
// editor.clear_highlights::<LinkGoToDefinitionState>(cx);
}
pub fn go_to_fetched_definition(

View file

@ -1,7 +1,8 @@
use super::{Bias, DisplayPoint, DisplaySnapshot, SelectionGoal, ToDisplayPoint};
use crate::{char_kind, CharKind, EditorStyle, ToOffset, ToPoint};
use gpui::TextSystem;
use gpui::{px, TextSystem};
use language::Point;
use serde::de::IntoDeserializer;
use std::ops::Range;
#[derive(Debug, PartialEq)]
@ -93,9 +94,9 @@ pub fn up_by_rows(
text_layout_details: &TextLayoutDetails,
) -> (DisplayPoint, SelectionGoal) {
let mut goal_x = match goal {
SelectionGoal::HorizontalPosition(x) => x,
SelectionGoal::WrappedHorizontalPosition((_, x)) => x,
SelectionGoal::HorizontalRange { end, .. } => end,
SelectionGoal::HorizontalPosition(x) => x.into(), // todo!("Can the fields in SelectionGoal by Pixels? We should extract a geometry crate and depend on that.")
SelectionGoal::WrappedHorizontalPosition((_, x)) => x.into(),
SelectionGoal::HorizontalRange { end, .. } => end.into(),
_ => map.x_for_point(start, text_layout_details),
};
@ -110,14 +111,17 @@ pub fn up_by_rows(
return (start, goal);
} else {
point = DisplayPoint::new(0, 0);
goal_x = 0.0;
goal_x = px(0.);
}
let mut clipped_point = map.clip_point(point, Bias::Left);
if clipped_point.row() < point.row() {
clipped_point = map.clip_point(point, Bias::Right);
}
(clipped_point, SelectionGoal::HorizontalPosition(goal_x))
(
clipped_point,
SelectionGoal::HorizontalPosition(goal_x.into()),
)
}
pub fn down_by_rows(
@ -129,9 +133,9 @@ pub fn down_by_rows(
text_layout_details: &TextLayoutDetails,
) -> (DisplayPoint, SelectionGoal) {
let mut goal_x = match goal {
SelectionGoal::HorizontalPosition(x) => x,
SelectionGoal::WrappedHorizontalPosition((_, x)) => x,
SelectionGoal::HorizontalRange { end, .. } => end,
SelectionGoal::HorizontalPosition(x) => x.into(),
SelectionGoal::WrappedHorizontalPosition((_, x)) => x.into(),
SelectionGoal::HorizontalRange { end, .. } => end.into(),
_ => map.x_for_point(start, text_layout_details),
};
@ -150,7 +154,10 @@ pub fn down_by_rows(
if clipped_point.row() > point.row() {
clipped_point = map.clip_point(point, Bias::Left);
}
(clipped_point, SelectionGoal::HorizontalPosition(goal_x))
(
clipped_point,
SelectionGoal::HorizontalPosition(goal_x.into()),
)
}
pub fn line_beginning(

View file

@ -3,7 +3,6 @@ use std::path::PathBuf;
use db::sqlez_macros::sql;
use db::{define_connection, query};
use gpui::EntityId;
use workspace::{ItemId, WorkspaceDb, WorkspaceId};
define_connection!(
@ -67,7 +66,7 @@ impl EditorDb {
query! {
pub async fn save_scroll_position(
item_id: EntityId,
item_id: ItemId,
workspace_id: WorkspaceId,
top_row: u32,
vertical_offset: f32,

View file

@ -16,7 +16,7 @@ use std::{
time::{Duration, Instant},
};
use util::ResultExt;
use workspace::WorkspaceId;
use workspace::{ItemId, WorkspaceId};
use self::{
autoscroll::{Autoscroll, AutoscrollStrategy},
@ -228,7 +228,7 @@ impl ScrollManager {
self.show_scrollbar(cx);
self.autoscroll_request.take();
if let Some(workspace_id) = workspace_id {
let item_id = cx.view().entity_id();
let item_id = cx.view().entity_id().as_u64() as ItemId;
cx.foreground_executor()
.spawn(async move {
@ -355,31 +355,31 @@ impl Editor {
// self.scroll_manager.anchor.scroll_position(&display_map)
// }
// pub fn set_scroll_anchor(&mut self, scroll_anchor: ScrollAnchor, cx: &mut ViewContext<Self>) {
// hide_hover(self, cx);
// let workspace_id = self.workspace.as_ref().map(|workspace| workspace.1);
// let top_row = scroll_anchor
// .anchor
// .to_point(&self.buffer().read(cx).snapshot(cx))
// .row;
// self.scroll_manager
// .set_anchor(scroll_anchor, top_row, true, false, workspace_id, cx);
// }
pub fn set_scroll_anchor(&mut self, scroll_anchor: ScrollAnchor, cx: &mut ViewContext<Self>) {
hide_hover(self, cx);
let workspace_id = self.workspace.as_ref().map(|workspace| workspace.1);
let top_row = scroll_anchor
.anchor
.to_point(&self.buffer().read(cx).snapshot(cx))
.row;
self.scroll_manager
.set_anchor(scroll_anchor, top_row, true, false, workspace_id, cx);
}
// pub(crate) fn set_scroll_anchor_remote(
// &mut self,
// scroll_anchor: ScrollAnchor,
// cx: &mut ViewContext<Self>,
// ) {
// hide_hover(self, cx);
// let workspace_id = self.workspace.as_ref().map(|workspace| workspace.1);
// let top_row = scroll_anchor
// .anchor
// .to_point(&self.buffer().read(cx).snapshot(cx))
// .row;
// self.scroll_manager
// .set_anchor(scroll_anchor, top_row, false, false, workspace_id, cx);
// }
pub(crate) fn set_scroll_anchor_remote(
&mut self,
scroll_anchor: ScrollAnchor,
cx: &mut ViewContext<Self>,
) {
hide_hover(self, cx);
let workspace_id = self.workspace.as_ref().map(|workspace| workspace.1);
let top_row = scroll_anchor
.anchor
.to_point(&self.buffer().read(cx).snapshot(cx))
.row;
self.scroll_manager
.set_anchor(scroll_anchor, top_row, false, false, workspace_id, cx);
}
// pub fn scroll_screen(&mut self, amount: &ScrollAmount, cx: &mut ViewContext<Self>) {
// if matches!(self.mode, EditorMode::SingleLine) {
@ -426,24 +426,24 @@ impl Editor {
// Ordering::Greater
// }
// pub fn read_scroll_position_from_db(
// &mut self,
// item_id: usize,
// workspace_id: WorkspaceId,
// cx: &mut ViewContext<Editor>,
// ) {
// let scroll_position = DB.get_scroll_position(item_id, workspace_id);
// if let Ok(Some((top_row, x, y))) = scroll_position {
// let top_anchor = self
// .buffer()
// .read(cx)
// .snapshot(cx)
// .anchor_at(Point::new(top_row as u32, 0), Bias::Left);
// let scroll_anchor = ScrollAnchor {
// offset: Point::new(x, y),
// anchor: top_anchor,
// };
// self.set_scroll_anchor(scroll_anchor, cx);
// }
// }
pub fn read_scroll_position_from_db(
&mut self,
item_id: usize,
workspace_id: WorkspaceId,
cx: &mut ViewContext<Editor>,
) {
let scroll_position = DB.get_scroll_position(item_id, workspace_id);
if let Ok(Some((top_row, x, y))) = scroll_position {
let top_anchor = self
.buffer()
.read(cx)
.snapshot(cx)
.anchor_at(Point::new(top_row as u32, 0), Bias::Left);
let scroll_anchor = ScrollAnchor {
offset: gpui::Point::new(x, y),
anchor: top_anchor,
};
self.set_scroll_anchor(scroll_anchor, cx);
}
}
}

View file

@ -1,5 +1,3 @@
use gpui::Pixels;
use crate::{Anchor, BufferSnapshot, TextDimension};
use std::cmp::Ordering;
use std::ops::Range;
@ -7,8 +5,8 @@ use std::ops::Range;
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum SelectionGoal {
None,
HorizontalPosition(Pixels),
HorizontalRange { start: Pixels, end: Pixels },
HorizontalPosition(f32), // todo!("Can we use pixels here without adding a runtime gpui dependency?")
HorizontalRange { start: f32, end: f32 },
WrappedHorizontalPosition((u32, f32)),
}