Get editor2 compiling with a ton of code commented out

Nathan Sobo created

Change summary

crates/editor2/src/display_map.rs           |   4 
crates/editor2/src/display_map/fold_map.rs  |   3 
crates/editor2/src/display_map/inlay_map.rs |   3 
crates/editor2/src/display_map/wrap_map.rs  |  26 
crates/editor2/src/editor.rs                | 434 ++++++++++----------
crates/editor2/src/element.rs               |   5 
crates/editor2/src/items.rs                 |  34 
crates/editor2/src/link_go_to_definition.rs | 475 +++++++++++-----------
crates/editor2/src/movement.rs              |  27 
crates/editor2/src/persistence.rs           |   3 
crates/editor2/src/scroll.rs                |  92 ++--
crates/text2/src/selection.rs               |   6 
12 files changed, 571 insertions(+), 541 deletions(-)

Detailed changes

crates/editor2/src/display_map.rs 🔗

@@ -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!(

crates/editor2/src/display_map/fold_map.rs 🔗

@@ -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 {

crates/editor2/src/display_map/inlay_map.rs 🔗

@@ -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);
     }
 }

crates/editor2/src/display_map/wrap_map.rs 🔗

@@ -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

crates/editor2/src/editor.rs 🔗

@@ -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(),
-    //             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
-    //     }
+    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>>,
-    //         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,
-    //             )
-    //         });
+    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,
+    //         )
+    //     });
 
-    //         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);
+    //     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.end_selection(cx);
-    //         this.scroll_manager.show_scrollbar(cx);
+    //     this._subscriptions.extend(project_subscriptions);
 
-    //         let editor_created_event = EditorCreated(cx.handle());
-    //         cx.emit_global(editor_created_event);
+    //     this.end_selection(cx);
+    //     this.scroll_manager.show_scrollbar(cx);
 
-    //         if mode == EditorMode::Full {
-    //             let should_auto_hide_scrollbars = cx.platform().should_auto_hide_scrollbars();
-    //             cx.set_global(ScrollbarAutoHide(should_auto_hide_scrollbars));
-    //         }
+    //     let editor_created_event = EditorCreated(cx.handle());
+    //     cx.emit_global(editor_created_event);
 
-    //         this.report_editor_event("open", None, cx);
-    //         this
+    //     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)
-    //     }
-
-    //     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());
-    //         }
-    //     }
+    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 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 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());
+        // }
+    }
 
-    //             cx.emit(Event::Edited);
-    //             Some(tx_id)
-    //         } else {
-    //             None
-    //         }
-    //     }
+    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
+        // }
+    }
 
     //     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 {

crates/editor2/src/element.rs 🔗

@@ -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.))

crates/editor2/src/items.rs 🔗

@@ -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
                         })
@@ -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;
-                }
-            }
-            _ => {}
-        }
-    }
+    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();
+//     editor.link_go_to_definition_state.last_trigger_point = trigger_point.clone();
 
-    if pending_nonempty_selection {
-        hide_link_definition(editor, cx);
-        return;
-    }
+//     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;
-        }
-    }
+//     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);
-}
+//     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);
-    }
+    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;
-    }
+//     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 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 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);
-                    }
-                }
-            })?;
+//     let excerpt_id = if let Some((excerpt_id, _, _)) = editor
+//         .buffer()
+//         .read(cx)
+//         .excerpt_containing(trigger_anchor.clone(), cx)
+//     {
+//         excerpt_id
+//     } else {
+//         return;
+//     };
 
-            Ok::<_, anyhow::Error>(())
-        }
-        .log_err()
-    });
+//     let project = if let Some(project) = editor.project.clone() {
+//         project
+//     } else {
+//         return;
+//     };
 
-    editor.link_go_to_definition_state.task = Some(task);
-}
+//     // 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(

crates/editor2/src/movement.rs 🔗

@@ -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(

crates/editor2/src/persistence.rs 🔗

@@ -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,

crates/editor2/src/scroll.rs 🔗

@@ -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);
+        }
+    }
 }

crates/text2/src/selection.rs 🔗

@@ -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)),
 }