Into the woods

Conrad Irwin created

Change summary

crates/editor2/Cargo.toml                      |    4 
crates/editor2/src/blink_manager.rs            |   27 
crates/editor2/src/display_map.rs              |  115 
crates/editor2/src/display_map/block_map.rs    |    6 
crates/editor2/src/display_map/wrap_map.rs     |   12 
crates/editor2/src/editor.rs                   | 1879 +++++++++----------
crates/editor2/src/editor_settings.rs          |    4 
crates/editor2/src/element.rs                  |   32 
crates/editor2/src/hover_popover.rs            |   58 
crates/editor2/src/inlay_hint_cache.rs         |  264 +-
crates/editor2/src/items.rs                    |  260 +-
crates/editor2/src/link_go_to_definition.rs    |    2 
crates/editor2/src/scroll.rs                   |  337 +-
crates/editor2/src/selections_collection.rs    |   47 
crates/editor2/src/test.rs                     |  133 
crates/editor2/src/test/editor_test_context.rs |  596 +++---
16 files changed, 1,884 insertions(+), 1,892 deletions(-)

Detailed changes

crates/editor2/Cargo.toml ๐Ÿ”—

@@ -35,7 +35,7 @@ git = { path = "../git" }
 gpui = { package = "gpui2", path = "../gpui2" }
 language = { package = "language2", path = "../language2" }
 lsp = { package = "lsp2", path = "../lsp2" }
-multi_buffer = { path = "../multi_buffer" }
+multi_buffer = { package = "multi_buffer2", path = "../multi_buffer2" }
 project = { package = "project2", path = "../project2" }
 rpc = { package = "rpc2", path = "../rpc2" }
 rich_text = { path = "../rich_text" }
@@ -80,7 +80,7 @@ util = { path = "../util", features = ["test-support"] }
 project = { package = "project2", path = "../project2", features = ["test-support"] }
 settings = { package = "settings2", path = "../settings2", features = ["test-support"] }
 workspace = { package = "workspace2", path = "../workspace2", features = ["test-support"] }
-multi_buffer = { path = "../multi_buffer", features = ["test-support"] }
+multi_buffer = { package = "multi_buffer2", path = "../multi_buffer2", features = ["test-support"] }
 
 ctor.workspace = true
 env_logger.workspace = true
@@ -1,5 +1,6 @@
 use crate::EditorSettings;
-use gpui::{Entity, ModelContext};
+use gpui::ModelContext;
+use settings::Settings;
 use settings::SettingsStore;
 use smol::Timer;
 use std::time::Duration;
@@ -16,7 +17,7 @@ pub struct BlinkManager {
 impl BlinkManager {
     pub fn new(blink_interval: Duration, cx: &mut ModelContext<Self>) -> Self {
         // Make sure we blink the cursors if the setting is re-enabled
-        cx.observe_global::<SettingsStore, _>(move |this, cx| {
+        cx.observe_global::<SettingsStore>(move |this, cx| {
             this.blink_cursors(this.blink_epoch, cx)
         })
         .detach();
@@ -41,14 +42,9 @@ impl BlinkManager {
 
         let epoch = self.next_blink_epoch();
         let interval = self.blink_interval;
-        cx.spawn(|this, mut cx| {
-            let this = this.downgrade();
-            async move {
-                Timer::after(interval).await;
-                if let Some(this) = this.upgrade(&cx) {
-                    this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
-                }
-            }
+        cx.spawn(|this, mut cx| async move {
+            Timer::after(interval).await;
+            this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
         })
         .detach();
     }
@@ -68,13 +64,10 @@ impl BlinkManager {
 
                 let epoch = self.next_blink_epoch();
                 let interval = self.blink_interval;
-                cx.spawn(|this, mut cx| {
-                    let this = this.downgrade();
-                    async move {
-                        Timer::after(interval).await;
-                        if let Some(this) = this.upgrade(&cx) {
-                            this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx));
-                        }
+                cx.spawn(|this, mut cx| async move {
+                    Timer::after(interval).await;
+                    if let Some(this) = this.upgrade() {
+                        this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx));
                     }
                 })
                 .detach();

crates/editor2/src/display_map.rs ๐Ÿ”—

@@ -497,62 +497,63 @@ impl DisplaySnapshot {
         )
     }
 
-    pub fn highlighted_chunks<'a>(
-        &'a self,
-        display_rows: Range<u32>,
-        language_aware: bool,
-        style: &'a EditorStyle,
-    ) -> impl Iterator<Item = HighlightedChunk<'a>> {
-        self.chunks(
-            display_rows,
-            language_aware,
-            Some(style.theme.hint),
-            Some(style.theme.suggestion),
-        )
-        .map(|chunk| {
-            let mut highlight_style = chunk
-                .syntax_highlight_id
-                .and_then(|id| id.style(&style.syntax));
-
-            if let Some(chunk_highlight) = chunk.highlight_style {
-                if let Some(highlight_style) = highlight_style.as_mut() {
-                    highlight_style.highlight(chunk_highlight);
-                } else {
-                    highlight_style = Some(chunk_highlight);
-                }
-            }
-
-            let mut diagnostic_highlight = HighlightStyle::default();
-
-            if chunk.is_unnecessary {
-                diagnostic_highlight.fade_out = Some(style.unnecessary_code_fade);
-            }
-
-            if let Some(severity) = chunk.diagnostic_severity {
-                // Omit underlines for HINT/INFO diagnostics on 'unnecessary' code.
-                if severity <= DiagnosticSeverity::WARNING || !chunk.is_unnecessary {
-                    let diagnostic_style = super::diagnostic_style(severity, true, style);
-                    diagnostic_highlight.underline = Some(UnderlineStyle {
-                        color: Some(diagnostic_style.message.text.color),
-                        thickness: 1.0.into(),
-                        wavy: true,
-                    });
-                }
-            }
-
-            if let Some(highlight_style) = highlight_style.as_mut() {
-                highlight_style.highlight(diagnostic_highlight);
-            } else {
-                highlight_style = Some(diagnostic_highlight);
-            }
-
-            HighlightedChunk {
-                chunk: chunk.text,
-                style: highlight_style,
-                is_tab: chunk.is_tab,
-            }
-        })
-    }
+    // pub fn highlighted_chunks<'a>(
+    //     &'a self,
+    //     display_rows: Range<u32>,
+    //     language_aware: bool,
+    //     style: &'a EditorStyle,
+    // ) -> impl Iterator<Item = HighlightedChunk<'a>> {
+    //     self.chunks(
+    //         display_rows,
+    //         language_aware,
+    //         Some(style.theme.hint),
+    //         Some(style.theme.suggestion),
+    //     )
+    //     .map(|chunk| {
+    //         let mut highlight_style = chunk
+    //             .syntax_highlight_id
+    //             .and_then(|id| id.style(&style.syntax));
+
+    //         if let Some(chunk_highlight) = chunk.highlight_style {
+    //             if let Some(highlight_style) = highlight_style.as_mut() {
+    //                 highlight_style.highlight(chunk_highlight);
+    //             } else {
+    //                 highlight_style = Some(chunk_highlight);
+    //             }
+    //         }
+
+    //         let mut diagnostic_highlight = HighlightStyle::default();
+
+    //         if chunk.is_unnecessary {
+    //             diagnostic_highlight.fade_out = Some(style.unnecessary_code_fade);
+    //         }
+
+    //         if let Some(severity) = chunk.diagnostic_severity {
+    //             // Omit underlines for HINT/INFO diagnostics on 'unnecessary' code.
+    //             if severity <= DiagnosticSeverity::WARNING || !chunk.is_unnecessary {
+    //                 todo!()
+    //                 // let diagnostic_style = super::diagnostic_style(severity, true, style);
+    //                 // diagnostic_highlight.underline = Some(UnderlineStyle {
+    //                 //     color: Some(diagnostic_style.message.text.color),
+    //                 //     thickness: 1.0.into(),
+    //                 //     wavy: true,
+    //                 // });
+    //             }
+    //         }
+
+    //         if let Some(highlight_style) = highlight_style.as_mut() {
+    //             highlight_style.highlight(diagnostic_highlight);
+    //         } else {
+    //             highlight_style = Some(diagnostic_highlight);
+    //         }
+
+    //         HighlightedChunk {
+    //             chunk: chunk.text,
+    //             style: highlight_style,
+    //             is_tab: chunk.is_tab,
+    //         }
+    //     })
+    // }
 
     pub fn lay_out_line_for_row(
         &self,
@@ -606,7 +607,7 @@ impl DisplaySnapshot {
             // });
         }
 
-        text_layout_cache.layout_text(&line, editor_style.text.font_size, &styles)
+        text_layout_cache.layout_text(&line, editor_style.text.font_size, &styles, None)
     }
 
     pub fn x_for_point(

crates/editor2/src/display_map/block_map.rs ๐Ÿ”—

@@ -932,15 +932,15 @@ impl BlockDisposition {
     }
 }
 
-impl<'a, 'b, 'c> Deref for BlockContext<'a, 'b, 'c> {
-    type Target = ViewContext<'a, 'b, Editor>;
+impl<'a> Deref for BlockContext<'a, '_> {
+    type Target = ViewContext<'a, Editor>;
 
     fn deref(&self) -> &Self::Target {
         self.view_context
     }
 }
 
-impl DerefMut for BlockContext<'_, '_, '_> {
+impl DerefMut for BlockContext<'_, '_> {
     fn deref_mut(&mut self) -> &mut Self::Target {
         self.view_context
     }

crates/editor2/src/display_map/wrap_map.rs ๐Ÿ”—

@@ -4,7 +4,7 @@ use super::{
     Highlights,
 };
 use crate::MultiBufferSnapshot;
-use gpui::{AppContext, FontId, Model, ModelContext, Pixels, Task};
+use gpui::{AppContext, FontId, LineWrapper, Model, ModelContext, Pixels, Task};
 use language::{Chunk, Point};
 use lazy_static::lazy_static;
 use smol::future::yield_now;
@@ -20,7 +20,7 @@ pub struct WrapMap {
     pending_edits: VecDeque<(TabSnapshot, Vec<TabEdit>)>,
     interpolated_edits: Patch<u32>,
     edits_since_sync: Patch<u32>,
-    wrap_width: Option<f32>,
+    wrap_width: Option<Pixels>,
     background_task: Option<Task<()>>,
     font: (FontId, Pixels),
 }
@@ -130,7 +130,11 @@ impl WrapMap {
         }
     }
 
-    pub fn set_wrap_width(&mut self, wrap_width: Option<f32>, cx: &mut ModelContext<Self>) -> bool {
+    pub fn set_wrap_width(
+        &mut self,
+        wrap_width: Option<Pixels>,
+        cx: &mut ModelContext<Self>,
+    ) -> bool {
         if wrap_width == self.wrap_width {
             return false;
         }
@@ -379,7 +383,7 @@ impl WrapSnapshot {
         &mut self,
         new_tab_snapshot: TabSnapshot,
         tab_edits: &[TabEdit],
-        wrap_width: f32,
+        wrap_width: Pixels,
         line_wrapper: &mut LineWrapper,
     ) -> Patch<u32> {
         #[derive(Debug)]

crates/editor2/src/editor.rs ๐Ÿ”—

@@ -19,7 +19,6 @@ pub mod selections_collection;
 mod editor_tests;
 #[cfg(any(test, feature = "test-support"))]
 pub mod test;
-
 use ::git::diff::DiffHunk;
 use aho_corasick::AhoCorasick;
 use anyhow::{anyhow, Context, Result};
@@ -38,8 +37,9 @@ pub use element::{
 use futures::FutureExt;
 use fuzzy::{StringMatch, StringMatchCandidate};
 use gpui::{
-    serde_json, AnyElement, AppContext, AsyncAppContext, ClipboardItem, Element, Entity, Hsla,
-    Model, Quad, Subscription, Task, Text, View, ViewContext, WeakView, WindowContext,
+    serde_json, AnyElement, AppContext, AsyncAppContext, ClipboardItem, Element, Entity,
+    EventEmitter, FontWeight, HighlightStyle, Hsla, Model, Pixels, Quad, Render, Subscription,
+    Task, Text, View, ViewContext, WeakView, WindowContext,
 };
 use highlight_matching_bracket::refresh_matching_bracket_highlights;
 use hover_popover::{hide_hover, HoverState};
@@ -74,30 +74,17 @@ use rpc::proto::{self, PeerId};
 use scroll::{
     autoscroll::Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide,
 };
-use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection};
+use selections_collection::SelectionsCollection;
 use serde::{Deserialize, Serialize};
-use settings::SettingsStore;
-use smallvec::SmallVec;
-use snippet::Snippet;
+use settings::Settings;
 use std::{
-    any::TypeId,
-    borrow::Cow,
-    cmp::{self, Ordering, Reverse},
-    mem,
-    num::NonZeroU32,
-    ops::{ControlFlow, Deref, DerefMut, Range, RangeInclusive},
-    path::Path,
+    ops::{Deref, DerefMut, Range},
     sync::Arc,
-    time::{Duration, Instant},
+    time::Duration,
 };
 pub use sum_tree::Bias;
-use sum_tree::TreeMap;
-use text::Rope;
-use theme::{DiagnosticStyle, Theme, ThemeSettings};
-use util::{post_inc, RangeExt, ResultExt, TryFutureExt};
-use workspace::{ItemNavHistory, SplitDirection, ViewId, Workspace};
-
-use crate::git::diff_hunk_to_display;
+use util::TryFutureExt;
+use workspace::{ItemNavHistory, ViewId, Workspace};
 
 const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
 const MAX_LINE_LEN: usize = 1024;
@@ -109,70 +96,70 @@ pub const DOCUMENT_HIGHLIGHTS_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis
 
 pub const FORMAT_TIMEOUT: Duration = Duration::from_secs(2);
 
-pub fn render_parsed_markdown<Tag: 'static>(
-    parsed: &language::ParsedMarkdown,
-    editor_style: &EditorStyle,
-    workspace: Option<WeakView<Workspace>>,
-    cx: &mut ViewContext<Editor>,
-) -> Text {
-    enum RenderedMarkdown {}
-
-    let parsed = parsed.clone();
-    let view_id = cx.view_id();
-    let code_span_background_color = editor_style.document_highlight_read_background;
-
-    let mut region_id = 0;
-
-    todo!()
-    // Text::new(parsed.text, editor_style.text.clone())
-    //     .with_highlights(
-    //         parsed
-    //             .highlights
-    //             .iter()
-    //             .filter_map(|(range, highlight)| {
-    //                 let highlight = highlight.to_highlight_style(&editor_style.syntax)?;
-    //                 Some((range.clone(), highlight))
-    //             })
-    //             .collect::<Vec<_>>(),
-    //     )
-    //     .with_custom_runs(parsed.region_ranges, move |ix, bounds, cx| {
-    //         region_id += 1;
-    //         let region = parsed.regions[ix].clone();
-
-    //         if let Some(link) = region.link {
-    //             cx.scene().push_cursor_region(CursorRegion {
-    //                 bounds,
-    //                 style: CursorStyle::PointingHand,
-    //             });
-    //             cx.scene().push_mouse_region(
-    //                 MouseRegion::new::<(RenderedMarkdown, Tag)>(view_id, region_id, bounds)
-    //                     .on_down::<Editor, _>(MouseButton::Left, move |_, _, cx| match &link {
-    //                         markdown::Link::Web { url } => cx.platform().open_url(url),
-    //                         markdown::Link::Path { path } => {
-    //                             if let Some(workspace) = &workspace {
-    //                                 _ = workspace.update(cx, |workspace, cx| {
-    //                                     workspace.open_abs_path(path.clone(), false, cx).detach();
-    //                                 });
-    //                             }
-    //                         }
-    //                     }),
-    //             );
-    //         }
-
-    //         if region.code {
-    //             cx.draw_quad(Quad {
-    //                 bounds,
-    //                 background: Some(code_span_background_color),
-    //                 corner_radii: (2.0).into(),
-    //                 order: todo!(),
-    //                 content_mask: todo!(),
-    //                 border_color: todo!(),
-    //                 border_widths: todo!(),
-    //             });
-    //         }
-    //     })
-    //     .with_soft_wrap(true)
-}
+// pub fn render_parsed_markdown<Tag: 'static>(
+//     parsed: &language::ParsedMarkdown,
+//     editor_style: &EditorStyle,
+//     workspace: Option<WeakView<Workspace>>,
+//     cx: &mut ViewContext<Editor>,
+// ) -> Text {
+//     enum RenderedMarkdown {}
+
+//     let parsed = parsed.clone();
+//     let view_id = cx.view_id();
+//     let code_span_background_color = editor_style.document_highlight_read_background;
+
+//     let mut region_id = 0;
+
+//     todo!()
+//     // Text::new(parsed.text, editor_style.text.clone())
+//     //     .with_highlights(
+//     //         parsed
+//     //             .highlights
+//     //             .iter()
+//     //             .filter_map(|(range, highlight)| {
+//     //                 let highlight = highlight.to_highlight_style(&editor_style.syntax)?;
+//     //                 Some((range.clone(), highlight))
+//     //             })
+//     //             .collect::<Vec<_>>(),
+//     //     )
+//     //     .with_custom_runs(parsed.region_ranges, move |ix, bounds, cx| {
+//     //         region_id += 1;
+//     //         let region = parsed.regions[ix].clone();
+
+//     //         if let Some(link) = region.link {
+//     //             cx.scene().push_cursor_region(CursorRegion {
+//     //                 bounds,
+//     //                 style: CursorStyle::PointingHand,
+//     //             });
+//     //             cx.scene().push_mouse_region(
+//     //                 MouseRegion::new::<(RenderedMarkdown, Tag)>(view_id, region_id, bounds)
+//     //                     .on_down::<Editor, _>(MouseButton::Left, move |_, _, cx| match &link {
+//     //                         markdown::Link::Web { url } => cx.platform().open_url(url),
+//     //                         markdown::Link::Path { path } => {
+//     //                             if let Some(workspace) = &workspace {
+//     //                                 _ = workspace.update(cx, |workspace, cx| {
+//     //                                     workspace.open_abs_path(path.clone(), false, cx).detach();
+//     //                                 });
+//     //                             }
+//     //                         }
+//     //                     }),
+//     //             );
+//     //         }
+
+//     //         if region.code {
+//     //             cx.draw_quad(Quad {
+//     //                 bounds,
+//     //                 background: Some(code_span_background_color),
+//     //                 corner_radii: (2.0).into(),
+//     //                 order: todo!(),
+//     //                 content_mask: todo!(),
+//     //                 border_color: todo!(),
+//     //                 border_widths: todo!(),
+//     //             });
+//     //         }
+//     //     })
+//     //     .with_soft_wrap(true)
+// }
 
 #[derive(Clone, Deserialize, PartialEq, Default)]
 pub struct SelectNext {
@@ -270,138 +257,138 @@ impl InlayId {
     }
 }
 
-actions!(
-    editor,
-    [
-        Cancel,
-        Backspace,
-        Delete,
-        Newline,
-        NewlineAbove,
-        NewlineBelow,
-        GoToDiagnostic,
-        GoToPrevDiagnostic,
-        GoToHunk,
-        GoToPrevHunk,
-        Indent,
-        Outdent,
-        DeleteLine,
-        DeleteToPreviousWordStart,
-        DeleteToPreviousSubwordStart,
-        DeleteToNextWordEnd,
-        DeleteToNextSubwordEnd,
-        DeleteToBeginningOfLine,
-        DeleteToEndOfLine,
-        CutToEndOfLine,
-        DuplicateLine,
-        MoveLineUp,
-        MoveLineDown,
-        JoinLines,
-        SortLinesCaseSensitive,
-        SortLinesCaseInsensitive,
-        ReverseLines,
-        ShuffleLines,
-        ConvertToUpperCase,
-        ConvertToLowerCase,
-        ConvertToTitleCase,
-        ConvertToSnakeCase,
-        ConvertToKebabCase,
-        ConvertToUpperCamelCase,
-        ConvertToLowerCamelCase,
-        Transpose,
-        Cut,
-        Copy,
-        Paste,
-        Undo,
-        Redo,
-        MoveUp,
-        PageUp,
-        MoveDown,
-        PageDown,
-        MoveLeft,
-        MoveRight,
-        MoveToPreviousWordStart,
-        MoveToPreviousSubwordStart,
-        MoveToNextWordEnd,
-        MoveToNextSubwordEnd,
-        MoveToBeginningOfLine,
-        MoveToEndOfLine,
-        MoveToStartOfParagraph,
-        MoveToEndOfParagraph,
-        MoveToBeginning,
-        MoveToEnd,
-        SelectUp,
-        SelectDown,
-        SelectLeft,
-        SelectRight,
-        SelectToPreviousWordStart,
-        SelectToPreviousSubwordStart,
-        SelectToNextWordEnd,
-        SelectToNextSubwordEnd,
-        SelectToStartOfParagraph,
-        SelectToEndOfParagraph,
-        SelectToBeginning,
-        SelectToEnd,
-        SelectAll,
-        SelectLine,
-        SplitSelectionIntoLines,
-        AddSelectionAbove,
-        AddSelectionBelow,
-        Tab,
-        TabPrev,
-        ShowCharacterPalette,
-        SelectLargerSyntaxNode,
-        SelectSmallerSyntaxNode,
-        GoToDefinition,
-        GoToDefinitionSplit,
-        GoToTypeDefinition,
-        GoToTypeDefinitionSplit,
-        MoveToEnclosingBracket,
-        UndoSelection,
-        RedoSelection,
-        FindAllReferences,
-        Rename,
-        ConfirmRename,
-        Fold,
-        UnfoldLines,
-        FoldSelectedRanges,
-        ShowCompletions,
-        OpenExcerpts,
-        RestartLanguageServer,
-        Hover,
-        Format,
-        ToggleSoftWrap,
-        ToggleInlayHints,
-        RevealInFinder,
-        CopyPath,
-        CopyRelativePath,
-        CopyHighlightJson,
-        ContextMenuFirst,
-        ContextMenuPrev,
-        ContextMenuNext,
-        ContextMenuLast,
-    ]
-);
-
-impl_actions!(
-    editor,
-    [
-        SelectNext,
-        SelectPrevious,
-        SelectAllMatches,
-        SelectToBeginningOfLine,
-        SelectToEndOfLine,
-        ToggleCodeActions,
-        MovePageUp,
-        MovePageDown,
-        ConfirmCompletion,
-        ConfirmCodeAction,
-        ToggleComments,
-        FoldAt,
-        UnfoldAt,
-        GutterHover
-    ]
-);
+// actions!(
+//     editor,
+//     [
+//         Cancel,
+//         Backspace,
+//         Delete,
+//         Newline,
+//         NewlineAbove,
+//         NewlineBelow,
+//         GoToDiagnostic,
+//         GoToPrevDiagnostic,
+//         GoToHunk,
+//         GoToPrevHunk,
+//         Indent,
+//         Outdent,
+//         DeleteLine,
+//         DeleteToPreviousWordStart,
+//         DeleteToPreviousSubwordStart,
+//         DeleteToNextWordEnd,
+//         DeleteToNextSubwordEnd,
+//         DeleteToBeginningOfLine,
+//         DeleteToEndOfLine,
+//         CutToEndOfLine,
+//         DuplicateLine,
+//         MoveLineUp,
+//         MoveLineDown,
+//         JoinLines,
+//         SortLinesCaseSensitive,
+//         SortLinesCaseInsensitive,
+//         ReverseLines,
+//         ShuffleLines,
+//         ConvertToUpperCase,
+//         ConvertToLowerCase,
+//         ConvertToTitleCase,
+//         ConvertToSnakeCase,
+//         ConvertToKebabCase,
+//         ConvertToUpperCamelCase,
+//         ConvertToLowerCamelCase,
+//         Transpose,
+//         Cut,
+//         Copy,
+//         Paste,
+//         Undo,
+//         Redo,
+//         MoveUp,
+//         PageUp,
+//         MoveDown,
+//         PageDown,
+//         MoveLeft,
+//         MoveRight,
+//         MoveToPreviousWordStart,
+//         MoveToPreviousSubwordStart,
+//         MoveToNextWordEnd,
+//         MoveToNextSubwordEnd,
+//         MoveToBeginningOfLine,
+//         MoveToEndOfLine,
+//         MoveToStartOfParagraph,
+//         MoveToEndOfParagraph,
+//         MoveToBeginning,
+//         MoveToEnd,
+//         SelectUp,
+//         SelectDown,
+//         SelectLeft,
+//         SelectRight,
+//         SelectToPreviousWordStart,
+//         SelectToPreviousSubwordStart,
+//         SelectToNextWordEnd,
+//         SelectToNextSubwordEnd,
+//         SelectToStartOfParagraph,
+//         SelectToEndOfParagraph,
+//         SelectToBeginning,
+//         SelectToEnd,
+//         SelectAll,
+//         SelectLine,
+//         SplitSelectionIntoLines,
+//         AddSelectionAbove,
+//         AddSelectionBelow,
+//         Tab,
+//         TabPrev,
+//         ShowCharacterPalette,
+//         SelectLargerSyntaxNode,
+//         SelectSmallerSyntaxNode,
+//         GoToDefinition,
+//         GoToDefinitionSplit,
+//         GoToTypeDefinition,
+//         GoToTypeDefinitionSplit,
+//         MoveToEnclosingBracket,
+//         UndoSelection,
+//         RedoSelection,
+//         FindAllReferences,
+//         Rename,
+//         ConfirmRename,
+//         Fold,
+//         UnfoldLines,
+//         FoldSelectedRanges,
+//         ShowCompletions,
+//         OpenExcerpts,
+//         RestartLanguageServer,
+//         Hover,
+//         Format,
+//         ToggleSoftWrap,
+//         ToggleInlayHints,
+//         RevealInFinder,
+//         CopyPath,
+//         CopyRelativePath,
+//         CopyHighlightJson,
+//         ContextMenuFirst,
+//         ContextMenuPrev,
+//         ContextMenuNext,
+//         ContextMenuLast,
+//     ]
+// );
+
+// impl_actions!(
+//     editor,
+//     [
+//         SelectNext,
+//         SelectPrevious,
+//         SelectAllMatches,
+//         SelectToBeginningOfLine,
+//         SelectToEndOfLine,
+//         ToggleCodeActions,
+//         MovePageUp,
+//         MovePageDown,
+//         ConfirmCompletion,
+//         ConfirmCodeAction,
+//         ToggleComments,
+//         FoldAt,
+//         UnfoldAt,
+//         GutterHover
+//     ]
+// );
 
 enum DocumentHighlightRead {}
 enum DocumentHighlightWrite {}
@@ -414,7 +401,7 @@ pub enum Direction {
 }
 
 pub fn init_settings(cx: &mut AppContext) {
-    settings::register::<EditorSettings>(cx);
+    EditorSettings::register(cx);
 }
 
 pub fn init(cx: &mut AppContext) {
@@ -574,7 +561,7 @@ pub enum SelectPhase {
     Update {
         position: DisplayPoint,
         goal_column: u32,
-        scroll_position: Point<Pixels>,
+        scroll_position: gpui::Point<Pixels>,
     },
     End,
 }
@@ -603,20 +590,20 @@ 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,
+    // pub placeholder_text: Option<TextStyle>,
+    //  pub theme: theme::Editor,
     pub theme_id: usize,
 }
 
 type CompletionId = usize;
 
-type GetFieldEditorTheme = dyn Fn(&theme::Theme) -> theme::FieldEditor;
-type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
+// type GetFieldEditorTheme = dyn Fn(&theme::Theme) -> theme::FieldEditor;
+// type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
 
-type BackgroundHighlight = (fn(&Theme) -> Hsla, Vec<Range<Anchor>>);
-type InlayBackgroundHighlight = (fn(&Theme) -> Hsla, Vec<InlayHighlight>);
+// type BackgroundHighlight = (fn(&Theme) -> Hsla, Vec<Range<Anchor>>);
+// type InlayBackgroundHighlight = (fn(&Theme) -> Hsla, Vec<InlayHighlight>);
 
 pub struct Editor {
     handle: WeakView<Self>,
@@ -635,8 +622,8 @@ pub struct Editor {
     ime_transaction: Option<TransactionId>,
     active_diagnostics: Option<ActiveDiagnosticGroup>,
     soft_wrap_mode_override: Option<language_settings::SoftWrap>,
-    get_field_editor_theme: Option<Arc<GetFieldEditorTheme>>,
-    override_text_style: Option<Box<OverrideTextStyle>>,
+    // get_field_editor_theme: Option<Arc<GetFieldEditorTheme>>,
+    // override_text_style: Option<Box<OverrideTextStyle>>,
     project: Option<Model<Project>>,
     collaboration_hub: Option<Box<dyn CollaborationHub>>,
     focused: bool,
@@ -647,8 +634,8 @@ pub struct Editor {
     show_wrap_guides: Option<bool>,
     placeholder_text: Option<Arc<str>>,
     highlighted_rows: Option<Range<u32>>,
-    background_highlights: BTreeMap<TypeId, BackgroundHighlight>,
-    inlay_background_highlights: TreeMap<Option<TypeId>, InlayBackgroundHighlight>,
+    // background_highlights: BTreeMap<TypeId, BackgroundHighlight>,
+    // inlay_background_highlights: TreeMap<Option<TypeId>, InlayBackgroundHighlight>,
     nav_history: Option<ItemNavHistory>,
     context_menu: RwLock<Option<ContextMenu>>,
     mouse_context_menu: View<context_menu::ContextMenu>,
@@ -663,7 +650,7 @@ pub struct Editor {
     collapse_matches: bool,
     autoindent_mode: Option<AutoindentMode>,
     workspace: Option<(WeakView<Workspace>, i64)>,
-    keymap_context_layers: BTreeMap<TypeId, KeymapContext>,
+    // keymap_context_layers: BTreeMap<TypeId, KeymapContext>,
     input_enabled: bool,
     read_only: bool,
     leader_peer_id: Option<PeerId>,
@@ -675,7 +662,7 @@ pub struct Editor {
     // inlay_hint_cache: InlayHintCache,
     next_inlay_id: usize,
     _subscriptions: Vec<Subscription>,
-    pixel_position_of_newest_cursor: Option<Point<Pixels>>,
+    pixel_position_of_newest_cursor: Option<gpui::Point<Pixels>>,
 }
 
 pub struct EditorSnapshot {
@@ -937,763 +924,763 @@ 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();
-    }
+// 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 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();
-    }
+//     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();
+//     }
 
-    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();
-    }
+//     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();
+//     }
 
-    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();
-    }
+//     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();
+//     }
 
-    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 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;
+//         }
 
-        let Some(project) = project else {
-            return;
-        };
-        let client = project.read(cx).client();
-        let language_registry = project.read(cx).languages().clone();
+//         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 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();
+//         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;
-                };
+//         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;
-                    }
-
-                    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;
-
-                    _ = 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 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;
-
-                    _ = this.update(&mut cx, |_, cx| cx.notify());
-                }
-            }
-        })
-        .detach();
-    }
+//                 for completion_index in completion_indices {
+//                     let completions_guard = completions.read();
+//                     let completion = &completions_guard[completion_index];
+//                     if completion.documentation.is_some() {
+//                         continue;
+//                     }
 
-    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 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;
 
-        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];
-        if completion.documentation.is_some() {
-            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 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);
 
-        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 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(),
-        };
-
-        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);
-        }
+//                     Self::resolve_completion_documentation_local(
+//                         server,
+//                         completions.clone(),
+//                         completion_index,
+//                         completion,
+//                         language_registry.clone(),
+//                     )
+//                     .await;
 
-        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)
-        };
+//                     _ = this.update(&mut cx, |_, cx| cx.notify());
+//                 }
+//             }
+//         })
+//         .detach();
+//     }
 
-        let mut completions = completions.write();
-        let completion = &mut completions[completion_index];
-        completion.documentation = Some(documentation);
-    }
+//     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;
+//         }
 
-    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;
-        }
+//         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 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 completions = self.completions.clone();
+//         let completions_guard = completions.read();
+//         let completion = &completions_guard[completion_index];
+//         if completion.documentation.is_some() {
+//             return;
+//         }
 
-    fn visible(&self) -> bool {
-        !self.matches.is_empty()
-    }
+//         let server_id = completion.server_id;
+//         let completion = completion.lsp_completion.clone();
+//         drop(completions_guard);
 
-    fn render(
-        &self,
-        style: EditorStyle,
-        workspace: Option<WeakView<Workspace>>,
-        cx: &mut ViewContext<Editor>,
-    ) -> AnyElement<Editor> {
-        enum CompletionTag {}
+//         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 settings = settings::get::<EditorSettings>(cx);
-        let show_completion_documentation = settings.show_completion_documentation;
+//             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;
 
-        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();
-                    }
-                }
+//                 _ = this.update(&mut cx, |_, cx| cx.notify());
+//             })
+//             .detach();
+//         } else {
+//             let Some(server) = project.read(cx).language_server_for_id(server_id) else {
+//                 return;
+//             };
 
-                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()
-    }
+//             cx.spawn(move |this, mut cx| async move {
+//                 Self::resolve_completion_documentation_local(
+//                     server,
+//                     completions,
+//                     completion_index,
+//                     completion,
+//                     language_registry,
+//                 )
+//                 .await;
 
-    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()
-        };
-
-        // 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)
-                    })
-                });
-            }
-        }
+//                 _ = this.update(&mut cx, |_, cx| cx.notify());
+//             })
+//             .detach();
+//         }
+//     }
 
-        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;
-            }
-        }
+//     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.matches = matches.into();
-        self.selected_item = 0;
-    }
-}
+//         let Some(response) = client
+//             .request(request)
+//             .await
+//             .context("completion documentation resolve proto request")
+//             .log_err()
+//         else {
+//             return;
+//         };
 
-#[derive(Clone)]
-struct CodeActionsMenu {
-    actions: Arc<[CodeAction]>,
-    buffer: Model<Buffer>,
-    selected_item: usize,
-    list: UniformListState,
-    deployed_from_indicator: bool,
-}
+//         if response.text.is_empty() {
+//             let mut completions = completions.write();
+//             let completion = &mut completions[completion_index];
+//             completion.documentation = Some(Documentation::Undocumented);
+//         }
 
-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()
-    }
+//         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)
+//         };
 
-    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();
-    }
+//         let mut completions = completions.write();
+//         let completion = &mut completions[completion_index];
+//         completion.documentation = Some(documentation);
+//     }
 
-    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();
-    }
+//     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;
+//         }
 
-    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()
-    }
+//         let request = server.request::<lsp::request::ResolveCompletionItem>(completion);
+//         let Some(completion_item) = request.await.log_err() else {
+//             return;
+//         };
 
-    fn visible(&self) -> bool {
-        !self.actions.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;
 
-    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();
-
-        if self.deployed_from_indicator {
-            *cursor_position.column_mut() = 0;
-        }
+//             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);
+//         }
+//     }
 
-        (cursor_position, element)
-    }
-}
+//     fn visible(&self) -> bool {
+//         !self.matches.is_empty()
+//     }
 
-pub struct CopilotState {
-    excerpt_id: Option<ExcerptId>,
-    pending_refresh: Task<Option<()>>,
-    pending_cycling_refresh: Task<Option<()>>,
-    cycled: bool,
-    completions: Vec<copilot::Completion>,
-    active_completion_index: usize,
-    suggestion: Option<Inlay>,
-}
+//     fn render(
+//         &self,
+//         style: EditorStyle,
+//         workspace: Option<WeakView<Workspace>>,
+//         cx: &mut ViewContext<Editor>,
+//     ) -> AnyElement<Editor> {
+//         enum CompletionTag {}
 
-impl Default for CopilotState {
-    fn default() -> Self {
-        Self {
-            excerpt_id: None,
-            pending_cycling_refresh: Task::ready(Some(())),
-            pending_refresh: Task::ready(Some(())),
-            completions: Default::default(),
-            active_completion_index: 0,
-            cycled: false,
-            suggestion: None,
-        }
-    }
-}
+//         let settings = settings::get::<EditorSettings>(cx);
+//         let show_completion_documentation = settings.show_completion_documentation;
 
-impl CopilotState {
-    fn active_completion(&self) -> Option<&copilot::Completion> {
-        self.completions.get(self.active_completion_index)
-    }
+//         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 text_for_active_completion(
-        &self,
-        cursor: Anchor,
-        buffer: &MultiBufferSnapshot,
-    ) -> Option<&str> {
-        use language::ToOffset as _;
+//                 len
+//             })
+//             .map(|(ix, _)| ix);
 
-        let completion = self.active_completion()?;
-        let excerpt_id = self.excerpt_id?;
-        let completion_buffer = buffer.buffer_for_excerpt(excerpt_id)?;
-        if excerpt_id != cursor.excerpt_id
-            || !completion.range.start.is_valid(completion_buffer)
-            || !completion.range.end.is_valid(completion_buffer)
-        {
-            return None;
-        }
+//         let completions = self.completions.clone();
+//         let matches = self.matches.clone();
+//         let selected_item = self.selected_item;
 
-        let mut completion_range = completion.range.to_offset(&completion_buffer);
-        let prefix_len = Self::common_prefix(
-            completion_buffer.chars_for_range(completion_range.clone()),
-            completion.text.chars(),
-        );
-        completion_range.start += prefix_len;
-        let suffix_len = Self::common_prefix(
-            completion_buffer.reversed_chars_for_range(completion_range.clone()),
-            completion.text[prefix_len..].chars().rev(),
-        );
-        completion_range.end = completion_range.end.saturating_sub(suffix_len);
+//         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();
 
-        if completion_range.is_empty()
-            && completion_range.start == cursor.text_anchor.to_offset(&completion_buffer)
-        {
-            Some(&completion.text[prefix_len..completion.text.len() - suffix_len])
-        } else {
-            None
-        }
-    }
+//                 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];
 
-    fn cycle_completions(&mut self, direction: Direction) {
-        match direction {
-            Direction::Prev => {
-                self.active_completion_index = if self.active_completion_index == 0 {
-                    self.completions.len().saturating_sub(1)
-                } else {
-                    self.active_completion_index - 1
+//                     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()
+//     }
+
+//     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()
+//         };
+
+//         // 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,
+    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()
+//     }
+
+//     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_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 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();
+
+//         if self.deployed_from_indicator {
+//             *cursor_position.column_mut() = 0;
+//         }
+
+//         (cursor_position, element)
+//     }
+// }
+
+pub struct CopilotState {
+    excerpt_id: Option<ExcerptId>,
+    pending_refresh: Task<Option<()>>,
+    pending_cycling_refresh: Task<Option<()>>,
+    cycled: bool,
+    completions: Vec<copilot::Completion>,
+    active_completion_index: usize,
+    suggestion: Option<Inlay>,
+}
+
+impl Default for CopilotState {
+    fn default() -> Self {
+        Self {
+            excerpt_id: None,
+            pending_cycling_refresh: Task::ready(Some(())),
+            pending_refresh: Task::ready(Some(())),
+            completions: Default::default(),
+            active_completion_index: 0,
+            cycled: false,
+            suggestion: None,
+        }
+    }
+}
+
+impl CopilotState {
+    fn active_completion(&self) -> Option<&copilot::Completion> {
+        self.completions.get(self.active_completion_index)
+    }
+
+    fn text_for_active_completion(
+        &self,
+        cursor: Anchor,
+        buffer: &MultiBufferSnapshot,
+    ) -> Option<&str> {
+        use language::ToOffset as _;
+
+        let completion = self.active_completion()?;
+        let excerpt_id = self.excerpt_id?;
+        let completion_buffer = buffer.buffer_for_excerpt(excerpt_id)?;
+        if excerpt_id != cursor.excerpt_id
+            || !completion.range.start.is_valid(completion_buffer)
+            || !completion.range.end.is_valid(completion_buffer)
+        {
+            return None;
+        }
+
+        let mut completion_range = completion.range.to_offset(&completion_buffer);
+        let prefix_len = Self::common_prefix(
+            completion_buffer.chars_for_range(completion_range.clone()),
+            completion.text.chars(),
+        );
+        completion_range.start += prefix_len;
+        let suffix_len = Self::common_prefix(
+            completion_buffer.reversed_chars_for_range(completion_range.clone()),
+            completion.text[prefix_len..].chars().rev(),
+        );
+        completion_range.end = completion_range.end.saturating_sub(suffix_len);
+
+        if completion_range.is_empty()
+            && completion_range.start == cursor.text_anchor.to_offset(&completion_buffer)
+        {
+            Some(&completion.text[prefix_len..completion.text.len() - suffix_len])
+        } else {
+            None
+        }
+    }
+
+    fn cycle_completions(&mut self, direction: Direction) {
+        match direction {
+            Direction::Prev => {
+                self.active_completion_index = if self.active_completion_index == 0 {
+                    self.completions.len().saturating_sub(1)
+                } else {
+                    self.active_completion_index - 1
                 };
             }
             Direction::Next => {

crates/editor2/src/editor_settings.rs ๐Ÿ”—

@@ -1,6 +1,6 @@
-use gpui::Settings;
 use schemars::JsonSchema;
 use serde::{Deserialize, Serialize};
+use settings::Settings;
 
 #[derive(Deserialize)]
 pub struct EditorSettings {
@@ -55,7 +55,7 @@ impl Settings for EditorSettings {
     fn load(
         default_value: &Self::FileContent,
         user_values: &[&Self::FileContent],
-        _: &gpui::AppContext,
+        _: &mut gpui::AppContext,
     ) -> anyhow::Result<Self> {
         Self::load_via_json_merge(default_value, user_values)
     }

crates/editor2/src/element.rs ๐Ÿ”—

@@ -3,9 +3,11 @@ use super::{
 };
 use crate::{
     display_map::{BlockStyle, DisplaySnapshot},
-    mouse_context_menu, EditorSettings, EditorStyle, GutterHover, UnfoldAt,
+    EditorStyle,
+};
+use gpui::{
+    px, relative, AnyElement, Bounds, Element, Hsla, Line, Pixels, Size, Style, TextRun, TextSystem,
 };
-use gpui::{AnyElement, Bounds, Element, Hsla, Line, Pixels, Size, Style, TextRun, TextSystem};
 use language::{CursorShape, Selection};
 use std::{ops::Range, sync::Arc};
 use sum_tree::Bias;
@@ -1997,7 +1999,10 @@ impl Element<Editor> for EditorElement {
         element_state: &mut Self::ElementState,
         cx: &mut gpui::ViewContext<Editor>,
     ) -> gpui::LayoutId {
-        cx.request_layout(Style::default().size_full(), None)
+        let mut style = Style::default();
+        style.size.width = relative(1.).into();
+        style.size.height = relative(1.).into();
+        cx.request_layout(&style, None)
     }
 
     fn paint(
@@ -2011,13 +2016,8 @@ impl Element<Editor> for EditorElement {
 
         let layout_text = cx.text_system().layout_text(
             "hello world",
-            text_style.font_size,
-            &[TextRun {
-                len: "hello world".len(),
-                font: text_style.font,
-                color: text_style.color,
-                underline: text_style.underline,
-            }],
+            text_style.font_size * cx.rem_size(),
+            &[text_style.to_run("hello world".len())],
             None,
         );
     }
@@ -2697,19 +2697,19 @@ impl PositionMap {
         position: gpui::Point<Pixels>,
     ) -> PointForPosition {
         let scroll_position = self.snapshot.scroll_position();
-        let position = position - text_bounds.origin();
-        let y = position.y().max(0.0).min(self.size.y());
-        let x = position.x() + (scroll_position.x() * self.em_width);
-        let row = (y / self.line_height + scroll_position.y()) as u32;
+        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 (column, x_overshoot_after_line_end) = if let Some(line) = self
             .line_layouts
-            .get(row as usize - scroll_position.y() as usize)
+            .get(row as usize - scroll_position.y.into())
             .map(|line_with_spaces| &line_with_spaces.line)
         {
             if let Some(ix) = line.index_for_x(x) {
                 (ix as u32, 0.0)
             } else {
-                (line.len() as u32, 0f32.max(x - line.width()))
+                (line.len() as u32, px(0.).max(x - line.width()))
             }
         } else {
             (0, x)

crates/editor2/src/hover_popover.rs ๐Ÿ”—

@@ -466,35 +466,35 @@ pub struct InfoPopover {
     parsed_content: ParsedMarkdown,
 }
 
-impl InfoPopover {
-    pub fn render(
-        &mut self,
-        style: &EditorStyle,
-        workspace: Option<WeakView<Workspace>>,
-        cx: &mut ViewContext<Editor>,
-    ) -> AnyElement<Editor> {
-        MouseEventHandler::new::<InfoPopover, _>(0, cx, |_, cx| {
-            Flex::column()
-                .scrollable::<HoverBlock>(0, None, cx)
-                .with_child(crate::render_parsed_markdown::<HoverBlock>(
-                    &self.parsed_content,
-                    style,
-                    workspace,
-                    cx,
-                ))
-                .contained()
-                .with_style(style.hover_popover.container)
-        })
-        .on_move(|_, _, _| {}) // Consume move events so they don't reach regions underneath.
-        .with_cursor_style(CursorStyle::Arrow)
-        .with_padding(Padding {
-            bottom: HOVER_POPOVER_GAP,
-            top: HOVER_POPOVER_GAP,
-            ..Default::default()
-        })
-        .into_any()
-    }
-}
+// impl InfoPopover {
+//     pub fn render(
+//         &mut self,
+//         style: &EditorStyle,
+//         workspace: Option<WeakView<Workspace>>,
+//         cx: &mut ViewContext<Editor>,
+//     ) -> AnyElement<Editor> {
+//         MouseEventHandler::new::<InfoPopover, _>(0, cx, |_, cx| {
+//             Flex::column()
+//                 .scrollable::<HoverBlock>(0, None, cx)
+//                 .with_child(crate::render_parsed_markdown::<HoverBlock>(
+//                     &self.parsed_content,
+//                     style,
+//                     workspace,
+//                     cx,
+//                 ))
+//                 .contained()
+//                 .with_style(style.hover_popover.container)
+//         })
+//         .on_move(|_, _, _| {}) // Consume move events so they don't reach regions underneath.
+//         .with_cursor_style(CursorStyle::Arrow)
+//         .with_padding(Padding {
+//             bottom: HOVER_POPOVER_GAP,
+//             top: HOVER_POPOVER_GAP,
+//             ..Default::default()
+//         })
+//         .into_any()
+//     }
+// }
 
 #[derive(Debug, Clone)]
 pub struct DiagnosticPopover {

crates/editor2/src/inlay_hint_cache.rs ๐Ÿ”—

@@ -521,7 +521,7 @@ impl InlayHintCache {
         buffer_id: u64,
         excerpt_id: ExcerptId,
         id: InlayId,
-        cx: &mut ViewContext<'_, '_, Editor>,
+        cx: &mut ViewContext<'_, Editor>,
     ) {
         if let Some(excerpt_hints) = self.hints.get(&excerpt_id) {
             let mut guard = excerpt_hints.write();
@@ -582,7 +582,7 @@ fn spawn_new_update_tasks(
     excerpts_to_query: HashMap<ExcerptId, (Model<Buffer>, Global, Range<usize>)>,
     invalidate: InvalidationStrategy,
     update_cache_version: usize,
-    cx: &mut ViewContext<'_, '_, Editor>,
+    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
@@ -760,7 +760,7 @@ fn new_update_task(
     visible_hints: Arc<Vec<Inlay>>,
     cached_excerpt_hints: Option<Arc<RwLock<CachedExcerptHints>>>,
     lsp_request_limiter: Arc<Semaphore>,
-    cx: &mut ViewContext<'_, '_, Editor>,
+    cx: &mut ViewContext<'_, Editor>,
 ) -> Task<()> {
     cx.spawn(|editor, mut cx| async move {
         let closure_cx = cx.clone();
@@ -836,134 +836,134 @@ fn new_update_task(
     })
 }
 
-async fn fetch_and_update_hints(
-    editor: gpui::WeakView<Editor>,
-    multi_buffer_snapshot: MultiBufferSnapshot,
-    buffer_snapshot: BufferSnapshot,
-    visible_hints: Arc<Vec<Inlay>>,
-    cached_excerpt_hints: Option<Arc<RwLock<CachedExcerptHints>>>,
-    query: ExcerptQuery,
-    invalidate: bool,
-    fetch_range: Range<language::Anchor>,
-    lsp_request_limiter: Arc<Semaphore>,
-    mut cx: gpui::AsyncAppContext,
-) -> anyhow::Result<()> {
-    let (lsp_request_guard, got_throttled) = if query.invalidate.should_invalidate() {
-        (None, false)
-    } else {
-        match lsp_request_limiter.try_acquire() {
-            Some(guard) => (Some(guard), false),
-            None => (Some(lsp_request_limiter.acquire().await), true),
-        }
-    };
-    let fetch_range_to_log =
-        fetch_range.start.to_point(&buffer_snapshot)..fetch_range.end.to_point(&buffer_snapshot);
-    let inlay_hints_fetch_task = editor
-        .update(&mut cx, |editor, cx| {
-            if got_throttled {
-                let query_not_around_visible_range = match editor.excerpt_visible_offsets(None, cx).remove(&query.excerpt_id) {
-                    Some((_, _, current_visible_range)) => {
-                        let visible_offset_length = current_visible_range.len();
-                        let double_visible_range = current_visible_range
-                            .start
-                            .saturating_sub(visible_offset_length)
-                            ..current_visible_range
-                                .end
-                                .saturating_add(visible_offset_length)
-                                .min(buffer_snapshot.len());
-                        !double_visible_range
-                            .contains(&fetch_range.start.to_offset(&buffer_snapshot))
-                            && !double_visible_range
-                                .contains(&fetch_range.end.to_offset(&buffer_snapshot))
-                    },
-                    None => true,
-                };
-                if query_not_around_visible_range {
-                    log::trace!("Fetching inlay hints for range {fetch_range_to_log:?} got throttled and fell off the current visible range, skipping.");
-                    if let Some(task_ranges) = editor
-                        .inlay_hint_cache
-                        .update_tasks
-                        .get_mut(&query.excerpt_id)
-                    {
-                        task_ranges.invalidate_range(&buffer_snapshot, &fetch_range);
-                    }
-                    return None;
-                }
-            }
-            editor
-                .buffer()
-                .read(cx)
-                .buffer(query.buffer_id)
-                .and_then(|buffer| {
-                    let project = editor.project.as_ref()?;
-                    Some(project.update(cx, |project, cx| {
-                        project.inlay_hints(buffer, fetch_range.clone(), cx)
-                    }))
-                })
-        })
-        .ok()
-        .flatten();
-    let new_hints = match inlay_hints_fetch_task {
-        Some(fetch_task) => {
-            log::debug!(
-                "Fetching inlay hints for range {fetch_range_to_log:?}, reason: {query_reason}, invalidate: {invalidate}",
-                query_reason = query.reason,
-            );
-            log::trace!(
-                "Currently visible hints: {visible_hints:?}, cached hints present: {}",
-                cached_excerpt_hints.is_some(),
-            );
-            fetch_task.await.context("inlay hint fetch task")?
-        }
-        None => return Ok(()),
-    };
-    drop(lsp_request_guard);
-    log::debug!(
-        "Fetched {} hints for range {fetch_range_to_log:?}",
-        new_hints.len()
-    );
-    log::trace!("Fetched hints: {new_hints:?}");
-
-    let background_task_buffer_snapshot = buffer_snapshot.clone();
-    let backround_fetch_range = fetch_range.clone();
-    let new_update = cx
-        .background()
-        .spawn(async move {
-            calculate_hint_updates(
-                query.excerpt_id,
-                invalidate,
-                backround_fetch_range,
-                new_hints,
-                &background_task_buffer_snapshot,
-                cached_excerpt_hints,
-                &visible_hints,
-            )
-        })
-        .await;
-    if let Some(new_update) = new_update {
-        log::debug!(
-            "Applying update for range {fetch_range_to_log:?}: remove from editor: {}, remove from cache: {}, add to cache: {}",
-            new_update.remove_from_visible.len(),
-            new_update.remove_from_cache.len(),
-            new_update.add_to_cache.len()
-        );
-        log::trace!("New update: {new_update:?}");
-        editor
-            .update(&mut cx, |editor, cx| {
-                apply_hint_update(
-                    editor,
-                    new_update,
-                    query,
-                    invalidate,
-                    buffer_snapshot,
-                    multi_buffer_snapshot,
-                    cx,
-                );
-            })
-            .ok();
-    }
-    Ok(())
-}
+// async fn fetch_and_update_hints(
+//     editor: gpui::WeakView<Editor>,
+//     multi_buffer_snapshot: MultiBufferSnapshot,
+//     buffer_snapshot: BufferSnapshot,
+//     visible_hints: Arc<Vec<Inlay>>,
+//     cached_excerpt_hints: Option<Arc<RwLock<CachedExcerptHints>>>,
+//     query: ExcerptQuery,
+//     invalidate: bool,
+//     fetch_range: Range<language::Anchor>,
+//     lsp_request_limiter: Arc<Semaphore>,
+//     mut cx: gpui::AsyncAppContext,
+// ) -> anyhow::Result<()> {
+//     let (lsp_request_guard, got_throttled) = if query.invalidate.should_invalidate() {
+//         (None, false)
+//     } else {
+//         match lsp_request_limiter.try_acquire() {
+//             Some(guard) => (Some(guard), false),
+//             None => (Some(lsp_request_limiter.acquire().await), true),
+//         }
+//     };
+//     let fetch_range_to_log =
+//         fetch_range.start.to_point(&buffer_snapshot)..fetch_range.end.to_point(&buffer_snapshot);
+//     let inlay_hints_fetch_task = editor
+//         .update(&mut cx, |editor, cx| {
+//             if got_throttled {
+//                 let query_not_around_visible_range = match editor.excerpt_visible_offsets(None, cx).remove(&query.excerpt_id) {
+//                     Some((_, _, current_visible_range)) => {
+//                         let visible_offset_length = current_visible_range.len();
+//                         let double_visible_range = current_visible_range
+//                             .start
+//                             .saturating_sub(visible_offset_length)
+//                             ..current_visible_range
+//                                 .end
+//                                 .saturating_add(visible_offset_length)
+//                                 .min(buffer_snapshot.len());
+//                         !double_visible_range
+//                             .contains(&fetch_range.start.to_offset(&buffer_snapshot))
+//                             && !double_visible_range
+//                                 .contains(&fetch_range.end.to_offset(&buffer_snapshot))
+//                     },
+//                     None => true,
+//                 };
+//                 if query_not_around_visible_range {
+//                     log::trace!("Fetching inlay hints for range {fetch_range_to_log:?} got throttled and fell off the current visible range, skipping.");
+//                     if let Some(task_ranges) = editor
+//                         .inlay_hint_cache
+//                         .update_tasks
+//                         .get_mut(&query.excerpt_id)
+//                     {
+//                         task_ranges.invalidate_range(&buffer_snapshot, &fetch_range);
+//                     }
+//                     return None;
+//                 }
+//             }
+//             editor
+//                 .buffer()
+//                 .read(cx)
+//                 .buffer(query.buffer_id)
+//                 .and_then(|buffer| {
+//                     let project = editor.project.as_ref()?;
+//                     Some(project.update(cx, |project, cx| {
+//                         project.inlay_hints(buffer, fetch_range.clone(), cx)
+//                     }))
+//                 })
+//         })
+//         .ok()
+//         .flatten();
+//     let new_hints = match inlay_hints_fetch_task {
+//         Some(fetch_task) => {
+//             log::debug!(
+//                 "Fetching inlay hints for range {fetch_range_to_log:?}, reason: {query_reason}, invalidate: {invalidate}",
+//                 query_reason = query.reason,
+//             );
+//             log::trace!(
+//                 "Currently visible hints: {visible_hints:?}, cached hints present: {}",
+//                 cached_excerpt_hints.is_some(),
+//             );
+//             fetch_task.await.context("inlay hint fetch task")?
+//         }
+//         None => return Ok(()),
+//     };
+//     drop(lsp_request_guard);
+//     log::debug!(
+//         "Fetched {} hints for range {fetch_range_to_log:?}",
+//         new_hints.len()
+//     );
+//     log::trace!("Fetched hints: {new_hints:?}");
+
+//     let background_task_buffer_snapshot = buffer_snapshot.clone();
+//     let backround_fetch_range = fetch_range.clone();
+//     let new_update = cx
+//         .background()
+//         .spawn(async move {
+//             calculate_hint_updates(
+//                 query.excerpt_id,
+//                 invalidate,
+//                 backround_fetch_range,
+//                 new_hints,
+//                 &background_task_buffer_snapshot,
+//                 cached_excerpt_hints,
+//                 &visible_hints,
+//             )
+//         })
+//         .await;
+//     if let Some(new_update) = new_update {
+//         log::debug!(
+//             "Applying update for range {fetch_range_to_log:?}: remove from editor: {}, remove from cache: {}, add to cache: {}",
+//             new_update.remove_from_visible.len(),
+//             new_update.remove_from_cache.len(),
+//             new_update.add_to_cache.len()
+//         );
+//         log::trace!("New update: {new_update:?}");
+//         editor
+//             .update(&mut cx, |editor, cx| {
+//                 apply_hint_update(
+//                     editor,
+//                     new_update,
+//                     query,
+//                     invalidate,
+//                     buffer_snapshot,
+//                     multi_buffer_snapshot,
+//                     cx,
+//                 );
+//             })
+//             .ok();
+//     }
+//     Ok(())
+// }
 
 fn calculate_hint_updates(
     excerpt_id: ExcerptId,
@@ -1071,7 +1071,7 @@ fn apply_hint_update(
     invalidate: bool,
     buffer_snapshot: BufferSnapshot,
     multi_buffer_snapshot: MultiBufferSnapshot,
-    cx: &mut ViewContext<'_, '_, Editor>,
+    cx: &mut ViewContext<'_, Editor>,
 ) {
     let cached_excerpt_hints = editor
         .inlay_hint_cache

crates/editor2/src/items.rs ๐Ÿ”—

@@ -7,8 +7,8 @@ use anyhow::{Context, Result};
 use collections::HashSet;
 use futures::future::try_join_all;
 use gpui::{
-    point, AnyElement, AppContext, AsyncAppContext, Entity, Model, Pixels, Subscription, Task,
-    View, ViewContext, WeakView,
+    point, AnyElement, AppContext, AsyncAppContext, Entity, Model, Pixels, SharedString,
+    Subscription, Task, View, ViewContext, WeakView,
 };
 use language::{
     proto::serialize_anchor as serialize_text_anchor, Bias, Buffer, OffsetRangeExt, Point,
@@ -304,133 +304,133 @@ 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<()> {
-    // Open all of the buffers of which excerpts were added to the editor.
-    let inserted_excerpt_buffer_ids = message
-        .inserted_excerpts
-        .iter()
-        .filter_map(|insertion| Some(insertion.excerpt.as_ref()?.buffer_id))
-        .collect::<HashSet<_>>();
-    let inserted_excerpt_buffers = project.update(cx, |project, cx| {
-        inserted_excerpt_buffer_ids
-            .into_iter()
-            .map(|id| project.open_buffer_by_id(id, cx))
-            .collect::<Vec<_>>()
-    });
-    let _inserted_excerpt_buffers = try_join_all(inserted_excerpt_buffers).await?;
-
-    // Update the editor's excerpts.
-    this.update(cx, |editor, cx| {
-        editor.buffer.update(cx, |multibuffer, cx| {
-            let mut removed_excerpt_ids = message
-                .deleted_excerpts
-                .into_iter()
-                .map(ExcerptId::from_proto)
-                .collect::<Vec<_>>();
-            removed_excerpt_ids.sort_by({
-                let multibuffer = multibuffer.read(cx);
-                move |a, b| a.cmp(&b, &multibuffer)
-            });
-
-            let mut insertions = message.inserted_excerpts.into_iter().peekable();
-            while let Some(insertion) = insertions.next() {
-                let Some(excerpt) = insertion.excerpt else {
-                    continue;
-                };
-                let Some(previous_excerpt_id) = insertion.previous_excerpt_id else {
-                    continue;
-                };
-                let buffer_id = excerpt.buffer_id;
-                let Some(buffer) = project.read(cx).buffer_for_id(buffer_id) else {
-                    continue;
-                };
-
-                let adjacent_excerpts = iter::from_fn(|| {
-                    let insertion = insertions.peek()?;
-                    if insertion.previous_excerpt_id.is_none()
-                        && insertion.excerpt.as_ref()?.buffer_id == buffer_id
-                    {
-                        insertions.next()?.excerpt
-                    } else {
-                        None
-                    }
-                });
-
-                multibuffer.insert_excerpts_with_ids_after(
-                    ExcerptId::from_proto(previous_excerpt_id),
-                    buffer,
-                    [excerpt]
-                        .into_iter()
-                        .chain(adjacent_excerpts)
-                        .filter_map(|excerpt| {
-                            Some((
-                                ExcerptId::from_proto(excerpt.id),
-                                deserialize_excerpt_range(excerpt)?,
-                            ))
-                        }),
-                    cx,
-                );
-            }
+// async fn update_editor_from_message(
+//     this: WeakView<Editor>,
+//     project: Model<Project>,
+//     message: proto::update_view::Editor,
+//     cx: &mut AsyncAppContext,
+// ) -> Result<()> {
+//     // Open all of the buffers of which excerpts were added to the editor.
+//     let inserted_excerpt_buffer_ids = message
+//         .inserted_excerpts
+//         .iter()
+//         .filter_map(|insertion| Some(insertion.excerpt.as_ref()?.buffer_id))
+//         .collect::<HashSet<_>>();
+//     let inserted_excerpt_buffers = project.update(cx, |project, cx| {
+//         inserted_excerpt_buffer_ids
+//             .into_iter()
+//             .map(|id| project.open_buffer_by_id(id, cx))
+//             .collect::<Vec<_>>()
+//     })?;
+//     let _inserted_excerpt_buffers = try_join_all(inserted_excerpt_buffers).await?;
+
+//     // Update the editor's excerpts.
+//     this.update(cx, |editor, cx| {
+//         editor.buffer.update(cx, |multibuffer, cx| {
+//             let mut removed_excerpt_ids = message
+//                 .deleted_excerpts
+//                 .into_iter()
+//                 .map(ExcerptId::from_proto)
+//                 .collect::<Vec<_>>();
+//             removed_excerpt_ids.sort_by({
+//                 let multibuffer = multibuffer.read(cx);
+//                 move |a, b| a.cmp(&b, &multibuffer)
+//             });
+
+//             let mut insertions = message.inserted_excerpts.into_iter().peekable();
+//             while let Some(insertion) = insertions.next() {
+//                 let Some(excerpt) = insertion.excerpt else {
+//                     continue;
+//                 };
+//                 let Some(previous_excerpt_id) = insertion.previous_excerpt_id else {
+//                     continue;
+//                 };
+//                 let buffer_id = excerpt.buffer_id;
+//                 let Some(buffer) = project.read(cx).buffer_for_id(buffer_id) else {
+//                     continue;
+//                 };
+
+//                 let adjacent_excerpts = iter::from_fn(|| {
+//                     let insertion = insertions.peek()?;
+//                     if insertion.previous_excerpt_id.is_none()
+//                         && insertion.excerpt.as_ref()?.buffer_id == buffer_id
+//                     {
+//                         insertions.next()?.excerpt
+//                     } else {
+//                         None
+//                     }
+//                 });
+
+//                 multibuffer.insert_excerpts_with_ids_after(
+//                     ExcerptId::from_proto(previous_excerpt_id),
+//                     buffer,
+//                     [excerpt]
+//                         .into_iter()
+//                         .chain(adjacent_excerpts)
+//                         .filter_map(|excerpt| {
+//                             Some((
+//                                 ExcerptId::from_proto(excerpt.id),
+//                                 deserialize_excerpt_range(excerpt)?,
+//                             ))
+//                         }),
+//                     cx,
+//                 );
+//             }
 
-            multibuffer.remove_excerpts(removed_excerpt_ids, cx);
-        });
-    })?;
-
-    // Deserialize the editor state.
-    let (selections, pending_selection, scroll_top_anchor) = this.update(cx, |editor, cx| {
-        let buffer = editor.buffer.read(cx).read(cx);
-        let selections = message
-            .selections
-            .into_iter()
-            .filter_map(|selection| deserialize_selection(&buffer, selection))
-            .collect::<Vec<_>>();
-        let pending_selection = message
-            .pending_selection
-            .and_then(|selection| deserialize_selection(&buffer, selection));
-        let scroll_top_anchor = message
-            .scroll_top_anchor
-            .and_then(|anchor| deserialize_anchor(&buffer, anchor));
-        anyhow::Ok((selections, pending_selection, scroll_top_anchor))
-    })??;
-
-    // Wait until the buffer has received all of the operations referenced by
-    // the editor's new state.
-    this.update(cx, |editor, cx| {
-        editor.buffer.update(cx, |buffer, cx| {
-            buffer.wait_for_anchors(
-                selections
-                    .iter()
-                    .chain(pending_selection.as_ref())
-                    .flat_map(|selection| [selection.start, selection.end])
-                    .chain(scroll_top_anchor),
-                cx,
-            )
-        })
-    })?
-    .await?;
-
-    // Update the editor's state.
-    this.update(cx, |editor, cx| {
-        if !selections.is_empty() || pending_selection.is_some() {
-            editor.set_selections_from_remote(selections, pending_selection, cx);
-            editor.request_autoscroll_remotely(Autoscroll::newest(), cx);
-        } else if let Some(scroll_top_anchor) = scroll_top_anchor {
-            editor.set_scroll_anchor_remote(
-                ScrollAnchor {
-                    anchor: scroll_top_anchor,
-                    offset: point(message.scroll_x, message.scroll_y),
-                },
-                cx,
-            );
-        }
-    })?;
-    Ok(())
-}
+//             multibuffer.remove_excerpts(removed_excerpt_ids, cx);
+//         });
+//     })?;
+
+//     // Deserialize the editor state.
+//     let (selections, pending_selection, scroll_top_anchor) = this.update(cx, |editor, cx| {
+//         let buffer = editor.buffer.read(cx).read(cx);
+//         let selections = message
+//             .selections
+//             .into_iter()
+//             .filter_map(|selection| deserialize_selection(&buffer, selection))
+//             .collect::<Vec<_>>();
+//         let pending_selection = message
+//             .pending_selection
+//             .and_then(|selection| deserialize_selection(&buffer, selection));
+//         let scroll_top_anchor = message
+//             .scroll_top_anchor
+//             .and_then(|anchor| deserialize_anchor(&buffer, anchor));
+//         anyhow::Ok((selections, pending_selection, scroll_top_anchor))
+//     })??;
+
+//     // Wait until the buffer has received all of the operations referenced by
+//     // the editor's new state.
+//     this.update(cx, |editor, cx| {
+//         editor.buffer.update(cx, |buffer, cx| {
+//             buffer.wait_for_anchors(
+//                 selections
+//                     .iter()
+//                     .chain(pending_selection.as_ref())
+//                     .flat_map(|selection| [selection.start, selection.end])
+//                     .chain(scroll_top_anchor),
+//                 cx,
+//             )
+//         })
+//     })?
+//     .await?;
+
+//     // Update the editor's state.
+//     this.update(cx, |editor, cx| {
+//         if !selections.is_empty() || pending_selection.is_some() {
+//             editor.set_selections_from_remote(selections, pending_selection, cx);
+//             editor.request_autoscroll_remotely(Autoscroll::newest(), cx);
+//         } else if let Some(scroll_top_anchor) = scroll_top_anchor {
+//             editor.set_scroll_anchor_remote(
+//                 ScrollAnchor {
+//                     anchor: scroll_top_anchor,
+//                     offset: point(message.scroll_x, message.scroll_y),
+//                 },
+//                 cx,
+//             );
+//         }
+//     })?;
+//     Ok(())
+// }
 
 fn serialize_excerpt(
     buffer_id: u64,
@@ -544,7 +544,7 @@ impl Item for Editor {
         }
     }
 
-    fn tab_tooltip_text(&self, cx: &AppContext) -> Option<Cow<str>> {
+    fn tab_tooltip_text(&self, cx: &AppContext) -> Option<SharedString> {
         let file_path = self
             .buffer()
             .read(cx)
@@ -559,7 +559,7 @@ impl Item for Editor {
         Some(file_path.into())
     }
 
-    fn tab_description<'a>(&'a self, detail: usize, cx: &'a AppContext) -> Option<Cow<str>> {
+    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()),
@@ -168,7 +168,7 @@ pub fn update_inlay_link_and_hover_points(
     editor: &mut Editor,
     cmd_held: bool,
     shift_held: bool,
-    cx: &mut ViewContext<'_, '_, Editor>,
+    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))

crates/editor2/src/scroll.rs ๐Ÿ”—

@@ -9,7 +9,7 @@ use crate::{
     Anchor, DisplayPoint, Editor, EditorMode, Event, InlayHintRefreshReason, MultiBufferSnapshot,
     ToPoint,
 };
-use gpui::{point, AppContext, Pixels, Task, ViewContext};
+use gpui::{point, px, AppContext, Pixels, Styled, Task, ViewContext};
 use language::{Bias, Point};
 use std::{
     cmp::Ordering,
@@ -44,7 +44,7 @@ impl ScrollAnchor {
         }
     }
 
-    pub fn scroll_position(&self, snapshot: &DisplaySnapshot) -> Point<Pixels> {
+    pub fn scroll_position(&self, snapshot: &DisplaySnapshot) -> gpui::Point<Pixels> {
         let mut scroll_position = self.offset;
         if self.anchor != Anchor::min() {
             let scroll_top = self.anchor.to_display_point(snapshot).row() as f32;
@@ -80,13 +80,13 @@ impl OngoingScroll {
         }
     }
 
-    pub fn filter(&self, delta: &mut Point<Pixels>) -> Option<Axis> {
+    pub fn filter(&self, delta: &mut gpui::Point<Pixels>) -> Option<Axis> {
         const UNLOCK_PERCENT: f32 = 1.9;
         const UNLOCK_LOWER_BOUND: f32 = 6.;
         let mut axis = self.axis;
 
-        let x = delta.x().abs();
-        let y = delta.y().abs();
+        let x = delta.x.abs();
+        let y = delta.y.abs();
         let duration = Instant::now().duration_since(self.last_event);
         if duration > SCROLL_EVENT_SEPARATION {
             //New ongoing scroll will start, determine axis
@@ -115,8 +115,12 @@ impl OngoingScroll {
         }
 
         match axis {
-            Some(Axis::Vertical) => *delta = point(0., delta.y()),
-            Some(Axis::Horizontal) => *delta = point(delta.x(), 0.),
+            Some(Axis::Vertical) => {
+                *delta = point(pk(0.), delta.y());
+            }
+            Some(Axis::Horizontal) => {
+                *delta = point(delta.x(), px(0.));
+            }
             None => {}
         }
 
@@ -167,13 +171,13 @@ impl ScrollManager {
         self.ongoing.axis = axis;
     }
 
-    pub fn scroll_position(&self, snapshot: &DisplaySnapshot) -> Point<Pixels> {
+    pub fn scroll_position(&self, snapshot: &DisplaySnapshot) -> gpui::Point<Pixels> {
         self.anchor.scroll_position(snapshot)
     }
 
     fn set_scroll_position(
         &mut self,
-        scroll_position: Point<Pixels>,
+        scroll_position: gpui::Point<Pixels>,
         map: &DisplaySnapshot,
         local: bool,
         autoscroll: bool,
@@ -282,160 +286,161 @@ impl ScrollManager {
     }
 }
 
-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: 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: 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>) -> 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);
-        }
-    }
-}
+// 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);
+//         }
+//     }
+// }

crates/editor2/src/selections_collection.rs ๐Ÿ”—

@@ -593,29 +593,30 @@ impl<'a> MutableSelectionsCollection<'a> {
     }
 
     pub fn select_anchor_ranges<I: IntoIterator<Item = Range<Anchor>>>(&mut self, ranges: I) {
-        let buffer = self.buffer.read(self.cx).snapshot(self.cx);
-        let selections = ranges
-            .into_iter()
-            .map(|range| {
-                let mut start = range.start;
-                let mut end = range.end;
-                let reversed = if start.cmp(&end, &buffer).is_gt() {
-                    mem::swap(&mut start, &mut end);
-                    true
-                } else {
-                    false
-                };
-                Selection {
-                    id: post_inc(&mut self.collection.next_selection_id),
-                    start,
-                    end,
-                    reversed,
-                    goal: SelectionGoal::None,
-                }
-            })
-            .collect::<Vec<_>>();
-
-        self.select_anchors(selections)
+        todo!()
+        // let buffer = self.buffer.read(self.cx).snapshot(self.cx);
+        // let selections = ranges
+        //     .into_iter()
+        //     .map(|range| {
+        //         let mut start = range.start;
+        //         let mut end = range.end;
+        //         let reversed = if start.cmp(&end, &buffer).is_gt() {
+        //             mem::swap(&mut start, &mut end);
+        //             true
+        //         } else {
+        //             false
+        //         };
+        //         Selection {
+        //             id: post_inc(&mut self.collection.next_selection_id),
+        //             start,
+        //             end,
+        //             reversed,
+        //             goal: SelectionGoal::None,
+        //         }
+        //     })
+        //     .collect::<Vec<_>>();
+
+        // self.select_anchors(selections)
     }
 
     pub fn new_selection_id(&mut self) -> usize {

crates/editor2/src/test.rs ๐Ÿ”—

@@ -1,80 +1,81 @@
 pub mod editor_lsp_test_context;
 pub mod editor_test_context;
 
-use crate::{
-    display_map::{DisplayMap, DisplaySnapshot, ToDisplayPoint},
-    DisplayPoint, Editor, EditorMode, MultiBuffer,
-};
+// todo!()
+// use crate::{
+//     display_map::{DisplayMap, DisplaySnapshot, ToDisplayPoint},
+//     DisplayPoint, Editor, EditorMode, MultiBuffer,
+// };
 
-use gpui::{Model, ViewContext};
+// use gpui::{Model, ViewContext};
 
-use project::Project;
-use util::test::{marked_text_offsets, marked_text_ranges};
+// use project::Project;
+// use util::test::{marked_text_offsets, marked_text_ranges};
 
-#[cfg(test)]
-#[ctor::ctor]
-fn init_logger() {
-    if std::env::var("RUST_LOG").is_ok() {
-        env_logger::init();
-    }
-}
+// #[cfg(test)]
+// #[ctor::ctor]
+// fn init_logger() {
+//     if std::env::var("RUST_LOG").is_ok() {
+//         env_logger::init();
+//     }
+// }
 
-// Returns a snapshot from text containing '|' character markers with the markers removed, and DisplayPoints for each one.
-pub fn marked_display_snapshot(
-    text: &str,
-    cx: &mut gpui::AppContext,
-) -> (DisplaySnapshot, Vec<DisplayPoint>) {
-    let (unmarked_text, markers) = marked_text_offsets(text);
+// // Returns a snapshot from text containing '|' character markers with the markers removed, and DisplayPoints for each one.
+// pub fn marked_display_snapshot(
+//     text: &str,
+//     cx: &mut gpui::AppContext,
+// ) -> (DisplaySnapshot, Vec<DisplayPoint>) {
+//     let (unmarked_text, markers) = marked_text_offsets(text);
 
-    let family_id = cx
-        .font_cache()
-        .load_family(&["Helvetica"], &Default::default())
-        .unwrap();
-    let font_id = cx
-        .font_cache()
-        .select_font(family_id, &Default::default())
-        .unwrap();
-    let font_size = 14.0;
+//     let family_id = cx
+//         .font_cache()
+//         .load_family(&["Helvetica"], &Default::default())
+//         .unwrap();
+//     let font_id = cx
+//         .font_cache()
+//         .select_font(family_id, &Default::default())
+//         .unwrap();
+//     let font_size = 14.0;
 
-    let buffer = MultiBuffer::build_simple(&unmarked_text, cx);
-    let display_map =
-        cx.add_model(|cx| DisplayMap::new(buffer, font_id, font_size, None, 1, 1, cx));
-    let snapshot = display_map.update(cx, |map, cx| map.snapshot(cx));
-    let markers = markers
-        .into_iter()
-        .map(|offset| offset.to_display_point(&snapshot))
-        .collect();
+//     let buffer = MultiBuffer::build_simple(&unmarked_text, cx);
+//     let display_map =
+//         cx.add_model(|cx| DisplayMap::new(buffer, font_id, font_size, None, 1, 1, cx));
+//     let snapshot = display_map.update(cx, |map, cx| map.snapshot(cx));
+//     let markers = markers
+//         .into_iter()
+//         .map(|offset| offset.to_display_point(&snapshot))
+//         .collect();
 
-    (snapshot, markers)
-}
+//     (snapshot, markers)
+// }
 
-pub fn select_ranges(editor: &mut Editor, marked_text: &str, cx: &mut ViewContext<Editor>) {
-    let (unmarked_text, text_ranges) = marked_text_ranges(marked_text, true);
-    assert_eq!(editor.text(cx), unmarked_text);
-    editor.change_selections(None, cx, |s| s.select_ranges(text_ranges));
-}
+// pub fn select_ranges(editor: &mut Editor, marked_text: &str, cx: &mut ViewContext<Editor>) {
+//     let (unmarked_text, text_ranges) = marked_text_ranges(marked_text, true);
+//     assert_eq!(editor.text(cx), unmarked_text);
+//     editor.change_selections(None, cx, |s| s.select_ranges(text_ranges));
+// }
 
-pub fn assert_text_with_selections(
-    editor: &mut Editor,
-    marked_text: &str,
-    cx: &mut ViewContext<Editor>,
-) {
-    let (unmarked_text, text_ranges) = marked_text_ranges(marked_text, true);
-    assert_eq!(editor.text(cx), unmarked_text);
-    assert_eq!(editor.selections.ranges(cx), text_ranges);
-}
+// pub fn assert_text_with_selections(
+//     editor: &mut Editor,
+//     marked_text: &str,
+//     cx: &mut ViewContext<Editor>,
+// ) {
+//     let (unmarked_text, text_ranges) = marked_text_ranges(marked_text, true);
+//     assert_eq!(editor.text(cx), unmarked_text);
+//     assert_eq!(editor.selections.ranges(cx), text_ranges);
+// }
 
-// RA thinks this is dead code even though it is used in a whole lot of tests
-#[allow(dead_code)]
-#[cfg(any(test, feature = "test-support"))]
-pub(crate) fn build_editor(buffer: Model<MultiBuffer>, cx: &mut ViewContext<Editor>) -> Editor {
-    Editor::new(EditorMode::Full, buffer, None, None, cx)
-}
+// // RA thinks this is dead code even though it is used in a whole lot of tests
+// #[allow(dead_code)]
+// #[cfg(any(test, feature = "test-support"))]
+// pub(crate) fn build_editor(buffer: Model<MultiBuffer>, cx: &mut ViewContext<Editor>) -> Editor {
+//     Editor::new(EditorMode::Full, buffer, None, None, cx)
+// }
 
-pub(crate) fn build_editor_with_project(
-    project: Model<Project>,
-    buffer: Model<MultiBuffer>,
-    cx: &mut ViewContext<Editor>,
-) -> Editor {
-    Editor::new(EditorMode::Full, buffer, Some(project), None, cx)
-}
+// pub(crate) fn build_editor_with_project(
+//     project: Model<Project>,
+//     buffer: Model<MultiBuffer>,
+//     cx: &mut ViewContext<Editor>,
+// ) -> Editor {
+//     Editor::new(EditorMode::Full, buffer, Some(project), None, cx)
+// }

crates/editor2/src/test/editor_test_context.rs ๐Ÿ”—

@@ -17,304 +17,304 @@ use util::{
     test::{generate_marked_text, marked_text_ranges},
 };
 
-use super::build_editor_with_project;
-
-pub struct EditorTestContext<'a> {
-    pub cx: &'a mut gpui::TestAppContext,
-    pub window: AnyWindowHandle,
-    pub editor: View<Editor>,
-}
-
-impl<'a> EditorTestContext<'a> {
-    pub async fn new(cx: &'a mut gpui::TestAppContext) -> EditorTestContext<'a> {
-        let fs = FakeFs::new(cx.background());
-        // fs.insert_file("/file", "".to_owned()).await;
-        fs.insert_tree(
-            "/root",
-            gpui::serde_json::json!({
-                "file": "",
-            }),
-        )
-        .await;
-        let project = Project::test(fs, ["/root".as_ref()], cx).await;
-        let buffer = project
-            .update(cx, |project, cx| {
-                project.open_local_buffer("/root/file", cx)
-            })
-            .await
-            .unwrap();
-        let window = cx.add_window(|cx| {
-            cx.focus_self();
-            build_editor_with_project(project, MultiBuffer::build_from_buffer(buffer, cx), cx)
-        });
-        let editor = window.root(cx);
-        Self {
-            cx,
-            window: window.into(),
-            editor,
-        }
-    }
-
-    pub fn condition(
-        &self,
-        predicate: impl FnMut(&Editor, &AppContext) -> bool,
-    ) -> impl Future<Output = ()> {
-        self.editor.condition(self.cx, predicate)
-    }
-
-    pub fn editor<F, T>(&self, read: F) -> T
-    where
-        F: FnOnce(&Editor, &ViewContext<Editor>) -> T,
-    {
-        self.editor.read_with(self.cx, read)
-    }
-
-    pub fn update_editor<F, T>(&mut self, update: F) -> T
-    where
-        F: FnOnce(&mut Editor, &mut ViewContext<Editor>) -> T,
-    {
-        self.editor.update(self.cx, update)
-    }
-
-    pub fn multibuffer<F, T>(&self, read: F) -> T
-    where
-        F: FnOnce(&MultiBuffer, &AppContext) -> T,
-    {
-        self.editor(|editor, cx| read(editor.buffer().read(cx), cx))
-    }
-
-    pub fn update_multibuffer<F, T>(&mut self, update: F) -> T
-    where
-        F: FnOnce(&mut MultiBuffer, &mut ModelContext<MultiBuffer>) -> T,
-    {
-        self.update_editor(|editor, cx| editor.buffer().update(cx, update))
-    }
-
-    pub fn buffer_text(&self) -> String {
-        self.multibuffer(|buffer, cx| buffer.snapshot(cx).text())
-    }
-
-    pub fn buffer<F, T>(&self, read: F) -> T
-    where
-        F: FnOnce(&Buffer, &AppContext) -> T,
-    {
-        self.multibuffer(|multibuffer, cx| {
-            let buffer = multibuffer.as_singleton().unwrap().read(cx);
-            read(buffer, cx)
-        })
-    }
-
-    pub fn update_buffer<F, T>(&mut self, update: F) -> T
-    where
-        F: FnOnce(&mut Buffer, &mut ModelContext<Buffer>) -> T,
-    {
-        self.update_multibuffer(|multibuffer, cx| {
-            let buffer = multibuffer.as_singleton().unwrap();
-            buffer.update(cx, update)
-        })
-    }
-
-    pub fn buffer_snapshot(&self) -> BufferSnapshot {
-        self.buffer(|buffer, _| buffer.snapshot())
-    }
-
-    // pub fn simulate_keystroke(&mut self, keystroke_text: &str) -> ContextHandle {
-    //     let keystroke_under_test_handle =
-    //         self.add_assertion_context(format!("Simulated Keystroke: {:?}", keystroke_text));
-    //     let keystroke = Keystroke::parse(keystroke_text).unwrap();
-
-    //     self.cx.dispatch_keystroke(self.window, keystroke, false);
-
-    //     keystroke_under_test_handle
-    // }
-
-    // pub fn simulate_keystrokes<const COUNT: usize>(
-    //     &mut self,
-    //     keystroke_texts: [&str; COUNT],
-    // ) -> ContextHandle {
-    //     let keystrokes_under_test_handle =
-    //         self.add_assertion_context(format!("Simulated Keystrokes: {:?}", keystroke_texts));
-    //     for keystroke_text in keystroke_texts.into_iter() {
-    //         self.simulate_keystroke(keystroke_text);
-    //     }
-    //     // it is common for keyboard shortcuts to kick off async actions, so this ensures that they are complete
-    //     // before returning.
-    //     // NOTE: we don't do this in simulate_keystroke() because a possible cause of bugs is that typing too
-    //     // quickly races with async actions.
-    //     if let Foreground::Deterministic { cx_id: _, executor } = self.cx.foreground().as_ref() {
-    //         executor.run_until_parked();
-    //     } else {
-    //         unreachable!();
-    //     }
-
-    //     keystrokes_under_test_handle
-    // }
-
-    pub fn ranges(&self, marked_text: &str) -> Vec<Range<usize>> {
-        let (unmarked_text, ranges) = marked_text_ranges(marked_text, false);
-        assert_eq!(self.buffer_text(), unmarked_text);
-        ranges
-    }
-
-    pub fn display_point(&mut self, marked_text: &str) -> DisplayPoint {
-        let ranges = self.ranges(marked_text);
-        let snapshot = self
-            .editor
-            .update(self.cx, |editor, cx| editor.snapshot(cx));
-        ranges[0].start.to_display_point(&snapshot)
-    }
-
-    // Returns anchors for the current buffer using `ยซ` and `ยป`
-    pub fn text_anchor_range(&self, marked_text: &str) -> Range<language::Anchor> {
-        let ranges = self.ranges(marked_text);
-        let snapshot = self.buffer_snapshot();
-        snapshot.anchor_before(ranges[0].start)..snapshot.anchor_after(ranges[0].end)
-    }
-
-    pub fn set_diff_base(&mut self, diff_base: Option<&str>) {
-        let diff_base = diff_base.map(String::from);
-        self.update_buffer(|buffer, cx| buffer.set_diff_base(diff_base, cx));
-    }
-
-    // /// Change the editor's text and selections using a string containing
-    // /// embedded range markers that represent the ranges and directions of
-    // /// each selection.
-    // ///
-    // /// Returns a context handle so that assertion failures can print what
-    // /// editor state was needed to cause the failure.
-    // ///
-    // /// See the `util::test::marked_text_ranges` function for more information.
-    // pub fn set_state(&mut self, marked_text: &str) -> ContextHandle {
-    //     let state_context = self.add_assertion_context(format!(
-    //         "Initial Editor State: \"{}\"",
-    //         marked_text.escape_debug().to_string()
-    //     ));
-    //     let (unmarked_text, selection_ranges) = marked_text_ranges(marked_text, true);
-    //     self.editor.update(self.cx, |editor, cx| {
-    //         editor.set_text(unmarked_text, cx);
-    //         editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
-    //             s.select_ranges(selection_ranges)
-    //         })
-    //     });
-    //     state_context
-    // }
-
-    // /// Only change the editor's selections
-    // pub fn set_selections_state(&mut self, marked_text: &str) -> ContextHandle {
-    //     let state_context = self.add_assertion_context(format!(
-    //         "Initial Editor State: \"{}\"",
-    //         marked_text.escape_debug().to_string()
-    //     ));
-    //     let (unmarked_text, selection_ranges) = marked_text_ranges(marked_text, true);
-    //     self.editor.update(self.cx, |editor, cx| {
-    //         assert_eq!(editor.text(cx), unmarked_text);
-    //         editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
-    //             s.select_ranges(selection_ranges)
-    //         })
-    //     });
-    //     state_context
-    // }
-
-    // /// Make an assertion about the editor's text and the ranges and directions
-    // /// of its selections using a string containing embedded range markers.
-    // ///
-    // /// See the `util::test::marked_text_ranges` function for more information.
-    // #[track_caller]
-    // pub fn assert_editor_state(&mut self, marked_text: &str) {
-    //     let (unmarked_text, expected_selections) = marked_text_ranges(marked_text, true);
-    //     let buffer_text = self.buffer_text();
-
-    //     if buffer_text != unmarked_text {
-    //         panic!("Unmarked text doesn't match buffer text\nBuffer text: {buffer_text:?}\nUnmarked text: {unmarked_text:?}\nRaw buffer text\n{buffer_text}Raw unmarked text\n{unmarked_text}");
-    //     }
-
-    //     self.assert_selections(expected_selections, marked_text.to_string())
-    // }
-
-    // pub fn editor_state(&mut self) -> String {
-    //     generate_marked_text(self.buffer_text().as_str(), &self.editor_selections(), true)
-    // }
-
-    // #[track_caller]
-    // pub fn assert_editor_background_highlights<Tag: 'static>(&mut self, marked_text: &str) {
-    //     let expected_ranges = self.ranges(marked_text);
-    //     let actual_ranges: Vec<Range<usize>> = self.update_editor(|editor, cx| {
-    //         let snapshot = editor.snapshot(cx);
-    //         editor
-    //             .background_highlights
-    //             .get(&TypeId::of::<Tag>())
-    //             .map(|h| h.1.clone())
-    //             .unwrap_or_default()
-    //             .into_iter()
-    //             .map(|range| range.to_offset(&snapshot.buffer_snapshot))
-    //             .collect()
-    //     });
-    //     assert_set_eq!(actual_ranges, expected_ranges);
-    // }
-
-    // #[track_caller]
-    // pub fn assert_editor_text_highlights<Tag: ?Sized + 'static>(&mut self, marked_text: &str) {
-    //     let expected_ranges = self.ranges(marked_text);
-    //     let snapshot = self.update_editor(|editor, cx| editor.snapshot(cx));
-    //     let actual_ranges: Vec<Range<usize>> = snapshot
-    //         .text_highlight_ranges::<Tag>()
-    //         .map(|ranges| ranges.as_ref().clone().1)
-    //         .unwrap_or_default()
-    //         .into_iter()
-    //         .map(|range| range.to_offset(&snapshot.buffer_snapshot))
-    //         .collect();
-    //     assert_set_eq!(actual_ranges, expected_ranges);
-    // }
-
-    // #[track_caller]
-    // pub fn assert_editor_selections(&mut self, expected_selections: Vec<Range<usize>>) {
-    //     let expected_marked_text =
-    //         generate_marked_text(&self.buffer_text(), &expected_selections, true);
-    //     self.assert_selections(expected_selections, expected_marked_text)
-    // }
-
-    // fn editor_selections(&self) -> Vec<Range<usize>> {
-    //     self.editor
-    //         .read_with(self.cx, |editor, cx| editor.selections.all::<usize>(cx))
-    //         .into_iter()
-    //         .map(|s| {
-    //             if s.reversed {
-    //                 s.end..s.start
-    //             } else {
-    //                 s.start..s.end
-    //             }
-    //         })
-    //         .collect::<Vec<_>>()
-    // }
-
-    // #[track_caller]
-    // fn assert_selections(
-    //     &mut self,
-    //     expected_selections: Vec<Range<usize>>,
-    //     expected_marked_text: String,
-    // ) {
-    //     let actual_selections = self.editor_selections();
-    //     let actual_marked_text =
-    //         generate_marked_text(&self.buffer_text(), &actual_selections, true);
-    //     if expected_selections != actual_selections {
-    //         panic!(
-    //             indoc! {"
-
-    //                 {}Editor has unexpected selections.
-
-    //                 Expected selections:
-    //                 {}
-
-    //                 Actual selections:
-    //                 {}
-    //             "},
-    //             self.assertion_context(),
-    //             expected_marked_text,
-    //             actual_marked_text,
-    //         );
-    //     }
-    // }
-}
+// use super::build_editor_with_project;
+
+// pub struct EditorTestContext<'a> {
+//     pub cx: &'a mut gpui::TestAppContext,
+//     pub window: AnyWindowHandle,
+//     pub editor: View<Editor>,
+// }
+
+// impl<'a> EditorTestContext<'a> {
+//     pub async fn new(cx: &'a mut gpui::TestAppContext) -> EditorTestContext<'a> {
+//         let fs = FakeFs::new(cx.background());
+//         // fs.insert_file("/file", "".to_owned()).await;
+//         fs.insert_tree(
+//             "/root",
+//             gpui::serde_json::json!({
+//                 "file": "",
+//             }),
+//         )
+//         .await;
+//         let project = Project::test(fs, ["/root".as_ref()], cx).await;
+//         let buffer = project
+//             .update(cx, |project, cx| {
+//                 project.open_local_buffer("/root/file", cx)
+//             })
+//             .await
+//             .unwrap();
+//         let window = cx.add_window(|cx| {
+//             cx.focus_self();
+//             build_editor_with_project(project, MultiBuffer::build_from_buffer(buffer, cx), cx)
+//         });
+//         let editor = window.root(cx);
+//         Self {
+//             cx,
+//             window: window.into(),
+//             editor,
+//         }
+//     }
+
+//     pub fn condition(
+//         &self,
+//         predicate: impl FnMut(&Editor, &AppContext) -> bool,
+//     ) -> impl Future<Output = ()> {
+//         self.editor.condition(self.cx, predicate)
+//     }
+
+//     pub fn editor<F, T>(&self, read: F) -> T
+//     where
+//         F: FnOnce(&Editor, &ViewContext<Editor>) -> T,
+//     {
+//         self.editor.update(self.cx, read)
+//     }
+
+//     pub fn update_editor<F, T>(&mut self, update: F) -> T
+//     where
+//         F: FnOnce(&mut Editor, &mut ViewContext<Editor>) -> T,
+//     {
+//         self.editor.update(self.cx, update)
+//     }
+
+//     pub fn multibuffer<F, T>(&self, read: F) -> T
+//     where
+//         F: FnOnce(&MultiBuffer, &AppContext) -> T,
+//     {
+//         self.editor(|editor, cx| read(editor.buffer().read(cx), cx))
+//     }
+
+//     pub fn update_multibuffer<F, T>(&mut self, update: F) -> T
+//     where
+//         F: FnOnce(&mut MultiBuffer, &mut ModelContext<MultiBuffer>) -> T,
+//     {
+//         self.update_editor(|editor, cx| editor.buffer().update(cx, update))
+//     }
+
+//     pub fn buffer_text(&self) -> String {
+//         self.multibuffer(|buffer, cx| buffer.snapshot(cx).text())
+//     }
+
+//     pub fn buffer<F, T>(&self, read: F) -> T
+//     where
+//         F: FnOnce(&Buffer, &AppContext) -> T,
+//     {
+//         self.multibuffer(|multibuffer, cx| {
+//             let buffer = multibuffer.as_singleton().unwrap().read(cx);
+//             read(buffer, cx)
+//         })
+//     }
+
+//     pub fn update_buffer<F, T>(&mut self, update: F) -> T
+//     where
+//         F: FnOnce(&mut Buffer, &mut ModelContext<Buffer>) -> T,
+//     {
+//         self.update_multibuffer(|multibuffer, cx| {
+//             let buffer = multibuffer.as_singleton().unwrap();
+//             buffer.update(cx, update)
+//         })
+//     }
+
+//     pub fn buffer_snapshot(&self) -> BufferSnapshot {
+//         self.buffer(|buffer, _| buffer.snapshot())
+//     }
+
+// pub fn simulate_keystroke(&mut self, keystroke_text: &str) -> ContextHandle {
+//     let keystroke_under_test_handle =
+//         self.add_assertion_context(format!("Simulated Keystroke: {:?}", keystroke_text));
+//     let keystroke = Keystroke::parse(keystroke_text).unwrap();
+
+//     self.cx.dispatch_keystroke(self.window, keystroke, false);
+
+//     keystroke_under_test_handle
+// }
+
+// pub fn simulate_keystrokes<const COUNT: usize>(
+//     &mut self,
+//     keystroke_texts: [&str; COUNT],
+// ) -> ContextHandle {
+//     let keystrokes_under_test_handle =
+//         self.add_assertion_context(format!("Simulated Keystrokes: {:?}", keystroke_texts));
+//     for keystroke_text in keystroke_texts.into_iter() {
+//         self.simulate_keystroke(keystroke_text);
+//     }
+//     // it is common for keyboard shortcuts to kick off async actions, so this ensures that they are complete
+//     // before returning.
+//     // NOTE: we don't do this in simulate_keystroke() because a possible cause of bugs is that typing too
+//     // quickly races with async actions.
+//     if let Foreground::Deterministic { cx_id: _, executor } = self.cx.foreground().as_ref() {
+//         executor.run_until_parked();
+//     } else {
+//         unreachable!();
+//     }
+
+//     keystrokes_under_test_handle
+// }
+
+// pub fn ranges(&self, marked_text: &str) -> Vec<Range<usize>> {
+//     let (unmarked_text, ranges) = marked_text_ranges(marked_text, false);
+//     assert_eq!(self.buffer_text(), unmarked_text);
+//     ranges
+// }
+
+// pub fn display_point(&mut self, marked_text: &str) -> DisplayPoint {
+//     let ranges = self.ranges(marked_text);
+//     let snapshot = self
+//         .editor
+//         .update(self.cx, |editor, cx| editor.snapshot(cx));
+//     ranges[0].start.to_display_point(&snapshot)
+// }
+
+// // Returns anchors for the current buffer using `ยซ` and `ยป`
+// pub fn text_anchor_range(&self, marked_text: &str) -> Range<language::Anchor> {
+//     let ranges = self.ranges(marked_text);
+//     let snapshot = self.buffer_snapshot();
+//     snapshot.anchor_before(ranges[0].start)..snapshot.anchor_after(ranges[0].end)
+// }
+
+// pub fn set_diff_base(&mut self, diff_base: Option<&str>) {
+//     let diff_base = diff_base.map(String::from);
+//     self.update_buffer(|buffer, cx| buffer.set_diff_base(diff_base, cx));
+// }
+
+// /// Change the editor's text and selections using a string containing
+// /// embedded range markers that represent the ranges and directions of
+// /// each selection.
+// ///
+// /// Returns a context handle so that assertion failures can print what
+// /// editor state was needed to cause the failure.
+// ///
+// /// See the `util::test::marked_text_ranges` function for more information.
+// pub fn set_state(&mut self, marked_text: &str) -> ContextHandle {
+//     let state_context = self.add_assertion_context(format!(
+//         "Initial Editor State: \"{}\"",
+//         marked_text.escape_debug().to_string()
+//     ));
+//     let (unmarked_text, selection_ranges) = marked_text_ranges(marked_text, true);
+//     self.editor.update(self.cx, |editor, cx| {
+//         editor.set_text(unmarked_text, cx);
+//         editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+//             s.select_ranges(selection_ranges)
+//         })
+//     });
+//     state_context
+// }
+
+// /// Only change the editor's selections
+// pub fn set_selections_state(&mut self, marked_text: &str) -> ContextHandle {
+//     let state_context = self.add_assertion_context(format!(
+//         "Initial Editor State: \"{}\"",
+//         marked_text.escape_debug().to_string()
+//     ));
+//     let (unmarked_text, selection_ranges) = marked_text_ranges(marked_text, true);
+//     self.editor.update(self.cx, |editor, cx| {
+//         assert_eq!(editor.text(cx), unmarked_text);
+//         editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
+//             s.select_ranges(selection_ranges)
+//         })
+//     });
+//     state_context
+// }
+
+// /// Make an assertion about the editor's text and the ranges and directions
+// /// of its selections using a string containing embedded range markers.
+// ///
+// /// See the `util::test::marked_text_ranges` function for more information.
+// #[track_caller]
+// pub fn assert_editor_state(&mut self, marked_text: &str) {
+//     let (unmarked_text, expected_selections) = marked_text_ranges(marked_text, true);
+//     let buffer_text = self.buffer_text();
+
+//     if buffer_text != unmarked_text {
+//         panic!("Unmarked text doesn't match buffer text\nBuffer text: {buffer_text:?}\nUnmarked text: {unmarked_text:?}\nRaw buffer text\n{buffer_text}Raw unmarked text\n{unmarked_text}");
+//     }
+
+//     self.assert_selections(expected_selections, marked_text.to_string())
+// }
+
+// pub fn editor_state(&mut self) -> String {
+//     generate_marked_text(self.buffer_text().as_str(), &self.editor_selections(), true)
+// }
+
+// #[track_caller]
+// pub fn assert_editor_background_highlights<Tag: 'static>(&mut self, marked_text: &str) {
+//     let expected_ranges = self.ranges(marked_text);
+//     let actual_ranges: Vec<Range<usize>> = self.update_editor(|editor, cx| {
+//         let snapshot = editor.snapshot(cx);
+//         editor
+//             .background_highlights
+//             .get(&TypeId::of::<Tag>())
+//             .map(|h| h.1.clone())
+//             .unwrap_or_default()
+//             .into_iter()
+//             .map(|range| range.to_offset(&snapshot.buffer_snapshot))
+//             .collect()
+//     });
+//     assert_set_eq!(actual_ranges, expected_ranges);
+// }
+
+// #[track_caller]
+// pub fn assert_editor_text_highlights<Tag: ?Sized + 'static>(&mut self, marked_text: &str) {
+//     let expected_ranges = self.ranges(marked_text);
+//     let snapshot = self.update_editor(|editor, cx| editor.snapshot(cx));
+//     let actual_ranges: Vec<Range<usize>> = snapshot
+//         .text_highlight_ranges::<Tag>()
+//         .map(|ranges| ranges.as_ref().clone().1)
+//         .unwrap_or_default()
+//         .into_iter()
+//         .map(|range| range.to_offset(&snapshot.buffer_snapshot))
+//         .collect();
+//     assert_set_eq!(actual_ranges, expected_ranges);
+// }
+
+// #[track_caller]
+// pub fn assert_editor_selections(&mut self, expected_selections: Vec<Range<usize>>) {
+//     let expected_marked_text =
+//         generate_marked_text(&self.buffer_text(), &expected_selections, true);
+//     self.assert_selections(expected_selections, expected_marked_text)
+// }
+
+// fn editor_selections(&self) -> Vec<Range<usize>> {
+//     self.editor
+//         .read_with(self.cx, |editor, cx| editor.selections.all::<usize>(cx))
+//         .into_iter()
+//         .map(|s| {
+//             if s.reversed {
+//                 s.end..s.start
+//             } else {
+//                 s.start..s.end
+//             }
+//         })
+//         .collect::<Vec<_>>()
+// }
+
+// #[track_caller]
+// fn assert_selections(
+//     &mut self,
+//     expected_selections: Vec<Range<usize>>,
+//     expected_marked_text: String,
+// ) {
+//     let actual_selections = self.editor_selections();
+//     let actual_marked_text =
+//         generate_marked_text(&self.buffer_text(), &actual_selections, true);
+//     if expected_selections != actual_selections {
+//         panic!(
+//             indoc! {"
+
+//                 {}Editor has unexpected selections.
+
+//                 Expected selections:
+//                 {}
+
+//                 Actual selections:
+//                 {}
+//             "},
+//             self.assertion_context(),
+//             expected_marked_text,
+//             actual_marked_text,
+//         );
+//     }
+// }
+// }
 
 impl<'a> Deref for EditorTestContext<'a> {
     type Target = gpui::TestAppContext;