Cargo.lock 🔗
@@ -8884,7 +8884,7 @@ dependencies = [
"ctor",
"digest 0.9.0",
"env_logger 0.9.3",
- "gpui",
+ "gpui2",
"lazy_static",
"log",
"parking_lot 0.11.2",
Nathan Sobo created
Cargo.lock | 2
crates/editor2/src/display_map.rs | 6
crates/editor2/src/editor.rs | 1319 +++++++++--------
crates/editor2/src/element.rs | 27
crates/editor2/src/highlight_matching_bracket.rs | 43
crates/editor2/src/hover_popover.rs | 237 +-
crates/editor2/src/inlay_hint_cache.rs | 568 +++---
crates/editor2/src/items.rs | 149 +
crates/editor2/src/link_go_to_definition.rs | 386 ++--
crates/editor2/src/mouse_context_menu.rs | 37
crates/editor2/src/persistence.rs | 3
crates/editor2/src/scroll.rs | 339 ++--
crates/editor2/src/scroll/autoscroll.rs | 34
crates/editor2/src/scroll/scroll_amount.rs | 27
crates/editor2/src/selections_collection.rs | 68
crates/gpui2/src/executor.rs | 1
crates/gpui2/src/geometry.rs | 12
crates/gpui2/src/platform/mac/text_system.rs | 1
crates/gpui2/src/style.rs | 9
crates/gpui2/src/text_system.rs | 2
crates/gpui2/src/text_system/line.rs | 4
crates/gpui2/src/text_system/line_layout.rs | 1
crates/gpui2/src/window.rs | 1
crates/text/Cargo.toml | 2
crates/text2/src/selection.rs | 6
crates/workspace2/src/item.rs | 18
26 files changed, 1,708 insertions(+), 1,594 deletions(-)
@@ -8884,7 +8884,7 @@ dependencies = [
"ctor",
"digest 0.9.0",
"env_logger 0.9.3",
- "gpui",
+ "gpui2",
"lazy_static",
"log",
"parking_lot 0.11.2",
@@ -60,7 +60,7 @@ impl DisplayMap {
buffer: Model<MultiBuffer>,
font: Font,
font_size: Pixels,
- wrap_width: Option<f32>,
+ wrap_width: Option<Pixels>,
buffer_header_height: u8,
excerpt_header_height: u8,
cx: &mut ModelContext<Self>,
@@ -241,7 +241,7 @@ impl DisplayMap {
pub fn set_font(&self, font: Font, font_size: Pixels, cx: &mut ModelContext<Self>) -> bool {
self.wrap_map
- .update(cx, |map, cx| map.set_font(font_id, font_size, cx))
+ .update(cx, |map, cx| map.set_font(font, font_size, cx))
}
pub fn set_fold_ellipses_color(&mut self, color: Hsla) -> bool {
@@ -621,7 +621,7 @@ impl DisplaySnapshot {
pub fn column_for_x(
&self,
display_row: u32,
- x_coordinate: f32,
+ x_coordinate: Pixels,
text_layout_details: &TextLayoutDetails,
) -> u32 {
let layout_line = self.lay_out_line_for_row(display_row, text_layout_details);
@@ -1,3 +1,4 @@
+#![allow(unused)]
mod blink_manager;
pub mod display_map;
mod editor_settings;
@@ -20,8 +21,9 @@ mod editor_tests;
#[cfg(any(test, feature = "test-support"))]
pub mod test;
use aho_corasick::AhoCorasick;
+use anyhow::Result;
use blink_manager::BlinkManager;
-use client::{Collaborator, ParticipantIndex};
+use client::{Client, Collaborator, ParticipantIndex};
use clock::ReplicaId;
use collections::{HashMap, HashSet, VecDeque};
pub use display_map::DisplayPoint;
@@ -33,8 +35,8 @@ pub use element::{
use futures::FutureExt;
use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::{
- AnyElement, AppContext, Element, EventEmitter, Model, Pixels, Render, Subscription, Task, View,
- ViewContext, WeakView,
+ AnyElement, AppContext, BackgroundExecutor, Element, EventEmitter, Model, Pixels, Render,
+ Subscription, Task, TextStyle, View, ViewContext, WeakView, WindowContext,
};
use hover_popover::HoverState;
pub use items::MAX_TAB_TITLE_LEN;
@@ -42,27 +44,30 @@ pub use language::{char_kind, CharKind};
use language::{
language_settings::{self, all_language_settings, InlayHintSettings},
AutoindentMode, BracketPair, Buffer, CodeAction, Completion, CursorShape, Diagnostic, Language,
- OffsetRangeExt, Point, Selection, SelectionGoal, TransactionId,
+ LanguageRegistry, OffsetRangeExt, Point, Selection, SelectionGoal, TransactionId,
};
use link_go_to_definition::LinkGoToDefinitionState;
+use lsp::{Documentation, LanguageServerId};
pub use multi_buffer::{
Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset,
ToPoint,
};
+use ordered_float::OrderedFloat;
use parking_lot::RwLock;
-use project::Project;
+use project::{FormatTrigger, Project};
use rpc::proto::*;
use scroll::{autoscroll::Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager};
use selections_collection::SelectionsCollection;
use serde::{Deserialize, Serialize};
use settings::Settings;
use std::{
+ cmp::Reverse,
ops::{Deref, DerefMut, Range},
sync::Arc,
time::Duration,
};
pub use sum_tree::Bias;
-use util::TryFutureExt;
+use util::{ResultExt, TryFutureExt};
use workspace::{ItemNavHistory, ViewId, Workspace};
const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
@@ -569,7 +574,7 @@ pub enum SoftWrap {
#[derive(Clone)]
pub struct EditorStyle {
- // pub text: TextStyle,
+ pub text: TextStyle,
pub line_height_scalar: f32,
// pub placeholder_text: Option<TextStyle>,
// pub theme: theme::Editor,
@@ -887,10 +892,11 @@ impl ContextMenu {
workspace: Option<WeakView<Workspace>>,
cx: &mut ViewContext<Editor>,
) -> (DisplayPoint, AnyElement<Editor>) {
- match self {
- ContextMenu::Completions(menu) => (cursor_position, menu.render(style, workspace, cx)),
- ContextMenu::CodeActions(menu) => menu.render(cursor_position, style, cx),
- }
+ todo!()
+ // match self {
+ // ContextMenu::Completions(menu) => (cursor_position, menu.render(style, workspace, cx)),
+ // ContextMenu::CodeActions(menu) => menu.render(cursor_position, style, cx),
+ // }
}
}
@@ -903,688 +909,715 @@ struct CompletionsMenu {
match_candidates: Arc<[StringMatchCandidate]>,
matches: Arc<[StringMatch]>,
selected_item: usize,
- // list: UniformListState,
+ list: UniformListState,
}
-// impl CompletionsMenu {
-// fn select_first(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
-// self.selected_item = 0;
-// self.list.scroll_to(ScrollTarget::Show(self.selected_item));
-// self.attempt_resolve_selected_completion_documentation(project, cx);
-// cx.notify();
-// }
+// todo!(this is fake)
+#[derive(Clone)]
+struct UniformListState;
-// fn select_prev(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
-// if self.selected_item > 0 {
-// self.selected_item -= 1;
-// } else {
-// self.selected_item = self.matches.len() - 1;
-// }
-// self.list.scroll_to(ScrollTarget::Show(self.selected_item));
-// self.attempt_resolve_selected_completion_documentation(project, cx);
-// cx.notify();
-// }
+// todo!(this is fake)
+impl UniformListState {
+ pub fn scroll_to(&mut self, target: ScrollTarget) {}
+}
-// fn select_next(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
-// if self.selected_item + 1 < self.matches.len() {
-// self.selected_item += 1;
-// } else {
-// self.selected_item = 0;
-// }
-// self.list.scroll_to(ScrollTarget::Show(self.selected_item));
-// self.attempt_resolve_selected_completion_documentation(project, cx);
-// cx.notify();
-// }
+// todo!(this is somewhat fake)
+#[derive(Debug)]
+pub enum ScrollTarget {
+ Show(usize),
+ Center(usize),
+}
-// fn select_last(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
-// self.selected_item = self.matches.len() - 1;
-// self.list.scroll_to(ScrollTarget::Show(self.selected_item));
-// self.attempt_resolve_selected_completion_documentation(project, cx);
-// cx.notify();
-// }
+impl CompletionsMenu {
+ fn select_first(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
+ self.selected_item = 0;
+ self.list.scroll_to(ScrollTarget::Show(self.selected_item));
+ self.attempt_resolve_selected_completion_documentation(project, cx);
+ cx.notify();
+ }
-// fn pre_resolve_completion_documentation(
-// &self,
-// project: Option<Model<Project>>,
-// cx: &mut ViewContext<Editor>,
-// ) {
-// let settings = settings::get::<EditorSettings>(cx);
-// if !settings.show_completion_documentation {
-// return;
-// }
+ fn select_prev(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
+ if self.selected_item > 0 {
+ self.selected_item -= 1;
+ } else {
+ self.selected_item = self.matches.len() - 1;
+ }
+ self.list.scroll_to(ScrollTarget::Show(self.selected_item));
+ self.attempt_resolve_selected_completion_documentation(project, cx);
+ cx.notify();
+ }
-// let Some(project) = project else {
-// return;
-// };
-// let client = project.read(cx).client();
-// let language_registry = project.read(cx).languages().clone();
-
-// let is_remote = project.read(cx).is_remote();
-// let project_id = project.read(cx).remote_id();
-
-// let completions = self.completions.clone();
-// let completion_indices: Vec<_> = self.matches.iter().map(|m| m.candidate_id).collect();
-
-// cx.spawn(move |this, mut cx| async move {
-// if is_remote {
-// let Some(project_id) = project_id else {
-// log::error!("Remote project without remote_id");
-// return;
-// };
-
-// for completion_index in completion_indices {
-// let completions_guard = completions.read();
-// let completion = &completions_guard[completion_index];
-// if completion.documentation.is_some() {
-// continue;
-// }
+ fn select_next(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
+ if self.selected_item + 1 < self.matches.len() {
+ self.selected_item += 1;
+ } else {
+ self.selected_item = 0;
+ }
+ self.list.scroll_to(ScrollTarget::Show(self.selected_item));
+ self.attempt_resolve_selected_completion_documentation(project, cx);
+ cx.notify();
+ }
-// let server_id = completion.server_id;
-// let completion = completion.lsp_completion.clone();
-// drop(completions_guard);
-
-// Self::resolve_completion_documentation_remote(
-// project_id,
-// server_id,
-// completions.clone(),
-// completion_index,
-// completion,
-// client.clone(),
-// language_registry.clone(),
-// )
-// .await;
+ fn select_last(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
+ self.selected_item = self.matches.len() - 1;
+ self.list.scroll_to(ScrollTarget::Show(self.selected_item));
+ self.attempt_resolve_selected_completion_documentation(project, cx);
+ cx.notify();
+ }
-// _ = this.update(&mut cx, |_, cx| cx.notify());
-// }
-// } else {
-// for completion_index in completion_indices {
-// let completions_guard = completions.read();
-// let completion = &completions_guard[completion_index];
-// if completion.documentation.is_some() {
-// continue;
-// }
+ fn pre_resolve_completion_documentation(
+ &self,
+ project: Option<Model<Project>>,
+ cx: &mut ViewContext<Editor>,
+ ) {
+ todo!("implementation below ");
+ }
+ // ) {
+ // let settings = EditorSettings::get_global(cx);
+ // if !settings.show_completion_documentation {
+ // return;
+ // }
-// let server_id = completion.server_id;
-// let completion = completion.lsp_completion.clone();
-// drop(completions_guard);
-
-// let server = project.read_with(&mut cx, |project, _| {
-// project.language_server_for_id(server_id)
-// });
-// let Some(server) = server else {
-// return;
-// };
-
-// Self::resolve_completion_documentation_local(
-// server,
-// completions.clone(),
-// completion_index,
-// completion,
-// language_registry.clone(),
-// )
-// .await;
+ // let Some(project) = project else {
+ // return;
+ // };
+ // let client = project.read(cx).client();
+ // let language_registry = project.read(cx).languages().clone();
-// _ = this.update(&mut cx, |_, cx| cx.notify());
-// }
-// }
-// })
-// .detach();
-// }
+ // let is_remote = project.read(cx).is_remote();
+ // let project_id = project.read(cx).remote_id();
-// fn attempt_resolve_selected_completion_documentation(
-// &mut self,
-// project: Option<&Model<Project>>,
-// cx: &mut ViewContext<Editor>,
-// ) {
-// let settings = settings::get::<EditorSettings>(cx);
-// if !settings.show_completion_documentation {
-// return;
-// }
+ // let completions = self.completions.clone();
+ // let completion_indices: Vec<_> = self.matches.iter().map(|m| m.candidate_id).collect();
-// let completion_index = self.matches[self.selected_item].candidate_id;
-// let Some(project) = project else {
-// return;
-// };
-// let language_registry = project.read(cx).languages().clone();
+ // cx.spawn(move |this, mut cx| async move {
+ // if is_remote {
+ // let Some(project_id) = project_id else {
+ // log::error!("Remote project without remote_id");
+ // return;
+ // };
-// let completions = self.completions.clone();
-// let completions_guard = completions.read();
-// let completion = &completions_guard[completion_index];
-// if completion.documentation.is_some() {
-// return;
-// }
+ // for completion_index in completion_indices {
+ // let completions_guard = completions.read();
+ // let completion = &completions_guard[completion_index];
+ // if completion.documentation.is_some() {
+ // continue;
+ // }
-// let server_id = completion.server_id;
-// let completion = completion.lsp_completion.clone();
-// drop(completions_guard);
+ // let server_id = completion.server_id;
+ // let completion = completion.lsp_completion.clone();
+ // drop(completions_guard);
+
+ // Self::resolve_completion_documentation_remote(
+ // project_id,
+ // server_id,
+ // completions.clone(),
+ // completion_index,
+ // completion,
+ // client.clone(),
+ // language_registry.clone(),
+ // )
+ // .await;
-// if project.read(cx).is_remote() {
-// let Some(project_id) = project.read(cx).remote_id() else {
-// log::error!("Remote project without remote_id");
-// return;
-// };
+ // _ = this.update(&mut cx, |_, cx| cx.notify());
+ // }
+ // } else {
+ // for completion_index in completion_indices {
+ // let completions_guard = completions.read();
+ // let completion = &completions_guard[completion_index];
+ // if completion.documentation.is_some() {
+ // continue;
+ // }
-// let client = project.read(cx).client();
-
-// cx.spawn(move |this, mut cx| async move {
-// Self::resolve_completion_documentation_remote(
-// project_id,
-// server_id,
-// completions.clone(),
-// completion_index,
-// completion,
-// client,
-// language_registry.clone(),
-// )
-// .await;
-
-// _ = this.update(&mut cx, |_, cx| cx.notify());
-// })
-// .detach();
-// } else {
-// let Some(server) = project.read(cx).language_server_for_id(server_id) else {
-// return;
-// };
+ // let server_id = completion.server_id;
+ // let completion = completion.lsp_completion.clone();
+ // drop(completions_guard);
-// cx.spawn(move |this, mut cx| async move {
-// Self::resolve_completion_documentation_local(
-// server,
-// completions,
-// completion_index,
-// completion,
-// language_registry,
-// )
-// .await;
-
-// _ = this.update(&mut cx, |_, cx| cx.notify());
-// })
-// .detach();
-// }
-// }
+ // let server = project.read_with(&mut cx, |project, _| {
+ // project.language_server_for_id(server_id)
+ // });
+ // let Some(server) = server else {
+ // return;
+ // };
-// async fn resolve_completion_documentation_remote(
-// project_id: u64,
-// server_id: LanguageServerId,
-// completions: Arc<RwLock<Box<[Completion]>>>,
-// completion_index: usize,
-// completion: lsp::CompletionItem,
-// client: Arc<Client>,
-// language_registry: Arc<LanguageRegistry>,
-// ) {
-// let request = proto::ResolveCompletionDocumentation {
-// project_id,
-// language_server_id: server_id.0 as u64,
-// lsp_completion: serde_json::to_string(&completion).unwrap().into_bytes(),
-// };
+ // Self::resolve_completion_documentation_local(
+ // server,
+ // completions.clone(),
+ // completion_index,
+ // completion,
+ // language_registry.clone(),
+ // )
+ // .await;
-// let Some(response) = client
-// .request(request)
-// .await
-// .context("completion documentation resolve proto request")
-// .log_err()
-// else {
-// return;
-// };
+ // _ = this.update(&mut cx, |_, cx| cx.notify());
+ // }
+ // }
+ // })
+ // .detach();
+ // }
-// if response.text.is_empty() {
-// let mut completions = completions.write();
-// let completion = &mut completions[completion_index];
-// completion.documentation = Some(Documentation::Undocumented);
-// }
+ fn attempt_resolve_selected_completion_documentation(
+ &mut self,
+ project: Option<&Model<Project>>,
+ cx: &mut ViewContext<Editor>,
+ ) {
+ let settings = EditorSettings::get_global(cx);
+ if !settings.show_completion_documentation {
+ return;
+ }
-// let documentation = if response.is_markdown {
-// Documentation::MultiLineMarkdown(
-// markdown::parse_markdown(&response.text, &language_registry, None).await,
-// )
-// } else if response.text.lines().count() <= 1 {
-// Documentation::SingleLine(response.text)
-// } else {
-// Documentation::MultiLinePlainText(response.text)
-// };
+ let completion_index = self.matches[self.selected_item].candidate_id;
+ let Some(project) = project else {
+ return;
+ };
+ let language_registry = project.read(cx).languages().clone();
+
+ let completions = self.completions.clone();
+ let completions_guard = completions.read();
+ let completion = &completions_guard[completion_index];
+ // todo!()
+ // if completion.documentation.is_some() {
+ // return;
+ // }
+
+ let server_id = completion.server_id;
+ let completion = completion.lsp_completion.clone();
+ drop(completions_guard);
+
+ if project.read(cx).is_remote() {
+ let Some(project_id) = project.read(cx).remote_id() else {
+ log::error!("Remote project without remote_id");
+ return;
+ };
+
+ let client = project.read(cx).client();
+
+ cx.spawn(move |this, mut cx| async move {
+ Self::resolve_completion_documentation_remote(
+ project_id,
+ server_id,
+ completions.clone(),
+ completion_index,
+ completion,
+ client,
+ language_registry.clone(),
+ )
+ .await;
+
+ _ = this.update(&mut cx, |_, cx| cx.notify());
+ })
+ .detach();
+ } else {
+ let Some(server) = project.read(cx).language_server_for_id(server_id) else {
+ return;
+ };
+
+ cx.spawn(move |this, mut cx| async move {
+ Self::resolve_completion_documentation_local(
+ server,
+ completions,
+ completion_index,
+ completion,
+ language_registry,
+ )
+ .await;
+
+ _ = this.update(&mut cx, |_, cx| cx.notify());
+ })
+ .detach();
+ }
+ }
-// let mut completions = completions.write();
-// let completion = &mut completions[completion_index];
-// completion.documentation = Some(documentation);
-// }
+ async fn resolve_completion_documentation_remote(
+ project_id: u64,
+ server_id: LanguageServerId,
+ completions: Arc<RwLock<Box<[Completion]>>>,
+ completion_index: usize,
+ completion: lsp::CompletionItem,
+ client: Arc<Client>,
+ language_registry: Arc<LanguageRegistry>,
+ ) {
+ todo!()
+ // let request = proto::ResolveCompletionDocumentation {
+ // project_id,
+ // language_server_id: server_id.0 as u64,
+ // lsp_completion: serde_json::to_string(&completion).unwrap().into_bytes(),
+ // };
+
+ // let Some(response) = client
+ // .request(request)
+ // .await
+ // .context("completion documentation resolve proto request")
+ // .log_err()
+ // else {
+ // return;
+ // };
+
+ // if response.text.is_empty() {
+ // let mut completions = completions.write();
+ // let completion = &mut completions[completion_index];
+ // completion.documentation = Some(Documentation::Undocumented);
+ // }
+
+ // let documentation = if response.is_markdown {
+ // Documentation::MultiLineMarkdown(
+ // markdown::parse_markdown(&response.text, &language_registry, None).await,
+ // )
+ // } else if response.text.lines().count() <= 1 {
+ // Documentation::SingleLine(response.text)
+ // } else {
+ // Documentation::MultiLinePlainText(response.text)
+ // };
+
+ // let mut completions = completions.write();
+ // let completion = &mut completions[completion_index];
+ // completion.documentation = Some(documentation);
+ }
-// async fn resolve_completion_documentation_local(
-// server: Arc<lsp::LanguageServer>,
-// completions: Arc<RwLock<Box<[Completion]>>>,
-// completion_index: usize,
-// completion: lsp::CompletionItem,
-// language_registry: Arc<LanguageRegistry>,
-// ) {
-// let can_resolve = server
-// .capabilities()
-// .completion_provider
-// .as_ref()
-// .and_then(|options| options.resolve_provider)
-// .unwrap_or(false);
-// if !can_resolve {
-// return;
-// }
+ async fn resolve_completion_documentation_local(
+ server: Arc<lsp::LanguageServer>,
+ completions: Arc<RwLock<Box<[Completion]>>>,
+ completion_index: usize,
+ completion: lsp::CompletionItem,
+ language_registry: Arc<LanguageRegistry>,
+ ) {
+ todo!()
+ // let can_resolve = server
+ // .capabilities()
+ // .completion_provider
+ // .as_ref()
+ // .and_then(|options| options.resolve_provider)
+ // .unwrap_or(false);
+ // if !can_resolve {
+ // return;
+ // }
+
+ // let request = server.request::<lsp::request::ResolveCompletionItem>(completion);
+ // let Some(completion_item) = request.await.log_err() else {
+ // return;
+ // };
+
+ // if let Some(lsp_documentation) = completion_item.documentation {
+ // let documentation = language::prepare_completion_documentation(
+ // &lsp_documentation,
+ // &language_registry,
+ // None, // TODO: Try to reasonably work out which language the completion is for
+ // )
+ // .await;
+
+ // let mut completions = completions.write();
+ // let completion = &mut completions[completion_index];
+ // completion.documentation = Some(documentation);
+ // } else {
+ // let mut completions = completions.write();
+ // let completion = &mut completions[completion_index];
+ // completion.documentation = Some(Documentation::Undocumented);
+ // }
+ }
-// let request = server.request::<lsp::request::ResolveCompletionItem>(completion);
-// let Some(completion_item) = request.await.log_err() else {
-// return;
-// };
+ fn visible(&self) -> bool {
+ !self.matches.is_empty()
+ }
-// if let Some(lsp_documentation) = completion_item.documentation {
-// let documentation = language::prepare_completion_documentation(
-// &lsp_documentation,
-// &language_registry,
-// None, // TODO: Try to reasonably work out which language the completion is for
-// )
-// .await;
-
-// let mut completions = completions.write();
-// let completion = &mut completions[completion_index];
-// completion.documentation = Some(documentation);
-// } else {
-// let mut completions = completions.write();
-// let completion = &mut completions[completion_index];
-// completion.documentation = Some(Documentation::Undocumented);
-// }
-// }
+ fn render(
+ &self,
+ style: EditorStyle,
+ workspace: Option<WeakView<Workspace>>,
+ cx: &mut ViewContext<Editor>,
+ ) {
+ todo!("old implementation below")
+ }
+ // ) -> AnyElement<Editor> {
+ // enum CompletionTag {}
+
+ // let settings = EditorSettings>(cx);
+ // let show_completion_documentation = settings.show_completion_documentation;
+
+ // let widest_completion_ix = self
+ // .matches
+ // .iter()
+ // .enumerate()
+ // .max_by_key(|(_, mat)| {
+ // let completions = self.completions.read();
+ // let completion = &completions[mat.candidate_id];
+ // let documentation = &completion.documentation;
+
+ // let mut len = completion.label.text.chars().count();
+ // if let Some(Documentation::SingleLine(text)) = documentation {
+ // if show_completion_documentation {
+ // len += text.chars().count();
+ // }
+ // }
-// fn visible(&self) -> bool {
-// !self.matches.is_empty()
-// }
+ // len
+ // })
+ // .map(|(ix, _)| ix);
-// fn render(
-// &self,
-// style: EditorStyle,
-// workspace: Option<WeakView<Workspace>>,
-// cx: &mut ViewContext<Editor>,
-// ) -> AnyElement<Editor> {
-// enum CompletionTag {}
-
-// let settings = settings::get::<EditorSettings>(cx);
-// let show_completion_documentation = settings.show_completion_documentation;
-
-// let widest_completion_ix = self
-// .matches
-// .iter()
-// .enumerate()
-// .max_by_key(|(_, mat)| {
-// let completions = self.completions.read();
-// let completion = &completions[mat.candidate_id];
-// let documentation = &completion.documentation;
-
-// let mut len = completion.label.text.chars().count();
-// if let Some(Documentation::SingleLine(text)) = documentation {
-// if show_completion_documentation {
-// len += text.chars().count();
-// }
-// }
+ // let completions = self.completions.clone();
+ // let matches = self.matches.clone();
+ // let selected_item = self.selected_item;
-// len
-// })
-// .map(|(ix, _)| ix);
-
-// let completions = self.completions.clone();
-// let matches = self.matches.clone();
-// let selected_item = self.selected_item;
-
-// let list = UniformList::new(self.list.clone(), matches.len(), cx, {
-// let style = style.clone();
-// move |_, range, items, cx| {
-// let start_ix = range.start;
-// let completions_guard = completions.read();
-
-// for (ix, mat) in matches[range].iter().enumerate() {
-// let item_ix = start_ix + ix;
-// let candidate_id = mat.candidate_id;
-// let completion = &completions_guard[candidate_id];
-
-// let documentation = if show_completion_documentation {
-// &completion.documentation
-// } else {
-// &None
-// };
-
-// items.push(
-// MouseEventHandler::new::<CompletionTag, _>(
-// mat.candidate_id,
-// cx,
-// |state, _| {
-// let item_style = if item_ix == selected_item {
-// style.autocomplete.selected_item
-// } else if state.hovered() {
-// style.autocomplete.hovered_item
-// } else {
-// style.autocomplete.item
-// };
-
-// let completion_label =
-// Text::new(completion.label.text.clone(), style.text.clone())
-// .with_soft_wrap(false)
-// .with_highlights(
-// combine_syntax_and_fuzzy_match_highlights(
-// &completion.label.text,
-// style.text.color.into(),
-// styled_runs_for_code_label(
-// &completion.label,
-// &style.syntax,
-// ),
-// &mat.positions,
-// ),
-// );
-
-// if let Some(Documentation::SingleLine(text)) = documentation {
-// Flex::row()
-// .with_child(completion_label)
-// .with_children((|| {
-// let text_style = TextStyle {
-// color: style.autocomplete.inline_docs_color,
-// font_size: style.text.font_size
-// * style.autocomplete.inline_docs_size_percent,
-// ..style.text.clone()
-// };
-
-// let label = Text::new(text.clone(), text_style)
-// .aligned()
-// .constrained()
-// .dynamically(move |constraint, _, _| {
-// gpui::SizeConstraint {
-// min: constraint.min,
-// max: vec2f(
-// constraint.max.x(),
-// constraint.min.y(),
-// ),
-// }
-// });
-
-// if Some(item_ix) == widest_completion_ix {
-// Some(
-// label
-// .contained()
-// .with_style(
-// style
-// .autocomplete
-// .inline_docs_container,
-// )
-// .into_any(),
-// )
-// } else {
-// Some(label.flex_float().into_any())
-// }
-// })())
-// .into_any()
-// } else {
-// completion_label.into_any()
-// }
-// .contained()
-// .with_style(item_style)
-// .constrained()
-// .dynamically(
-// move |constraint, _, _| {
-// if Some(item_ix) == widest_completion_ix {
-// constraint
-// } else {
-// gpui::SizeConstraint {
-// min: constraint.min,
-// max: constraint.min,
-// }
-// }
-// },
-// )
-// },
-// )
-// .with_cursor_style(CursorStyle::PointingHand)
-// .on_down(MouseButton::Left, move |_, this, cx| {
-// this.confirm_completion(
-// &ConfirmCompletion {
-// item_ix: Some(item_ix),
-// },
-// cx,
-// )
-// .map(|task| task.detach());
-// })
-// .constrained()
-// .with_min_width(style.autocomplete.completion_min_width)
-// .with_max_width(style.autocomplete.completion_max_width)
-// .into_any(),
-// );
-// }
-// }
-// })
-// .with_width_from_item(widest_completion_ix);
-
-// enum MultiLineDocumentation {}
-
-// Flex::row()
-// .with_child(list.flex(1., false))
-// .with_children({
-// let mat = &self.matches[selected_item];
-// let completions = self.completions.read();
-// let completion = &completions[mat.candidate_id];
-// let documentation = &completion.documentation;
-
-// match documentation {
-// Some(Documentation::MultiLinePlainText(text)) => Some(
-// Flex::column()
-// .scrollable::<MultiLineDocumentation>(0, None, cx)
-// .with_child(
-// Text::new(text.clone(), style.text.clone()).with_soft_wrap(true),
-// )
-// .contained()
-// .with_style(style.autocomplete.alongside_docs_container)
-// .constrained()
-// .with_max_width(style.autocomplete.alongside_docs_max_width)
-// .flex(1., false),
-// ),
-
-// Some(Documentation::MultiLineMarkdown(parsed)) => Some(
-// Flex::column()
-// .scrollable::<MultiLineDocumentation>(0, None, cx)
-// .with_child(render_parsed_markdown::<MultiLineDocumentation>(
-// parsed, &style, workspace, cx,
-// ))
-// .contained()
-// .with_style(style.autocomplete.alongside_docs_container)
-// .constrained()
-// .with_max_width(style.autocomplete.alongside_docs_max_width)
-// .flex(1., false),
-// ),
-
-// _ => None,
-// }
-// })
-// .contained()
-// .with_style(style.autocomplete.container)
-// .into_any()
-// }
+ // let list = UniformList::new(self.list.clone(), matches.len(), cx, {
+ // let style = style.clone();
+ // move |_, range, items, cx| {
+ // let start_ix = range.start;
+ // let completions_guard = completions.read();
-// pub async fn filter(&mut self, query: Option<&str>, executor: Arc<executor::Background>) {
-// let mut matches = if let Some(query) = query {
-// fuzzy::match_strings(
-// &self.match_candidates,
-// query,
-// query.chars().any(|c| c.is_uppercase()),
-// 100,
-// &Default::default(),
-// executor,
-// )
-// .await
-// } else {
-// self.match_candidates
-// .iter()
-// .enumerate()
-// .map(|(candidate_id, candidate)| StringMatch {
-// candidate_id,
-// score: Default::default(),
-// positions: Default::default(),
-// string: candidate.string.clone(),
-// })
-// .collect()
-// };
+ // for (ix, mat) in matches[range].iter().enumerate() {
+ // let item_ix = start_ix + ix;
+ // let candidate_id = mat.candidate_id;
+ // let completion = &completions_guard[candidate_id];
-// // Remove all candidates where the query's start does not match the start of any word in the candidate
-// if let Some(query) = query {
-// if let Some(query_start) = query.chars().next() {
-// matches.retain(|string_match| {
-// split_words(&string_match.string).any(|word| {
-// // Check that the first codepoint of the word as lowercase matches the first
-// // codepoint of the query as lowercase
-// word.chars()
-// .flat_map(|codepoint| codepoint.to_lowercase())
-// .zip(query_start.to_lowercase())
-// .all(|(word_cp, query_cp)| word_cp == query_cp)
-// })
-// });
-// }
-// }
+ // let documentation = if show_completion_documentation {
+ // &completion.documentation
+ // } else {
+ // &None
+ // };
-// let completions = self.completions.read();
-// matches.sort_unstable_by_key(|mat| {
-// let completion = &completions[mat.candidate_id];
-// (
-// completion.lsp_completion.sort_text.as_ref(),
-// Reverse(OrderedFloat(mat.score)),
-// completion.sort_key(),
-// )
-// });
-// drop(completions);
+ // items.push(
+ // MouseEventHandler::new::<CompletionTag, _>(
+ // mat.candidate_id,
+ // cx,
+ // |state, _| {
+ // let item_style = if item_ix == selected_item {
+ // style.autocomplete.selected_item
+ // } else if state.hovered() {
+ // style.autocomplete.hovered_item
+ // } else {
+ // style.autocomplete.item
+ // };
-// for mat in &mut matches {
-// let completions = self.completions.read();
-// let filter_start = completions[mat.candidate_id].label.filter_range.start;
-// for position in &mut mat.positions {
-// *position += filter_start;
-// }
-// }
+ // let completion_label =
+ // Text::new(completion.label.text.clone(), style.text.clone())
+ // .with_soft_wrap(false)
+ // .with_highlights(
+ // combine_syntax_and_fuzzy_match_highlights(
+ // &completion.label.text,
+ // style.text.color.into(),
+ // styled_runs_for_code_label(
+ // &completion.label,
+ // &style.syntax,
+ // ),
+ // &mat.positions,
+ // ),
+ // );
-// self.matches = matches.into();
-// self.selected_item = 0;
-// }
-// }
+ // if let Some(Documentation::SingleLine(text)) = documentation {
+ // Flex::row()
+ // .with_child(completion_label)
+ // .with_children((|| {
+ // let text_style = TextStyle {
+ // color: style.autocomplete.inline_docs_color,
+ // font_size: style.text.font_size
+ // * style.autocomplete.inline_docs_size_percent,
+ // ..style.text.clone()
+ // };
+
+ // let label = Text::new(text.clone(), text_style)
+ // .aligned()
+ // .constrained()
+ // .dynamically(move |constraint, _, _| {
+ // gpui::SizeConstraint {
+ // min: constraint.min,
+ // max: vec2f(
+ // constraint.max.x(),
+ // constraint.min.y(),
+ // ),
+ // }
+ // });
+
+ // if Some(item_ix) == widest_completion_ix {
+ // Some(
+ // label
+ // .contained()
+ // .with_style(
+ // style
+ // .autocomplete
+ // .inline_docs_container,
+ // )
+ // .into_any(),
+ // )
+ // } else {
+ // Some(label.flex_float().into_any())
+ // }
+ // })())
+ // .into_any()
+ // } else {
+ // completion_label.into_any()
+ // }
+ // .contained()
+ // .with_style(item_style)
+ // .constrained()
+ // .dynamically(
+ // move |constraint, _, _| {
+ // if Some(item_ix) == widest_completion_ix {
+ // constraint
+ // } else {
+ // gpui::SizeConstraint {
+ // min: constraint.min,
+ // max: constraint.min,
+ // }
+ // }
+ // },
+ // )
+ // },
+ // )
+ // .with_cursor_style(CursorStyle::PointingHand)
+ // .on_down(MouseButton::Left, move |_, this, cx| {
+ // this.confirm_completion(
+ // &ConfirmCompletion {
+ // item_ix: Some(item_ix),
+ // },
+ // cx,
+ // )
+ // .map(|task| task.detach());
+ // })
+ // .constrained()
+ // .with_min_width(style.autocomplete.completion_min_width)
+ // .with_max_width(style.autocomplete.completion_max_width)
+ // .into_any(),
+ // );
+ // }
+ // }
+ // })
+ // .with_width_from_item(widest_completion_ix);
+
+ // enum MultiLineDocumentation {}
+
+ // Flex::row()
+ // .with_child(list.flex(1., false))
+ // .with_children({
+ // let mat = &self.matches[selected_item];
+ // let completions = self.completions.read();
+ // let completion = &completions[mat.candidate_id];
+ // let documentation = &completion.documentation;
+
+ // match documentation {
+ // Some(Documentation::MultiLinePlainText(text)) => Some(
+ // Flex::column()
+ // .scrollable::<MultiLineDocumentation>(0, None, cx)
+ // .with_child(
+ // Text::new(text.clone(), style.text.clone()).with_soft_wrap(true),
+ // )
+ // .contained()
+ // .with_style(style.autocomplete.alongside_docs_container)
+ // .constrained()
+ // .with_max_width(style.autocomplete.alongside_docs_max_width)
+ // .flex(1., false),
+ // ),
+
+ // Some(Documentation::MultiLineMarkdown(parsed)) => Some(
+ // Flex::column()
+ // .scrollable::<MultiLineDocumentation>(0, None, cx)
+ // .with_child(render_parsed_markdown::<MultiLineDocumentation>(
+ // parsed, &style, workspace, cx,
+ // ))
+ // .contained()
+ // .with_style(style.autocomplete.alongside_docs_container)
+ // .constrained()
+ // .with_max_width(style.autocomplete.alongside_docs_max_width)
+ // .flex(1., false),
+ // ),
+
+ // _ => None,
+ // }
+ // })
+ // .contained()
+ // .with_style(style.autocomplete.container)
+ // .into_any()
+ // }
+
+ pub async fn filter(&mut self, query: Option<&str>, executor: BackgroundExecutor) {
+ let mut matches = if let Some(query) = query {
+ fuzzy::match_strings(
+ &self.match_candidates,
+ query,
+ query.chars().any(|c| c.is_uppercase()),
+ 100,
+ &Default::default(),
+ executor,
+ )
+ .await
+ } else {
+ self.match_candidates
+ .iter()
+ .enumerate()
+ .map(|(candidate_id, candidate)| StringMatch {
+ candidate_id,
+ score: Default::default(),
+ positions: Default::default(),
+ string: candidate.string.clone(),
+ })
+ .collect()
+ };
+
+ // Remove all candidates where the query's start does not match the start of any word in the candidate
+ if let Some(query) = query {
+ if let Some(query_start) = query.chars().next() {
+ matches.retain(|string_match| {
+ split_words(&string_match.string).any(|word| {
+ // Check that the first codepoint of the word as lowercase matches the first
+ // codepoint of the query as lowercase
+ word.chars()
+ .flat_map(|codepoint| codepoint.to_lowercase())
+ .zip(query_start.to_lowercase())
+ .all(|(word_cp, query_cp)| word_cp == query_cp)
+ })
+ });
+ }
+ }
+
+ let completions = self.completions.read();
+ matches.sort_unstable_by_key(|mat| {
+ let completion = &completions[mat.candidate_id];
+ (
+ completion.lsp_completion.sort_text.as_ref(),
+ Reverse(OrderedFloat(mat.score)),
+ completion.sort_key(),
+ )
+ });
+ drop(completions);
+
+ for mat in &mut matches {
+ let completions = self.completions.read();
+ let filter_start = completions[mat.candidate_id].label.filter_range.start;
+ for position in &mut mat.positions {
+ *position += filter_start;
+ }
+ }
+
+ self.matches = matches.into();
+ self.selected_item = 0;
+ }
+}
#[derive(Clone)]
struct CodeActionsMenu {
actions: Arc<[CodeAction]>,
buffer: Model<Buffer>,
selected_item: usize,
- // list: UniformListState,
+ list: UniformListState,
deployed_from_indicator: bool,
}
-// impl CodeActionsMenu {
-// fn select_first(&mut self, cx: &mut ViewContext<Editor>) {
-// self.selected_item = 0;
-// self.list.scroll_to(ScrollTarget::Show(self.selected_item));
-// cx.notify()
-// }
+impl CodeActionsMenu {
+ fn select_first(&mut self, cx: &mut ViewContext<Editor>) {
+ self.selected_item = 0;
+ self.list.scroll_to(ScrollTarget::Show(self.selected_item));
+ cx.notify()
+ }
-// fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
-// if self.selected_item > 0 {
-// self.selected_item -= 1;
-// } else {
-// self.selected_item = self.actions.len() - 1;
-// }
-// self.list.scroll_to(ScrollTarget::Show(self.selected_item));
-// cx.notify();
-// }
+ fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
+ if self.selected_item > 0 {
+ self.selected_item -= 1;
+ } else {
+ self.selected_item = self.actions.len() - 1;
+ }
+ self.list.scroll_to(ScrollTarget::Show(self.selected_item));
+ cx.notify();
+ }
-// fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
-// if self.selected_item + 1 < self.actions.len() {
-// self.selected_item += 1;
-// } else {
-// self.selected_item = 0;
-// }
-// self.list.scroll_to(ScrollTarget::Show(self.selected_item));
-// cx.notify();
-// }
+ fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
+ if self.selected_item + 1 < self.actions.len() {
+ self.selected_item += 1;
+ } else {
+ self.selected_item = 0;
+ }
+ self.list.scroll_to(ScrollTarget::Show(self.selected_item));
+ cx.notify();
+ }
-// fn select_last(&mut self, cx: &mut ViewContext<Editor>) {
-// self.selected_item = self.actions.len() - 1;
-// self.list.scroll_to(ScrollTarget::Show(self.selected_item));
-// cx.notify()
-// }
+ fn select_last(&mut self, cx: &mut ViewContext<Editor>) {
+ self.selected_item = self.actions.len() - 1;
+ self.list.scroll_to(ScrollTarget::Show(self.selected_item));
+ cx.notify()
+ }
-// fn visible(&self) -> bool {
-// !self.actions.is_empty()
-// }
+ fn visible(&self) -> bool {
+ !self.actions.is_empty()
+ }
-// fn render(
-// &self,
-// mut cursor_position: DisplayPoint,
-// style: EditorStyle,
-// cx: &mut ViewContext<Editor>,
-// ) -> (DisplayPoint, AnyElement<Editor>) {
-// enum ActionTag {}
-
-// let container_style = style.autocomplete.container;
-// let actions = self.actions.clone();
-// let selected_item = self.selected_item;
-// let element = UniformList::new(
-// self.list.clone(),
-// actions.len(),
-// cx,
-// move |_, range, items, cx| {
-// let start_ix = range.start;
-// for (ix, action) in actions[range].iter().enumerate() {
-// let item_ix = start_ix + ix;
-// items.push(
-// MouseEventHandler::new::<ActionTag, _>(item_ix, cx, |state, _| {
-// let item_style = if item_ix == selected_item {
-// style.autocomplete.selected_item
-// } else if state.hovered() {
-// style.autocomplete.hovered_item
-// } else {
-// style.autocomplete.item
-// };
-
-// Text::new(action.lsp_action.title.clone(), style.text.clone())
-// .with_soft_wrap(false)
-// .contained()
-// .with_style(item_style)
-// })
-// .with_cursor_style(CursorStyle::PointingHand)
-// .on_down(MouseButton::Left, move |_, this, cx| {
-// let workspace = this
-// .workspace
-// .as_ref()
-// .and_then(|(workspace, _)| workspace.upgrade(cx));
-// cx.window_context().defer(move |cx| {
-// if let Some(workspace) = workspace {
-// workspace.update(cx, |workspace, cx| {
-// if let Some(task) = Editor::confirm_code_action(
-// workspace,
-// &ConfirmCodeAction {
-// item_ix: Some(item_ix),
-// },
-// cx,
-// ) {
-// task.detach_and_log_err(cx);
-// }
-// });
-// }
-// });
-// })
-// .into_any(),
-// );
-// }
-// },
-// )
-// .with_width_from_item(
-// self.actions
-// .iter()
-// .enumerate()
-// .max_by_key(|(_, action)| action.lsp_action.title.chars().count())
-// .map(|(ix, _)| ix),
-// )
-// .contained()
-// .with_style(container_style)
-// .into_any();
+ fn render(
+ &self,
+ mut cursor_position: DisplayPoint,
+ style: EditorStyle,
+ cx: &mut ViewContext<Editor>,
+ ) -> (DisplayPoint, AnyElement<Editor>) {
+ todo!("old version below")
+ }
+ // enum ActionTag {}
+
+ // let container_style = style.autocomplete.container;
+ // let actions = self.actions.clone();
+ // let selected_item = self.selected_item;
+ // let element = UniformList::new(
+ // self.list.clone(),
+ // actions.len(),
+ // cx,
+ // move |_, range, items, cx| {
+ // let start_ix = range.start;
+ // for (ix, action) in actions[range].iter().enumerate() {
+ // let item_ix = start_ix + ix;
+ // items.push(
+ // MouseEventHandler::new::<ActionTag, _>(item_ix, cx, |state, _| {
+ // let item_style = if item_ix == selected_item {
+ // style.autocomplete.selected_item
+ // } else if state.hovered() {
+ // style.autocomplete.hovered_item
+ // } else {
+ // style.autocomplete.item
+ // };
-// if self.deployed_from_indicator {
-// *cursor_position.column_mut() = 0;
-// }
+ // Text::new(action.lsp_action.title.clone(), style.text.clone())
+ // .with_soft_wrap(false)
+ // .contained()
+ // .with_style(item_style)
+ // })
+ // .with_cursor_style(CursorStyle::PointingHand)
+ // .on_down(MouseButton::Left, move |_, this, cx| {
+ // let workspace = this
+ // .workspace
+ // .as_ref()
+ // .and_then(|(workspace, _)| workspace.upgrade(cx));
+ // cx.window_context().defer(move |cx| {
+ // if let Some(workspace) = workspace {
+ // workspace.update(cx, |workspace, cx| {
+ // if let Some(task) = Editor::confirm_code_action(
+ // workspace,
+ // &ConfirmCodeAction {
+ // item_ix: Some(item_ix),
+ // },
+ // cx,
+ // ) {
+ // task.detach_and_log_err(cx);
+ // }
+ // });
+ // }
+ // });
+ // })
+ // .into_any(),
+ // );
+ // }
+ // },
+ // )
+ // .with_width_from_item(
+ // self.actions
+ // .iter()
+ // .enumerate()
+ // .max_by_key(|(_, action)| action.lsp_action.title.chars().count())
+ // .map(|(ix, _)| ix),
+ // )
+ // .contained()
+ // .with_style(container_style)
+ // .into_any();
-// (cursor_position, element)
-// }
-// }
+ // if self.deployed_from_indicator {
+ // *cursor_position.column_mut() = 0;
+ // }
+
+ // (cursor_position, element)
+ // }
+}
pub struct CopilotState {
excerpt_id: Option<ExcerptId>,
@@ -5,10 +5,13 @@ use crate::{
display_map::{BlockStyle, DisplaySnapshot},
EditorStyle,
};
+use anyhow::Result;
use gpui::{
- px, relative, AnyElement, Bounds, Element, Hsla, Line, Pixels, Size, Style, TextRun, TextSystem,
+ black, px, relative, AnyElement, Bounds, Element, Hsla, Line, Pixels, Size, Style, TextRun,
+ TextSystem,
};
use language::{CursorShape, Selection};
+use smallvec::SmallVec;
use std::{ops::Range, sync::Arc};
use sum_tree::Bias;
@@ -2700,16 +2703,16 @@ impl PositionMap {
let position = position - text_bounds.origin;
let y = position.y.max(px(0.)).min(self.size.width);
let x = position.x + (scroll_position.x * self.em_width);
- let row = (y / self.line_height + scroll_position.y).into();
+ let row = (f32::from(y / self.line_height) + scroll_position.y) as u32;
let (column, x_overshoot_after_line_end) = if let Some(line) = self
.line_layouts
.get(row as usize - scroll_position.y.into())
- .map(|line_with_spaces| &line_with_spaces.line)
+ .map(|LineWithInvisibles { line, .. }| line)
{
if let Some(ix) = line.index_for_x(x) {
- (ix as u32, 0.0)
+ (ix as u32, px(0.))
} else {
- (line.len() as u32, px(0.).max(x - line.width()))
+ (line.len as u32, px(0.).max(x - line.width()))
}
} else {
(0, x)
@@ -2719,7 +2722,7 @@ impl PositionMap {
let previous_valid = self.snapshot.clip_point(exact_unclipped, Bias::Left);
let next_valid = self.snapshot.clip_point(exact_unclipped, Bias::Right);
- let column_overshoot_after_line_end = (x_overshoot_after_line_end / self.em_advance) as u32;
+ let column_overshoot_after_line_end = (x_overshoot_after_line_end / self.em_advance).into();
*exact_unclipped.column_mut() += column_overshoot_after_line_end;
PointForPosition {
previous_valid,
@@ -2740,8 +2743,9 @@ fn layout_line(
row: u32,
snapshot: &EditorSnapshot,
style: &EditorStyle,
+ rem_size: Pixels,
text_system: &TextSystem,
-) -> Line {
+) -> Result<SmallVec<[Line; 1]>> {
let mut line = snapshot.line(row);
if line.len() > MAX_LINE_LEN {
@@ -2753,15 +2757,16 @@ fn layout_line(
line.truncate(len);
}
- text_system.layout_str(
+ text_system.layout_text(
&line,
- style.text.font_size,
+ style.text.font_size * rem_size,
&[TextRun {
len: snapshot.line_len(row) as usize,
- font: style.text.font.clone(),
- color: Hsla::black(),
+ font: style.text.font(),
+ color: black(),
underline: Default::default(),
}],
+ None,
)
}
@@ -5,29 +5,30 @@ use crate::{Editor, RangeToAnchorExt};
enum MatchingBracketHighlight {}
pub fn refresh_matching_bracket_highlights(editor: &mut Editor, cx: &mut ViewContext<Editor>) {
- editor.clear_background_highlights::<MatchingBracketHighlight>(cx);
+ todo!()
+ // // editor.clear_background_highlights::<MatchingBracketHighlight>(cx);
- let newest_selection = editor.selections.newest::<usize>(cx);
- // Don't highlight brackets if the selection isn't empty
- if !newest_selection.is_empty() {
- return;
- }
+ // let newest_selection = editor.selections.newest::<usize>(cx);
+ // // Don't highlight brackets if the selection isn't empty
+ // if !newest_selection.is_empty() {
+ // return;
+ // }
- let head = newest_selection.head();
- let snapshot = editor.snapshot(cx);
- if let Some((opening_range, closing_range)) = snapshot
- .buffer_snapshot
- .innermost_enclosing_bracket_ranges(head..head)
- {
- editor.highlight_background::<MatchingBracketHighlight>(
- vec![
- opening_range.to_anchors(&snapshot.buffer_snapshot),
- closing_range.to_anchors(&snapshot.buffer_snapshot),
- ],
- |theme| theme.editor.document_highlight_read_background,
- cx,
- )
- }
+ // let head = newest_selection.head();
+ // let snapshot = editor.snapshot(cx);
+ // if let Some((opening_range, closing_range)) = snapshot
+ // .buffer_snapshot
+ // .innermost_enclosing_bracket_ranges(head..head)
+ // {
+ // editor.highlight_background::<MatchingBracketHighlight>(
+ // vec![
+ // opening_range.to_anchors(&snapshot.buffer_snapshot),
+ // closing_range.to_anchors(&snapshot.buffer_snapshot),
+ // ],
+ // |theme| theme.editor.document_highlight_read_background,
+ // cx,
+ // )
+ // }
}
// #[cfg(test)]
@@ -1,17 +1,14 @@
use crate::{
- display_map::{InlayOffset, ToDisplayPoint},
+ display_map::InlayOffset,
link_go_to_definition::{InlayHighlight, RangeInEditor},
Anchor, AnchorRangeExt, DisplayPoint, Editor, EditorSettings, EditorSnapshot, EditorStyle,
ExcerptId, RangeToAnchorExt,
};
use futures::FutureExt;
-use gpui::{
- AnyElement, AppContext, CursorStyle, Element, Model, MouseButton, Task, ViewContext, WeakView,
-};
-use language::{
- markdown, Bias, DiagnosticEntry, DiagnosticSeverity, Language, LanguageRegistry, ParsedMarkdown,
-};
+use gpui::{AnyElement, AppContext, Model, Task, ViewContext, WeakView};
+use language::{markdown, Bias, DiagnosticEntry, Language, LanguageRegistry, ParsedMarkdown};
use project::{HoverBlock, HoverBlockKind, InlayHintLabelPart, Project};
+use settings::Settings;
use std::{ops::Range, sync::Arc, time::Duration};
use util::TryFutureExt;
use workspace::Workspace;
@@ -77,63 +74,64 @@ pub fn find_hovered_hint_part(
}
pub fn hover_at_inlay(editor: &mut Editor, inlay_hover: InlayHover, cx: &mut ViewContext<Editor>) {
- if EditorSettings::get_global(cx).hover_popover_enabled {
- if editor.pending_rename.is_some() {
- return;
- }
-
- let Some(project) = editor.project.clone() else {
- return;
- };
-
- if let Some(InfoPopover { symbol_range, .. }) = &editor.hover_state.info_popover {
- if let RangeInEditor::Inlay(range) = symbol_range {
- if range == &inlay_hover.range {
- // Hover triggered from same location as last time. Don't show again.
- return;
- }
- }
- hide_hover(editor, cx);
- }
-
- let task = cx.spawn(|this, mut cx| {
- async move {
- cx.background()
- .timer(Duration::from_millis(HOVER_DELAY_MILLIS))
- .await;
- this.update(&mut cx, |this, _| {
- this.hover_state.diagnostic_popover = None;
- })?;
-
- let language_registry = project.update(&mut cx, |p, _| p.languages().clone());
- let blocks = vec![inlay_hover.tooltip];
- let parsed_content = parse_blocks(&blocks, &language_registry, None).await;
-
- let hover_popover = InfoPopover {
- project: project.clone(),
- symbol_range: RangeInEditor::Inlay(inlay_hover.range.clone()),
- blocks,
- parsed_content,
- };
-
- this.update(&mut cx, |this, cx| {
- // Highlight the selected symbol using a background highlight
- this.highlight_inlay_background::<HoverState>(
- vec![inlay_hover.range],
- |theme| theme.editor.hover_popover.highlight,
- cx,
- );
- this.hover_state.info_popover = Some(hover_popover);
- cx.notify();
- })?;
-
- anyhow::Ok(())
- }
- .log_err()
- });
-
- editor.hover_state.info_task = Some(task);
- }
+ todo!()
+ // if EditorSettings::get_global(cx).hover_popover_enabled {
+ // if editor.pending_rename.is_some() {
+ // return;
+ // }
+
+ // let Some(project) = editor.project.clone() else {
+ // return;
+ // };
+
+ // if let Some(InfoPopover { symbol_range, .. }) = &editor.hover_state.info_popover {
+ // if let RangeInEditor::Inlay(range) = symbol_range {
+ // if range == &inlay_hover.range {
+ // // Hover triggered from same location as last time. Don't show again.
+ // return;
+ // }
+ // }
+ // hide_hover(editor, cx);
+ // }
+
+ // let task = cx.spawn(|this, mut cx| {
+ // async move {
+ // cx.background_executor()
+ // .timer(Duration::from_millis(HOVER_DELAY_MILLIS))
+ // .await;
+ // this.update(&mut cx, |this, _| {
+ // this.hover_state.diagnostic_popover = None;
+ // })?;
+
+ // let language_registry = project.update(&mut cx, |p, _| p.languages().clone())?;
+ // let blocks = vec![inlay_hover.tooltip];
+ // let parsed_content = parse_blocks(&blocks, &language_registry, None).await;
+
+ // let hover_popover = InfoPopover {
+ // project: project.clone(),
+ // symbol_range: RangeInEditor::Inlay(inlay_hover.range.clone()),
+ // blocks,
+ // parsed_content,
+ // };
+
+ // this.update(&mut cx, |this, cx| {
+ // // Highlight the selected symbol using a background highlight
+ // this.highlight_inlay_background::<HoverState>(
+ // vec![inlay_hover.range],
+ // |theme| theme.editor.hover_popover.highlight,
+ // cx,
+ // );
+ // this.hover_state.info_popover = Some(hover_popover);
+ // cx.notify();
+ // })?;
+
+ // anyhow::Ok(())
+ // }
+ // .log_err()
+ // });
+
+ // editor.hover_state.info_task = Some(task);
+ // }
}
/// Hides the type information popup.
@@ -146,7 +144,8 @@ pub fn hide_hover(editor: &mut Editor, cx: &mut ViewContext<Editor>) -> bool {
editor.hover_state.info_task = None;
editor.hover_state.triggered_from = None;
- editor.clear_background_highlights::<HoverState>(cx);
+ // todo!()
+ // editor.clear_background_highlights::<HoverState>(cx);
if did_hide {
cx.notify();
@@ -237,11 +236,11 @@ fn show_hover(
let delay = if !ignore_timeout {
// Construct delay task to wait for later
let total_delay = Some(
- cx.background()
+ cx.background_executor()
.timer(Duration::from_millis(HOVER_DELAY_MILLIS)),
);
- cx.background()
+ cx.background_executor()
.timer(Duration::from_millis(HOVER_REQUEST_DELAY_MILLIS))
.await;
total_delay
@@ -250,11 +249,11 @@ fn show_hover(
};
// query the LSP for hover info
- let hover_request = cx.update(|cx| {
+ let hover_request = cx.update(|_, cx| {
project.update(cx, |project, cx| {
project.hover(&buffer, buffer_position, cx)
})
- });
+ })?;
if let Some(delay) = delay {
delay.await;
@@ -308,7 +307,8 @@ fn show_hover(
anchor..anchor
};
- let language_registry = project.update(&mut cx, |p, _| p.languages().clone());
+ let language_registry =
+ project.update(&mut cx, |p, _| p.languages().clone())?;
let blocks = hover_result.contents;
let language = hover_result.language;
let parsed_content = parse_blocks(&blocks, &language_registry, language).await;
@@ -325,22 +325,23 @@ fn show_hover(
};
this.update(&mut cx, |this, cx| {
- if let Some(symbol_range) = hover_popover
- .as_ref()
- .and_then(|hover_popover| hover_popover.symbol_range.as_text_range())
- {
- // Highlight the selected symbol using a background highlight
- this.highlight_background::<HoverState>(
- vec![symbol_range],
- |theme| theme.editor.hover_popover.highlight,
- cx,
- );
- } else {
- this.clear_background_highlights::<HoverState>(cx);
- }
-
- this.hover_state.info_popover = hover_popover;
- cx.notify();
+ todo!();
+ // if let Some(symbol_range) = hover_popover
+ // .as_ref()
+ // .and_then(|hover_popover| hover_popover.symbol_range.as_text_range())
+ // {
+ // // Highlight the selected symbol using a background highlight
+ // this.highlight_background::<HoverState>(
+ // vec![symbol_range],
+ // |theme| theme.editor.hover_popover.highlight,
+ // cx,
+ // );
+ // } else {
+ // this.clear_background_highlights::<HoverState>(cx);
+ // }
+ //
+ // this.hover_state.info_popover = hover_popover;
+ // cx.notify();
})?;
Ok::<_, anyhow::Error>(())
@@ -424,38 +425,40 @@ impl HoverState {
workspace: Option<WeakView<Workspace>>,
cx: &mut ViewContext<Editor>,
) -> Option<(DisplayPoint, Vec<AnyElement<Editor>>)> {
- // If there is a diagnostic, position the popovers based on that.
- // Otherwise use the start of the hover range
- let anchor = self
- .diagnostic_popover
- .as_ref()
- .map(|diagnostic_popover| &diagnostic_popover.local_diagnostic.range.start)
- .or_else(|| {
- self.info_popover
- .as_ref()
- .map(|info_popover| match &info_popover.symbol_range {
- RangeInEditor::Text(range) => &range.start,
- RangeInEditor::Inlay(range) => &range.inlay_position,
- })
- })?;
- let point = anchor.to_display_point(&snapshot.display_snapshot);
-
- // Don't render if the relevant point isn't on screen
- if !self.visible() || !visible_rows.contains(&point.row()) {
- return None;
- }
-
- let mut elements = Vec::new();
-
- if let Some(diagnostic_popover) = self.diagnostic_popover.as_ref() {
- elements.push(diagnostic_popover.render(style, cx));
- }
- if let Some(info_popover) = self.info_popover.as_mut() {
- elements.push(info_popover.render(style, workspace, cx));
- }
-
- Some((point, elements))
+ todo!("old version below")
}
+ // // If there is a diagnostic, position the popovers based on that.
+ // // Otherwise use the start of the hover range
+ // let anchor = self
+ // .diagnostic_popover
+ // .as_ref()
+ // .map(|diagnostic_popover| &diagnostic_popover.local_diagnostic.range.start)
+ // .or_else(|| {
+ // self.info_popover
+ // .as_ref()
+ // .map(|info_popover| match &info_popover.symbol_range {
+ // RangeInEditor::Text(range) => &range.start,
+ // RangeInEditor::Inlay(range) => &range.inlay_position,
+ // })
+ // })?;
+ // let point = anchor.to_display_point(&snapshot.display_snapshot);
+
+ // // Don't render if the relevant point isn't on screen
+ // if !self.visible() || !visible_rows.contains(&point.row()) {
+ // return None;
+ // }
+
+ // let mut elements = Vec::new();
+
+ // if let Some(diagnostic_popover) = self.diagnostic_popover.as_ref() {
+ // elements.push(diagnostic_popover.render(style, cx));
+ // }
+ // if let Some(info_popover) = self.info_popover.as_mut() {
+ // elements.push(info_popover.render(style, workspace, cx));
+ // }
+
+ // Some((point, elements))
+ // }
}
#[derive(Debug, Clone)]
@@ -553,17 +553,18 @@ impl InlayHintCache {
let mut resolved_hint =
resolved_hint_task.await.context("hint resolve task")?;
editor.update(&mut cx, |editor, _| {
- if let Some(excerpt_hints) =
- editor.inlay_hint_cache.hints.get(&excerpt_id)
- {
- let mut guard = excerpt_hints.write();
- if let Some(cached_hint) = guard.hints_by_id.get_mut(&id) {
- if cached_hint.resolve_state == ResolveState::Resolving {
- resolved_hint.resolve_state = ResolveState::Resolved;
- *cached_hint = resolved_hint;
- }
- }
- }
+ todo!()
+ // if let Some(excerpt_hints) =
+ // editor.inlay_hint_cache.hints.get(&excerpt_id)
+ // {
+ // let mut guard = excerpt_hints.write();
+ // if let Some(cached_hint) = guard.hints_by_id.get_mut(&id) {
+ // if cached_hint.resolve_state == ResolveState::Resolving {
+ // resolved_hint.resolve_state = ResolveState::Resolved;
+ // *cached_hint = resolved_hint;
+ // }
+ // }
+ // }
})?;
}
@@ -584,89 +585,91 @@ fn spawn_new_update_tasks(
update_cache_version: usize,
cx: &mut ViewContext<'_, Editor>,
) {
- let visible_hints = Arc::new(editor.visible_inlay_hints(cx));
- for (excerpt_id, (excerpt_buffer, new_task_buffer_version, excerpt_visible_range)) in
- excerpts_to_query
- {
- if excerpt_visible_range.is_empty() {
- continue;
- }
- let buffer = excerpt_buffer.read(cx);
- let buffer_id = buffer.remote_id();
- let buffer_snapshot = buffer.snapshot();
- if buffer_snapshot
- .version()
- .changed_since(&new_task_buffer_version)
- {
- continue;
- }
-
- let cached_excerpt_hints = editor.inlay_hint_cache.hints.get(&excerpt_id).cloned();
- if let Some(cached_excerpt_hints) = &cached_excerpt_hints {
- let cached_excerpt_hints = cached_excerpt_hints.read();
- let cached_buffer_version = &cached_excerpt_hints.buffer_version;
- if cached_excerpt_hints.version > update_cache_version
- || cached_buffer_version.changed_since(&new_task_buffer_version)
- {
- continue;
- }
- };
-
- let (multi_buffer_snapshot, Some(query_ranges)) =
- editor.buffer.update(cx, |multi_buffer, cx| {
- (
- multi_buffer.snapshot(cx),
- determine_query_ranges(
- multi_buffer,
- excerpt_id,
- &excerpt_buffer,
- excerpt_visible_range,
- cx,
- ),
- )
- })
- else {
- return;
- };
- let query = ExcerptQuery {
- buffer_id,
- excerpt_id,
- cache_version: update_cache_version,
- invalidate,
- reason,
- };
+ todo!("old version below");
+}
+// let visible_hints = Arc::new(editor.visible_inlay_hints(cx));
+// for (excerpt_id, (excerpt_buffer, new_task_buffer_version, excerpt_visible_range)) in
+// excerpts_to_query
+// {
+// if excerpt_visible_range.is_empty() {
+// continue;
+// }
+// let buffer = excerpt_buffer.read(cx);
+// let buffer_id = buffer.remote_id();
+// let buffer_snapshot = buffer.snapshot();
+// if buffer_snapshot
+// .version()
+// .changed_since(&new_task_buffer_version)
+// {
+// continue;
+// }
- let new_update_task = |query_ranges| {
- new_update_task(
- query,
- query_ranges,
- multi_buffer_snapshot,
- buffer_snapshot.clone(),
- Arc::clone(&visible_hints),
- cached_excerpt_hints,
- Arc::clone(&editor.inlay_hint_cache.lsp_request_limiter),
- cx,
- )
- };
+// let cached_excerpt_hints = editor.inlay_hint_cache.hints.get(&excerpt_id).cloned();
+// if let Some(cached_excerpt_hints) = &cached_excerpt_hints {
+// let cached_excerpt_hints = cached_excerpt_hints.read();
+// let cached_buffer_version = &cached_excerpt_hints.buffer_version;
+// if cached_excerpt_hints.version > update_cache_version
+// || cached_buffer_version.changed_since(&new_task_buffer_version)
+// {
+// continue;
+// }
+// };
+
+// let (multi_buffer_snapshot, Some(query_ranges)) =
+// editor.buffer.update(cx, |multi_buffer, cx| {
+// (
+// multi_buffer.snapshot(cx),
+// determine_query_ranges(
+// multi_buffer,
+// excerpt_id,
+// &excerpt_buffer,
+// excerpt_visible_range,
+// cx,
+// ),
+// )
+// })
+// else {
+// return;
+// };
+// let query = ExcerptQuery {
+// buffer_id,
+// excerpt_id,
+// cache_version: update_cache_version,
+// invalidate,
+// reason,
+// };
+
+// let new_update_task = |query_ranges| {
+// new_update_task(
+// query,
+// query_ranges,
+// multi_buffer_snapshot,
+// buffer_snapshot.clone(),
+// Arc::clone(&visible_hints),
+// cached_excerpt_hints,
+// Arc::clone(&editor.inlay_hint_cache.lsp_request_limiter),
+// cx,
+// )
+// };
- match editor.inlay_hint_cache.update_tasks.entry(excerpt_id) {
- hash_map::Entry::Occupied(mut o) => {
- o.get_mut().update_cached_tasks(
- &buffer_snapshot,
- query_ranges,
- invalidate,
- new_update_task,
- );
- }
- hash_map::Entry::Vacant(v) => {
- v.insert(TasksForRanges::new(
- query_ranges.clone(),
- new_update_task(query_ranges),
- ));
- }
- }
- }
-}
+// match editor.inlay_hint_cache.update_tasks.entry(excerpt_id) {
+// hash_map::Entry::Occupied(mut o) => {
+// o.get_mut().update_cached_tasks(
+// &buffer_snapshot,
+// query_ranges,
+// invalidate,
+// new_update_task,
+// );
+// }
+// hash_map::Entry::Vacant(v) => {
+// v.insert(TasksForRanges::new(
+// query_ranges.clone(),
+// new_update_task(query_ranges),
+// ));
+// }
+// }
+// }
+// }
#[derive(Debug, Clone)]
struct QueryRanges {
@@ -762,78 +765,79 @@ fn new_update_task(
lsp_request_limiter: Arc<Semaphore>,
cx: &mut ViewContext<'_, Editor>,
) -> Task<()> {
- cx.spawn(|editor, mut cx| async move {
- let closure_cx = cx.clone();
- let fetch_and_update_hints = |invalidate, range| {
- fetch_and_update_hints(
- editor.clone(),
- multi_buffer_snapshot.clone(),
- buffer_snapshot.clone(),
- Arc::clone(&visible_hints),
- cached_excerpt_hints.as_ref().map(Arc::clone),
- query,
- invalidate,
- range,
- Arc::clone(&lsp_request_limiter),
- closure_cx.clone(),
- )
- };
- let visible_range_update_results = future::join_all(query_ranges.visible.into_iter().map(
- |visible_range| async move {
- (
- visible_range.clone(),
- fetch_and_update_hints(query.invalidate.should_invalidate(), visible_range)
- .await,
- )
- },
- ))
- .await;
-
- let hint_delay = cx.background().timer(Duration::from_millis(
- INVISIBLE_RANGES_HINTS_REQUEST_DELAY_MILLIS,
- ));
-
- let mut query_range_failed = |range: &Range<language::Anchor>, e: anyhow::Error| {
- log::error!("inlay hint update task for range {range:?} failed: {e:#}");
- editor
- .update(&mut cx, |editor, _| {
- if let Some(task_ranges) = editor
- .inlay_hint_cache
- .update_tasks
- .get_mut(&query.excerpt_id)
- {
- task_ranges.invalidate_range(&buffer_snapshot, &range);
- }
- })
- .ok()
- };
-
- for (range, result) in visible_range_update_results {
- if let Err(e) = result {
- query_range_failed(&range, e);
- }
- }
-
- hint_delay.await;
- let invisible_range_update_results = future::join_all(
- query_ranges
- .before_visible
- .into_iter()
- .chain(query_ranges.after_visible.into_iter())
- .map(|invisible_range| async move {
- (
- invisible_range.clone(),
- fetch_and_update_hints(false, invisible_range).await,
- )
- }),
- )
- .await;
- for (range, result) in invisible_range_update_results {
- if let Err(e) = result {
- query_range_failed(&range, e);
- }
- }
- })
+ todo!()
+ // cx.spawn(|editor, mut cx| async move {
+ // let closure_cx = cx.clone();
+ // let fetch_and_update_hints = |invalidate, range| {
+ // fetch_and_update_hints(
+ // editor.clone(),
+ // multi_buffer_snapshot.clone(),
+ // buffer_snapshot.clone(),
+ // Arc::clone(&visible_hints),
+ // cached_excerpt_hints.as_ref().map(Arc::clone),
+ // query,
+ // invalidate,
+ // range,
+ // Arc::clone(&lsp_request_limiter),
+ // closure_cx.clone(),
+ // )
+ // };
+ // let visible_range_update_results = future::join_all(query_ranges.visible.into_iter().map(
+ // |visible_range| async move {
+ // (
+ // visible_range.clone(),
+ // fetch_and_update_hints(query.invalidate.should_invalidate(), visible_range)
+ // .await,
+ // )
+ // },
+ // ))
+ // .await;
+
+ // let hint_delay = cx.background().timer(Duration::from_millis(
+ // INVISIBLE_RANGES_HINTS_REQUEST_DELAY_MILLIS,
+ // ));
+
+ // let mut query_range_failed = |range: &Range<language::Anchor>, e: anyhow::Error| {
+ // log::error!("inlay hint update task for range {range:?} failed: {e:#}");
+ // editor
+ // .update(&mut cx, |editor, _| {
+ // if let Some(task_ranges) = editor
+ // .inlay_hint_cache
+ // .update_tasks
+ // .get_mut(&query.excerpt_id)
+ // {
+ // task_ranges.invalidate_range(&buffer_snapshot, &range);
+ // }
+ // })
+ // .ok()
+ // };
+
+ // for (range, result) in visible_range_update_results {
+ // if let Err(e) = result {
+ // query_range_failed(&range, e);
+ // }
+ // }
+
+ // hint_delay.await;
+ // let invisible_range_update_results = future::join_all(
+ // query_ranges
+ // .before_visible
+ // .into_iter()
+ // .chain(query_ranges.after_visible.into_iter())
+ // .map(|invisible_range| async move {
+ // (
+ // invisible_range.clone(),
+ // fetch_and_update_hints(false, invisible_range).await,
+ // )
+ // }),
+ // )
+ // .await;
+ // for (range, result) in invisible_range_update_results {
+ // if let Err(e) = result {
+ // query_range_failed(&range, e);
+ // }
+ // }
+ // })
}
// async fn fetch_and_update_hints(
@@ -1073,126 +1077,128 @@ fn apply_hint_update(
multi_buffer_snapshot: MultiBufferSnapshot,
cx: &mut ViewContext<'_, Editor>,
) {
- let cached_excerpt_hints = editor
- .inlay_hint_cache
- .hints
- .entry(new_update.excerpt_id)
- .or_insert_with(|| {
- Arc::new(RwLock::new(CachedExcerptHints {
- version: query.cache_version,
- buffer_version: buffer_snapshot.version().clone(),
- buffer_id: query.buffer_id,
- ordered_hints: Vec::new(),
- hints_by_id: HashMap::default(),
- }))
- });
- let mut cached_excerpt_hints = cached_excerpt_hints.write();
- match query.cache_version.cmp(&cached_excerpt_hints.version) {
- cmp::Ordering::Less => return,
- cmp::Ordering::Greater | cmp::Ordering::Equal => {
- cached_excerpt_hints.version = query.cache_version;
- }
- }
-
- let mut cached_inlays_changed = !new_update.remove_from_cache.is_empty();
- cached_excerpt_hints
- .ordered_hints
- .retain(|hint_id| !new_update.remove_from_cache.contains(hint_id));
- cached_excerpt_hints
- .hints_by_id
- .retain(|hint_id, _| !new_update.remove_from_cache.contains(hint_id));
- let mut splice = InlaySplice {
- to_remove: new_update.remove_from_visible,
- to_insert: Vec::new(),
- };
- for new_hint in new_update.add_to_cache {
- let insert_position = match cached_excerpt_hints
- .ordered_hints
- .binary_search_by(|probe| {
- cached_excerpt_hints.hints_by_id[probe]
- .position
- .cmp(&new_hint.position, &buffer_snapshot)
- }) {
- Ok(i) => {
- let mut insert_position = Some(i);
- for id in &cached_excerpt_hints.ordered_hints[i..] {
- let cached_hint = &cached_excerpt_hints.hints_by_id[id];
- if new_hint
- .position
- .cmp(&cached_hint.position, &buffer_snapshot)
- .is_gt()
- {
- break;
- }
- if cached_hint.text() == new_hint.text() {
- insert_position = None;
- break;
- }
- }
- insert_position
- }
- Err(i) => Some(i),
- };
+ todo!("old implementation commented below")
+}
+// let cached_excerpt_hints = editor
+// .inlay_hint_cache
+// .hints
+// .entry(new_update.excerpt_id)
+// .or_insert_with(|| {
+// Arc::new(RwLock::new(CachedExcerptHints {
+// version: query.cache_version,
+// buffer_version: buffer_snapshot.version().clone(),
+// buffer_id: query.buffer_id,
+// ordered_hints: Vec::new(),
+// hints_by_id: HashMap::default(),
+// }))
+// });
+// let mut cached_excerpt_hints = cached_excerpt_hints.write();
+// match query.cache_version.cmp(&cached_excerpt_hints.version) {
+// cmp::Ordering::Less => return,
+// cmp::Ordering::Greater | cmp::Ordering::Equal => {
+// cached_excerpt_hints.version = query.cache_version;
+// }
+// }
- if let Some(insert_position) = insert_position {
- let new_inlay_id = post_inc(&mut editor.next_inlay_id);
- if editor
- .inlay_hint_cache
- .allowed_hint_kinds
- .contains(&new_hint.kind)
- {
- let new_hint_position =
- multi_buffer_snapshot.anchor_in_excerpt(query.excerpt_id, new_hint.position);
- splice
- .to_insert
- .push(Inlay::hint(new_inlay_id, new_hint_position, &new_hint));
- }
- let new_id = InlayId::Hint(new_inlay_id);
- cached_excerpt_hints.hints_by_id.insert(new_id, new_hint);
- cached_excerpt_hints
- .ordered_hints
- .insert(insert_position, new_id);
- cached_inlays_changed = true;
- }
- }
- cached_excerpt_hints.buffer_version = buffer_snapshot.version().clone();
- drop(cached_excerpt_hints);
+// let mut cached_inlays_changed = !new_update.remove_from_cache.is_empty();
+// cached_excerpt_hints
+// .ordered_hints
+// .retain(|hint_id| !new_update.remove_from_cache.contains(hint_id));
+// cached_excerpt_hints
+// .hints_by_id
+// .retain(|hint_id, _| !new_update.remove_from_cache.contains(hint_id));
+// let mut splice = InlaySplice {
+// to_remove: new_update.remove_from_visible,
+// to_insert: Vec::new(),
+// };
+// for new_hint in new_update.add_to_cache {
+// let insert_position = match cached_excerpt_hints
+// .ordered_hints
+// .binary_search_by(|probe| {
+// cached_excerpt_hints.hints_by_id[probe]
+// .position
+// .cmp(&new_hint.position, &buffer_snapshot)
+// }) {
+// Ok(i) => {
+// let mut insert_position = Some(i);
+// for id in &cached_excerpt_hints.ordered_hints[i..] {
+// let cached_hint = &cached_excerpt_hints.hints_by_id[id];
+// if new_hint
+// .position
+// .cmp(&cached_hint.position, &buffer_snapshot)
+// .is_gt()
+// {
+// break;
+// }
+// if cached_hint.text() == new_hint.text() {
+// insert_position = None;
+// break;
+// }
+// }
+// insert_position
+// }
+// Err(i) => Some(i),
+// };
+
+// if let Some(insert_position) = insert_position {
+// let new_inlay_id = post_inc(&mut editor.next_inlay_id);
+// if editor
+// .inlay_hint_cache
+// .allowed_hint_kinds
+// .contains(&new_hint.kind)
+// {
+// let new_hint_position =
+// multi_buffer_snapshot.anchor_in_excerpt(query.excerpt_id, new_hint.position);
+// splice
+// .to_insert
+// .push(Inlay::hint(new_inlay_id, new_hint_position, &new_hint));
+// }
+// let new_id = InlayId::Hint(new_inlay_id);
+// cached_excerpt_hints.hints_by_id.insert(new_id, new_hint);
+// cached_excerpt_hints
+// .ordered_hints
+// .insert(insert_position, new_id);
+// cached_inlays_changed = true;
+// }
+// }
+// cached_excerpt_hints.buffer_version = buffer_snapshot.version().clone();
+// drop(cached_excerpt_hints);
- if invalidate {
- let mut outdated_excerpt_caches = HashSet::default();
- for (excerpt_id, excerpt_hints) in &editor.inlay_hint_cache().hints {
- let excerpt_hints = excerpt_hints.read();
- if excerpt_hints.buffer_id == query.buffer_id
- && excerpt_id != &query.excerpt_id
- && buffer_snapshot
- .version()
- .changed_since(&excerpt_hints.buffer_version)
- {
- outdated_excerpt_caches.insert(*excerpt_id);
- splice
- .to_remove
- .extend(excerpt_hints.ordered_hints.iter().copied());
- }
- }
- cached_inlays_changed |= !outdated_excerpt_caches.is_empty();
- editor
- .inlay_hint_cache
- .hints
- .retain(|excerpt_id, _| !outdated_excerpt_caches.contains(excerpt_id));
- }
+// if invalidate {
+// let mut outdated_excerpt_caches = HashSet::default();
+// for (excerpt_id, excerpt_hints) in &editor.inlay_hint_cache().hints {
+// let excerpt_hints = excerpt_hints.read();
+// if excerpt_hints.buffer_id == query.buffer_id
+// && excerpt_id != &query.excerpt_id
+// && buffer_snapshot
+// .version()
+// .changed_since(&excerpt_hints.buffer_version)
+// {
+// outdated_excerpt_caches.insert(*excerpt_id);
+// splice
+// .to_remove
+// .extend(excerpt_hints.ordered_hints.iter().copied());
+// }
+// }
+// cached_inlays_changed |= !outdated_excerpt_caches.is_empty();
+// editor
+// .inlay_hint_cache
+// .hints
+// .retain(|excerpt_id, _| !outdated_excerpt_caches.contains(excerpt_id));
+// }
- let InlaySplice {
- to_remove,
- to_insert,
- } = splice;
- let displayed_inlays_changed = !to_remove.is_empty() || !to_insert.is_empty();
- if cached_inlays_changed || displayed_inlays_changed {
- editor.inlay_hint_cache.version += 1;
- }
- if displayed_inlays_changed {
- editor.splice_inlay_hints(to_remove, to_insert, cx)
- }
-}
+// let InlaySplice {
+// to_remove,
+// to_insert,
+// } = splice;
+// let displayed_inlays_changed = !to_remove.is_empty() || !to_insert.is_empty();
+// if cached_inlays_changed || displayed_inlays_changed {
+// editor.inlay_hint_cache.version += 1;
+// }
+// if displayed_inlays_changed {
+// editor.splice_inlay_hints(to_remove, to_insert, cx)
+// }
+// }
// #[cfg(test)]
// pub mod tests {
@@ -7,7 +7,7 @@ use anyhow::{Context, Result};
use collections::HashSet;
use futures::future::try_join_all;
use gpui::{
- point, AnyElement, AppContext, AsyncAppContext, Entity, Model, Pixels, SharedString,
+ point, AnyElement, AppContext, AsyncAppContext, Entity, EntityId, Model, Pixels, SharedString,
Subscription, Task, View, ViewContext, WeakView,
};
use language::{
@@ -26,6 +26,7 @@ use std::{
sync::Arc,
};
use text::Selection;
+use theme::ThemeVariant;
use util::{paths::PathExt, ResultExt, TryFutureExt};
use workspace::item::{BreadcrumbText, FollowableItemHandle};
use workspace::{
@@ -306,12 +307,15 @@ impl FollowableItem for Editor {
}
}
-// async fn update_editor_from_message(
-// this: WeakView<Editor>,
-// project: Model<Project>,
-// message: proto::update_view::Editor,
-// cx: &mut AsyncAppContext,
-// ) -> Result<()> {
+async fn update_editor_from_message(
+ this: WeakView<Editor>,
+ project: Model<Project>,
+ message: proto::update_view::Editor,
+ cx: &mut AsyncAppContext,
+) -> Result<()> {
+ todo!()
+}
+// Previous implementation of the above
// // Open all of the buffers of which excerpts were added to the editor.
// let inserted_excerpt_buffer_ids = message
// .inserted_excerpts
@@ -512,38 +516,39 @@ fn deserialize_anchor(buffer: &MultiBufferSnapshot, anchor: proto::EditorAnchor)
impl Item for Editor {
fn navigate(&mut self, data: Box<dyn std::any::Any>, cx: &mut ViewContext<Self>) -> bool {
- if let Ok(data) = data.downcast::<NavigationData>() {
- let newest_selection = self.selections.newest::<Point>(cx);
- let buffer = self.buffer.read(cx).read(cx);
- let offset = if buffer.can_resolve(&data.cursor_anchor) {
- data.cursor_anchor.to_point(&buffer)
- } else {
- buffer.clip_point(data.cursor_position, Bias::Left)
- };
-
- let mut scroll_anchor = data.scroll_anchor;
- if !buffer.can_resolve(&scroll_anchor.anchor) {
- scroll_anchor.anchor = buffer.anchor_before(
- buffer.clip_point(Point::new(data.scroll_top_row, 0), Bias::Left),
- );
- }
-
- drop(buffer);
-
- if newest_selection.head() == offset {
- false
- } else {
- let nav_history = self.nav_history.take();
- self.set_scroll_anchor(scroll_anchor, cx);
- self.change_selections(Some(Autoscroll::fit()), cx, |s| {
- s.select_ranges([offset..offset])
- });
- self.nav_history = nav_history;
- true
- }
- } else {
- false
- }
+ todo!();
+ // if let Ok(data) = data.downcast::<NavigationData>() {
+ // let newest_selection = self.selections.newest::<Point>(cx);
+ // let buffer = self.buffer.read(cx).read(cx);
+ // let offset = if buffer.can_resolve(&data.cursor_anchor) {
+ // data.cursor_anchor.to_point(&buffer)
+ // } else {
+ // buffer.clip_point(data.cursor_position, Bias::Left)
+ // };
+
+ // let mut scroll_anchor = data.scroll_anchor;
+ // if !buffer.can_resolve(&scroll_anchor.anchor) {
+ // scroll_anchor.anchor = buffer.anchor_before(
+ // buffer.clip_point(Point::new(data.scroll_top_row, 0), Bias::Left),
+ // );
+ // }
+
+ // drop(buffer);
+
+ // if newest_selection.head() == offset {
+ // false
+ // } else {
+ // let nav_history = self.nav_history.take();
+ // self.set_scroll_anchor(scroll_anchor, cx);
+ // self.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ // s.select_ranges([offset..offset])
+ // });
+ // self.nav_history = nav_history;
+ // true
+ // }
+ // } else {
+ // false
+ // }
}
fn tab_tooltip_text(&self, cx: &AppContext) -> Option<SharedString> {
@@ -563,8 +568,8 @@ impl Item for Editor {
fn tab_description<'a>(&'a self, detail: usize, cx: &'a AppContext) -> Option<SharedString> {
match path_for_buffer(&self.buffer, detail, true, cx)? {
- Cow::Borrowed(path) => Some(path.to_string_lossy),
- Cow::Owned(path) => Some(path.to_string_lossy.to_string().into()),
+ Cow::Borrowed(path) => Some(path.to_string_lossy().into()),
+ Cow::Owned(path) => Some(path.to_string_lossy().to_string().into()),
}
}
@@ -590,10 +595,14 @@ impl Item for Editor {
// .into_any()
}
- fn for_each_project_item(&self, cx: &AppContext, f: &mut dyn FnMut(usize, &dyn project::Item)) {
+ fn for_each_project_item(
+ &self,
+ cx: &AppContext,
+ f: &mut dyn FnMut(EntityId, &dyn project::Item),
+ ) {
self.buffer
.read(cx)
- .for_each_buffer(|buffer| f(buffer.id(), buffer.read(cx)));
+ .for_each_buffer(|buffer| f(buffer.entity_id(), buffer.read(cx)));
}
fn is_singleton(&self, cx: &AppContext) -> bool {
@@ -652,20 +661,24 @@ impl Item for Editor {
if buffers.len() == 1 {
project
- .update(&mut cx, |project, cx| project.save_buffers(buffers, cx))
+ .update(&mut cx, |project, cx| project.save_buffers(buffers, cx))?
.await?;
} else {
// For multi-buffers, only save those ones that contain changes. For clean buffers
// we simulate saving by calling `Buffer::did_save`, so that language servers or
// other downstream listeners of save events get notified.
let (dirty_buffers, clean_buffers) = buffers.into_iter().partition(|buffer| {
- buffer.read_with(&cx, |buffer, _| buffer.is_dirty || buffer.has_conflict())
+ buffer
+ .update(&mut cx, |buffer, _| {
+ buffer.is_dirty() || buffer.has_conflict()
+ })
+ .unwrap_or(false)
});
project
.update(&mut cx, |project, cx| {
project.save_buffers(dirty_buffers, cx)
- })
+ })?
.await?;
for buffer in clean_buffers {
buffer.update(&mut cx, |buffer, cx| {
@@ -760,7 +773,7 @@ impl Item for Editor {
ToolbarItemLocation::PrimaryLeft { flex: None }
}
- fn breadcrumbs(&self, cx: &AppContext) -> Option<Vec<BreadcrumbText>> {
+ fn breadcrumbs(&self, variant: &ThemeVariant, cx: &AppContext) -> Option<Vec<BreadcrumbText>> {
todo!();
// let cursor = self.selections.newest_anchor().head();
// let multibuffer = &self.buffer().read(cx);
@@ -806,7 +819,7 @@ impl Item for Editor {
if let Some(file) = buffer.read(cx).file().and_then(|file| file.as_local()) {
let path = file.abs_path(cx);
- cx.background()
+ cx.background_executor()
.spawn(async move {
DB.save_path(item_id, workspace_id, path.clone())
.await
@@ -913,15 +926,17 @@ impl SearchableItem for Editor {
}
fn clear_matches(&mut self, cx: &mut ViewContext<Self>) {
- self.clear_background_highlights::<BufferSearchHighlights>(cx);
+ todo!()
+ // self.clear_background_highlights::<BufferSearchHighlights>(cx);
}
fn update_matches(&mut self, matches: Vec<Range<Anchor>>, cx: &mut ViewContext<Self>) {
- self.highlight_background::<BufferSearchHighlights>(
- matches,
- |theme| theme.search.match_background,
- cx,
- );
+ todo!()
+ // self.highlight_background::<BufferSearchHighlights>(
+ // matches,
+ // |theme| theme.search.match_background,
+ // cx,
+ // );
}
fn query_suggestion(&mut self, cx: &mut ViewContext<Self>) -> String {
@@ -952,20 +967,22 @@ impl SearchableItem for Editor {
matches: Vec<Range<Anchor>>,
cx: &mut ViewContext<Self>,
) {
- self.unfold_ranges([matches[index].clone()], false, true, cx);
- let range = self.range_for_match(&matches[index]);
- self.change_selections(Some(Autoscroll::fit()), cx, |s| {
- s.select_ranges([range]);
- })
+ todo!()
+ // self.unfold_ranges([matches[index].clone()], false, true, cx);
+ // let range = self.range_for_match(&matches[index]);
+ // self.change_selections(Some(Autoscroll::fit()), cx, |s| {
+ // s.select_ranges([range]);
+ // })
}
fn select_matches(&mut self, matches: Vec<Self::Match>, cx: &mut ViewContext<Self>) {
- self.unfold_ranges(matches.clone(), false, false, cx);
- let mut ranges = Vec::new();
- for m in &matches {
- ranges.push(self.range_for_match(&m))
- }
- self.change_selections(None, cx, |s| s.select_ranges(ranges));
+ todo!()
+ // self.unfold_ranges(matches.clone(), false, false, cx);
+ // let mut ranges = Vec::new();
+ // for m in &matches {
+ // ranges.push(self.range_for_match(&m))
+ // }
+ // self.change_selections(None, cx, |s| s.select_ranges(ranges));
}
fn replace(
&mut self,
@@ -1044,7 +1061,7 @@ impl SearchableItem for Editor {
cx: &mut ViewContext<Self>,
) -> Task<Vec<Range<Anchor>>> {
let buffer = self.buffer().read(cx).snapshot(cx);
- cx.background().spawn(async move {
+ cx.background_executor().spawn(async move {
let mut ranges = Vec::new();
if let Some((_, _, excerpt_buffer)) = buffer.as_singleton() {
ranges.extend(
@@ -170,170 +170,173 @@ pub fn update_inlay_link_and_hover_points(
shift_held: bool,
cx: &mut ViewContext<'_, Editor>,
) {
- let hovered_offset = if point_for_position.column_overshoot_after_line_end == 0 {
- Some(snapshot.display_point_to_inlay_offset(point_for_position.exact_unclipped, Bias::Left))
- } else {
- None
- };
- let mut go_to_definition_updated = false;
- let mut hover_updated = false;
- if let Some(hovered_offset) = hovered_offset {
- let buffer_snapshot = editor.buffer().read(cx).snapshot(cx);
- let previous_valid_anchor = buffer_snapshot.anchor_at(
- point_for_position.previous_valid.to_point(snapshot),
- Bias::Left,
- );
- let next_valid_anchor = buffer_snapshot.anchor_at(
- point_for_position.next_valid.to_point(snapshot),
- Bias::Right,
- );
- if let Some(hovered_hint) = editor
- .visible_inlay_hints(cx)
- .into_iter()
- .skip_while(|hint| {
- hint.position
- .cmp(&previous_valid_anchor, &buffer_snapshot)
- .is_lt()
- })
- .take_while(|hint| {
- hint.position
- .cmp(&next_valid_anchor, &buffer_snapshot)
- .is_le()
- })
- .max_by_key(|hint| hint.id)
- {
- let inlay_hint_cache = editor.inlay_hint_cache();
- let excerpt_id = previous_valid_anchor.excerpt_id;
- if let Some(cached_hint) = inlay_hint_cache.hint_by_id(excerpt_id, hovered_hint.id) {
- match cached_hint.resolve_state {
- ResolveState::CanResolve(_, _) => {
- if let Some(buffer_id) = previous_valid_anchor.buffer_id {
- inlay_hint_cache.spawn_hint_resolve(
- buffer_id,
- excerpt_id,
- hovered_hint.id,
- cx,
- );
- }
- }
- ResolveState::Resolved => {
- let mut extra_shift_left = 0;
- let mut extra_shift_right = 0;
- if cached_hint.padding_left {
- extra_shift_left += 1;
- extra_shift_right += 1;
- }
- if cached_hint.padding_right {
- extra_shift_right += 1;
- }
- match cached_hint.label {
- project::InlayHintLabel::String(_) => {
- if let Some(tooltip) = cached_hint.tooltip {
- hover_popover::hover_at_inlay(
- editor,
- InlayHover {
- excerpt: excerpt_id,
- tooltip: match tooltip {
- InlayHintTooltip::String(text) => HoverBlock {
- text,
- kind: HoverBlockKind::PlainText,
- },
- InlayHintTooltip::MarkupContent(content) => {
- HoverBlock {
- text: content.value,
- kind: content.kind,
- }
- }
- },
- range: InlayHighlight {
- inlay: hovered_hint.id,
- inlay_position: hovered_hint.position,
- range: extra_shift_left
- ..hovered_hint.text.len() + extra_shift_right,
- },
- },
- cx,
- );
- hover_updated = true;
- }
- }
- project::InlayHintLabel::LabelParts(label_parts) => {
- let hint_start =
- snapshot.anchor_to_inlay_offset(hovered_hint.position);
- if let Some((hovered_hint_part, part_range)) =
- hover_popover::find_hovered_hint_part(
- label_parts,
- hint_start,
- hovered_offset,
- )
- {
- let highlight_start =
- (part_range.start - hint_start).0 + extra_shift_left;
- let highlight_end =
- (part_range.end - hint_start).0 + extra_shift_right;
- let highlight = InlayHighlight {
- inlay: hovered_hint.id,
- inlay_position: hovered_hint.position,
- range: highlight_start..highlight_end,
- };
- if let Some(tooltip) = hovered_hint_part.tooltip {
- hover_popover::hover_at_inlay(
- editor,
- InlayHover {
- excerpt: excerpt_id,
- tooltip: match tooltip {
- InlayHintLabelPartTooltip::String(text) => {
- HoverBlock {
- text,
- kind: HoverBlockKind::PlainText,
- }
- }
- InlayHintLabelPartTooltip::MarkupContent(
- content,
- ) => HoverBlock {
- text: content.value,
- kind: content.kind,
- },
- },
- range: highlight.clone(),
- },
- cx,
- );
- hover_updated = true;
- }
- if let Some((language_server_id, location)) =
- hovered_hint_part.location
- {
- go_to_definition_updated = true;
- update_go_to_definition_link(
- editor,
- Some(GoToDefinitionTrigger::InlayHint(
- highlight,
- location,
- language_server_id,
- )),
- cmd_held,
- shift_held,
- cx,
- );
- }
- }
- }
- };
- }
- ResolveState::Resolving => {}
- }
- }
- }
- }
-
- if !go_to_definition_updated {
- update_go_to_definition_link(editor, None, cmd_held, shift_held, cx);
- }
- if !hover_updated {
- hover_popover::hover_at(editor, None, cx);
- }
+ todo!("old implementation below")
}
+// ) {
+// let hovered_offset = if point_for_position.column_overshoot_after_line_end == 0 {
+// Some(snapshot.display_point_to_inlay_offset(point_for_position.exact_unclipped, Bias::Left))
+// } else {
+// None
+// };
+// let mut go_to_definition_updated = false;
+// let mut hover_updated = false;
+// if let Some(hovered_offset) = hovered_offset {
+// let buffer_snapshot = editor.buffer().read(cx).snapshot(cx);
+// let previous_valid_anchor = buffer_snapshot.anchor_at(
+// point_for_position.previous_valid.to_point(snapshot),
+// Bias::Left,
+// );
+// let next_valid_anchor = buffer_snapshot.anchor_at(
+// point_for_position.next_valid.to_point(snapshot),
+// Bias::Right,
+// );
+// if let Some(hovered_hint) = editor
+// .visible_inlay_hints(cx)
+// .into_iter()
+// .skip_while(|hint| {
+// hint.position
+// .cmp(&previous_valid_anchor, &buffer_snapshot)
+// .is_lt()
+// })
+// .take_while(|hint| {
+// hint.position
+// .cmp(&next_valid_anchor, &buffer_snapshot)
+// .is_le()
+// })
+// .max_by_key(|hint| hint.id)
+// {
+// let inlay_hint_cache = editor.inlay_hint_cache();
+// let excerpt_id = previous_valid_anchor.excerpt_id;
+// if let Some(cached_hint) = inlay_hint_cache.hint_by_id(excerpt_id, hovered_hint.id) {
+// match cached_hint.resolve_state {
+// ResolveState::CanResolve(_, _) => {
+// if let Some(buffer_id) = previous_valid_anchor.buffer_id {
+// inlay_hint_cache.spawn_hint_resolve(
+// buffer_id,
+// excerpt_id,
+// hovered_hint.id,
+// cx,
+// );
+// }
+// }
+// ResolveState::Resolved => {
+// let mut extra_shift_left = 0;
+// let mut extra_shift_right = 0;
+// if cached_hint.padding_left {
+// extra_shift_left += 1;
+// extra_shift_right += 1;
+// }
+// if cached_hint.padding_right {
+// extra_shift_right += 1;
+// }
+// match cached_hint.label {
+// project::InlayHintLabel::String(_) => {
+// if let Some(tooltip) = cached_hint.tooltip {
+// hover_popover::hover_at_inlay(
+// editor,
+// InlayHover {
+// excerpt: excerpt_id,
+// tooltip: match tooltip {
+// InlayHintTooltip::String(text) => HoverBlock {
+// text,
+// kind: HoverBlockKind::PlainText,
+// },
+// InlayHintTooltip::MarkupContent(content) => {
+// HoverBlock {
+// text: content.value,
+// kind: content.kind,
+// }
+// }
+// },
+// range: InlayHighlight {
+// inlay: hovered_hint.id,
+// inlay_position: hovered_hint.position,
+// range: extra_shift_left
+// ..hovered_hint.text.len() + extra_shift_right,
+// },
+// },
+// cx,
+// );
+// hover_updated = true;
+// }
+// }
+// project::InlayHintLabel::LabelParts(label_parts) => {
+// let hint_start =
+// snapshot.anchor_to_inlay_offset(hovered_hint.position);
+// if let Some((hovered_hint_part, part_range)) =
+// hover_popover::find_hovered_hint_part(
+// label_parts,
+// hint_start,
+// hovered_offset,
+// )
+// {
+// let highlight_start =
+// (part_range.start - hint_start).0 + extra_shift_left;
+// let highlight_end =
+// (part_range.end - hint_start).0 + extra_shift_right;
+// let highlight = InlayHighlight {
+// inlay: hovered_hint.id,
+// inlay_position: hovered_hint.position,
+// range: highlight_start..highlight_end,
+// };
+// if let Some(tooltip) = hovered_hint_part.tooltip {
+// hover_popover::hover_at_inlay(
+// editor,
+// InlayHover {
+// excerpt: excerpt_id,
+// tooltip: match tooltip {
+// InlayHintLabelPartTooltip::String(text) => {
+// HoverBlock {
+// text,
+// kind: HoverBlockKind::PlainText,
+// }
+// }
+// InlayHintLabelPartTooltip::MarkupContent(
+// content,
+// ) => HoverBlock {
+// text: content.value,
+// kind: content.kind,
+// },
+// },
+// range: highlight.clone(),
+// },
+// cx,
+// );
+// hover_updated = true;
+// }
+// if let Some((language_server_id, location)) =
+// hovered_hint_part.location
+// {
+// go_to_definition_updated = true;
+// update_go_to_definition_link(
+// editor,
+// Some(GoToDefinitionTrigger::InlayHint(
+// highlight,
+// location,
+// language_server_id,
+// )),
+// cmd_held,
+// shift_held,
+// cx,
+// );
+// }
+// }
+// }
+// };
+// }
+// ResolveState::Resolving => {}
+// }
+// }
+// }
+// }
+
+// if !go_to_definition_updated {
+// update_go_to_definition_link(editor, None, cmd_held, shift_held, cx);
+// }
+// if !hover_updated {
+// hover_popover::hover_at(editor, None, cx);
+// }
+// }
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum LinkDefinitionKind {
@@ -570,34 +573,35 @@ fn go_to_fetched_definition_of_kind(
split: bool,
cx: &mut ViewContext<Editor>,
) {
- let cached_definitions = editor.link_go_to_definition_state.definitions.clone();
- hide_link_definition(editor, cx);
- let cached_definitions_kind = editor.link_go_to_definition_state.kind;
-
- let is_correct_kind = cached_definitions_kind == Some(kind);
- if !cached_definitions.is_empty() && is_correct_kind {
- if !editor.focused {
- cx.focus_self();
- }
-
- editor.navigate_to_definitions(cached_definitions, split, cx);
- } else {
- editor.select(
- SelectPhase::Begin {
- position: point.next_valid,
- add: false,
- click_count: 1,
- },
- cx,
- );
-
- if point.as_valid().is_some() {
- match kind {
- LinkDefinitionKind::Symbol => editor.go_to_definition(&Default::default(), cx),
- LinkDefinitionKind::Type => editor.go_to_type_definition(&Default::default(), cx),
- }
- }
- }
+ todo!();
+ // let cached_definitions = editor.link_go_to_definition_state.definitions.clone();
+ // hide_link_definition(editor, cx);
+ // let cached_definitions_kind = editor.link_go_to_definition_state.kind;
+
+ // let is_correct_kind = cached_definitions_kind == Some(kind);
+ // if !cached_definitions.is_empty() && is_correct_kind {
+ // if !editor.focused {
+ // cx.focus_self();
+ // }
+
+ // editor.navigate_to_definitions(cached_definitions, split, cx);
+ // } else {
+ // editor.select(
+ // SelectPhase::Begin {
+ // position: point.next_valid,
+ // add: false,
+ // click_count: 1,
+ // },
+ // cx,
+ // );
+
+ // if point.as_valid().is_some() {
+ // match kind {
+ // LinkDefinitionKind::Symbol => editor.go_to_definition(&Default::default(), cx),
+ // LinkDefinitionKind::Type => editor.go_to_type_definition(&Default::default(), cx),
+ // }
+ // }
+ // }
}
// #[cfg(test)]
@@ -8,27 +8,28 @@ pub fn deploy_context_menu(
point: DisplayPoint,
cx: &mut ViewContext<Editor>,
) {
- if !editor.focused {
- cx.focus_self();
- }
+ todo!();
- // Don't show context menu for inline editors
- if editor.mode() != EditorMode::Full {
- return;
- }
+ // if !editor.focused {
+ // cx.focus_self();
+ // }
- // Don't show the context menu if there isn't a project associated with this editor
- if editor.project.is_none() {
- return;
- }
+ // // Don't show context menu for inline editors
+ // if editor.mode() != EditorMode::Full {
+ // return;
+ // }
- // Move the cursor to the clicked location so that dispatched actions make sense
- editor.change_selections(None, cx, |s| {
- s.clear_disjoint();
- s.set_pending_display_range(point..point, SelectMode::Character);
- });
+ // // Don't show the context menu if there isn't a project associated with this editor
+ // if editor.project.is_none() {
+ // return;
+ // }
+
+ // // Move the cursor to the clicked location so that dispatched actions make sense
+ // editor.change_selections(None, cx, |s| {
+ // s.clear_disjoint();
+ // s.set_pending_display_range(point..point, SelectMode::Character);
+ // });
- // todo!()
// editor.mouse_context_menu.update(cx, |menu, cx| {
// menu.show(
// position,
@@ -50,7 +51,7 @@ pub fn deploy_context_menu(
// cx,
// );
// });
- cx.notify();
+ // cx.notify();
}
// #[cfg(test)]
@@ -3,6 +3,7 @@ use std::path::PathBuf;
use db::sqlez_macros::sql;
use db::{define_connection, query};
+use gpui::EntityId;
use workspace::{ItemId, WorkspaceDb, WorkspaceId};
define_connection!(
@@ -66,7 +67,7 @@ impl EditorDb {
query! {
pub async fn save_scroll_position(
- item_id: ItemId,
+ item_id: EntityId,
workspace_id: WorkspaceId,
top_row: u32,
vertical_offset: f32,
@@ -9,7 +9,7 @@ use crate::{
Anchor, DisplayPoint, Editor, EditorMode, Event, InlayHintRefreshReason, MultiBufferSnapshot,
ToPoint,
};
-use gpui::{point, px, AppContext, Pixels, Styled, Task, ViewContext};
+use gpui::{point, px, AppContext, Entity, Pixels, Styled, Task, ViewContext};
use language::{Bias, Point};
use std::{
cmp::Ordering,
@@ -39,18 +39,18 @@ pub struct ScrollAnchor {
impl ScrollAnchor {
fn new() -> Self {
Self {
- offset: gpui::Point::zero(),
+ offset: gpui::Point::default(),
anchor: Anchor::min(),
}
}
- pub fn scroll_position(&self, snapshot: &DisplaySnapshot) -> gpui::Point<Pixels> {
+ pub fn scroll_position(&self, snapshot: &DisplaySnapshot) -> gpui::Point<f32> {
let mut scroll_position = self.offset;
if self.anchor != Anchor::min() {
let scroll_top = self.anchor.to_display_point(snapshot).row() as f32;
- scroll_position.set_y(scroll_top + scroll_position.y);
+ scroll_position.y = scroll_top + scroll_position.y;
} else {
- scroll_position.set_y(0.);
+ scroll_position.y = 0.;
}
scroll_position
}
@@ -133,7 +133,7 @@ pub struct ScrollManager {
anchor: ScrollAnchor,
ongoing: OngoingScroll,
autoscroll_request: Option<(Autoscroll, bool)>,
- last_autoscroll: Option<(gpui::Point<Pixels>, f32, f32, AutoscrollStrategy)>,
+ last_autoscroll: Option<(gpui::Point<f32>, f32, f32, AutoscrollStrategy)>,
show_scrollbars: bool,
hide_scrollbar_task: Option<Task<()>>,
visible_line_count: Option<f32>,
@@ -171,7 +171,7 @@ impl ScrollManager {
self.ongoing.axis = axis;
}
- pub fn scroll_position(&self, snapshot: &DisplaySnapshot) -> gpui::Point<Pixels> {
+ pub fn scroll_position(&self, snapshot: &DisplaySnapshot) -> gpui::Point<f32> {
self.anchor.scroll_position(snapshot)
}
@@ -188,7 +188,7 @@ impl ScrollManager {
(
ScrollAnchor {
anchor: Anchor::min(),
- offset: scroll_position.max(Point::zero()),
+ offset: scroll_position.max(&gpui::Point::default()),
},
0,
)
@@ -228,9 +228,9 @@ impl ScrollManager {
self.show_scrollbar(cx);
self.autoscroll_request.take();
if let Some(workspace_id) = workspace_id {
- let item_id = cx.view_id();
+ let item_id = cx.view().entity_id();
- cx.background()
+ cx.foreground_executor()
.spawn(async move {
DB.save_scroll_position(
item_id,
@@ -255,7 +255,9 @@ impl ScrollManager {
if cx.default_global::<ScrollbarAutoHide>().0 {
self.hide_scrollbar_task = Some(cx.spawn(|editor, mut cx| async move {
- cx.background().timer(SCROLLBAR_SHOW_INTERVAL).await;
+ cx.background_executor()
+ .timer(SCROLLBAR_SHOW_INTERVAL)
+ .await;
editor
.update(&mut cx, |editor, cx| {
editor.scroll_manager.show_scrollbars = false;
@@ -287,160 +289,161 @@ impl ScrollManager {
}
// todo!()
-// impl Editor {
-// pub fn vertical_scroll_margin(&mut self) -> usize {
-// self.scroll_manager.vertical_scroll_margin as usize
-// }
-
-// pub fn set_vertical_scroll_margin(&mut self, margin_rows: usize, cx: &mut ViewContext<Self>) {
-// self.scroll_manager.vertical_scroll_margin = margin_rows as f32;
-// cx.notify();
-// }
-
-// pub fn visible_line_count(&self) -> Option<f32> {
-// self.scroll_manager.visible_line_count
-// }
-
-// pub(crate) fn set_visible_line_count(&mut self, lines: f32, cx: &mut ViewContext<Self>) {
-// let opened_first_time = self.scroll_manager.visible_line_count.is_none();
-// self.scroll_manager.visible_line_count = Some(lines);
-// if opened_first_time {
-// cx.spawn(|editor, mut cx| async move {
-// editor
-// .update(&mut cx, |editor, cx| {
-// editor.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx)
-// })
-// .ok()
-// })
-// .detach()
-// }
-// }
-
-// pub fn set_scroll_position(
-// &mut self,
-// scroll_position: gpui::Point<Pixels>,
-// cx: &mut ViewContext<Self>,
-// ) {
-// self.set_scroll_position_internal(scroll_position, true, false, cx);
-// }
-
-// pub(crate) fn set_scroll_position_internal(
-// &mut self,
-// scroll_position: gpui::Point<Pixels>,
-// local: bool,
-// autoscroll: bool,
-// cx: &mut ViewContext<Self>,
-// ) {
-// let map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-
-// hide_hover(self, cx);
-// let workspace_id = self.workspace.as_ref().map(|workspace| workspace.1);
-// self.scroll_manager.set_scroll_position(
-// scroll_position,
-// &map,
-// local,
-// autoscroll,
-// workspace_id,
-// cx,
-// );
-
-// self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
-// }
-
-// pub fn scroll_position(&self, cx: &mut ViewContext<Self>) -> gpui::Point<Pixels> {
-// let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-// self.scroll_manager.anchor.scroll_position(&display_map)
-// }
-
-// pub fn set_scroll_anchor(&mut self, scroll_anchor: ScrollAnchor, cx: &mut ViewContext<Self>) {
-// hide_hover(self, cx);
-// let workspace_id = self.workspace.as_ref().map(|workspace| workspace.1);
-// let top_row = scroll_anchor
-// .anchor
-// .to_point(&self.buffer().read(cx).snapshot(cx))
-// .row;
-// self.scroll_manager
-// .set_anchor(scroll_anchor, top_row, true, false, workspace_id, cx);
-// }
-
-// pub(crate) fn set_scroll_anchor_remote(
-// &mut self,
-// scroll_anchor: ScrollAnchor,
-// cx: &mut ViewContext<Self>,
-// ) {
-// hide_hover(self, cx);
-// let workspace_id = self.workspace.as_ref().map(|workspace| workspace.1);
-// let top_row = scroll_anchor
-// .anchor
-// .to_point(&self.buffer().read(cx).snapshot(cx))
-// .row;
-// self.scroll_manager
-// .set_anchor(scroll_anchor, top_row, false, false, workspace_id, cx);
-// }
-
-// pub fn scroll_screen(&mut self, amount: &ScrollAmount, cx: &mut ViewContext<Self>) {
-// if matches!(self.mode, EditorMode::SingleLine) {
-// cx.propagate_action();
-// return;
-// }
-
-// if self.take_rename(true, cx).is_some() {
-// return;
-// }
-
-// let cur_position = self.scroll_position(cx);
-// let new_pos = cur_position + point(0., amount.lines(self));
-// self.set_scroll_position(new_pos, cx);
-// }
-
-// /// Returns an ordering. The newest selection is:
-// /// Ordering::Equal => on screen
-// /// Ordering::Less => above the screen
-// /// Ordering::Greater => below the screen
-// pub fn newest_selection_on_screen(&self, cx: &mut AppContext) -> Ordering {
-// let snapshot = self.display_map.update(cx, |map, cx| map.snapshot(cx));
-// let newest_head = self
-// .selections
-// .newest_anchor()
-// .head()
-// .to_display_point(&snapshot);
-// let screen_top = self
-// .scroll_manager
-// .anchor
-// .anchor
-// .to_display_point(&snapshot);
-
-// if screen_top > newest_head {
-// return Ordering::Less;
-// }
-
-// if let Some(visible_lines) = self.visible_line_count() {
-// if newest_head.row() < screen_top.row() + visible_lines as u32 {
-// return Ordering::Equal;
-// }
-// }
-
-// Ordering::Greater
-// }
-
-// pub fn read_scroll_position_from_db(
-// &mut self,
-// item_id: usize,
-// workspace_id: WorkspaceId,
-// cx: &mut ViewContext<Editor>,
-// ) {
-// let scroll_position = DB.get_scroll_position(item_id, workspace_id);
-// if let Ok(Some((top_row, x, y))) = scroll_position {
-// let top_anchor = self
-// .buffer()
-// .read(cx)
-// .snapshot(cx)
-// .anchor_at(Point::new(top_row as u32, 0), Bias::Left);
-// let scroll_anchor = ScrollAnchor {
-// offset: Point::new(x, y),
-// anchor: top_anchor,
-// };
-// self.set_scroll_anchor(scroll_anchor, cx);
-// }
-// }
-// }
+impl Editor {
+ // pub fn vertical_scroll_margin(&mut self) -> usize {
+ // self.scroll_manager.vertical_scroll_margin as usize
+ // }
+
+ // pub fn set_vertical_scroll_margin(&mut self, margin_rows: usize, cx: &mut ViewContext<Self>) {
+ // self.scroll_manager.vertical_scroll_margin = margin_rows as f32;
+ // cx.notify();
+ // }
+
+ // pub fn visible_line_count(&self) -> Option<f32> {
+ // self.scroll_manager.visible_line_count
+ // }
+
+ // pub(crate) fn set_visible_line_count(&mut self, lines: f32, cx: &mut ViewContext<Self>) {
+ // let opened_first_time = self.scroll_manager.visible_line_count.is_none();
+ // self.scroll_manager.visible_line_count = Some(lines);
+ // if opened_first_time {
+ // cx.spawn(|editor, mut cx| async move {
+ // editor
+ // .update(&mut cx, |editor, cx| {
+ // editor.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx)
+ // })
+ // .ok()
+ // })
+ // .detach()
+ // }
+ // }
+
+ pub fn set_scroll_position(
+ &mut self,
+ scroll_position: gpui::Point<f32>,
+ cx: &mut ViewContext<Self>,
+ ) {
+ self.set_scroll_position_internal(scroll_position, true, false, cx);
+ }
+
+ pub(crate) fn set_scroll_position_internal(
+ &mut self,
+ scroll_position: gpui::Point<f32>,
+ local: bool,
+ autoscroll: bool,
+ cx: &mut ViewContext<Self>,
+ ) {
+ let map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
+
+ hide_hover(self, cx);
+ let workspace_id = self.workspace.as_ref().map(|workspace| workspace.1);
+ self.scroll_manager.set_scroll_position(
+ scroll_position,
+ &map,
+ local,
+ autoscroll,
+ workspace_id,
+ cx,
+ );
+
+ // todo!()
+ // self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
+ }
+
+ // pub fn scroll_position(&self, cx: &mut ViewContext<Self>) -> gpui::Point<Pixels> {
+ // let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
+ // self.scroll_manager.anchor.scroll_position(&display_map)
+ // }
+
+ // pub fn set_scroll_anchor(&mut self, scroll_anchor: ScrollAnchor, cx: &mut ViewContext<Self>) {
+ // hide_hover(self, cx);
+ // let workspace_id = self.workspace.as_ref().map(|workspace| workspace.1);
+ // let top_row = scroll_anchor
+ // .anchor
+ // .to_point(&self.buffer().read(cx).snapshot(cx))
+ // .row;
+ // self.scroll_manager
+ // .set_anchor(scroll_anchor, top_row, true, false, workspace_id, cx);
+ // }
+
+ // pub(crate) fn set_scroll_anchor_remote(
+ // &mut self,
+ // scroll_anchor: ScrollAnchor,
+ // cx: &mut ViewContext<Self>,
+ // ) {
+ // hide_hover(self, cx);
+ // let workspace_id = self.workspace.as_ref().map(|workspace| workspace.1);
+ // let top_row = scroll_anchor
+ // .anchor
+ // .to_point(&self.buffer().read(cx).snapshot(cx))
+ // .row;
+ // self.scroll_manager
+ // .set_anchor(scroll_anchor, top_row, false, false, workspace_id, cx);
+ // }
+
+ // pub fn scroll_screen(&mut self, amount: &ScrollAmount, cx: &mut ViewContext<Self>) {
+ // if matches!(self.mode, EditorMode::SingleLine) {
+ // cx.propagate_action();
+ // return;
+ // }
+
+ // if self.take_rename(true, cx).is_some() {
+ // return;
+ // }
+
+ // let cur_position = self.scroll_position(cx);
+ // let new_pos = cur_position + point(0., amount.lines(self));
+ // self.set_scroll_position(new_pos, cx);
+ // }
+
+ // /// Returns an ordering. The newest selection is:
+ // /// Ordering::Equal => on screen
+ // /// Ordering::Less => above the screen
+ // /// Ordering::Greater => below the screen
+ // pub fn newest_selection_on_screen(&self, cx: &mut AppContext) -> Ordering {
+ // let snapshot = self.display_map.update(cx, |map, cx| map.snapshot(cx));
+ // let newest_head = self
+ // .selections
+ // .newest_anchor()
+ // .head()
+ // .to_display_point(&snapshot);
+ // let screen_top = self
+ // .scroll_manager
+ // .anchor
+ // .anchor
+ // .to_display_point(&snapshot);
+
+ // if screen_top > newest_head {
+ // return Ordering::Less;
+ // }
+
+ // if let Some(visible_lines) = self.visible_line_count() {
+ // if newest_head.row() < screen_top.row() + visible_lines as u32 {
+ // return Ordering::Equal;
+ // }
+ // }
+
+ // Ordering::Greater
+ // }
+
+ // pub fn read_scroll_position_from_db(
+ // &mut self,
+ // item_id: usize,
+ // workspace_id: WorkspaceId,
+ // cx: &mut ViewContext<Editor>,
+ // ) {
+ // let scroll_position = DB.get_scroll_position(item_id, workspace_id);
+ // if let Ok(Some((top_row, x, y))) = scroll_position {
+ // let top_anchor = self
+ // .buffer()
+ // .read(cx)
+ // .snapshot(cx)
+ // .anchor_at(Point::new(top_row as u32, 0), Bias::Left);
+ // let scroll_anchor = ScrollAnchor {
+ // offset: Point::new(x, y),
+ // anchor: top_anchor,
+ // };
+ // self.set_scroll_anchor(scroll_anchor, cx);
+ // }
+ // }
+}
@@ -1,6 +1,6 @@
-use std::cmp;
+use std::{cmp, f32};
-use gpui::ViewContext;
+use gpui::{px, Pixels, ViewContext};
use language::Point;
use crate::{display_map::ToDisplayPoint, Editor, EditorMode, LineWithInvisibles};
@@ -61,7 +61,7 @@ impl Editor {
display_map.max_point().row() as f32
};
if scroll_position.y > max_scroll_top {
- scroll_position.set_y(max_scroll_top);
+ scroll_position.y = (max_scroll_top);
self.set_scroll_position(scroll_position, cx);
}
@@ -143,24 +143,24 @@ impl Editor {
let needs_scroll_down = target_bottom >= end_row;
if needs_scroll_up && !needs_scroll_down {
- scroll_position.set_y(target_top);
+ scroll_position.y = (target_top);
self.set_scroll_position_internal(scroll_position, local, true, cx);
}
if !needs_scroll_up && needs_scroll_down {
- scroll_position.set_y(target_bottom - visible_lines);
+ scroll_position.y = (target_bottom - visible_lines);
self.set_scroll_position_internal(scroll_position, local, true, cx);
}
}
AutoscrollStrategy::Center => {
- scroll_position.set_y((target_top - margin).max(0.0));
+ scroll_position.y = ((target_top - margin).max(0.0));
self.set_scroll_position_internal(scroll_position, local, true, cx);
}
AutoscrollStrategy::Top => {
- scroll_position.set_y((target_top).max(0.0));
+ scroll_position.y = ((target_top).max(0.0));
self.set_scroll_position_internal(scroll_position, local, true, cx);
}
AutoscrollStrategy::Bottom => {
- scroll_position.set_y((target_bottom - visible_lines).max(0.0));
+ scroll_position.y = ((target_bottom - visible_lines).max(0.0));
self.set_scroll_position_internal(scroll_position, local, true, cx);
}
}
@@ -178,9 +178,9 @@ impl Editor {
pub fn autoscroll_horizontally(
&mut self,
start_row: u32,
- viewport_width: f32,
- scroll_width: f32,
- max_glyph_width: f32,
+ viewport_width: Pixels,
+ scroll_width: Pixels,
+ max_glyph_width: Pixels,
layouts: &[LineWithInvisibles],
cx: &mut ViewContext<Self>,
) -> bool {
@@ -191,11 +191,11 @@ impl Editor {
let mut target_right;
if self.highlighted_rows.is_some() {
- target_left = 0.0_f32;
- target_right = 0.0_f32;
+ target_left = px(0.);
+ target_right = px(0.);
} else {
- target_left = std::f32::INFINITY;
- target_right = 0.0_f32;
+ target_left = px(f32::INFINITY);
+ target_right = px(0.);
for selection in selections {
let head = selection.head().to_display_point(&display_map);
if head.row() >= start_row && head.row() < start_row + layouts.len() as u32 {
@@ -226,11 +226,11 @@ impl Editor {
let scroll_right = scroll_left + viewport_width;
if target_left < scroll_left {
- self.scroll_manager.anchor.offset.x = (target_left / max_glyph_width);
+ self.scroll_manager.anchor.offset.x = (target_left / max_glyph_width).into();
true
} else if target_right > scroll_right {
self.scroll_manager.anchor.offset.x =
- ((target_right - viewport_width) / max_glyph_width);
+ ((target_right - viewport_width) / max_glyph_width).into();
true
} else {
false
@@ -11,18 +11,19 @@ pub enum ScrollAmount {
impl ScrollAmount {
pub fn lines(&self, editor: &mut Editor) -> f32 {
- match self {
- Self::Line(count) => *count,
- Self::Page(count) => editor
- .visible_line_count()
- .map(|mut l| {
- // for full pages subtract one to leave an anchor line
- if count.abs() == 1.0 {
- l -= 1.0
- }
- (l * count).trunc()
- })
- .unwrap_or(0.),
- }
+ todo!()
+ // match self {
+ // Self::Line(count) => *count,
+ // Self::Page(count) => editor
+ // .visible_line_count()
+ // .map(|mut l| {
+ // // for full pages subtract one to leave an anchor line
+ // if count.abs() == 1.0 {
+ // l -= 1.0
+ // }
+ // (l * count).trunc()
+ // })
+ // .unwrap_or(0.),
+ // }
}
}
@@ -6,7 +6,7 @@ use std::{
};
use collections::HashMap;
-use gpui::{AppContext, Model};
+use gpui::{AppContext, Model, Pixels};
use itertools::Itertools;
use language::{Bias, Point, Selection, SelectionGoal, TextDimension, ToPoint};
use util::post_inc;
@@ -302,39 +302,39 @@ impl SelectionsCollection {
.collect()
}
- pub fn build_columnar_selection(
- &mut self,
- display_map: &DisplaySnapshot,
- row: u32,
- positions: &Range<f32>,
- reversed: bool,
- text_layout_details: &TextLayoutDetails,
- ) -> Option<Selection<Point>> {
- let is_empty = positions.start == positions.end;
- let line_len = display_map.line_len(row);
-
- let layed_out_line = display_map.lay_out_line_for_row(row, &text_layout_details);
-
- let start_col = layed_out_line.closest_index_for_x(positions.start) as u32;
- if start_col < line_len || (is_empty && positions.start == layed_out_line.width()) {
- let start = DisplayPoint::new(row, start_col);
- let end_col = layed_out_line.closest_index_for_x(positions.end) as u32;
- let end = DisplayPoint::new(row, end_col);
-
- Some(Selection {
- id: post_inc(&mut self.next_selection_id),
- start: start.to_point(display_map),
- end: end.to_point(display_map),
- reversed,
- goal: SelectionGoal::HorizontalRange {
- start: positions.start,
- end: positions.end,
- },
- })
- } else {
- None
- }
- }
+ // pub fn build_columnar_selection(
+ // &mut self,
+ // display_map: &DisplaySnapshot,
+ // row: u32,
+ // positions: &Range<Pixels>,
+ // reversed: bool,
+ // text_layout_details: &TextLayoutDetails,
+ // ) -> Option<Selection<Point>> {
+ // let is_empty = positions.start == positions.end;
+ // let line_len = display_map.line_len(row);
+
+ // let layed_out_line = display_map.lay_out_line_for_row(row, &text_layout_details);
+
+ // let start_col = layed_out_line.closest_index_for_x(positions.start) as u32;
+ // if start_col < line_len || (is_empty && positions.start == layed_out_line.width()) {
+ // let start = DisplayPoint::new(row, start_col);
+ // let end_col = layed_out_line.closest_index_for_x(positions.end) as u32;
+ // let end = DisplayPoint::new(row, end_col);
+
+ // Some(Selection {
+ // id: post_inc(&mut self.next_selection_id),
+ // start: start.to_point(display_map),
+ // end: end.to_point(display_map),
+ // reversed,
+ // goal: SelectionGoal::HorizontalRange {
+ // start: positions.start,
+ // end: positions.end,
+ // },
+ // })
+ // } else {
+ // None
+ // }
+ // }
pub(crate) fn change_with<R>(
&mut self,
@@ -29,6 +29,7 @@ pub struct ForegroundExecutor {
}
#[must_use]
+#[derive(Debug)]
pub enum Task<T> {
Ready(Option<T>),
Spawned(async_task::Task<T>),
@@ -819,6 +819,18 @@ impl From<Pixels> for f64 {
}
}
+impl From<Pixels> for u32 {
+ fn from(pixels: Pixels) -> Self {
+ pixels.0 as u32
+ }
+}
+
+impl From<Pixels> for usize {
+ fn from(pixels: Pixels) -> Self {
+ pixels.0 as usize
+ }
+}
+
#[derive(
Add, AddAssign, Clone, Copy, Default, Div, Eq, Hash, Ord, PartialEq, PartialOrd, Sub, SubAssign,
)]
@@ -411,6 +411,7 @@ impl MacTextSystemState {
descent: typographic_bounds.descent.into(),
runs,
font_size,
+ len: text.len(),
}
}
@@ -167,6 +167,15 @@ impl TextStyle {
Ok(self)
}
+ pub fn font(&self) -> Font {
+ Font {
+ family: self.font_family.clone(),
+ features: self.font_features.clone(),
+ weight: self.font_weight,
+ style: self.font_style,
+ }
+ }
+
pub fn to_run(&self, len: usize) -> TextRun {
TextRun {
len,
@@ -151,7 +151,7 @@ impl TextSystem {
pub fn layout_text(
&self,
- text: &SharedString,
+ text: &str,
font_size: Pixels,
runs: &[TextRun],
wrap_width: Option<Pixels>,
@@ -29,6 +29,10 @@ impl Line {
)
}
+ pub fn width(&self) -> Pixels {
+ self.layout.width
+ }
+
pub fn wrap_count(&self) -> usize {
self.layout.wrap_boundaries.len()
}
@@ -16,6 +16,7 @@ pub struct LineLayout {
pub ascent: Pixels,
pub descent: Pixels,
pub runs: Vec<ShapedRun>,
+ pub len: usize,
}
#[derive(Debug)]
@@ -1655,6 +1655,7 @@ impl<'a, V: 'static> ViewContext<'a, V> {
}
}
+ // todo!("change this to return a reference");
pub fn view(&self) -> View<V> {
self.view.clone()
}
@@ -30,7 +30,7 @@ regex.workspace = true
[dev-dependencies]
collections = { path = "../collections", features = ["test-support"] }
-gpui = { path = "../gpui", features = ["test-support"] }
+gpui = { package = "gpui2", path = "../gpui2", features = ["test-support"] }
util = { path = "../util", features = ["test-support"] }
ctor.workspace = true
env_logger.workspace = true
@@ -1,3 +1,5 @@
+use gpui::Pixels;
+
use crate::{Anchor, BufferSnapshot, TextDimension};
use std::cmp::Ordering;
use std::ops::Range;
@@ -5,8 +7,8 @@ use std::ops::Range;
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum SelectionGoal {
None,
- HorizontalPosition(f32),
- HorizontalRange { start: f32, end: f32 },
+ HorizontalPosition(Pixels),
+ HorizontalRange { start: Pixels, end: Pixels },
WrappedHorizontalPosition((u32, f32)),
}
@@ -104,7 +104,11 @@ pub trait Item: Render + EventEmitter {
}
fn tab_content<V: 'static>(&self, detail: Option<usize>, cx: &AppContext) -> AnyElement<V>;
- fn for_each_project_item(&self, _: &AppContext, _: &mut dyn FnMut(usize, &dyn project2::Item)) {
+ fn for_each_project_item(
+ &self,
+ _: &AppContext,
+ _: &mut dyn FnMut(EntityId, &dyn project2::Item),
+ ) {
} // (model id, Item)
fn is_singleton(&self, _cx: &AppContext) -> bool {
false
@@ -219,8 +223,12 @@ pub trait ItemHandle: 'static + Send {
fn dragged_tab_content(&self, detail: Option<usize>, cx: &AppContext) -> AnyElement<Workspace>;
fn project_path(&self, cx: &AppContext) -> Option<ProjectPath>;
fn project_entry_ids(&self, cx: &AppContext) -> SmallVec<[ProjectEntryId; 3]>;
- fn project_item_model_ids(&self, cx: &AppContext) -> SmallVec<[usize; 3]>;
- fn for_each_project_item(&self, _: &AppContext, _: &mut dyn FnMut(usize, &dyn project2::Item));
+ fn project_item_model_ids(&self, cx: &AppContext) -> SmallVec<[EntityId; 3]>;
+ fn for_each_project_item(
+ &self,
+ _: &AppContext,
+ _: &mut dyn FnMut(EntityId, &dyn project2::Item),
+ );
fn is_singleton(&self, cx: &AppContext) -> bool;
fn boxed_clone(&self) -> Box<dyn ItemHandle>;
fn clone_on_split(
@@ -331,7 +339,7 @@ impl<T: Item> ItemHandle for View<T> {
result
}
- fn project_item_model_ids(&self, cx: &AppContext) -> SmallVec<[usize; 3]> {
+ fn project_item_model_ids(&self, cx: &AppContext) -> SmallVec<[EntityId; 3]> {
let mut result = SmallVec::new();
self.read(cx).for_each_project_item(cx, &mut |id, _| {
result.push(id);
@@ -342,7 +350,7 @@ impl<T: Item> ItemHandle for View<T> {
fn for_each_project_item(
&self,
cx: &AppContext,
- f: &mut dyn FnMut(usize, &dyn project2::Item),
+ f: &mut dyn FnMut(EntityId, &dyn project2::Item),
) {
self.read(cx).for_each_project_item(cx, f)
}