WIP

Nathan Sobo created

Change summary

Cargo.lock                                       |    2 
crates/editor2/src/display_map.rs                |    6 
crates/editor2/src/editor.rs                     | 1319 +++++++++--------
crates/editor2/src/element.rs                    |   27 
crates/editor2/src/highlight_matching_bracket.rs |   43 
crates/editor2/src/hover_popover.rs              |  237 +-
crates/editor2/src/inlay_hint_cache.rs           |  568 +++---
crates/editor2/src/items.rs                      |  149 +
crates/editor2/src/link_go_to_definition.rs      |  386 ++--
crates/editor2/src/mouse_context_menu.rs         |   37 
crates/editor2/src/persistence.rs                |    3 
crates/editor2/src/scroll.rs                     |  339 ++--
crates/editor2/src/scroll/autoscroll.rs          |   34 
crates/editor2/src/scroll/scroll_amount.rs       |   27 
crates/editor2/src/selections_collection.rs      |   68 
crates/gpui2/src/executor.rs                     |    1 
crates/gpui2/src/geometry.rs                     |   12 
crates/gpui2/src/platform/mac/text_system.rs     |    1 
crates/gpui2/src/style.rs                        |    9 
crates/gpui2/src/text_system.rs                  |    2 
crates/gpui2/src/text_system/line.rs             |    4 
crates/gpui2/src/text_system/line_layout.rs      |    1 
crates/gpui2/src/window.rs                       |    1 
crates/text/Cargo.toml                           |    2 
crates/text2/src/selection.rs                    |    6 
crates/workspace2/src/item.rs                    |   18 
26 files changed, 1,708 insertions(+), 1,594 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -8884,7 +8884,7 @@ dependencies = [
  "ctor",
  "digest 0.9.0",
  "env_logger 0.9.3",
- "gpui",
+ "gpui2",
  "lazy_static",
  "log",
  "parking_lot 0.11.2",

crates/editor2/src/display_map.rs 🔗

@@ -60,7 +60,7 @@ impl DisplayMap {
         buffer: Model<MultiBuffer>,
         font: Font,
         font_size: Pixels,
-        wrap_width: Option<f32>,
+        wrap_width: Option<Pixels>,
         buffer_header_height: u8,
         excerpt_header_height: u8,
         cx: &mut ModelContext<Self>,
@@ -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_id, font_size, cx))
+            .update(cx, |map, cx| map.set_font(font, font_size, cx))
     }
 
     pub fn set_fold_ellipses_color(&mut self, color: Hsla) -> bool {
@@ -621,7 +621,7 @@ impl DisplaySnapshot {
     pub fn column_for_x(
         &self,
         display_row: u32,
-        x_coordinate: f32,
+        x_coordinate: Pixels,
         text_layout_details: &TextLayoutDetails,
     ) -> u32 {
         let layout_line = self.lay_out_line_for_row(display_row, text_layout_details);

crates/editor2/src/editor.rs 🔗

@@ -1,3 +1,4 @@
+#![allow(unused)]
 mod blink_manager;
 pub mod display_map;
 mod editor_settings;
@@ -20,8 +21,9 @@ mod editor_tests;
 #[cfg(any(test, feature = "test-support"))]
 pub mod test;
 use aho_corasick::AhoCorasick;
+use anyhow::Result;
 use blink_manager::BlinkManager;
-use client::{Collaborator, ParticipantIndex};
+use client::{Client, Collaborator, ParticipantIndex};
 use clock::ReplicaId;
 use collections::{HashMap, HashSet, VecDeque};
 pub use display_map::DisplayPoint;
@@ -33,8 +35,8 @@ pub use element::{
 use futures::FutureExt;
 use fuzzy::{StringMatch, StringMatchCandidate};
 use gpui::{
-    AnyElement, AppContext, Element, EventEmitter, Model, Pixels, Render, Subscription, Task, View,
-    ViewContext, WeakView,
+    AnyElement, AppContext, BackgroundExecutor, Element, EventEmitter, Model, Pixels, Render,
+    Subscription, Task, TextStyle, View, ViewContext, WeakView, WindowContext,
 };
 use hover_popover::HoverState;
 pub use items::MAX_TAB_TITLE_LEN;
@@ -42,27 +44,30 @@ pub use language::{char_kind, CharKind};
 use language::{
     language_settings::{self, all_language_settings, InlayHintSettings},
     AutoindentMode, BracketPair, Buffer, CodeAction, Completion, CursorShape, Diagnostic, Language,
-    OffsetRangeExt, Point, Selection, SelectionGoal, TransactionId,
+    LanguageRegistry, OffsetRangeExt, Point, Selection, SelectionGoal, TransactionId,
 };
 use link_go_to_definition::LinkGoToDefinitionState;
+use lsp::{Documentation, LanguageServerId};
 pub use multi_buffer::{
     Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset,
     ToPoint,
 };
+use ordered_float::OrderedFloat;
 use parking_lot::RwLock;
-use project::Project;
+use project::{FormatTrigger, Project};
 use rpc::proto::*;
 use scroll::{autoscroll::Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager};
 use selections_collection::SelectionsCollection;
 use serde::{Deserialize, Serialize};
 use settings::Settings;
 use std::{
+    cmp::Reverse,
     ops::{Deref, DerefMut, Range},
     sync::Arc,
     time::Duration,
 };
 pub use sum_tree::Bias;
-use util::TryFutureExt;
+use util::{ResultExt, TryFutureExt};
 use workspace::{ItemNavHistory, ViewId, Workspace};
 
 const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
@@ -569,7 +574,7 @@ pub enum SoftWrap {
 
 #[derive(Clone)]
 pub struct EditorStyle {
-    //  pub text: TextStyle,
+    pub text: TextStyle,
     pub line_height_scalar: f32,
     // pub placeholder_text: Option<TextStyle>,
     //  pub theme: theme::Editor,
@@ -887,10 +892,11 @@ impl ContextMenu {
         workspace: Option<WeakView<Workspace>>,
         cx: &mut ViewContext<Editor>,
     ) -> (DisplayPoint, AnyElement<Editor>) {
-        match self {
-            ContextMenu::Completions(menu) => (cursor_position, menu.render(style, workspace, cx)),
-            ContextMenu::CodeActions(menu) => menu.render(cursor_position, style, cx),
-        }
+        todo!()
+        // match self {
+        //     ContextMenu::Completions(menu) => (cursor_position, menu.render(style, workspace, cx)),
+        //     ContextMenu::CodeActions(menu) => menu.render(cursor_position, style, cx),
+        // }
     }
 }
 
@@ -903,688 +909,715 @@ struct CompletionsMenu {
     match_candidates: Arc<[StringMatchCandidate]>,
     matches: Arc<[StringMatch]>,
     selected_item: usize,
-    // list: UniformListState,
+    list: UniformListState,
 }
 
-// impl CompletionsMenu {
-//     fn select_first(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
-//         self.selected_item = 0;
-//         self.list.scroll_to(ScrollTarget::Show(self.selected_item));
-//         self.attempt_resolve_selected_completion_documentation(project, cx);
-//         cx.notify();
-//     }
+// todo!(this is fake)
+#[derive(Clone)]
+struct UniformListState;
 
-//     fn select_prev(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
-//         if self.selected_item > 0 {
-//             self.selected_item -= 1;
-//         } else {
-//             self.selected_item = self.matches.len() - 1;
-//         }
-//         self.list.scroll_to(ScrollTarget::Show(self.selected_item));
-//         self.attempt_resolve_selected_completion_documentation(project, cx);
-//         cx.notify();
-//     }
+// todo!(this is fake)
+impl UniformListState {
+    pub fn scroll_to(&mut self, target: ScrollTarget) {}
+}
 
-//     fn select_next(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
-//         if self.selected_item + 1 < self.matches.len() {
-//             self.selected_item += 1;
-//         } else {
-//             self.selected_item = 0;
-//         }
-//         self.list.scroll_to(ScrollTarget::Show(self.selected_item));
-//         self.attempt_resolve_selected_completion_documentation(project, cx);
-//         cx.notify();
-//     }
+// todo!(this is somewhat fake)
+#[derive(Debug)]
+pub enum ScrollTarget {
+    Show(usize),
+    Center(usize),
+}
 
-//     fn select_last(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
-//         self.selected_item = self.matches.len() - 1;
-//         self.list.scroll_to(ScrollTarget::Show(self.selected_item));
-//         self.attempt_resolve_selected_completion_documentation(project, cx);
-//         cx.notify();
-//     }
+impl CompletionsMenu {
+    fn select_first(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
+        self.selected_item = 0;
+        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
+        self.attempt_resolve_selected_completion_documentation(project, cx);
+        cx.notify();
+    }
 
-//     fn pre_resolve_completion_documentation(
-//         &self,
-//         project: Option<Model<Project>>,
-//         cx: &mut ViewContext<Editor>,
-//     ) {
-//         let settings = settings::get::<EditorSettings>(cx);
-//         if !settings.show_completion_documentation {
-//             return;
-//         }
+    fn select_prev(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
+        if self.selected_item > 0 {
+            self.selected_item -= 1;
+        } else {
+            self.selected_item = self.matches.len() - 1;
+        }
+        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
+        self.attempt_resolve_selected_completion_documentation(project, cx);
+        cx.notify();
+    }
 
-//         let Some(project) = project else {
-//             return;
-//         };
-//         let client = project.read(cx).client();
-//         let language_registry = project.read(cx).languages().clone();
-
-//         let is_remote = project.read(cx).is_remote();
-//         let project_id = project.read(cx).remote_id();
-
-//         let completions = self.completions.clone();
-//         let completion_indices: Vec<_> = self.matches.iter().map(|m| m.candidate_id).collect();
-
-//         cx.spawn(move |this, mut cx| async move {
-//             if is_remote {
-//                 let Some(project_id) = project_id else {
-//                     log::error!("Remote project without remote_id");
-//                     return;
-//                 };
-
-//                 for completion_index in completion_indices {
-//                     let completions_guard = completions.read();
-//                     let completion = &completions_guard[completion_index];
-//                     if completion.documentation.is_some() {
-//                         continue;
-//                     }
+    fn select_next(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
+        if self.selected_item + 1 < self.matches.len() {
+            self.selected_item += 1;
+        } else {
+            self.selected_item = 0;
+        }
+        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
+        self.attempt_resolve_selected_completion_documentation(project, cx);
+        cx.notify();
+    }
 
-//                     let server_id = completion.server_id;
-//                     let completion = completion.lsp_completion.clone();
-//                     drop(completions_guard);
-
-//                     Self::resolve_completion_documentation_remote(
-//                         project_id,
-//                         server_id,
-//                         completions.clone(),
-//                         completion_index,
-//                         completion,
-//                         client.clone(),
-//                         language_registry.clone(),
-//                     )
-//                     .await;
+    fn select_last(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
+        self.selected_item = self.matches.len() - 1;
+        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
+        self.attempt_resolve_selected_completion_documentation(project, cx);
+        cx.notify();
+    }
 
-//                     _ = this.update(&mut cx, |_, cx| cx.notify());
-//                 }
-//             } else {
-//                 for completion_index in completion_indices {
-//                     let completions_guard = completions.read();
-//                     let completion = &completions_guard[completion_index];
-//                     if completion.documentation.is_some() {
-//                         continue;
-//                     }
+    fn pre_resolve_completion_documentation(
+        &self,
+        project: Option<Model<Project>>,
+        cx: &mut ViewContext<Editor>,
+    ) {
+        todo!("implementation below ");
+    }
+    // ) {
+    //     let settings = EditorSettings::get_global(cx);
+    //     if !settings.show_completion_documentation {
+    //         return;
+    //     }
 
-//                     let server_id = completion.server_id;
-//                     let completion = completion.lsp_completion.clone();
-//                     drop(completions_guard);
-
-//                     let server = project.read_with(&mut cx, |project, _| {
-//                         project.language_server_for_id(server_id)
-//                     });
-//                     let Some(server) = server else {
-//                         return;
-//                     };
-
-//                     Self::resolve_completion_documentation_local(
-//                         server,
-//                         completions.clone(),
-//                         completion_index,
-//                         completion,
-//                         language_registry.clone(),
-//                     )
-//                     .await;
+    //     let Some(project) = project else {
+    //         return;
+    //     };
+    //     let client = project.read(cx).client();
+    //     let language_registry = project.read(cx).languages().clone();
 
-//                     _ = this.update(&mut cx, |_, cx| cx.notify());
-//                 }
-//             }
-//         })
-//         .detach();
-//     }
+    //     let is_remote = project.read(cx).is_remote();
+    //     let project_id = project.read(cx).remote_id();
 
-//     fn attempt_resolve_selected_completion_documentation(
-//         &mut self,
-//         project: Option<&Model<Project>>,
-//         cx: &mut ViewContext<Editor>,
-//     ) {
-//         let settings = settings::get::<EditorSettings>(cx);
-//         if !settings.show_completion_documentation {
-//             return;
-//         }
+    //     let completions = self.completions.clone();
+    //     let completion_indices: Vec<_> = self.matches.iter().map(|m| m.candidate_id).collect();
 
-//         let completion_index = self.matches[self.selected_item].candidate_id;
-//         let Some(project) = project else {
-//             return;
-//         };
-//         let language_registry = project.read(cx).languages().clone();
+    //     cx.spawn(move |this, mut cx| async move {
+    //         if is_remote {
+    //             let Some(project_id) = project_id else {
+    //                 log::error!("Remote project without remote_id");
+    //                 return;
+    //             };
 
-//         let completions = self.completions.clone();
-//         let completions_guard = completions.read();
-//         let completion = &completions_guard[completion_index];
-//         if completion.documentation.is_some() {
-//             return;
-//         }
+    //             for completion_index in completion_indices {
+    //                 let completions_guard = completions.read();
+    //                 let completion = &completions_guard[completion_index];
+    //                 if completion.documentation.is_some() {
+    //                     continue;
+    //                 }
 
-//         let server_id = completion.server_id;
-//         let completion = completion.lsp_completion.clone();
-//         drop(completions_guard);
+    //                 let server_id = completion.server_id;
+    //                 let completion = completion.lsp_completion.clone();
+    //                 drop(completions_guard);
+
+    //                 Self::resolve_completion_documentation_remote(
+    //                     project_id,
+    //                     server_id,
+    //                     completions.clone(),
+    //                     completion_index,
+    //                     completion,
+    //                     client.clone(),
+    //                     language_registry.clone(),
+    //                 )
+    //                 .await;
 
-//         if project.read(cx).is_remote() {
-//             let Some(project_id) = project.read(cx).remote_id() else {
-//                 log::error!("Remote project without remote_id");
-//                 return;
-//             };
+    //                 _ = this.update(&mut cx, |_, cx| cx.notify());
+    //             }
+    //         } else {
+    //             for completion_index in completion_indices {
+    //                 let completions_guard = completions.read();
+    //                 let completion = &completions_guard[completion_index];
+    //                 if completion.documentation.is_some() {
+    //                     continue;
+    //                 }
 
-//             let client = project.read(cx).client();
-
-//             cx.spawn(move |this, mut cx| async move {
-//                 Self::resolve_completion_documentation_remote(
-//                     project_id,
-//                     server_id,
-//                     completions.clone(),
-//                     completion_index,
-//                     completion,
-//                     client,
-//                     language_registry.clone(),
-//                 )
-//                 .await;
-
-//                 _ = this.update(&mut cx, |_, cx| cx.notify());
-//             })
-//             .detach();
-//         } else {
-//             let Some(server) = project.read(cx).language_server_for_id(server_id) else {
-//                 return;
-//             };
+    //                 let server_id = completion.server_id;
+    //                 let completion = completion.lsp_completion.clone();
+    //                 drop(completions_guard);
 
-//             cx.spawn(move |this, mut cx| async move {
-//                 Self::resolve_completion_documentation_local(
-//                     server,
-//                     completions,
-//                     completion_index,
-//                     completion,
-//                     language_registry,
-//                 )
-//                 .await;
-
-//                 _ = this.update(&mut cx, |_, cx| cx.notify());
-//             })
-//             .detach();
-//         }
-//     }
+    //                 let server = project.read_with(&mut cx, |project, _| {
+    //                     project.language_server_for_id(server_id)
+    //                 });
+    //                 let Some(server) = server else {
+    //                     return;
+    //                 };
 
-//     async fn resolve_completion_documentation_remote(
-//         project_id: u64,
-//         server_id: LanguageServerId,
-//         completions: Arc<RwLock<Box<[Completion]>>>,
-//         completion_index: usize,
-//         completion: lsp::CompletionItem,
-//         client: Arc<Client>,
-//         language_registry: Arc<LanguageRegistry>,
-//     ) {
-//         let request = proto::ResolveCompletionDocumentation {
-//             project_id,
-//             language_server_id: server_id.0 as u64,
-//             lsp_completion: serde_json::to_string(&completion).unwrap().into_bytes(),
-//         };
+    //                 Self::resolve_completion_documentation_local(
+    //                     server,
+    //                     completions.clone(),
+    //                     completion_index,
+    //                     completion,
+    //                     language_registry.clone(),
+    //                 )
+    //                 .await;
 
-//         let Some(response) = client
-//             .request(request)
-//             .await
-//             .context("completion documentation resolve proto request")
-//             .log_err()
-//         else {
-//             return;
-//         };
+    //                 _ = this.update(&mut cx, |_, cx| cx.notify());
+    //             }
+    //         }
+    //     })
+    //     .detach();
+    // }
 
-//         if response.text.is_empty() {
-//             let mut completions = completions.write();
-//             let completion = &mut completions[completion_index];
-//             completion.documentation = Some(Documentation::Undocumented);
-//         }
+    fn attempt_resolve_selected_completion_documentation(
+        &mut self,
+        project: Option<&Model<Project>>,
+        cx: &mut ViewContext<Editor>,
+    ) {
+        let settings = EditorSettings::get_global(cx);
+        if !settings.show_completion_documentation {
+            return;
+        }
 
-//         let documentation = if response.is_markdown {
-//             Documentation::MultiLineMarkdown(
-//                 markdown::parse_markdown(&response.text, &language_registry, None).await,
-//             )
-//         } else if response.text.lines().count() <= 1 {
-//             Documentation::SingleLine(response.text)
-//         } else {
-//             Documentation::MultiLinePlainText(response.text)
-//         };
+        let completion_index = self.matches[self.selected_item].candidate_id;
+        let Some(project) = project else {
+            return;
+        };
+        let language_registry = project.read(cx).languages().clone();
+
+        let completions = self.completions.clone();
+        let completions_guard = completions.read();
+        let completion = &completions_guard[completion_index];
+        // todo!()
+        // if completion.documentation.is_some() {
+        //     return;
+        // }
+
+        let server_id = completion.server_id;
+        let completion = completion.lsp_completion.clone();
+        drop(completions_guard);
+
+        if project.read(cx).is_remote() {
+            let Some(project_id) = project.read(cx).remote_id() else {
+                log::error!("Remote project without remote_id");
+                return;
+            };
+
+            let client = project.read(cx).client();
+
+            cx.spawn(move |this, mut cx| async move {
+                Self::resolve_completion_documentation_remote(
+                    project_id,
+                    server_id,
+                    completions.clone(),
+                    completion_index,
+                    completion,
+                    client,
+                    language_registry.clone(),
+                )
+                .await;
+
+                _ = this.update(&mut cx, |_, cx| cx.notify());
+            })
+            .detach();
+        } else {
+            let Some(server) = project.read(cx).language_server_for_id(server_id) else {
+                return;
+            };
+
+            cx.spawn(move |this, mut cx| async move {
+                Self::resolve_completion_documentation_local(
+                    server,
+                    completions,
+                    completion_index,
+                    completion,
+                    language_registry,
+                )
+                .await;
+
+                _ = this.update(&mut cx, |_, cx| cx.notify());
+            })
+            .detach();
+        }
+    }
 
-//         let mut completions = completions.write();
-//         let completion = &mut completions[completion_index];
-//         completion.documentation = Some(documentation);
-//     }
+    async fn resolve_completion_documentation_remote(
+        project_id: u64,
+        server_id: LanguageServerId,
+        completions: Arc<RwLock<Box<[Completion]>>>,
+        completion_index: usize,
+        completion: lsp::CompletionItem,
+        client: Arc<Client>,
+        language_registry: Arc<LanguageRegistry>,
+    ) {
+        todo!()
+        // let request = proto::ResolveCompletionDocumentation {
+        //     project_id,
+        //     language_server_id: server_id.0 as u64,
+        //     lsp_completion: serde_json::to_string(&completion).unwrap().into_bytes(),
+        // };
+
+        // let Some(response) = client
+        //     .request(request)
+        //     .await
+        //     .context("completion documentation resolve proto request")
+        //     .log_err()
+        // else {
+        //     return;
+        // };
+
+        // if response.text.is_empty() {
+        //     let mut completions = completions.write();
+        //     let completion = &mut completions[completion_index];
+        //     completion.documentation = Some(Documentation::Undocumented);
+        // }
+
+        // let documentation = if response.is_markdown {
+        //     Documentation::MultiLineMarkdown(
+        //         markdown::parse_markdown(&response.text, &language_registry, None).await,
+        //     )
+        // } else if response.text.lines().count() <= 1 {
+        //     Documentation::SingleLine(response.text)
+        // } else {
+        //     Documentation::MultiLinePlainText(response.text)
+        // };
+
+        // let mut completions = completions.write();
+        // let completion = &mut completions[completion_index];
+        // completion.documentation = Some(documentation);
+    }
 
-//     async fn resolve_completion_documentation_local(
-//         server: Arc<lsp::LanguageServer>,
-//         completions: Arc<RwLock<Box<[Completion]>>>,
-//         completion_index: usize,
-//         completion: lsp::CompletionItem,
-//         language_registry: Arc<LanguageRegistry>,
-//     ) {
-//         let can_resolve = server
-//             .capabilities()
-//             .completion_provider
-//             .as_ref()
-//             .and_then(|options| options.resolve_provider)
-//             .unwrap_or(false);
-//         if !can_resolve {
-//             return;
-//         }
+    async fn resolve_completion_documentation_local(
+        server: Arc<lsp::LanguageServer>,
+        completions: Arc<RwLock<Box<[Completion]>>>,
+        completion_index: usize,
+        completion: lsp::CompletionItem,
+        language_registry: Arc<LanguageRegistry>,
+    ) {
+        todo!()
+        // let can_resolve = server
+        //     .capabilities()
+        //     .completion_provider
+        //     .as_ref()
+        //     .and_then(|options| options.resolve_provider)
+        //     .unwrap_or(false);
+        // if !can_resolve {
+        //     return;
+        // }
+
+        // let request = server.request::<lsp::request::ResolveCompletionItem>(completion);
+        // let Some(completion_item) = request.await.log_err() else {
+        //     return;
+        // };
+
+        // if let Some(lsp_documentation) = completion_item.documentation {
+        //     let documentation = language::prepare_completion_documentation(
+        //         &lsp_documentation,
+        //         &language_registry,
+        //         None, // TODO: Try to reasonably work out which language the completion is for
+        //     )
+        //     .await;
+
+        //     let mut completions = completions.write();
+        //     let completion = &mut completions[completion_index];
+        //     completion.documentation = Some(documentation);
+        // } else {
+        //     let mut completions = completions.write();
+        //     let completion = &mut completions[completion_index];
+        //     completion.documentation = Some(Documentation::Undocumented);
+        // }
+    }
 
-//         let request = server.request::<lsp::request::ResolveCompletionItem>(completion);
-//         let Some(completion_item) = request.await.log_err() else {
-//             return;
-//         };
+    fn visible(&self) -> bool {
+        !self.matches.is_empty()
+    }
 
-//         if let Some(lsp_documentation) = completion_item.documentation {
-//             let documentation = language::prepare_completion_documentation(
-//                 &lsp_documentation,
-//                 &language_registry,
-//                 None, // TODO: Try to reasonably work out which language the completion is for
-//             )
-//             .await;
-
-//             let mut completions = completions.write();
-//             let completion = &mut completions[completion_index];
-//             completion.documentation = Some(documentation);
-//         } else {
-//             let mut completions = completions.write();
-//             let completion = &mut completions[completion_index];
-//             completion.documentation = Some(Documentation::Undocumented);
-//         }
-//     }
+    fn render(
+        &self,
+        style: EditorStyle,
+        workspace: Option<WeakView<Workspace>>,
+        cx: &mut ViewContext<Editor>,
+    ) {
+        todo!("old implementation below")
+    }
+    // ) -> AnyElement<Editor> {
+    //     enum CompletionTag {}
+
+    //     let settings = EditorSettings>(cx);
+    //     let show_completion_documentation = settings.show_completion_documentation;
+
+    //     let widest_completion_ix = self
+    //         .matches
+    //         .iter()
+    //         .enumerate()
+    //         .max_by_key(|(_, mat)| {
+    //             let completions = self.completions.read();
+    //             let completion = &completions[mat.candidate_id];
+    //             let documentation = &completion.documentation;
+
+    //             let mut len = completion.label.text.chars().count();
+    //             if let Some(Documentation::SingleLine(text)) = documentation {
+    //                 if show_completion_documentation {
+    //                     len += text.chars().count();
+    //                 }
+    //             }
 
-//     fn visible(&self) -> bool {
-//         !self.matches.is_empty()
-//     }
+    //             len
+    //         })
+    //         .map(|(ix, _)| ix);
 
-//     fn render(
-//         &self,
-//         style: EditorStyle,
-//         workspace: Option<WeakView<Workspace>>,
-//         cx: &mut ViewContext<Editor>,
-//     ) -> AnyElement<Editor> {
-//         enum CompletionTag {}
-
-//         let settings = settings::get::<EditorSettings>(cx);
-//         let show_completion_documentation = settings.show_completion_documentation;
-
-//         let widest_completion_ix = self
-//             .matches
-//             .iter()
-//             .enumerate()
-//             .max_by_key(|(_, mat)| {
-//                 let completions = self.completions.read();
-//                 let completion = &completions[mat.candidate_id];
-//                 let documentation = &completion.documentation;
-
-//                 let mut len = completion.label.text.chars().count();
-//                 if let Some(Documentation::SingleLine(text)) = documentation {
-//                     if show_completion_documentation {
-//                         len += text.chars().count();
-//                     }
-//                 }
+    //     let completions = self.completions.clone();
+    //     let matches = self.matches.clone();
+    //     let selected_item = self.selected_item;
 
-//                 len
-//             })
-//             .map(|(ix, _)| ix);
-
-//         let completions = self.completions.clone();
-//         let matches = self.matches.clone();
-//         let selected_item = self.selected_item;
-
-//         let list = UniformList::new(self.list.clone(), matches.len(), cx, {
-//             let style = style.clone();
-//             move |_, range, items, cx| {
-//                 let start_ix = range.start;
-//                 let completions_guard = completions.read();
-
-//                 for (ix, mat) in matches[range].iter().enumerate() {
-//                     let item_ix = start_ix + ix;
-//                     let candidate_id = mat.candidate_id;
-//                     let completion = &completions_guard[candidate_id];
-
-//                     let documentation = if show_completion_documentation {
-//                         &completion.documentation
-//                     } else {
-//                         &None
-//                     };
-
-//                     items.push(
-//                         MouseEventHandler::new::<CompletionTag, _>(
-//                             mat.candidate_id,
-//                             cx,
-//                             |state, _| {
-//                                 let item_style = if item_ix == selected_item {
-//                                     style.autocomplete.selected_item
-//                                 } else if state.hovered() {
-//                                     style.autocomplete.hovered_item
-//                                 } else {
-//                                     style.autocomplete.item
-//                                 };
-
-//                                 let completion_label =
-//                                     Text::new(completion.label.text.clone(), style.text.clone())
-//                                         .with_soft_wrap(false)
-//                                         .with_highlights(
-//                                             combine_syntax_and_fuzzy_match_highlights(
-//                                                 &completion.label.text,
-//                                                 style.text.color.into(),
-//                                                 styled_runs_for_code_label(
-//                                                     &completion.label,
-//                                                     &style.syntax,
-//                                                 ),
-//                                                 &mat.positions,
-//                                             ),
-//                                         );
-
-//                                 if let Some(Documentation::SingleLine(text)) = documentation {
-//                                     Flex::row()
-//                                         .with_child(completion_label)
-//                                         .with_children((|| {
-//                                             let text_style = TextStyle {
-//                                                 color: style.autocomplete.inline_docs_color,
-//                                                 font_size: style.text.font_size
-//                                                     * style.autocomplete.inline_docs_size_percent,
-//                                                 ..style.text.clone()
-//                                             };
-
-//                                             let label = Text::new(text.clone(), text_style)
-//                                                 .aligned()
-//                                                 .constrained()
-//                                                 .dynamically(move |constraint, _, _| {
-//                                                     gpui::SizeConstraint {
-//                                                         min: constraint.min,
-//                                                         max: vec2f(
-//                                                             constraint.max.x(),
-//                                                             constraint.min.y(),
-//                                                         ),
-//                                                     }
-//                                                 });
-
-//                                             if Some(item_ix) == widest_completion_ix {
-//                                                 Some(
-//                                                     label
-//                                                         .contained()
-//                                                         .with_style(
-//                                                             style
-//                                                                 .autocomplete
-//                                                                 .inline_docs_container,
-//                                                         )
-//                                                         .into_any(),
-//                                                 )
-//                                             } else {
-//                                                 Some(label.flex_float().into_any())
-//                                             }
-//                                         })())
-//                                         .into_any()
-//                                 } else {
-//                                     completion_label.into_any()
-//                                 }
-//                                 .contained()
-//                                 .with_style(item_style)
-//                                 .constrained()
-//                                 .dynamically(
-//                                     move |constraint, _, _| {
-//                                         if Some(item_ix) == widest_completion_ix {
-//                                             constraint
-//                                         } else {
-//                                             gpui::SizeConstraint {
-//                                                 min: constraint.min,
-//                                                 max: constraint.min,
-//                                             }
-//                                         }
-//                                     },
-//                                 )
-//                             },
-//                         )
-//                         .with_cursor_style(CursorStyle::PointingHand)
-//                         .on_down(MouseButton::Left, move |_, this, cx| {
-//                             this.confirm_completion(
-//                                 &ConfirmCompletion {
-//                                     item_ix: Some(item_ix),
-//                                 },
-//                                 cx,
-//                             )
-//                             .map(|task| task.detach());
-//                         })
-//                         .constrained()
-//                         .with_min_width(style.autocomplete.completion_min_width)
-//                         .with_max_width(style.autocomplete.completion_max_width)
-//                         .into_any(),
-//                     );
-//                 }
-//             }
-//         })
-//         .with_width_from_item(widest_completion_ix);
-
-//         enum MultiLineDocumentation {}
-
-//         Flex::row()
-//             .with_child(list.flex(1., false))
-//             .with_children({
-//                 let mat = &self.matches[selected_item];
-//                 let completions = self.completions.read();
-//                 let completion = &completions[mat.candidate_id];
-//                 let documentation = &completion.documentation;
-
-//                 match documentation {
-//                     Some(Documentation::MultiLinePlainText(text)) => Some(
-//                         Flex::column()
-//                             .scrollable::<MultiLineDocumentation>(0, None, cx)
-//                             .with_child(
-//                                 Text::new(text.clone(), style.text.clone()).with_soft_wrap(true),
-//                             )
-//                             .contained()
-//                             .with_style(style.autocomplete.alongside_docs_container)
-//                             .constrained()
-//                             .with_max_width(style.autocomplete.alongside_docs_max_width)
-//                             .flex(1., false),
-//                     ),
-
-//                     Some(Documentation::MultiLineMarkdown(parsed)) => Some(
-//                         Flex::column()
-//                             .scrollable::<MultiLineDocumentation>(0, None, cx)
-//                             .with_child(render_parsed_markdown::<MultiLineDocumentation>(
-//                                 parsed, &style, workspace, cx,
-//                             ))
-//                             .contained()
-//                             .with_style(style.autocomplete.alongside_docs_container)
-//                             .constrained()
-//                             .with_max_width(style.autocomplete.alongside_docs_max_width)
-//                             .flex(1., false),
-//                     ),
-
-//                     _ => None,
-//                 }
-//             })
-//             .contained()
-//             .with_style(style.autocomplete.container)
-//             .into_any()
-//     }
+    //     let list = UniformList::new(self.list.clone(), matches.len(), cx, {
+    //         let style = style.clone();
+    //         move |_, range, items, cx| {
+    //             let start_ix = range.start;
+    //             let completions_guard = completions.read();
 
-//     pub async fn filter(&mut self, query: Option<&str>, executor: Arc<executor::Background>) {
-//         let mut matches = if let Some(query) = query {
-//             fuzzy::match_strings(
-//                 &self.match_candidates,
-//                 query,
-//                 query.chars().any(|c| c.is_uppercase()),
-//                 100,
-//                 &Default::default(),
-//                 executor,
-//             )
-//             .await
-//         } else {
-//             self.match_candidates
-//                 .iter()
-//                 .enumerate()
-//                 .map(|(candidate_id, candidate)| StringMatch {
-//                     candidate_id,
-//                     score: Default::default(),
-//                     positions: Default::default(),
-//                     string: candidate.string.clone(),
-//                 })
-//                 .collect()
-//         };
+    //             for (ix, mat) in matches[range].iter().enumerate() {
+    //                 let item_ix = start_ix + ix;
+    //                 let candidate_id = mat.candidate_id;
+    //                 let completion = &completions_guard[candidate_id];
 
-//         // Remove all candidates where the query's start does not match the start of any word in the candidate
-//         if let Some(query) = query {
-//             if let Some(query_start) = query.chars().next() {
-//                 matches.retain(|string_match| {
-//                     split_words(&string_match.string).any(|word| {
-//                         // Check that the first codepoint of the word as lowercase matches the first
-//                         // codepoint of the query as lowercase
-//                         word.chars()
-//                             .flat_map(|codepoint| codepoint.to_lowercase())
-//                             .zip(query_start.to_lowercase())
-//                             .all(|(word_cp, query_cp)| word_cp == query_cp)
-//                     })
-//                 });
-//             }
-//         }
+    //                 let documentation = if show_completion_documentation {
+    //                     &completion.documentation
+    //                 } else {
+    //                     &None
+    //                 };
 
-//         let completions = self.completions.read();
-//         matches.sort_unstable_by_key(|mat| {
-//             let completion = &completions[mat.candidate_id];
-//             (
-//                 completion.lsp_completion.sort_text.as_ref(),
-//                 Reverse(OrderedFloat(mat.score)),
-//                 completion.sort_key(),
-//             )
-//         });
-//         drop(completions);
+    //                 items.push(
+    //                     MouseEventHandler::new::<CompletionTag, _>(
+    //                         mat.candidate_id,
+    //                         cx,
+    //                         |state, _| {
+    //                             let item_style = if item_ix == selected_item {
+    //                                 style.autocomplete.selected_item
+    //                             } else if state.hovered() {
+    //                                 style.autocomplete.hovered_item
+    //                             } else {
+    //                                 style.autocomplete.item
+    //                             };
 
-//         for mat in &mut matches {
-//             let completions = self.completions.read();
-//             let filter_start = completions[mat.candidate_id].label.filter_range.start;
-//             for position in &mut mat.positions {
-//                 *position += filter_start;
-//             }
-//         }
+    //                             let completion_label =
+    //                                 Text::new(completion.label.text.clone(), style.text.clone())
+    //                                     .with_soft_wrap(false)
+    //                                     .with_highlights(
+    //                                         combine_syntax_and_fuzzy_match_highlights(
+    //                                             &completion.label.text,
+    //                                             style.text.color.into(),
+    //                                             styled_runs_for_code_label(
+    //                                                 &completion.label,
+    //                                                 &style.syntax,
+    //                                             ),
+    //                                             &mat.positions,
+    //                                         ),
+    //                                     );
 
-//         self.matches = matches.into();
-//         self.selected_item = 0;
-//     }
-// }
+    //                             if let Some(Documentation::SingleLine(text)) = documentation {
+    //                                 Flex::row()
+    //                                     .with_child(completion_label)
+    //                                     .with_children((|| {
+    //                                         let text_style = TextStyle {
+    //                                             color: style.autocomplete.inline_docs_color,
+    //                                             font_size: style.text.font_size
+    //                                                 * style.autocomplete.inline_docs_size_percent,
+    //                                             ..style.text.clone()
+    //                                         };
+
+    //                                         let label = Text::new(text.clone(), text_style)
+    //                                             .aligned()
+    //                                             .constrained()
+    //                                             .dynamically(move |constraint, _, _| {
+    //                                                 gpui::SizeConstraint {
+    //                                                     min: constraint.min,
+    //                                                     max: vec2f(
+    //                                                         constraint.max.x(),
+    //                                                         constraint.min.y(),
+    //                                                     ),
+    //                                                 }
+    //                                             });
+
+    //                                         if Some(item_ix) == widest_completion_ix {
+    //                                             Some(
+    //                                                 label
+    //                                                     .contained()
+    //                                                     .with_style(
+    //                                                         style
+    //                                                             .autocomplete
+    //                                                             .inline_docs_container,
+    //                                                     )
+    //                                                     .into_any(),
+    //                                             )
+    //                                         } else {
+    //                                             Some(label.flex_float().into_any())
+    //                                         }
+    //                                     })())
+    //                                     .into_any()
+    //                             } else {
+    //                                 completion_label.into_any()
+    //                             }
+    //                             .contained()
+    //                             .with_style(item_style)
+    //                             .constrained()
+    //                             .dynamically(
+    //                                 move |constraint, _, _| {
+    //                                     if Some(item_ix) == widest_completion_ix {
+    //                                         constraint
+    //                                     } else {
+    //                                         gpui::SizeConstraint {
+    //                                             min: constraint.min,
+    //                                             max: constraint.min,
+    //                                         }
+    //                                     }
+    //                                 },
+    //                             )
+    //                         },
+    //                     )
+    //                     .with_cursor_style(CursorStyle::PointingHand)
+    //                     .on_down(MouseButton::Left, move |_, this, cx| {
+    //                         this.confirm_completion(
+    //                             &ConfirmCompletion {
+    //                                 item_ix: Some(item_ix),
+    //                             },
+    //                             cx,
+    //                         )
+    //                         .map(|task| task.detach());
+    //                     })
+    //                     .constrained()
+    //                     .with_min_width(style.autocomplete.completion_min_width)
+    //                     .with_max_width(style.autocomplete.completion_max_width)
+    //                     .into_any(),
+    //                 );
+    //             }
+    //         }
+    //     })
+    //     .with_width_from_item(widest_completion_ix);
+
+    //     enum MultiLineDocumentation {}
+
+    //     Flex::row()
+    //         .with_child(list.flex(1., false))
+    //         .with_children({
+    //             let mat = &self.matches[selected_item];
+    //             let completions = self.completions.read();
+    //             let completion = &completions[mat.candidate_id];
+    //             let documentation = &completion.documentation;
+
+    //             match documentation {
+    //                 Some(Documentation::MultiLinePlainText(text)) => Some(
+    //                     Flex::column()
+    //                         .scrollable::<MultiLineDocumentation>(0, None, cx)
+    //                         .with_child(
+    //                             Text::new(text.clone(), style.text.clone()).with_soft_wrap(true),
+    //                         )
+    //                         .contained()
+    //                         .with_style(style.autocomplete.alongside_docs_container)
+    //                         .constrained()
+    //                         .with_max_width(style.autocomplete.alongside_docs_max_width)
+    //                         .flex(1., false),
+    //                 ),
+
+    //                 Some(Documentation::MultiLineMarkdown(parsed)) => Some(
+    //                     Flex::column()
+    //                         .scrollable::<MultiLineDocumentation>(0, None, cx)
+    //                         .with_child(render_parsed_markdown::<MultiLineDocumentation>(
+    //                             parsed, &style, workspace, cx,
+    //                         ))
+    //                         .contained()
+    //                         .with_style(style.autocomplete.alongside_docs_container)
+    //                         .constrained()
+    //                         .with_max_width(style.autocomplete.alongside_docs_max_width)
+    //                         .flex(1., false),
+    //                 ),
+
+    //                 _ => None,
+    //             }
+    //         })
+    //         .contained()
+    //         .with_style(style.autocomplete.container)
+    //         .into_any()
+    // }
+
+    pub async fn filter(&mut self, query: Option<&str>, executor: BackgroundExecutor) {
+        let mut matches = if let Some(query) = query {
+            fuzzy::match_strings(
+                &self.match_candidates,
+                query,
+                query.chars().any(|c| c.is_uppercase()),
+                100,
+                &Default::default(),
+                executor,
+            )
+            .await
+        } else {
+            self.match_candidates
+                .iter()
+                .enumerate()
+                .map(|(candidate_id, candidate)| StringMatch {
+                    candidate_id,
+                    score: Default::default(),
+                    positions: Default::default(),
+                    string: candidate.string.clone(),
+                })
+                .collect()
+        };
+
+        // Remove all candidates where the query's start does not match the start of any word in the candidate
+        if let Some(query) = query {
+            if let Some(query_start) = query.chars().next() {
+                matches.retain(|string_match| {
+                    split_words(&string_match.string).any(|word| {
+                        // Check that the first codepoint of the word as lowercase matches the first
+                        // codepoint of the query as lowercase
+                        word.chars()
+                            .flat_map(|codepoint| codepoint.to_lowercase())
+                            .zip(query_start.to_lowercase())
+                            .all(|(word_cp, query_cp)| word_cp == query_cp)
+                    })
+                });
+            }
+        }
+
+        let completions = self.completions.read();
+        matches.sort_unstable_by_key(|mat| {
+            let completion = &completions[mat.candidate_id];
+            (
+                completion.lsp_completion.sort_text.as_ref(),
+                Reverse(OrderedFloat(mat.score)),
+                completion.sort_key(),
+            )
+        });
+        drop(completions);
+
+        for mat in &mut matches {
+            let completions = self.completions.read();
+            let filter_start = completions[mat.candidate_id].label.filter_range.start;
+            for position in &mut mat.positions {
+                *position += filter_start;
+            }
+        }
+
+        self.matches = matches.into();
+        self.selected_item = 0;
+    }
+}
 
 #[derive(Clone)]
 struct CodeActionsMenu {
     actions: Arc<[CodeAction]>,
     buffer: Model<Buffer>,
     selected_item: usize,
-    // list: UniformListState,
+    list: UniformListState,
     deployed_from_indicator: bool,
 }
 
-// impl CodeActionsMenu {
-//     fn select_first(&mut self, cx: &mut ViewContext<Editor>) {
-//         self.selected_item = 0;
-//         self.list.scroll_to(ScrollTarget::Show(self.selected_item));
-//         cx.notify()
-//     }
+impl CodeActionsMenu {
+    fn select_first(&mut self, cx: &mut ViewContext<Editor>) {
+        self.selected_item = 0;
+        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
+        cx.notify()
+    }
 
-//     fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
-//         if self.selected_item > 0 {
-//             self.selected_item -= 1;
-//         } else {
-//             self.selected_item = self.actions.len() - 1;
-//         }
-//         self.list.scroll_to(ScrollTarget::Show(self.selected_item));
-//         cx.notify();
-//     }
+    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
+        if self.selected_item > 0 {
+            self.selected_item -= 1;
+        } else {
+            self.selected_item = self.actions.len() - 1;
+        }
+        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
+        cx.notify();
+    }
 
-//     fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
-//         if self.selected_item + 1 < self.actions.len() {
-//             self.selected_item += 1;
-//         } else {
-//             self.selected_item = 0;
-//         }
-//         self.list.scroll_to(ScrollTarget::Show(self.selected_item));
-//         cx.notify();
-//     }
+    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
+        if self.selected_item + 1 < self.actions.len() {
+            self.selected_item += 1;
+        } else {
+            self.selected_item = 0;
+        }
+        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
+        cx.notify();
+    }
 
-//     fn select_last(&mut self, cx: &mut ViewContext<Editor>) {
-//         self.selected_item = self.actions.len() - 1;
-//         self.list.scroll_to(ScrollTarget::Show(self.selected_item));
-//         cx.notify()
-//     }
+    fn select_last(&mut self, cx: &mut ViewContext<Editor>) {
+        self.selected_item = self.actions.len() - 1;
+        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
+        cx.notify()
+    }
 
-//     fn visible(&self) -> bool {
-//         !self.actions.is_empty()
-//     }
+    fn visible(&self) -> bool {
+        !self.actions.is_empty()
+    }
 
-//     fn render(
-//         &self,
-//         mut cursor_position: DisplayPoint,
-//         style: EditorStyle,
-//         cx: &mut ViewContext<Editor>,
-//     ) -> (DisplayPoint, AnyElement<Editor>) {
-//         enum ActionTag {}
-
-//         let container_style = style.autocomplete.container;
-//         let actions = self.actions.clone();
-//         let selected_item = self.selected_item;
-//         let element = UniformList::new(
-//             self.list.clone(),
-//             actions.len(),
-//             cx,
-//             move |_, range, items, cx| {
-//                 let start_ix = range.start;
-//                 for (ix, action) in actions[range].iter().enumerate() {
-//                     let item_ix = start_ix + ix;
-//                     items.push(
-//                         MouseEventHandler::new::<ActionTag, _>(item_ix, cx, |state, _| {
-//                             let item_style = if item_ix == selected_item {
-//                                 style.autocomplete.selected_item
-//                             } else if state.hovered() {
-//                                 style.autocomplete.hovered_item
-//                             } else {
-//                                 style.autocomplete.item
-//                             };
-
-//                             Text::new(action.lsp_action.title.clone(), style.text.clone())
-//                                 .with_soft_wrap(false)
-//                                 .contained()
-//                                 .with_style(item_style)
-//                         })
-//                         .with_cursor_style(CursorStyle::PointingHand)
-//                         .on_down(MouseButton::Left, move |_, this, cx| {
-//                             let workspace = this
-//                                 .workspace
-//                                 .as_ref()
-//                                 .and_then(|(workspace, _)| workspace.upgrade(cx));
-//                             cx.window_context().defer(move |cx| {
-//                                 if let Some(workspace) = workspace {
-//                                     workspace.update(cx, |workspace, cx| {
-//                                         if let Some(task) = Editor::confirm_code_action(
-//                                             workspace,
-//                                             &ConfirmCodeAction {
-//                                                 item_ix: Some(item_ix),
-//                                             },
-//                                             cx,
-//                                         ) {
-//                                             task.detach_and_log_err(cx);
-//                                         }
-//                                     });
-//                                 }
-//                             });
-//                         })
-//                         .into_any(),
-//                     );
-//                 }
-//             },
-//         )
-//         .with_width_from_item(
-//             self.actions
-//                 .iter()
-//                 .enumerate()
-//                 .max_by_key(|(_, action)| action.lsp_action.title.chars().count())
-//                 .map(|(ix, _)| ix),
-//         )
-//         .contained()
-//         .with_style(container_style)
-//         .into_any();
+    fn render(
+        &self,
+        mut cursor_position: DisplayPoint,
+        style: EditorStyle,
+        cx: &mut ViewContext<Editor>,
+    ) -> (DisplayPoint, AnyElement<Editor>) {
+        todo!("old version below")
+    }
+    //     enum ActionTag {}
+
+    //     let container_style = style.autocomplete.container;
+    //     let actions = self.actions.clone();
+    //     let selected_item = self.selected_item;
+    //     let element = UniformList::new(
+    //         self.list.clone(),
+    //         actions.len(),
+    //         cx,
+    //         move |_, range, items, cx| {
+    //             let start_ix = range.start;
+    //             for (ix, action) in actions[range].iter().enumerate() {
+    //                 let item_ix = start_ix + ix;
+    //                 items.push(
+    //                     MouseEventHandler::new::<ActionTag, _>(item_ix, cx, |state, _| {
+    //                         let item_style = if item_ix == selected_item {
+    //                             style.autocomplete.selected_item
+    //                         } else if state.hovered() {
+    //                             style.autocomplete.hovered_item
+    //                         } else {
+    //                             style.autocomplete.item
+    //                         };
 
-//         if self.deployed_from_indicator {
-//             *cursor_position.column_mut() = 0;
-//         }
+    //                         Text::new(action.lsp_action.title.clone(), style.text.clone())
+    //                             .with_soft_wrap(false)
+    //                             .contained()
+    //                             .with_style(item_style)
+    //                     })
+    //                     .with_cursor_style(CursorStyle::PointingHand)
+    //                     .on_down(MouseButton::Left, move |_, this, cx| {
+    //                         let workspace = this
+    //                             .workspace
+    //                             .as_ref()
+    //                             .and_then(|(workspace, _)| workspace.upgrade(cx));
+    //                         cx.window_context().defer(move |cx| {
+    //                             if let Some(workspace) = workspace {
+    //                                 workspace.update(cx, |workspace, cx| {
+    //                                     if let Some(task) = Editor::confirm_code_action(
+    //                                         workspace,
+    //                                         &ConfirmCodeAction {
+    //                                             item_ix: Some(item_ix),
+    //                                         },
+    //                                         cx,
+    //                                     ) {
+    //                                         task.detach_and_log_err(cx);
+    //                                     }
+    //                                 });
+    //                             }
+    //                         });
+    //                     })
+    //                     .into_any(),
+    //                 );
+    //             }
+    //         },
+    //     )
+    //     .with_width_from_item(
+    //         self.actions
+    //             .iter()
+    //             .enumerate()
+    //             .max_by_key(|(_, action)| action.lsp_action.title.chars().count())
+    //             .map(|(ix, _)| ix),
+    //     )
+    //     .contained()
+    //     .with_style(container_style)
+    //     .into_any();
 
-//         (cursor_position, element)
-//     }
-// }
+    //     if self.deployed_from_indicator {
+    //         *cursor_position.column_mut() = 0;
+    //     }
+
+    //     (cursor_position, element)
+    // }
+}
 
 pub struct CopilotState {
     excerpt_id: Option<ExcerptId>,

crates/editor2/src/element.rs 🔗

@@ -5,10 +5,13 @@ use crate::{
     display_map::{BlockStyle, DisplaySnapshot},
     EditorStyle,
 };
+use anyhow::Result;
 use gpui::{
-    px, relative, AnyElement, Bounds, Element, Hsla, Line, Pixels, Size, Style, TextRun, TextSystem,
+    black, px, relative, AnyElement, Bounds, Element, Hsla, Line, Pixels, Size, Style, TextRun,
+    TextSystem,
 };
 use language::{CursorShape, Selection};
+use smallvec::SmallVec;
 use std::{ops::Range, sync::Arc};
 use sum_tree::Bias;
 
@@ -2700,16 +2703,16 @@ impl PositionMap {
         let position = position - text_bounds.origin;
         let y = position.y.max(px(0.)).min(self.size.width);
         let x = position.x + (scroll_position.x * self.em_width);
-        let row = (y / self.line_height + scroll_position.y).into();
+        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(|line_with_spaces| &line_with_spaces.line)
+            .map(|LineWithInvisibles { line, .. }| line)
         {
             if let Some(ix) = line.index_for_x(x) {
-                (ix as u32, 0.0)
+                (ix as u32, px(0.))
             } else {
-                (line.len() as u32, px(0.).max(x - line.width()))
+                (line.len as u32, px(0.).max(x - line.width()))
             }
         } else {
             (0, x)
@@ -2719,7 +2722,7 @@ impl PositionMap {
         let previous_valid = self.snapshot.clip_point(exact_unclipped, Bias::Left);
         let next_valid = self.snapshot.clip_point(exact_unclipped, Bias::Right);
 
-        let column_overshoot_after_line_end = (x_overshoot_after_line_end / self.em_advance) as u32;
+        let column_overshoot_after_line_end = (x_overshoot_after_line_end / self.em_advance).into();
         *exact_unclipped.column_mut() += column_overshoot_after_line_end;
         PointForPosition {
             previous_valid,
@@ -2740,8 +2743,9 @@ fn layout_line(
     row: u32,
     snapshot: &EditorSnapshot,
     style: &EditorStyle,
+    rem_size: Pixels,
     text_system: &TextSystem,
-) -> Line {
+) -> Result<SmallVec<[Line; 1]>> {
     let mut line = snapshot.line(row);
 
     if line.len() > MAX_LINE_LEN {
@@ -2753,15 +2757,16 @@ fn layout_line(
         line.truncate(len);
     }
 
-    text_system.layout_str(
+    text_system.layout_text(
         &line,
-        style.text.font_size,
+        style.text.font_size * rem_size,
         &[TextRun {
             len: snapshot.line_len(row) as usize,
-            font: style.text.font.clone(),
-            color: Hsla::black(),
+            font: style.text.font(),
+            color: black(),
             underline: Default::default(),
         }],
+        None,
     )
 }
 

crates/editor2/src/highlight_matching_bracket.rs 🔗

@@ -5,29 +5,30 @@ use crate::{Editor, RangeToAnchorExt};
 enum MatchingBracketHighlight {}
 
 pub fn refresh_matching_bracket_highlights(editor: &mut Editor, cx: &mut ViewContext<Editor>) {
-    editor.clear_background_highlights::<MatchingBracketHighlight>(cx);
+    todo!()
+    // // editor.clear_background_highlights::<MatchingBracketHighlight>(cx);
 
-    let newest_selection = editor.selections.newest::<usize>(cx);
-    // Don't highlight brackets if the selection isn't empty
-    if !newest_selection.is_empty() {
-        return;
-    }
+    // let newest_selection = editor.selections.newest::<usize>(cx);
+    // // Don't highlight brackets if the selection isn't empty
+    // if !newest_selection.is_empty() {
+    //     return;
+    // }
 
-    let head = newest_selection.head();
-    let snapshot = editor.snapshot(cx);
-    if let Some((opening_range, closing_range)) = snapshot
-        .buffer_snapshot
-        .innermost_enclosing_bracket_ranges(head..head)
-    {
-        editor.highlight_background::<MatchingBracketHighlight>(
-            vec![
-                opening_range.to_anchors(&snapshot.buffer_snapshot),
-                closing_range.to_anchors(&snapshot.buffer_snapshot),
-            ],
-            |theme| theme.editor.document_highlight_read_background,
-            cx,
-        )
-    }
+    // let head = newest_selection.head();
+    // let snapshot = editor.snapshot(cx);
+    // if let Some((opening_range, closing_range)) = snapshot
+    //     .buffer_snapshot
+    //     .innermost_enclosing_bracket_ranges(head..head)
+    // {
+    //     editor.highlight_background::<MatchingBracketHighlight>(
+    //         vec![
+    //             opening_range.to_anchors(&snapshot.buffer_snapshot),
+    //             closing_range.to_anchors(&snapshot.buffer_snapshot),
+    //         ],
+    //         |theme| theme.editor.document_highlight_read_background,
+    //         cx,
+    //     )
+    // }
 }
 
 // #[cfg(test)]

crates/editor2/src/hover_popover.rs 🔗

@@ -1,17 +1,14 @@
 use crate::{
-    display_map::{InlayOffset, ToDisplayPoint},
+    display_map::InlayOffset,
     link_go_to_definition::{InlayHighlight, RangeInEditor},
     Anchor, AnchorRangeExt, DisplayPoint, Editor, EditorSettings, EditorSnapshot, EditorStyle,
     ExcerptId, RangeToAnchorExt,
 };
 use futures::FutureExt;
-use gpui::{
-    AnyElement, AppContext, CursorStyle, Element, Model, MouseButton, Task, ViewContext, WeakView,
-};
-use language::{
-    markdown, Bias, DiagnosticEntry, DiagnosticSeverity, Language, LanguageRegistry, ParsedMarkdown,
-};
+use gpui::{AnyElement, AppContext, Model, Task, ViewContext, WeakView};
+use language::{markdown, Bias, DiagnosticEntry, Language, LanguageRegistry, ParsedMarkdown};
 use project::{HoverBlock, HoverBlockKind, InlayHintLabelPart, Project};
+use settings::Settings;
 use std::{ops::Range, sync::Arc, time::Duration};
 use util::TryFutureExt;
 use workspace::Workspace;
@@ -77,63 +74,64 @@ pub fn find_hovered_hint_part(
 }
 
 pub fn hover_at_inlay(editor: &mut Editor, inlay_hover: InlayHover, cx: &mut ViewContext<Editor>) {
-    if EditorSettings::get_global(cx).hover_popover_enabled {
-        if editor.pending_rename.is_some() {
-            return;
-        }
-
-        let Some(project) = editor.project.clone() else {
-            return;
-        };
-
-        if let Some(InfoPopover { symbol_range, .. }) = &editor.hover_state.info_popover {
-            if let RangeInEditor::Inlay(range) = symbol_range {
-                if range == &inlay_hover.range {
-                    // Hover triggered from same location as last time. Don't show again.
-                    return;
-                }
-            }
-            hide_hover(editor, cx);
-        }
-
-        let task = cx.spawn(|this, mut cx| {
-            async move {
-                cx.background()
-                    .timer(Duration::from_millis(HOVER_DELAY_MILLIS))
-                    .await;
-                this.update(&mut cx, |this, _| {
-                    this.hover_state.diagnostic_popover = None;
-                })?;
-
-                let language_registry = project.update(&mut cx, |p, _| p.languages().clone());
-                let blocks = vec![inlay_hover.tooltip];
-                let parsed_content = parse_blocks(&blocks, &language_registry, None).await;
-
-                let hover_popover = InfoPopover {
-                    project: project.clone(),
-                    symbol_range: RangeInEditor::Inlay(inlay_hover.range.clone()),
-                    blocks,
-                    parsed_content,
-                };
-
-                this.update(&mut cx, |this, cx| {
-                    // Highlight the selected symbol using a background highlight
-                    this.highlight_inlay_background::<HoverState>(
-                        vec![inlay_hover.range],
-                        |theme| theme.editor.hover_popover.highlight,
-                        cx,
-                    );
-                    this.hover_state.info_popover = Some(hover_popover);
-                    cx.notify();
-                })?;
-
-                anyhow::Ok(())
-            }
-            .log_err()
-        });
-
-        editor.hover_state.info_task = Some(task);
-    }
+    todo!()
+    // if EditorSettings::get_global(cx).hover_popover_enabled {
+    //     if editor.pending_rename.is_some() {
+    //         return;
+    //     }
+
+    //     let Some(project) = editor.project.clone() else {
+    //         return;
+    //     };
+
+    //     if let Some(InfoPopover { symbol_range, .. }) = &editor.hover_state.info_popover {
+    //         if let RangeInEditor::Inlay(range) = symbol_range {
+    //             if range == &inlay_hover.range {
+    //                 // Hover triggered from same location as last time. Don't show again.
+    //                 return;
+    //             }
+    //         }
+    //         hide_hover(editor, cx);
+    //     }
+
+    //     let task = cx.spawn(|this, mut cx| {
+    //         async move {
+    //             cx.background_executor()
+    //                 .timer(Duration::from_millis(HOVER_DELAY_MILLIS))
+    //                 .await;
+    //             this.update(&mut cx, |this, _| {
+    //                 this.hover_state.diagnostic_popover = None;
+    //             })?;
+
+    //             let language_registry = project.update(&mut cx, |p, _| p.languages().clone())?;
+    //             let blocks = vec![inlay_hover.tooltip];
+    //             let parsed_content = parse_blocks(&blocks, &language_registry, None).await;
+
+    //             let hover_popover = InfoPopover {
+    //                 project: project.clone(),
+    //                 symbol_range: RangeInEditor::Inlay(inlay_hover.range.clone()),
+    //                 blocks,
+    //                 parsed_content,
+    //             };
+
+    //             this.update(&mut cx, |this, cx| {
+    //                 // Highlight the selected symbol using a background highlight
+    //                 this.highlight_inlay_background::<HoverState>(
+    //                     vec![inlay_hover.range],
+    //                     |theme| theme.editor.hover_popover.highlight,
+    //                     cx,
+    //                 );
+    //                 this.hover_state.info_popover = Some(hover_popover);
+    //                 cx.notify();
+    //             })?;
+
+    //             anyhow::Ok(())
+    //         }
+    //         .log_err()
+    //     });
+
+    //     editor.hover_state.info_task = Some(task);
+    // }
 }
 
 /// Hides the type information popup.
@@ -146,7 +144,8 @@ pub fn hide_hover(editor: &mut Editor, cx: &mut ViewContext<Editor>) -> bool {
     editor.hover_state.info_task = None;
     editor.hover_state.triggered_from = None;
 
-    editor.clear_background_highlights::<HoverState>(cx);
+    // todo!()
+    // editor.clear_background_highlights::<HoverState>(cx);
 
     if did_hide {
         cx.notify();
@@ -237,11 +236,11 @@ fn show_hover(
             let delay = if !ignore_timeout {
                 // Construct delay task to wait for later
                 let total_delay = Some(
-                    cx.background()
+                    cx.background_executor()
                         .timer(Duration::from_millis(HOVER_DELAY_MILLIS)),
                 );
 
-                cx.background()
+                cx.background_executor()
                     .timer(Duration::from_millis(HOVER_REQUEST_DELAY_MILLIS))
                     .await;
                 total_delay
@@ -250,11 +249,11 @@ fn show_hover(
             };
 
             // query the LSP for hover info
-            let hover_request = cx.update(|cx| {
+            let hover_request = cx.update(|_, cx| {
                 project.update(cx, |project, cx| {
                     project.hover(&buffer, buffer_position, cx)
                 })
-            });
+            })?;
 
             if let Some(delay) = delay {
                 delay.await;
@@ -308,7 +307,8 @@ fn show_hover(
                         anchor..anchor
                     };
 
-                    let language_registry = project.update(&mut cx, |p, _| p.languages().clone());
+                    let language_registry =
+                        project.update(&mut cx, |p, _| p.languages().clone())?;
                     let blocks = hover_result.contents;
                     let language = hover_result.language;
                     let parsed_content = parse_blocks(&blocks, &language_registry, language).await;
@@ -325,22 +325,23 @@ fn show_hover(
             };
 
             this.update(&mut cx, |this, cx| {
-                if let Some(symbol_range) = hover_popover
-                    .as_ref()
-                    .and_then(|hover_popover| hover_popover.symbol_range.as_text_range())
-                {
-                    // Highlight the selected symbol using a background highlight
-                    this.highlight_background::<HoverState>(
-                        vec![symbol_range],
-                        |theme| theme.editor.hover_popover.highlight,
-                        cx,
-                    );
-                } else {
-                    this.clear_background_highlights::<HoverState>(cx);
-                }
-
-                this.hover_state.info_popover = hover_popover;
-                cx.notify();
+                todo!();
+                // if let Some(symbol_range) = hover_popover
+                //     .as_ref()
+                //     .and_then(|hover_popover| hover_popover.symbol_range.as_text_range())
+                // {
+                //     // Highlight the selected symbol using a background highlight
+                //     this.highlight_background::<HoverState>(
+                //         vec![symbol_range],
+                //         |theme| theme.editor.hover_popover.highlight,
+                //         cx,
+                //     );
+                // } else {
+                //     this.clear_background_highlights::<HoverState>(cx);
+                // }
+                //
+                // this.hover_state.info_popover = hover_popover;
+                // cx.notify();
             })?;
 
             Ok::<_, anyhow::Error>(())
@@ -424,38 +425,40 @@ impl HoverState {
         workspace: Option<WeakView<Workspace>>,
         cx: &mut ViewContext<Editor>,
     ) -> Option<(DisplayPoint, Vec<AnyElement<Editor>>)> {
-        // If there is a diagnostic, position the popovers based on that.
-        // Otherwise use the start of the hover range
-        let anchor = self
-            .diagnostic_popover
-            .as_ref()
-            .map(|diagnostic_popover| &diagnostic_popover.local_diagnostic.range.start)
-            .or_else(|| {
-                self.info_popover
-                    .as_ref()
-                    .map(|info_popover| match &info_popover.symbol_range {
-                        RangeInEditor::Text(range) => &range.start,
-                        RangeInEditor::Inlay(range) => &range.inlay_position,
-                    })
-            })?;
-        let point = anchor.to_display_point(&snapshot.display_snapshot);
-
-        // Don't render if the relevant point isn't on screen
-        if !self.visible() || !visible_rows.contains(&point.row()) {
-            return None;
-        }
-
-        let mut elements = Vec::new();
-
-        if let Some(diagnostic_popover) = self.diagnostic_popover.as_ref() {
-            elements.push(diagnostic_popover.render(style, cx));
-        }
-        if let Some(info_popover) = self.info_popover.as_mut() {
-            elements.push(info_popover.render(style, workspace, cx));
-        }
-
-        Some((point, elements))
+        todo!("old version below")
     }
+    //     // If there is a diagnostic, position the popovers based on that.
+    //     // Otherwise use the start of the hover range
+    //     let anchor = self
+    //         .diagnostic_popover
+    //         .as_ref()
+    //         .map(|diagnostic_popover| &diagnostic_popover.local_diagnostic.range.start)
+    //         .or_else(|| {
+    //             self.info_popover
+    //                 .as_ref()
+    //                 .map(|info_popover| match &info_popover.symbol_range {
+    //                     RangeInEditor::Text(range) => &range.start,
+    //                     RangeInEditor::Inlay(range) => &range.inlay_position,
+    //                 })
+    //         })?;
+    //     let point = anchor.to_display_point(&snapshot.display_snapshot);
+
+    //     // Don't render if the relevant point isn't on screen
+    //     if !self.visible() || !visible_rows.contains(&point.row()) {
+    //         return None;
+    //     }
+
+    //     let mut elements = Vec::new();
+
+    //     if let Some(diagnostic_popover) = self.diagnostic_popover.as_ref() {
+    //         elements.push(diagnostic_popover.render(style, cx));
+    //     }
+    //     if let Some(info_popover) = self.info_popover.as_mut() {
+    //         elements.push(info_popover.render(style, workspace, cx));
+    //     }
+
+    //     Some((point, elements))
+    // }
 }
 
 #[derive(Debug, Clone)]

crates/editor2/src/inlay_hint_cache.rs 🔗

@@ -553,17 +553,18 @@ impl InlayHintCache {
                             let mut resolved_hint =
                                 resolved_hint_task.await.context("hint resolve task")?;
                             editor.update(&mut cx, |editor, _| {
-                                if let Some(excerpt_hints) =
-                                    editor.inlay_hint_cache.hints.get(&excerpt_id)
-                                {
-                                    let mut guard = excerpt_hints.write();
-                                    if let Some(cached_hint) = guard.hints_by_id.get_mut(&id) {
-                                        if cached_hint.resolve_state == ResolveState::Resolving {
-                                            resolved_hint.resolve_state = ResolveState::Resolved;
-                                            *cached_hint = resolved_hint;
-                                        }
-                                    }
-                                }
+                                todo!()
+                                // if let Some(excerpt_hints) =
+                                //     editor.inlay_hint_cache.hints.get(&excerpt_id)
+                                // {
+                                //     let mut guard = excerpt_hints.write();
+                                //     if let Some(cached_hint) = guard.hints_by_id.get_mut(&id) {
+                                //         if cached_hint.resolve_state == ResolveState::Resolving {
+                                //             resolved_hint.resolve_state = ResolveState::Resolved;
+                                //             *cached_hint = resolved_hint;
+                                //         }
+                                //     }
+                                // }
                             })?;
                         }
 
@@ -584,89 +585,91 @@ fn spawn_new_update_tasks(
     update_cache_version: usize,
     cx: &mut ViewContext<'_, Editor>,
 ) {
-    let visible_hints = Arc::new(editor.visible_inlay_hints(cx));
-    for (excerpt_id, (excerpt_buffer, new_task_buffer_version, excerpt_visible_range)) in
-        excerpts_to_query
-    {
-        if excerpt_visible_range.is_empty() {
-            continue;
-        }
-        let buffer = excerpt_buffer.read(cx);
-        let buffer_id = buffer.remote_id();
-        let buffer_snapshot = buffer.snapshot();
-        if buffer_snapshot
-            .version()
-            .changed_since(&new_task_buffer_version)
-        {
-            continue;
-        }
-
-        let cached_excerpt_hints = editor.inlay_hint_cache.hints.get(&excerpt_id).cloned();
-        if let Some(cached_excerpt_hints) = &cached_excerpt_hints {
-            let cached_excerpt_hints = cached_excerpt_hints.read();
-            let cached_buffer_version = &cached_excerpt_hints.buffer_version;
-            if cached_excerpt_hints.version > update_cache_version
-                || cached_buffer_version.changed_since(&new_task_buffer_version)
-            {
-                continue;
-            }
-        };
-
-        let (multi_buffer_snapshot, Some(query_ranges)) =
-            editor.buffer.update(cx, |multi_buffer, cx| {
-                (
-                    multi_buffer.snapshot(cx),
-                    determine_query_ranges(
-                        multi_buffer,
-                        excerpt_id,
-                        &excerpt_buffer,
-                        excerpt_visible_range,
-                        cx,
-                    ),
-                )
-            })
-        else {
-            return;
-        };
-        let query = ExcerptQuery {
-            buffer_id,
-            excerpt_id,
-            cache_version: update_cache_version,
-            invalidate,
-            reason,
-        };
+    todo!("old version below");
+}
+//     let visible_hints = Arc::new(editor.visible_inlay_hints(cx));
+//     for (excerpt_id, (excerpt_buffer, new_task_buffer_version, excerpt_visible_range)) in
+//         excerpts_to_query
+//     {
+//         if excerpt_visible_range.is_empty() {
+//             continue;
+//         }
+//         let buffer = excerpt_buffer.read(cx);
+//         let buffer_id = buffer.remote_id();
+//         let buffer_snapshot = buffer.snapshot();
+//         if buffer_snapshot
+//             .version()
+//             .changed_since(&new_task_buffer_version)
+//         {
+//             continue;
+//         }
 
-        let new_update_task = |query_ranges| {
-            new_update_task(
-                query,
-                query_ranges,
-                multi_buffer_snapshot,
-                buffer_snapshot.clone(),
-                Arc::clone(&visible_hints),
-                cached_excerpt_hints,
-                Arc::clone(&editor.inlay_hint_cache.lsp_request_limiter),
-                cx,
-            )
-        };
+//         let cached_excerpt_hints = editor.inlay_hint_cache.hints.get(&excerpt_id).cloned();
+//         if let Some(cached_excerpt_hints) = &cached_excerpt_hints {
+//             let cached_excerpt_hints = cached_excerpt_hints.read();
+//             let cached_buffer_version = &cached_excerpt_hints.buffer_version;
+//             if cached_excerpt_hints.version > update_cache_version
+//                 || cached_buffer_version.changed_since(&new_task_buffer_version)
+//             {
+//                 continue;
+//             }
+//         };
+
+//         let (multi_buffer_snapshot, Some(query_ranges)) =
+//             editor.buffer.update(cx, |multi_buffer, cx| {
+//                 (
+//                     multi_buffer.snapshot(cx),
+//                     determine_query_ranges(
+//                         multi_buffer,
+//                         excerpt_id,
+//                         &excerpt_buffer,
+//                         excerpt_visible_range,
+//                         cx,
+//                     ),
+//                 )
+//             })
+//         else {
+//             return;
+//         };
+//         let query = ExcerptQuery {
+//             buffer_id,
+//             excerpt_id,
+//             cache_version: update_cache_version,
+//             invalidate,
+//             reason,
+//         };
+
+//         let new_update_task = |query_ranges| {
+//             new_update_task(
+//                 query,
+//                 query_ranges,
+//                 multi_buffer_snapshot,
+//                 buffer_snapshot.clone(),
+//                 Arc::clone(&visible_hints),
+//                 cached_excerpt_hints,
+//                 Arc::clone(&editor.inlay_hint_cache.lsp_request_limiter),
+//                 cx,
+//             )
+//         };
 
-        match editor.inlay_hint_cache.update_tasks.entry(excerpt_id) {
-            hash_map::Entry::Occupied(mut o) => {
-                o.get_mut().update_cached_tasks(
-                    &buffer_snapshot,
-                    query_ranges,
-                    invalidate,
-                    new_update_task,
-                );
-            }
-            hash_map::Entry::Vacant(v) => {
-                v.insert(TasksForRanges::new(
-                    query_ranges.clone(),
-                    new_update_task(query_ranges),
-                ));
-            }
-        }
-    }
-}
+//         match editor.inlay_hint_cache.update_tasks.entry(excerpt_id) {
+//             hash_map::Entry::Occupied(mut o) => {
+//                 o.get_mut().update_cached_tasks(
+//                     &buffer_snapshot,
+//                     query_ranges,
+//                     invalidate,
+//                     new_update_task,
+//                 );
+//             }
+//             hash_map::Entry::Vacant(v) => {
+//                 v.insert(TasksForRanges::new(
+//                     query_ranges.clone(),
+//                     new_update_task(query_ranges),
+//                 ));
+//             }
+//         }
+//     }
+// }
 
 #[derive(Debug, Clone)]
 struct QueryRanges {
@@ -762,78 +765,79 @@ fn new_update_task(
     lsp_request_limiter: Arc<Semaphore>,
     cx: &mut ViewContext<'_, Editor>,
 ) -> Task<()> {
-    cx.spawn(|editor, mut cx| async move {
-        let closure_cx = cx.clone();
-        let fetch_and_update_hints = |invalidate, range| {
-            fetch_and_update_hints(
-                editor.clone(),
-                multi_buffer_snapshot.clone(),
-                buffer_snapshot.clone(),
-                Arc::clone(&visible_hints),
-                cached_excerpt_hints.as_ref().map(Arc::clone),
-                query,
-                invalidate,
-                range,
-                Arc::clone(&lsp_request_limiter),
-                closure_cx.clone(),
-            )
-        };
-        let visible_range_update_results = future::join_all(query_ranges.visible.into_iter().map(
-            |visible_range| async move {
-                (
-                    visible_range.clone(),
-                    fetch_and_update_hints(query.invalidate.should_invalidate(), visible_range)
-                        .await,
-                )
-            },
-        ))
-        .await;
-
-        let hint_delay = cx.background().timer(Duration::from_millis(
-            INVISIBLE_RANGES_HINTS_REQUEST_DELAY_MILLIS,
-        ));
-
-        let mut query_range_failed = |range: &Range<language::Anchor>, e: anyhow::Error| {
-            log::error!("inlay hint update task for range {range:?} failed: {e:#}");
-            editor
-                .update(&mut cx, |editor, _| {
-                    if let Some(task_ranges) = editor
-                        .inlay_hint_cache
-                        .update_tasks
-                        .get_mut(&query.excerpt_id)
-                    {
-                        task_ranges.invalidate_range(&buffer_snapshot, &range);
-                    }
-                })
-                .ok()
-        };
-
-        for (range, result) in visible_range_update_results {
-            if let Err(e) = result {
-                query_range_failed(&range, e);
-            }
-        }
-
-        hint_delay.await;
-        let invisible_range_update_results = future::join_all(
-            query_ranges
-                .before_visible
-                .into_iter()
-                .chain(query_ranges.after_visible.into_iter())
-                .map(|invisible_range| async move {
-                    (
-                        invisible_range.clone(),
-                        fetch_and_update_hints(false, invisible_range).await,
-                    )
-                }),
-        )
-        .await;
-        for (range, result) in invisible_range_update_results {
-            if let Err(e) = result {
-                query_range_failed(&range, e);
-            }
-        }
-    })
+    todo!()
+    // cx.spawn(|editor, mut cx| async move {
+    //     let closure_cx = cx.clone();
+    //     let fetch_and_update_hints = |invalidate, range| {
+    //         fetch_and_update_hints(
+    //             editor.clone(),
+    //             multi_buffer_snapshot.clone(),
+    //             buffer_snapshot.clone(),
+    //             Arc::clone(&visible_hints),
+    //             cached_excerpt_hints.as_ref().map(Arc::clone),
+    //             query,
+    //             invalidate,
+    //             range,
+    //             Arc::clone(&lsp_request_limiter),
+    //             closure_cx.clone(),
+    //         )
+    //     };
+    //     let visible_range_update_results = future::join_all(query_ranges.visible.into_iter().map(
+    //         |visible_range| async move {
+    //             (
+    //                 visible_range.clone(),
+    //                 fetch_and_update_hints(query.invalidate.should_invalidate(), visible_range)
+    //                     .await,
+    //             )
+    //         },
+    //     ))
+    //     .await;
+
+    //     let hint_delay = cx.background().timer(Duration::from_millis(
+    //         INVISIBLE_RANGES_HINTS_REQUEST_DELAY_MILLIS,
+    //     ));
+
+    //     let mut query_range_failed = |range: &Range<language::Anchor>, e: anyhow::Error| {
+    //         log::error!("inlay hint update task for range {range:?} failed: {e:#}");
+    //         editor
+    //             .update(&mut cx, |editor, _| {
+    //                 if let Some(task_ranges) = editor
+    //                     .inlay_hint_cache
+    //                     .update_tasks
+    //                     .get_mut(&query.excerpt_id)
+    //                 {
+    //                     task_ranges.invalidate_range(&buffer_snapshot, &range);
+    //                 }
+    //             })
+    //             .ok()
+    //     };
+
+    //     for (range, result) in visible_range_update_results {
+    //         if let Err(e) = result {
+    //             query_range_failed(&range, e);
+    //         }
+    //     }
+
+    //     hint_delay.await;
+    //     let invisible_range_update_results = future::join_all(
+    //         query_ranges
+    //             .before_visible
+    //             .into_iter()
+    //             .chain(query_ranges.after_visible.into_iter())
+    //             .map(|invisible_range| async move {
+    //                 (
+    //                     invisible_range.clone(),
+    //                     fetch_and_update_hints(false, invisible_range).await,
+    //                 )
+    //             }),
+    //     )
+    //     .await;
+    //     for (range, result) in invisible_range_update_results {
+    //         if let Err(e) = result {
+    //             query_range_failed(&range, e);
+    //         }
+    //     }
+    // })
 }
 
 // async fn fetch_and_update_hints(
@@ -1073,126 +1077,128 @@ fn apply_hint_update(
     multi_buffer_snapshot: MultiBufferSnapshot,
     cx: &mut ViewContext<'_, Editor>,
 ) {
-    let cached_excerpt_hints = editor
-        .inlay_hint_cache
-        .hints
-        .entry(new_update.excerpt_id)
-        .or_insert_with(|| {
-            Arc::new(RwLock::new(CachedExcerptHints {
-                version: query.cache_version,
-                buffer_version: buffer_snapshot.version().clone(),
-                buffer_id: query.buffer_id,
-                ordered_hints: Vec::new(),
-                hints_by_id: HashMap::default(),
-            }))
-        });
-    let mut cached_excerpt_hints = cached_excerpt_hints.write();
-    match query.cache_version.cmp(&cached_excerpt_hints.version) {
-        cmp::Ordering::Less => return,
-        cmp::Ordering::Greater | cmp::Ordering::Equal => {
-            cached_excerpt_hints.version = query.cache_version;
-        }
-    }
-
-    let mut cached_inlays_changed = !new_update.remove_from_cache.is_empty();
-    cached_excerpt_hints
-        .ordered_hints
-        .retain(|hint_id| !new_update.remove_from_cache.contains(hint_id));
-    cached_excerpt_hints
-        .hints_by_id
-        .retain(|hint_id, _| !new_update.remove_from_cache.contains(hint_id));
-    let mut splice = InlaySplice {
-        to_remove: new_update.remove_from_visible,
-        to_insert: Vec::new(),
-    };
-    for new_hint in new_update.add_to_cache {
-        let insert_position = match cached_excerpt_hints
-            .ordered_hints
-            .binary_search_by(|probe| {
-                cached_excerpt_hints.hints_by_id[probe]
-                    .position
-                    .cmp(&new_hint.position, &buffer_snapshot)
-            }) {
-            Ok(i) => {
-                let mut insert_position = Some(i);
-                for id in &cached_excerpt_hints.ordered_hints[i..] {
-                    let cached_hint = &cached_excerpt_hints.hints_by_id[id];
-                    if new_hint
-                        .position
-                        .cmp(&cached_hint.position, &buffer_snapshot)
-                        .is_gt()
-                    {
-                        break;
-                    }
-                    if cached_hint.text() == new_hint.text() {
-                        insert_position = None;
-                        break;
-                    }
-                }
-                insert_position
-            }
-            Err(i) => Some(i),
-        };
+    todo!("old implementation commented below")
+}
+//     let cached_excerpt_hints = editor
+//         .inlay_hint_cache
+//         .hints
+//         .entry(new_update.excerpt_id)
+//         .or_insert_with(|| {
+//             Arc::new(RwLock::new(CachedExcerptHints {
+//                 version: query.cache_version,
+//                 buffer_version: buffer_snapshot.version().clone(),
+//                 buffer_id: query.buffer_id,
+//                 ordered_hints: Vec::new(),
+//                 hints_by_id: HashMap::default(),
+//             }))
+//         });
+//     let mut cached_excerpt_hints = cached_excerpt_hints.write();
+//     match query.cache_version.cmp(&cached_excerpt_hints.version) {
+//         cmp::Ordering::Less => return,
+//         cmp::Ordering::Greater | cmp::Ordering::Equal => {
+//             cached_excerpt_hints.version = query.cache_version;
+//         }
+//     }
 
-        if let Some(insert_position) = insert_position {
-            let new_inlay_id = post_inc(&mut editor.next_inlay_id);
-            if editor
-                .inlay_hint_cache
-                .allowed_hint_kinds
-                .contains(&new_hint.kind)
-            {
-                let new_hint_position =
-                    multi_buffer_snapshot.anchor_in_excerpt(query.excerpt_id, new_hint.position);
-                splice
-                    .to_insert
-                    .push(Inlay::hint(new_inlay_id, new_hint_position, &new_hint));
-            }
-            let new_id = InlayId::Hint(new_inlay_id);
-            cached_excerpt_hints.hints_by_id.insert(new_id, new_hint);
-            cached_excerpt_hints
-                .ordered_hints
-                .insert(insert_position, new_id);
-            cached_inlays_changed = true;
-        }
-    }
-    cached_excerpt_hints.buffer_version = buffer_snapshot.version().clone();
-    drop(cached_excerpt_hints);
+//     let mut cached_inlays_changed = !new_update.remove_from_cache.is_empty();
+//     cached_excerpt_hints
+//         .ordered_hints
+//         .retain(|hint_id| !new_update.remove_from_cache.contains(hint_id));
+//     cached_excerpt_hints
+//         .hints_by_id
+//         .retain(|hint_id, _| !new_update.remove_from_cache.contains(hint_id));
+//     let mut splice = InlaySplice {
+//         to_remove: new_update.remove_from_visible,
+//         to_insert: Vec::new(),
+//     };
+//     for new_hint in new_update.add_to_cache {
+//         let insert_position = match cached_excerpt_hints
+//             .ordered_hints
+//             .binary_search_by(|probe| {
+//                 cached_excerpt_hints.hints_by_id[probe]
+//                     .position
+//                     .cmp(&new_hint.position, &buffer_snapshot)
+//             }) {
+//             Ok(i) => {
+//                 let mut insert_position = Some(i);
+//                 for id in &cached_excerpt_hints.ordered_hints[i..] {
+//                     let cached_hint = &cached_excerpt_hints.hints_by_id[id];
+//                     if new_hint
+//                         .position
+//                         .cmp(&cached_hint.position, &buffer_snapshot)
+//                         .is_gt()
+//                     {
+//                         break;
+//                     }
+//                     if cached_hint.text() == new_hint.text() {
+//                         insert_position = None;
+//                         break;
+//                     }
+//                 }
+//                 insert_position
+//             }
+//             Err(i) => Some(i),
+//         };
+
+//         if let Some(insert_position) = insert_position {
+//             let new_inlay_id = post_inc(&mut editor.next_inlay_id);
+//             if editor
+//                 .inlay_hint_cache
+//                 .allowed_hint_kinds
+//                 .contains(&new_hint.kind)
+//             {
+//                 let new_hint_position =
+//                     multi_buffer_snapshot.anchor_in_excerpt(query.excerpt_id, new_hint.position);
+//                 splice
+//                     .to_insert
+//                     .push(Inlay::hint(new_inlay_id, new_hint_position, &new_hint));
+//             }
+//             let new_id = InlayId::Hint(new_inlay_id);
+//             cached_excerpt_hints.hints_by_id.insert(new_id, new_hint);
+//             cached_excerpt_hints
+//                 .ordered_hints
+//                 .insert(insert_position, new_id);
+//             cached_inlays_changed = true;
+//         }
+//     }
+//     cached_excerpt_hints.buffer_version = buffer_snapshot.version().clone();
+//     drop(cached_excerpt_hints);
 
-    if invalidate {
-        let mut outdated_excerpt_caches = HashSet::default();
-        for (excerpt_id, excerpt_hints) in &editor.inlay_hint_cache().hints {
-            let excerpt_hints = excerpt_hints.read();
-            if excerpt_hints.buffer_id == query.buffer_id
-                && excerpt_id != &query.excerpt_id
-                && buffer_snapshot
-                    .version()
-                    .changed_since(&excerpt_hints.buffer_version)
-            {
-                outdated_excerpt_caches.insert(*excerpt_id);
-                splice
-                    .to_remove
-                    .extend(excerpt_hints.ordered_hints.iter().copied());
-            }
-        }
-        cached_inlays_changed |= !outdated_excerpt_caches.is_empty();
-        editor
-            .inlay_hint_cache
-            .hints
-            .retain(|excerpt_id, _| !outdated_excerpt_caches.contains(excerpt_id));
-    }
+//     if invalidate {
+//         let mut outdated_excerpt_caches = HashSet::default();
+//         for (excerpt_id, excerpt_hints) in &editor.inlay_hint_cache().hints {
+//             let excerpt_hints = excerpt_hints.read();
+//             if excerpt_hints.buffer_id == query.buffer_id
+//                 && excerpt_id != &query.excerpt_id
+//                 && buffer_snapshot
+//                     .version()
+//                     .changed_since(&excerpt_hints.buffer_version)
+//             {
+//                 outdated_excerpt_caches.insert(*excerpt_id);
+//                 splice
+//                     .to_remove
+//                     .extend(excerpt_hints.ordered_hints.iter().copied());
+//             }
+//         }
+//         cached_inlays_changed |= !outdated_excerpt_caches.is_empty();
+//         editor
+//             .inlay_hint_cache
+//             .hints
+//             .retain(|excerpt_id, _| !outdated_excerpt_caches.contains(excerpt_id));
+//     }
 
-    let InlaySplice {
-        to_remove,
-        to_insert,
-    } = splice;
-    let displayed_inlays_changed = !to_remove.is_empty() || !to_insert.is_empty();
-    if cached_inlays_changed || displayed_inlays_changed {
-        editor.inlay_hint_cache.version += 1;
-    }
-    if displayed_inlays_changed {
-        editor.splice_inlay_hints(to_remove, to_insert, cx)
-    }
-}
+//     let InlaySplice {
+//         to_remove,
+//         to_insert,
+//     } = splice;
+//     let displayed_inlays_changed = !to_remove.is_empty() || !to_insert.is_empty();
+//     if cached_inlays_changed || displayed_inlays_changed {
+//         editor.inlay_hint_cache.version += 1;
+//     }
+//     if displayed_inlays_changed {
+//         editor.splice_inlay_hints(to_remove, to_insert, cx)
+//     }
+// }
 
 // #[cfg(test)]
 // pub mod tests {

crates/editor2/src/items.rs 🔗

@@ -7,7 +7,7 @@ use anyhow::{Context, Result};
 use collections::HashSet;
 use futures::future::try_join_all;
 use gpui::{
-    point, AnyElement, AppContext, AsyncAppContext, Entity, Model, Pixels, SharedString,
+    point, AnyElement, AppContext, AsyncAppContext, Entity, EntityId, Model, Pixels, SharedString,
     Subscription, Task, View, ViewContext, WeakView,
 };
 use language::{
@@ -26,6 +26,7 @@ use std::{
     sync::Arc,
 };
 use text::Selection;
+use theme::ThemeVariant;
 use util::{paths::PathExt, ResultExt, TryFutureExt};
 use workspace::item::{BreadcrumbText, FollowableItemHandle};
 use workspace::{
@@ -306,12 +307,15 @@ impl FollowableItem for Editor {
     }
 }
 
-// async fn update_editor_from_message(
-//     this: WeakView<Editor>,
-//     project: Model<Project>,
-//     message: proto::update_view::Editor,
-//     cx: &mut AsyncAppContext,
-// ) -> Result<()> {
+async fn update_editor_from_message(
+    this: WeakView<Editor>,
+    project: Model<Project>,
+    message: proto::update_view::Editor,
+    cx: &mut AsyncAppContext,
+) -> Result<()> {
+    todo!()
+}
+// Previous implementation of the above
 //     // Open all of the buffers of which excerpts were added to the editor.
 //     let inserted_excerpt_buffer_ids = message
 //         .inserted_excerpts
@@ -512,38 +516,39 @@ fn deserialize_anchor(buffer: &MultiBufferSnapshot, anchor: proto::EditorAnchor)
 
 impl Item for Editor {
     fn navigate(&mut self, data: Box<dyn std::any::Any>, cx: &mut ViewContext<Self>) -> bool {
-        if let Ok(data) = data.downcast::<NavigationData>() {
-            let newest_selection = self.selections.newest::<Point>(cx);
-            let buffer = self.buffer.read(cx).read(cx);
-            let offset = if buffer.can_resolve(&data.cursor_anchor) {
-                data.cursor_anchor.to_point(&buffer)
-            } else {
-                buffer.clip_point(data.cursor_position, Bias::Left)
-            };
-
-            let mut scroll_anchor = data.scroll_anchor;
-            if !buffer.can_resolve(&scroll_anchor.anchor) {
-                scroll_anchor.anchor = buffer.anchor_before(
-                    buffer.clip_point(Point::new(data.scroll_top_row, 0), Bias::Left),
-                );
-            }
-
-            drop(buffer);
-
-            if newest_selection.head() == offset {
-                false
-            } else {
-                let nav_history = self.nav_history.take();
-                self.set_scroll_anchor(scroll_anchor, cx);
-                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
-                    s.select_ranges([offset..offset])
-                });
-                self.nav_history = nav_history;
-                true
-            }
-        } else {
-            false
-        }
+        todo!();
+        // if let Ok(data) = data.downcast::<NavigationData>() {
+        //     let newest_selection = self.selections.newest::<Point>(cx);
+        //     let buffer = self.buffer.read(cx).read(cx);
+        //     let offset = if buffer.can_resolve(&data.cursor_anchor) {
+        //         data.cursor_anchor.to_point(&buffer)
+        //     } else {
+        //         buffer.clip_point(data.cursor_position, Bias::Left)
+        //     };
+
+        //     let mut scroll_anchor = data.scroll_anchor;
+        //     if !buffer.can_resolve(&scroll_anchor.anchor) {
+        //         scroll_anchor.anchor = buffer.anchor_before(
+        //             buffer.clip_point(Point::new(data.scroll_top_row, 0), Bias::Left),
+        //         );
+        //     }
+
+        //     drop(buffer);
+
+        //     if newest_selection.head() == offset {
+        //         false
+        //     } else {
+        //         let nav_history = self.nav_history.take();
+        //         self.set_scroll_anchor(scroll_anchor, cx);
+        //         self.change_selections(Some(Autoscroll::fit()), cx, |s| {
+        //             s.select_ranges([offset..offset])
+        //         });
+        //         self.nav_history = nav_history;
+        //         true
+        //     }
+        // } else {
+        //     false
+        // }
     }
 
     fn tab_tooltip_text(&self, cx: &AppContext) -> Option<SharedString> {
@@ -563,8 +568,8 @@ impl Item for Editor {
 
     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),
-            Cow::Owned(path) => Some(path.to_string_lossy.to_string().into()),
+            Cow::Borrowed(path) => Some(path.to_string_lossy().into()),
+            Cow::Owned(path) => Some(path.to_string_lossy().to_string().into()),
         }
     }
 
@@ -590,10 +595,14 @@ impl Item for Editor {
         //     .into_any()
     }
 
-    fn for_each_project_item(&self, cx: &AppContext, f: &mut dyn FnMut(usize, &dyn project::Item)) {
+    fn for_each_project_item(
+        &self,
+        cx: &AppContext,
+        f: &mut dyn FnMut(EntityId, &dyn project::Item),
+    ) {
         self.buffer
             .read(cx)
-            .for_each_buffer(|buffer| f(buffer.id(), buffer.read(cx)));
+            .for_each_buffer(|buffer| f(buffer.entity_id(), buffer.read(cx)));
     }
 
     fn is_singleton(&self, cx: &AppContext) -> bool {
@@ -652,20 +661,24 @@ impl Item for Editor {
 
             if buffers.len() == 1 {
                 project
-                    .update(&mut cx, |project, cx| project.save_buffers(buffers, cx))
+                    .update(&mut cx, |project, cx| project.save_buffers(buffers, cx))?
                     .await?;
             } else {
                 // For multi-buffers, only save those ones that contain changes. For clean buffers
                 // we simulate saving by calling `Buffer::did_save`, so that language servers or
                 // other downstream listeners of save events get notified.
                 let (dirty_buffers, clean_buffers) = buffers.into_iter().partition(|buffer| {
-                    buffer.read_with(&cx, |buffer, _| buffer.is_dirty || buffer.has_conflict())
+                    buffer
+                        .update(&mut cx, |buffer, _| {
+                            buffer.is_dirty() || buffer.has_conflict()
+                        })
+                        .unwrap_or(false)
                 });
 
                 project
                     .update(&mut cx, |project, cx| {
                         project.save_buffers(dirty_buffers, cx)
-                    })
+                    })?
                     .await?;
                 for buffer in clean_buffers {
                     buffer.update(&mut cx, |buffer, cx| {
@@ -760,7 +773,7 @@ impl Item for Editor {
         ToolbarItemLocation::PrimaryLeft { flex: None }
     }
 
-    fn breadcrumbs(&self, cx: &AppContext) -> Option<Vec<BreadcrumbText>> {
+    fn breadcrumbs(&self, variant: &ThemeVariant, cx: &AppContext) -> Option<Vec<BreadcrumbText>> {
         todo!();
         // let cursor = self.selections.newest_anchor().head();
         // let multibuffer = &self.buffer().read(cx);
@@ -806,7 +819,7 @@ impl Item for Editor {
             if let Some(file) = buffer.read(cx).file().and_then(|file| file.as_local()) {
                 let path = file.abs_path(cx);
 
-                cx.background()
+                cx.background_executor()
                     .spawn(async move {
                         DB.save_path(item_id, workspace_id, path.clone())
                             .await
@@ -913,15 +926,17 @@ impl SearchableItem for Editor {
     }
 
     fn clear_matches(&mut self, cx: &mut ViewContext<Self>) {
-        self.clear_background_highlights::<BufferSearchHighlights>(cx);
+        todo!()
+        // self.clear_background_highlights::<BufferSearchHighlights>(cx);
     }
 
     fn update_matches(&mut self, matches: Vec<Range<Anchor>>, cx: &mut ViewContext<Self>) {
-        self.highlight_background::<BufferSearchHighlights>(
-            matches,
-            |theme| theme.search.match_background,
-            cx,
-        );
+        todo!()
+        // self.highlight_background::<BufferSearchHighlights>(
+        //     matches,
+        //     |theme| theme.search.match_background,
+        //     cx,
+        // );
     }
 
     fn query_suggestion(&mut self, cx: &mut ViewContext<Self>) -> String {
@@ -952,20 +967,22 @@ impl SearchableItem for Editor {
         matches: Vec<Range<Anchor>>,
         cx: &mut ViewContext<Self>,
     ) {
-        self.unfold_ranges([matches[index].clone()], false, true, cx);
-        let range = self.range_for_match(&matches[index]);
-        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
-            s.select_ranges([range]);
-        })
+        todo!()
+        // self.unfold_ranges([matches[index].clone()], false, true, cx);
+        // let range = self.range_for_match(&matches[index]);
+        // self.change_selections(Some(Autoscroll::fit()), cx, |s| {
+        //     s.select_ranges([range]);
+        // })
     }
 
     fn select_matches(&mut self, matches: Vec<Self::Match>, cx: &mut ViewContext<Self>) {
-        self.unfold_ranges(matches.clone(), false, false, cx);
-        let mut ranges = Vec::new();
-        for m in &matches {
-            ranges.push(self.range_for_match(&m))
-        }
-        self.change_selections(None, cx, |s| s.select_ranges(ranges));
+        todo!()
+        // self.unfold_ranges(matches.clone(), false, false, cx);
+        // let mut ranges = Vec::new();
+        // for m in &matches {
+        //     ranges.push(self.range_for_match(&m))
+        // }
+        // self.change_selections(None, cx, |s| s.select_ranges(ranges));
     }
     fn replace(
         &mut self,
@@ -1044,7 +1061,7 @@ impl SearchableItem for Editor {
         cx: &mut ViewContext<Self>,
     ) -> Task<Vec<Range<Anchor>>> {
         let buffer = self.buffer().read(cx).snapshot(cx);
-        cx.background().spawn(async move {
+        cx.background_executor().spawn(async move {
             let mut ranges = Vec::new();
             if let Some((_, _, excerpt_buffer)) = buffer.as_singleton() {
                 ranges.extend(
@@ -170,170 +170,173 @@ pub fn update_inlay_link_and_hover_points(
     shift_held: bool,
     cx: &mut ViewContext<'_, Editor>,
 ) {
-    let hovered_offset = if point_for_position.column_overshoot_after_line_end == 0 {
-        Some(snapshot.display_point_to_inlay_offset(point_for_position.exact_unclipped, Bias::Left))
-    } else {
-        None
-    };
-    let mut go_to_definition_updated = false;
-    let mut hover_updated = false;
-    if let Some(hovered_offset) = hovered_offset {
-        let buffer_snapshot = editor.buffer().read(cx).snapshot(cx);
-        let previous_valid_anchor = buffer_snapshot.anchor_at(
-            point_for_position.previous_valid.to_point(snapshot),
-            Bias::Left,
-        );
-        let next_valid_anchor = buffer_snapshot.anchor_at(
-            point_for_position.next_valid.to_point(snapshot),
-            Bias::Right,
-        );
-        if let Some(hovered_hint) = editor
-            .visible_inlay_hints(cx)
-            .into_iter()
-            .skip_while(|hint| {
-                hint.position
-                    .cmp(&previous_valid_anchor, &buffer_snapshot)
-                    .is_lt()
-            })
-            .take_while(|hint| {
-                hint.position
-                    .cmp(&next_valid_anchor, &buffer_snapshot)
-                    .is_le()
-            })
-            .max_by_key(|hint| hint.id)
-        {
-            let inlay_hint_cache = editor.inlay_hint_cache();
-            let excerpt_id = previous_valid_anchor.excerpt_id;
-            if let Some(cached_hint) = inlay_hint_cache.hint_by_id(excerpt_id, hovered_hint.id) {
-                match cached_hint.resolve_state {
-                    ResolveState::CanResolve(_, _) => {
-                        if let Some(buffer_id) = previous_valid_anchor.buffer_id {
-                            inlay_hint_cache.spawn_hint_resolve(
-                                buffer_id,
-                                excerpt_id,
-                                hovered_hint.id,
-                                cx,
-                            );
-                        }
-                    }
-                    ResolveState::Resolved => {
-                        let mut extra_shift_left = 0;
-                        let mut extra_shift_right = 0;
-                        if cached_hint.padding_left {
-                            extra_shift_left += 1;
-                            extra_shift_right += 1;
-                        }
-                        if cached_hint.padding_right {
-                            extra_shift_right += 1;
-                        }
-                        match cached_hint.label {
-                            project::InlayHintLabel::String(_) => {
-                                if let Some(tooltip) = cached_hint.tooltip {
-                                    hover_popover::hover_at_inlay(
-                                        editor,
-                                        InlayHover {
-                                            excerpt: excerpt_id,
-                                            tooltip: match tooltip {
-                                                InlayHintTooltip::String(text) => HoverBlock {
-                                                    text,
-                                                    kind: HoverBlockKind::PlainText,
-                                                },
-                                                InlayHintTooltip::MarkupContent(content) => {
-                                                    HoverBlock {
-                                                        text: content.value,
-                                                        kind: content.kind,
-                                                    }
-                                                }
-                                            },
-                                            range: InlayHighlight {
-                                                inlay: hovered_hint.id,
-                                                inlay_position: hovered_hint.position,
-                                                range: extra_shift_left
-                                                    ..hovered_hint.text.len() + extra_shift_right,
-                                            },
-                                        },
-                                        cx,
-                                    );
-                                    hover_updated = true;
-                                }
-                            }
-                            project::InlayHintLabel::LabelParts(label_parts) => {
-                                let hint_start =
-                                    snapshot.anchor_to_inlay_offset(hovered_hint.position);
-                                if let Some((hovered_hint_part, part_range)) =
-                                    hover_popover::find_hovered_hint_part(
-                                        label_parts,
-                                        hint_start,
-                                        hovered_offset,
-                                    )
-                                {
-                                    let highlight_start =
-                                        (part_range.start - hint_start).0 + extra_shift_left;
-                                    let highlight_end =
-                                        (part_range.end - hint_start).0 + extra_shift_right;
-                                    let highlight = InlayHighlight {
-                                        inlay: hovered_hint.id,
-                                        inlay_position: hovered_hint.position,
-                                        range: highlight_start..highlight_end,
-                                    };
-                                    if let Some(tooltip) = hovered_hint_part.tooltip {
-                                        hover_popover::hover_at_inlay(
-                                            editor,
-                                            InlayHover {
-                                                excerpt: excerpt_id,
-                                                tooltip: match tooltip {
-                                                    InlayHintLabelPartTooltip::String(text) => {
-                                                        HoverBlock {
-                                                            text,
-                                                            kind: HoverBlockKind::PlainText,
-                                                        }
-                                                    }
-                                                    InlayHintLabelPartTooltip::MarkupContent(
-                                                        content,
-                                                    ) => HoverBlock {
-                                                        text: content.value,
-                                                        kind: content.kind,
-                                                    },
-                                                },
-                                                range: highlight.clone(),
-                                            },
-                                            cx,
-                                        );
-                                        hover_updated = true;
-                                    }
-                                    if let Some((language_server_id, location)) =
-                                        hovered_hint_part.location
-                                    {
-                                        go_to_definition_updated = true;
-                                        update_go_to_definition_link(
-                                            editor,
-                                            Some(GoToDefinitionTrigger::InlayHint(
-                                                highlight,
-                                                location,
-                                                language_server_id,
-                                            )),
-                                            cmd_held,
-                                            shift_held,
-                                            cx,
-                                        );
-                                    }
-                                }
-                            }
-                        };
-                    }
-                    ResolveState::Resolving => {}
-                }
-            }
-        }
-    }
-
-    if !go_to_definition_updated {
-        update_go_to_definition_link(editor, None, cmd_held, shift_held, cx);
-    }
-    if !hover_updated {
-        hover_popover::hover_at(editor, None, cx);
-    }
+    todo!("old implementation below")
 }
+// ) {
+//     let hovered_offset = if point_for_position.column_overshoot_after_line_end == 0 {
+//         Some(snapshot.display_point_to_inlay_offset(point_for_position.exact_unclipped, Bias::Left))
+//     } else {
+//         None
+//     };
+//     let mut go_to_definition_updated = false;
+//     let mut hover_updated = false;
+//     if let Some(hovered_offset) = hovered_offset {
+//         let buffer_snapshot = editor.buffer().read(cx).snapshot(cx);
+//         let previous_valid_anchor = buffer_snapshot.anchor_at(
+//             point_for_position.previous_valid.to_point(snapshot),
+//             Bias::Left,
+//         );
+//         let next_valid_anchor = buffer_snapshot.anchor_at(
+//             point_for_position.next_valid.to_point(snapshot),
+//             Bias::Right,
+//         );
+//         if let Some(hovered_hint) = editor
+//             .visible_inlay_hints(cx)
+//             .into_iter()
+//             .skip_while(|hint| {
+//                 hint.position
+//                     .cmp(&previous_valid_anchor, &buffer_snapshot)
+//                     .is_lt()
+//             })
+//             .take_while(|hint| {
+//                 hint.position
+//                     .cmp(&next_valid_anchor, &buffer_snapshot)
+//                     .is_le()
+//             })
+//             .max_by_key(|hint| hint.id)
+//         {
+//             let inlay_hint_cache = editor.inlay_hint_cache();
+//             let excerpt_id = previous_valid_anchor.excerpt_id;
+//             if let Some(cached_hint) = inlay_hint_cache.hint_by_id(excerpt_id, hovered_hint.id) {
+//                 match cached_hint.resolve_state {
+//                     ResolveState::CanResolve(_, _) => {
+//                         if let Some(buffer_id) = previous_valid_anchor.buffer_id {
+//                             inlay_hint_cache.spawn_hint_resolve(
+//                                 buffer_id,
+//                                 excerpt_id,
+//                                 hovered_hint.id,
+//                                 cx,
+//                             );
+//                         }
+//                     }
+//                     ResolveState::Resolved => {
+//                         let mut extra_shift_left = 0;
+//                         let mut extra_shift_right = 0;
+//                         if cached_hint.padding_left {
+//                             extra_shift_left += 1;
+//                             extra_shift_right += 1;
+//                         }
+//                         if cached_hint.padding_right {
+//                             extra_shift_right += 1;
+//                         }
+//                         match cached_hint.label {
+//                             project::InlayHintLabel::String(_) => {
+//                                 if let Some(tooltip) = cached_hint.tooltip {
+//                                     hover_popover::hover_at_inlay(
+//                                         editor,
+//                                         InlayHover {
+//                                             excerpt: excerpt_id,
+//                                             tooltip: match tooltip {
+//                                                 InlayHintTooltip::String(text) => HoverBlock {
+//                                                     text,
+//                                                     kind: HoverBlockKind::PlainText,
+//                                                 },
+//                                                 InlayHintTooltip::MarkupContent(content) => {
+//                                                     HoverBlock {
+//                                                         text: content.value,
+//                                                         kind: content.kind,
+//                                                     }
+//                                                 }
+//                                             },
+//                                             range: InlayHighlight {
+//                                                 inlay: hovered_hint.id,
+//                                                 inlay_position: hovered_hint.position,
+//                                                 range: extra_shift_left
+//                                                     ..hovered_hint.text.len() + extra_shift_right,
+//                                             },
+//                                         },
+//                                         cx,
+//                                     );
+//                                     hover_updated = true;
+//                                 }
+//                             }
+//                             project::InlayHintLabel::LabelParts(label_parts) => {
+//                                 let hint_start =
+//                                     snapshot.anchor_to_inlay_offset(hovered_hint.position);
+//                                 if let Some((hovered_hint_part, part_range)) =
+//                                     hover_popover::find_hovered_hint_part(
+//                                         label_parts,
+//                                         hint_start,
+//                                         hovered_offset,
+//                                     )
+//                                 {
+//                                     let highlight_start =
+//                                         (part_range.start - hint_start).0 + extra_shift_left;
+//                                     let highlight_end =
+//                                         (part_range.end - hint_start).0 + extra_shift_right;
+//                                     let highlight = InlayHighlight {
+//                                         inlay: hovered_hint.id,
+//                                         inlay_position: hovered_hint.position,
+//                                         range: highlight_start..highlight_end,
+//                                     };
+//                                     if let Some(tooltip) = hovered_hint_part.tooltip {
+//                                         hover_popover::hover_at_inlay(
+//                                             editor,
+//                                             InlayHover {
+//                                                 excerpt: excerpt_id,
+//                                                 tooltip: match tooltip {
+//                                                     InlayHintLabelPartTooltip::String(text) => {
+//                                                         HoverBlock {
+//                                                             text,
+//                                                             kind: HoverBlockKind::PlainText,
+//                                                         }
+//                                                     }
+//                                                     InlayHintLabelPartTooltip::MarkupContent(
+//                                                         content,
+//                                                     ) => HoverBlock {
+//                                                         text: content.value,
+//                                                         kind: content.kind,
+//                                                     },
+//                                                 },
+//                                                 range: highlight.clone(),
+//                                             },
+//                                             cx,
+//                                         );
+//                                         hover_updated = true;
+//                                     }
+//                                     if let Some((language_server_id, location)) =
+//                                         hovered_hint_part.location
+//                                     {
+//                                         go_to_definition_updated = true;
+//                                         update_go_to_definition_link(
+//                                             editor,
+//                                             Some(GoToDefinitionTrigger::InlayHint(
+//                                                 highlight,
+//                                                 location,
+//                                                 language_server_id,
+//                                             )),
+//                                             cmd_held,
+//                                             shift_held,
+//                                             cx,
+//                                         );
+//                                     }
+//                                 }
+//                             }
+//                         };
+//                     }
+//                     ResolveState::Resolving => {}
+//                 }
+//             }
+//         }
+//     }
+
+//     if !go_to_definition_updated {
+//         update_go_to_definition_link(editor, None, cmd_held, shift_held, cx);
+//     }
+//     if !hover_updated {
+//         hover_popover::hover_at(editor, None, cx);
+//     }
+// }
 
 #[derive(Debug, Clone, Copy, PartialEq)]
 pub enum LinkDefinitionKind {
@@ -570,34 +573,35 @@ fn go_to_fetched_definition_of_kind(
     split: bool,
     cx: &mut ViewContext<Editor>,
 ) {
-    let cached_definitions = editor.link_go_to_definition_state.definitions.clone();
-    hide_link_definition(editor, cx);
-    let cached_definitions_kind = editor.link_go_to_definition_state.kind;
-
-    let is_correct_kind = cached_definitions_kind == Some(kind);
-    if !cached_definitions.is_empty() && is_correct_kind {
-        if !editor.focused {
-            cx.focus_self();
-        }
-
-        editor.navigate_to_definitions(cached_definitions, split, cx);
-    } else {
-        editor.select(
-            SelectPhase::Begin {
-                position: point.next_valid,
-                add: false,
-                click_count: 1,
-            },
-            cx,
-        );
-
-        if point.as_valid().is_some() {
-            match kind {
-                LinkDefinitionKind::Symbol => editor.go_to_definition(&Default::default(), cx),
-                LinkDefinitionKind::Type => editor.go_to_type_definition(&Default::default(), cx),
-            }
-        }
-    }
+    todo!();
+    // let cached_definitions = editor.link_go_to_definition_state.definitions.clone();
+    // hide_link_definition(editor, cx);
+    // let cached_definitions_kind = editor.link_go_to_definition_state.kind;
+
+    // let is_correct_kind = cached_definitions_kind == Some(kind);
+    // if !cached_definitions.is_empty() && is_correct_kind {
+    //     if !editor.focused {
+    //         cx.focus_self();
+    //     }
+
+    //     editor.navigate_to_definitions(cached_definitions, split, cx);
+    // } else {
+    //     editor.select(
+    //         SelectPhase::Begin {
+    //             position: point.next_valid,
+    //             add: false,
+    //             click_count: 1,
+    //         },
+    //         cx,
+    //     );
+
+    //     if point.as_valid().is_some() {
+    //         match kind {
+    //             LinkDefinitionKind::Symbol => editor.go_to_definition(&Default::default(), cx),
+    //             LinkDefinitionKind::Type => editor.go_to_type_definition(&Default::default(), cx),
+    //         }
+    //     }
+    // }
 }
 
 // #[cfg(test)]

crates/editor2/src/mouse_context_menu.rs 🔗

@@ -8,27 +8,28 @@ pub fn deploy_context_menu(
     point: DisplayPoint,
     cx: &mut ViewContext<Editor>,
 ) {
-    if !editor.focused {
-        cx.focus_self();
-    }
+    todo!();
 
-    // Don't show context menu for inline editors
-    if editor.mode() != EditorMode::Full {
-        return;
-    }
+    // if !editor.focused {
+    //     cx.focus_self();
+    // }
 
-    // Don't show the context menu if there isn't a project associated with this editor
-    if editor.project.is_none() {
-        return;
-    }
+    // // Don't show context menu for inline editors
+    // if editor.mode() != EditorMode::Full {
+    //     return;
+    // }
 
-    // Move the cursor to the clicked location so that dispatched actions make sense
-    editor.change_selections(None, cx, |s| {
-        s.clear_disjoint();
-        s.set_pending_display_range(point..point, SelectMode::Character);
-    });
+    // // Don't show the context menu if there isn't a project associated with this editor
+    // if editor.project.is_none() {
+    //     return;
+    // }
+
+    // // Move the cursor to the clicked location so that dispatched actions make sense
+    // editor.change_selections(None, cx, |s| {
+    //     s.clear_disjoint();
+    //     s.set_pending_display_range(point..point, SelectMode::Character);
+    // });
 
-    // todo!()
     // editor.mouse_context_menu.update(cx, |menu, cx| {
     //     menu.show(
     //         position,
@@ -50,7 +51,7 @@ pub fn deploy_context_menu(
     //         cx,
     //     );
     // });
-    cx.notify();
+    // cx.notify();
 }
 
 // #[cfg(test)]

crates/editor2/src/persistence.rs 🔗

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

crates/editor2/src/scroll.rs 🔗

@@ -9,7 +9,7 @@ use crate::{
     Anchor, DisplayPoint, Editor, EditorMode, Event, InlayHintRefreshReason, MultiBufferSnapshot,
     ToPoint,
 };
-use gpui::{point, px, AppContext, Pixels, Styled, Task, ViewContext};
+use gpui::{point, px, AppContext, Entity, Pixels, Styled, Task, ViewContext};
 use language::{Bias, Point};
 use std::{
     cmp::Ordering,
@@ -39,18 +39,18 @@ pub struct ScrollAnchor {
 impl ScrollAnchor {
     fn new() -> Self {
         Self {
-            offset: gpui::Point::zero(),
+            offset: gpui::Point::default(),
             anchor: Anchor::min(),
         }
     }
 
-    pub fn scroll_position(&self, snapshot: &DisplaySnapshot) -> gpui::Point<Pixels> {
+    pub fn scroll_position(&self, snapshot: &DisplaySnapshot) -> gpui::Point<f32> {
         let mut scroll_position = self.offset;
         if self.anchor != Anchor::min() {
             let scroll_top = self.anchor.to_display_point(snapshot).row() as f32;
-            scroll_position.set_y(scroll_top + scroll_position.y);
+            scroll_position.y = scroll_top + scroll_position.y;
         } else {
-            scroll_position.set_y(0.);
+            scroll_position.y = 0.;
         }
         scroll_position
     }
@@ -133,7 +133,7 @@ pub struct ScrollManager {
     anchor: ScrollAnchor,
     ongoing: OngoingScroll,
     autoscroll_request: Option<(Autoscroll, bool)>,
-    last_autoscroll: Option<(gpui::Point<Pixels>, f32, f32, AutoscrollStrategy)>,
+    last_autoscroll: Option<(gpui::Point<f32>, f32, f32, AutoscrollStrategy)>,
     show_scrollbars: bool,
     hide_scrollbar_task: Option<Task<()>>,
     visible_line_count: Option<f32>,
@@ -171,7 +171,7 @@ impl ScrollManager {
         self.ongoing.axis = axis;
     }
 
-    pub fn scroll_position(&self, snapshot: &DisplaySnapshot) -> gpui::Point<Pixels> {
+    pub fn scroll_position(&self, snapshot: &DisplaySnapshot) -> gpui::Point<f32> {
         self.anchor.scroll_position(snapshot)
     }
 
@@ -188,7 +188,7 @@ impl ScrollManager {
             (
                 ScrollAnchor {
                     anchor: Anchor::min(),
-                    offset: scroll_position.max(Point::zero()),
+                    offset: scroll_position.max(&gpui::Point::default()),
                 },
                 0,
             )
@@ -228,9 +228,9 @@ impl ScrollManager {
         self.show_scrollbar(cx);
         self.autoscroll_request.take();
         if let Some(workspace_id) = workspace_id {
-            let item_id = cx.view_id();
+            let item_id = cx.view().entity_id();
 
-            cx.background()
+            cx.foreground_executor()
                 .spawn(async move {
                     DB.save_scroll_position(
                         item_id,
@@ -255,7 +255,9 @@ impl ScrollManager {
 
         if cx.default_global::<ScrollbarAutoHide>().0 {
             self.hide_scrollbar_task = Some(cx.spawn(|editor, mut cx| async move {
-                cx.background().timer(SCROLLBAR_SHOW_INTERVAL).await;
+                cx.background_executor()
+                    .timer(SCROLLBAR_SHOW_INTERVAL)
+                    .await;
                 editor
                     .update(&mut cx, |editor, cx| {
                         editor.scroll_manager.show_scrollbars = false;
@@ -287,160 +289,161 @@ impl ScrollManager {
 }
 
 // todo!()
-// impl Editor {
-//     pub fn vertical_scroll_margin(&mut self) -> usize {
-//         self.scroll_manager.vertical_scroll_margin as usize
-//     }
-
-//     pub fn set_vertical_scroll_margin(&mut self, margin_rows: usize, cx: &mut ViewContext<Self>) {
-//         self.scroll_manager.vertical_scroll_margin = margin_rows as f32;
-//         cx.notify();
-//     }
-
-//     pub fn visible_line_count(&self) -> Option<f32> {
-//         self.scroll_manager.visible_line_count
-//     }
-
-//     pub(crate) fn set_visible_line_count(&mut self, lines: f32, cx: &mut ViewContext<Self>) {
-//         let opened_first_time = self.scroll_manager.visible_line_count.is_none();
-//         self.scroll_manager.visible_line_count = Some(lines);
-//         if opened_first_time {
-//             cx.spawn(|editor, mut cx| async move {
-//                 editor
-//                     .update(&mut cx, |editor, cx| {
-//                         editor.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx)
-//                     })
-//                     .ok()
-//             })
-//             .detach()
-//         }
-//     }
-
-//     pub fn set_scroll_position(
-//         &mut self,
-//         scroll_position: gpui::Point<Pixels>,
-//         cx: &mut ViewContext<Self>,
-//     ) {
-//         self.set_scroll_position_internal(scroll_position, true, false, cx);
-//     }
-
-//     pub(crate) fn set_scroll_position_internal(
-//         &mut self,
-//         scroll_position: gpui::Point<Pixels>,
-//         local: bool,
-//         autoscroll: bool,
-//         cx: &mut ViewContext<Self>,
-//     ) {
-//         let map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-
-//         hide_hover(self, cx);
-//         let workspace_id = self.workspace.as_ref().map(|workspace| workspace.1);
-//         self.scroll_manager.set_scroll_position(
-//             scroll_position,
-//             &map,
-//             local,
-//             autoscroll,
-//             workspace_id,
-//             cx,
-//         );
-
-//         self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
-//     }
-
-//     pub fn scroll_position(&self, cx: &mut ViewContext<Self>) -> gpui::Point<Pixels> {
-//         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-//         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(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) {
-//             cx.propagate_action();
-//             return;
-//         }
-
-//         if self.take_rename(true, cx).is_some() {
-//             return;
-//         }
-
-//         let cur_position = self.scroll_position(cx);
-//         let new_pos = cur_position + point(0., amount.lines(self));
-//         self.set_scroll_position(new_pos, cx);
-//     }
-
-//     /// Returns an ordering. The newest selection is:
-//     ///     Ordering::Equal => on screen
-//     ///     Ordering::Less => above the screen
-//     ///     Ordering::Greater => below the screen
-//     pub fn newest_selection_on_screen(&self, cx: &mut AppContext) -> Ordering {
-//         let snapshot = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-//         let newest_head = self
-//             .selections
-//             .newest_anchor()
-//             .head()
-//             .to_display_point(&snapshot);
-//         let screen_top = self
-//             .scroll_manager
-//             .anchor
-//             .anchor
-//             .to_display_point(&snapshot);
-
-//         if screen_top > newest_head {
-//             return Ordering::Less;
-//         }
-
-//         if let Some(visible_lines) = self.visible_line_count() {
-//             if newest_head.row() < screen_top.row() + visible_lines as u32 {
-//                 return Ordering::Equal;
-//             }
-//         }
-
-//         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);
-//         }
-//     }
-// }
+impl Editor {
+    //     pub fn vertical_scroll_margin(&mut self) -> usize {
+    //         self.scroll_manager.vertical_scroll_margin as usize
+    //     }
+
+    //     pub fn set_vertical_scroll_margin(&mut self, margin_rows: usize, cx: &mut ViewContext<Self>) {
+    //         self.scroll_manager.vertical_scroll_margin = margin_rows as f32;
+    //         cx.notify();
+    //     }
+
+    //     pub fn visible_line_count(&self) -> Option<f32> {
+    //         self.scroll_manager.visible_line_count
+    //     }
+
+    //     pub(crate) fn set_visible_line_count(&mut self, lines: f32, cx: &mut ViewContext<Self>) {
+    //         let opened_first_time = self.scroll_manager.visible_line_count.is_none();
+    //         self.scroll_manager.visible_line_count = Some(lines);
+    //         if opened_first_time {
+    //             cx.spawn(|editor, mut cx| async move {
+    //                 editor
+    //                     .update(&mut cx, |editor, cx| {
+    //                         editor.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx)
+    //                     })
+    //                     .ok()
+    //             })
+    //             .detach()
+    //         }
+    //     }
+
+    pub fn set_scroll_position(
+        &mut self,
+        scroll_position: gpui::Point<f32>,
+        cx: &mut ViewContext<Self>,
+    ) {
+        self.set_scroll_position_internal(scroll_position, true, false, cx);
+    }
+
+    pub(crate) fn set_scroll_position_internal(
+        &mut self,
+        scroll_position: gpui::Point<f32>,
+        local: bool,
+        autoscroll: bool,
+        cx: &mut ViewContext<Self>,
+    ) {
+        let map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
+
+        hide_hover(self, cx);
+        let workspace_id = self.workspace.as_ref().map(|workspace| workspace.1);
+        self.scroll_manager.set_scroll_position(
+            scroll_position,
+            &map,
+            local,
+            autoscroll,
+            workspace_id,
+            cx,
+        );
+
+        // todo!()
+        // self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
+    }
+
+    //     pub fn scroll_position(&self, cx: &mut ViewContext<Self>) -> gpui::Point<Pixels> {
+    //         let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
+    //         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(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) {
+    //             cx.propagate_action();
+    //             return;
+    //         }
+
+    //         if self.take_rename(true, cx).is_some() {
+    //             return;
+    //         }
+
+    //         let cur_position = self.scroll_position(cx);
+    //         let new_pos = cur_position + point(0., amount.lines(self));
+    //         self.set_scroll_position(new_pos, cx);
+    //     }
+
+    //     /// Returns an ordering. The newest selection is:
+    //     ///     Ordering::Equal => on screen
+    //     ///     Ordering::Less => above the screen
+    //     ///     Ordering::Greater => below the screen
+    //     pub fn newest_selection_on_screen(&self, cx: &mut AppContext) -> Ordering {
+    //         let snapshot = self.display_map.update(cx, |map, cx| map.snapshot(cx));
+    //         let newest_head = self
+    //             .selections
+    //             .newest_anchor()
+    //             .head()
+    //             .to_display_point(&snapshot);
+    //         let screen_top = self
+    //             .scroll_manager
+    //             .anchor
+    //             .anchor
+    //             .to_display_point(&snapshot);
+
+    //         if screen_top > newest_head {
+    //             return Ordering::Less;
+    //         }
+
+    //         if let Some(visible_lines) = self.visible_line_count() {
+    //             if newest_head.row() < screen_top.row() + visible_lines as u32 {
+    //                 return Ordering::Equal;
+    //             }
+    //         }
+
+    //         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);
+    //         }
+    //     }
+}

crates/editor2/src/scroll/autoscroll.rs 🔗

@@ -1,6 +1,6 @@
-use std::cmp;
+use std::{cmp, f32};
 
-use gpui::ViewContext;
+use gpui::{px, Pixels, ViewContext};
 use language::Point;
 
 use crate::{display_map::ToDisplayPoint, Editor, EditorMode, LineWithInvisibles};
@@ -61,7 +61,7 @@ impl Editor {
             display_map.max_point().row() as f32
         };
         if scroll_position.y > max_scroll_top {
-            scroll_position.set_y(max_scroll_top);
+            scroll_position.y = (max_scroll_top);
             self.set_scroll_position(scroll_position, cx);
         }
 
@@ -143,24 +143,24 @@ impl Editor {
                 let needs_scroll_down = target_bottom >= end_row;
 
                 if needs_scroll_up && !needs_scroll_down {
-                    scroll_position.set_y(target_top);
+                    scroll_position.y = (target_top);
                     self.set_scroll_position_internal(scroll_position, local, true, cx);
                 }
                 if !needs_scroll_up && needs_scroll_down {
-                    scroll_position.set_y(target_bottom - visible_lines);
+                    scroll_position.y = (target_bottom - visible_lines);
                     self.set_scroll_position_internal(scroll_position, local, true, cx);
                 }
             }
             AutoscrollStrategy::Center => {
-                scroll_position.set_y((target_top - margin).max(0.0));
+                scroll_position.y = ((target_top - margin).max(0.0));
                 self.set_scroll_position_internal(scroll_position, local, true, cx);
             }
             AutoscrollStrategy::Top => {
-                scroll_position.set_y((target_top).max(0.0));
+                scroll_position.y = ((target_top).max(0.0));
                 self.set_scroll_position_internal(scroll_position, local, true, cx);
             }
             AutoscrollStrategy::Bottom => {
-                scroll_position.set_y((target_bottom - visible_lines).max(0.0));
+                scroll_position.y = ((target_bottom - visible_lines).max(0.0));
                 self.set_scroll_position_internal(scroll_position, local, true, cx);
             }
         }
@@ -178,9 +178,9 @@ impl Editor {
     pub fn autoscroll_horizontally(
         &mut self,
         start_row: u32,
-        viewport_width: f32,
-        scroll_width: f32,
-        max_glyph_width: f32,
+        viewport_width: Pixels,
+        scroll_width: Pixels,
+        max_glyph_width: Pixels,
         layouts: &[LineWithInvisibles],
         cx: &mut ViewContext<Self>,
     ) -> bool {
@@ -191,11 +191,11 @@ impl Editor {
         let mut target_right;
 
         if self.highlighted_rows.is_some() {
-            target_left = 0.0_f32;
-            target_right = 0.0_f32;
+            target_left = px(0.);
+            target_right = px(0.);
         } else {
-            target_left = std::f32::INFINITY;
-            target_right = 0.0_f32;
+            target_left = px(f32::INFINITY);
+            target_right = px(0.);
             for selection in selections {
                 let head = selection.head().to_display_point(&display_map);
                 if head.row() >= start_row && head.row() < start_row + layouts.len() as u32 {
@@ -226,11 +226,11 @@ impl Editor {
         let scroll_right = scroll_left + viewport_width;
 
         if target_left < scroll_left {
-            self.scroll_manager.anchor.offset.x = (target_left / max_glyph_width);
+            self.scroll_manager.anchor.offset.x = (target_left / max_glyph_width).into();
             true
         } else if target_right > scroll_right {
             self.scroll_manager.anchor.offset.x =
-                ((target_right - viewport_width) / max_glyph_width);
+                ((target_right - viewport_width) / max_glyph_width).into();
             true
         } else {
             false

crates/editor2/src/scroll/scroll_amount.rs 🔗

@@ -11,18 +11,19 @@ pub enum ScrollAmount {
 
 impl ScrollAmount {
     pub fn lines(&self, editor: &mut Editor) -> f32 {
-        match self {
-            Self::Line(count) => *count,
-            Self::Page(count) => editor
-                .visible_line_count()
-                .map(|mut l| {
-                    // for full pages subtract one to leave an anchor line
-                    if count.abs() == 1.0 {
-                        l -= 1.0
-                    }
-                    (l * count).trunc()
-                })
-                .unwrap_or(0.),
-        }
+        todo!()
+        // match self {
+        //     Self::Line(count) => *count,
+        //     Self::Page(count) => editor
+        //         .visible_line_count()
+        //         .map(|mut l| {
+        //             // for full pages subtract one to leave an anchor line
+        //             if count.abs() == 1.0 {
+        //                 l -= 1.0
+        //             }
+        //             (l * count).trunc()
+        //         })
+        //         .unwrap_or(0.),
+        // }
     }
 }

crates/editor2/src/selections_collection.rs 🔗

@@ -6,7 +6,7 @@ use std::{
 };
 
 use collections::HashMap;
-use gpui::{AppContext, Model};
+use gpui::{AppContext, Model, Pixels};
 use itertools::Itertools;
 use language::{Bias, Point, Selection, SelectionGoal, TextDimension, ToPoint};
 use util::post_inc;
@@ -302,39 +302,39 @@ impl SelectionsCollection {
             .collect()
     }
 
-    pub fn build_columnar_selection(
-        &mut self,
-        display_map: &DisplaySnapshot,
-        row: u32,
-        positions: &Range<f32>,
-        reversed: bool,
-        text_layout_details: &TextLayoutDetails,
-    ) -> Option<Selection<Point>> {
-        let is_empty = positions.start == positions.end;
-        let line_len = display_map.line_len(row);
-
-        let layed_out_line = display_map.lay_out_line_for_row(row, &text_layout_details);
-
-        let start_col = layed_out_line.closest_index_for_x(positions.start) as u32;
-        if start_col < line_len || (is_empty && positions.start == layed_out_line.width()) {
-            let start = DisplayPoint::new(row, start_col);
-            let end_col = layed_out_line.closest_index_for_x(positions.end) as u32;
-            let end = DisplayPoint::new(row, end_col);
-
-            Some(Selection {
-                id: post_inc(&mut self.next_selection_id),
-                start: start.to_point(display_map),
-                end: end.to_point(display_map),
-                reversed,
-                goal: SelectionGoal::HorizontalRange {
-                    start: positions.start,
-                    end: positions.end,
-                },
-            })
-        } else {
-            None
-        }
-    }
+    // pub fn build_columnar_selection(
+    //     &mut self,
+    //     display_map: &DisplaySnapshot,
+    //     row: u32,
+    //     positions: &Range<Pixels>,
+    //     reversed: bool,
+    //     text_layout_details: &TextLayoutDetails,
+    // ) -> Option<Selection<Point>> {
+    //     let is_empty = positions.start == positions.end;
+    //     let line_len = display_map.line_len(row);
+
+    //     let layed_out_line = display_map.lay_out_line_for_row(row, &text_layout_details);
+
+    //     let start_col = layed_out_line.closest_index_for_x(positions.start) as u32;
+    //     if start_col < line_len || (is_empty && positions.start == layed_out_line.width()) {
+    //         let start = DisplayPoint::new(row, start_col);
+    //         let end_col = layed_out_line.closest_index_for_x(positions.end) as u32;
+    //         let end = DisplayPoint::new(row, end_col);
+
+    //         Some(Selection {
+    //             id: post_inc(&mut self.next_selection_id),
+    //             start: start.to_point(display_map),
+    //             end: end.to_point(display_map),
+    //             reversed,
+    //             goal: SelectionGoal::HorizontalRange {
+    //                 start: positions.start,
+    //                 end: positions.end,
+    //             },
+    //         })
+    //     } else {
+    //         None
+    //     }
+    // }
 
     pub(crate) fn change_with<R>(
         &mut self,

crates/gpui2/src/executor.rs 🔗

@@ -29,6 +29,7 @@ pub struct ForegroundExecutor {
 }
 
 #[must_use]
+#[derive(Debug)]
 pub enum Task<T> {
     Ready(Option<T>),
     Spawned(async_task::Task<T>),

crates/gpui2/src/geometry.rs 🔗

@@ -819,6 +819,18 @@ impl From<Pixels> for f64 {
     }
 }
 
+impl From<Pixels> for u32 {
+    fn from(pixels: Pixels) -> Self {
+        pixels.0 as u32
+    }
+}
+
+impl From<Pixels> for usize {
+    fn from(pixels: Pixels) -> Self {
+        pixels.0 as usize
+    }
+}
+
 #[derive(
     Add, AddAssign, Clone, Copy, Default, Div, Eq, Hash, Ord, PartialEq, PartialOrd, Sub, SubAssign,
 )]

crates/gpui2/src/style.rs 🔗

@@ -167,6 +167,15 @@ impl TextStyle {
         Ok(self)
     }
 
+    pub fn font(&self) -> Font {
+        Font {
+            family: self.font_family.clone(),
+            features: self.font_features.clone(),
+            weight: self.font_weight,
+            style: self.font_style,
+        }
+    }
+
     pub fn to_run(&self, len: usize) -> TextRun {
         TextRun {
             len,

crates/gpui2/src/text_system.rs 🔗

@@ -151,7 +151,7 @@ impl TextSystem {
 
     pub fn layout_text(
         &self,
-        text: &SharedString,
+        text: &str,
         font_size: Pixels,
         runs: &[TextRun],
         wrap_width: Option<Pixels>,

crates/gpui2/src/text_system/line.rs 🔗

@@ -29,6 +29,10 @@ impl Line {
         )
     }
 
+    pub fn width(&self) -> Pixels {
+        self.layout.width
+    }
+
     pub fn wrap_count(&self) -> usize {
         self.layout.wrap_boundaries.len()
     }

crates/gpui2/src/window.rs 🔗

@@ -1655,6 +1655,7 @@ impl<'a, V: 'static> ViewContext<'a, V> {
         }
     }
 
+    // todo!("change this to return a reference");
     pub fn view(&self) -> View<V> {
         self.view.clone()
     }

crates/text/Cargo.toml 🔗

@@ -30,7 +30,7 @@ regex.workspace = true
 
 [dev-dependencies]
 collections = { path = "../collections", features = ["test-support"] }
-gpui = { path = "../gpui", features = ["test-support"] }
+gpui = { package = "gpui2", path = "../gpui2", features = ["test-support"] }
 util = { path = "../util", features = ["test-support"] }
 ctor.workspace = true
 env_logger.workspace = true

crates/text2/src/selection.rs 🔗

@@ -1,3 +1,5 @@
+use gpui::Pixels;
+
 use crate::{Anchor, BufferSnapshot, TextDimension};
 use std::cmp::Ordering;
 use std::ops::Range;
@@ -5,8 +7,8 @@ use std::ops::Range;
 #[derive(Copy, Clone, Debug, PartialEq)]
 pub enum SelectionGoal {
     None,
-    HorizontalPosition(f32),
-    HorizontalRange { start: f32, end: f32 },
+    HorizontalPosition(Pixels),
+    HorizontalRange { start: Pixels, end: Pixels },
     WrappedHorizontalPosition((u32, f32)),
 }
 

crates/workspace2/src/item.rs 🔗

@@ -104,7 +104,11 @@ pub trait Item: Render + EventEmitter {
     }
     fn tab_content<V: 'static>(&self, detail: Option<usize>, cx: &AppContext) -> AnyElement<V>;
 
-    fn for_each_project_item(&self, _: &AppContext, _: &mut dyn FnMut(usize, &dyn project2::Item)) {
+    fn for_each_project_item(
+        &self,
+        _: &AppContext,
+        _: &mut dyn FnMut(EntityId, &dyn project2::Item),
+    ) {
     } // (model id, Item)
     fn is_singleton(&self, _cx: &AppContext) -> bool {
         false
@@ -219,8 +223,12 @@ pub trait ItemHandle: 'static + Send {
     fn dragged_tab_content(&self, detail: Option<usize>, cx: &AppContext) -> AnyElement<Workspace>;
     fn project_path(&self, cx: &AppContext) -> Option<ProjectPath>;
     fn project_entry_ids(&self, cx: &AppContext) -> SmallVec<[ProjectEntryId; 3]>;
-    fn project_item_model_ids(&self, cx: &AppContext) -> SmallVec<[usize; 3]>;
-    fn for_each_project_item(&self, _: &AppContext, _: &mut dyn FnMut(usize, &dyn project2::Item));
+    fn project_item_model_ids(&self, cx: &AppContext) -> SmallVec<[EntityId; 3]>;
+    fn for_each_project_item(
+        &self,
+        _: &AppContext,
+        _: &mut dyn FnMut(EntityId, &dyn project2::Item),
+    );
     fn is_singleton(&self, cx: &AppContext) -> bool;
     fn boxed_clone(&self) -> Box<dyn ItemHandle>;
     fn clone_on_split(
@@ -331,7 +339,7 @@ impl<T: Item> ItemHandle for View<T> {
         result
     }
 
-    fn project_item_model_ids(&self, cx: &AppContext) -> SmallVec<[usize; 3]> {
+    fn project_item_model_ids(&self, cx: &AppContext) -> SmallVec<[EntityId; 3]> {
         let mut result = SmallVec::new();
         self.read(cx).for_each_project_item(cx, &mut |id, _| {
             result.push(id);
@@ -342,7 +350,7 @@ impl<T: Item> ItemHandle for View<T> {
     fn for_each_project_item(
         &self,
         cx: &AppContext,
-        f: &mut dyn FnMut(usize, &dyn project2::Item),
+        f: &mut dyn FnMut(EntityId, &dyn project2::Item),
     ) {
         self.read(cx).for_each_project_item(cx, f)
     }