This commit is contained in:
Nathan Sobo 2023-11-02 22:56:04 -06:00
parent a731f8fb1e
commit f3b8a9d8c2
26 changed files with 1782 additions and 1665 deletions

2
Cargo.lock generated
View file

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

View file

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

View file

@ -1,3 +1,4 @@
#![allow(unused)]
mod blink_manager; mod blink_manager;
pub mod display_map; pub mod display_map;
mod editor_settings; mod editor_settings;
@ -20,8 +21,9 @@ mod editor_tests;
#[cfg(any(test, feature = "test-support"))] #[cfg(any(test, feature = "test-support"))]
pub mod test; pub mod test;
use aho_corasick::AhoCorasick; use aho_corasick::AhoCorasick;
use anyhow::Result;
use blink_manager::BlinkManager; use blink_manager::BlinkManager;
use client::{Collaborator, ParticipantIndex}; use client::{Client, Collaborator, ParticipantIndex};
use clock::ReplicaId; use clock::ReplicaId;
use collections::{HashMap, HashSet, VecDeque}; use collections::{HashMap, HashSet, VecDeque};
pub use display_map::DisplayPoint; pub use display_map::DisplayPoint;
@ -33,8 +35,8 @@ pub use element::{
use futures::FutureExt; use futures::FutureExt;
use fuzzy::{StringMatch, StringMatchCandidate}; use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::{ use gpui::{
AnyElement, AppContext, Element, EventEmitter, Model, Pixels, Render, Subscription, Task, View, AnyElement, AppContext, BackgroundExecutor, Element, EventEmitter, Model, Pixels, Render,
ViewContext, WeakView, Subscription, Task, TextStyle, View, ViewContext, WeakView, WindowContext,
}; };
use hover_popover::HoverState; use hover_popover::HoverState;
pub use items::MAX_TAB_TITLE_LEN; pub use items::MAX_TAB_TITLE_LEN;
@ -42,27 +44,30 @@ pub use language::{char_kind, CharKind};
use language::{ use language::{
language_settings::{self, all_language_settings, InlayHintSettings}, language_settings::{self, all_language_settings, InlayHintSettings},
AutoindentMode, BracketPair, Buffer, CodeAction, Completion, CursorShape, Diagnostic, Language, 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 link_go_to_definition::LinkGoToDefinitionState;
use lsp::{Documentation, LanguageServerId};
pub use multi_buffer::{ pub use multi_buffer::{
Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset, Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset,
ToPoint, ToPoint,
}; };
use ordered_float::OrderedFloat;
use parking_lot::RwLock; use parking_lot::RwLock;
use project::Project; use project::{FormatTrigger, Project};
use rpc::proto::*; use rpc::proto::*;
use scroll::{autoscroll::Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager}; use scroll::{autoscroll::Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager};
use selections_collection::SelectionsCollection; use selections_collection::SelectionsCollection;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use settings::Settings; use settings::Settings;
use std::{ use std::{
cmp::Reverse,
ops::{Deref, DerefMut, Range}, ops::{Deref, DerefMut, Range},
sync::Arc, sync::Arc,
time::Duration, time::Duration,
}; };
pub use sum_tree::Bias; pub use sum_tree::Bias;
use util::TryFutureExt; use util::{ResultExt, TryFutureExt};
use workspace::{ItemNavHistory, ViewId, Workspace}; use workspace::{ItemNavHistory, ViewId, Workspace};
const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500); const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
@ -569,7 +574,7 @@ pub enum SoftWrap {
#[derive(Clone)] #[derive(Clone)]
pub struct EditorStyle { pub struct EditorStyle {
// pub text: TextStyle, pub text: TextStyle,
pub line_height_scalar: f32, pub line_height_scalar: f32,
// pub placeholder_text: Option<TextStyle>, // pub placeholder_text: Option<TextStyle>,
// pub theme: theme::Editor, // pub theme: theme::Editor,
@ -887,10 +892,11 @@ impl ContextMenu {
workspace: Option<WeakView<Workspace>>, workspace: Option<WeakView<Workspace>>,
cx: &mut ViewContext<Editor>, cx: &mut ViewContext<Editor>,
) -> (DisplayPoint, AnyElement<Editor>) { ) -> (DisplayPoint, AnyElement<Editor>) {
match self { todo!()
ContextMenu::Completions(menu) => (cursor_position, menu.render(style, workspace, cx)), // match self {
ContextMenu::CodeActions(menu) => menu.render(cursor_position, style, cx), // ContextMenu::Completions(menu) => (cursor_position, menu.render(style, workspace, cx)),
} // ContextMenu::CodeActions(menu) => menu.render(cursor_position, style, cx),
// }
} }
} }
@ -903,52 +909,71 @@ struct CompletionsMenu {
match_candidates: Arc<[StringMatchCandidate]>, match_candidates: Arc<[StringMatchCandidate]>,
matches: Arc<[StringMatch]>, matches: Arc<[StringMatch]>,
selected_item: usize, selected_item: usize,
// list: UniformListState, list: UniformListState,
} }
// impl CompletionsMenu { // todo!(this is fake)
// fn select_first(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) { #[derive(Clone)]
// self.selected_item = 0; struct UniformListState;
// self.list.scroll_to(ScrollTarget::Show(self.selected_item));
// self.attempt_resolve_selected_completion_documentation(project, cx);
// cx.notify();
// }
// fn select_prev(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) { // todo!(this is fake)
// if self.selected_item > 0 { impl UniformListState {
// self.selected_item -= 1; pub fn scroll_to(&mut self, target: ScrollTarget) {}
// } else { }
// self.selected_item = self.matches.len() - 1;
// }
// self.list.scroll_to(ScrollTarget::Show(self.selected_item));
// self.attempt_resolve_selected_completion_documentation(project, cx);
// cx.notify();
// }
// fn select_next(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) { // todo!(this is somewhat fake)
// if self.selected_item + 1 < self.matches.len() { #[derive(Debug)]
// self.selected_item += 1; pub enum ScrollTarget {
// } else { Show(usize),
// self.selected_item = 0; Center(usize),
// } }
// self.list.scroll_to(ScrollTarget::Show(self.selected_item));
// self.attempt_resolve_selected_completion_documentation(project, cx);
// cx.notify();
// }
// fn select_last(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) { impl CompletionsMenu {
// self.selected_item = self.matches.len() - 1; fn select_first(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
// self.list.scroll_to(ScrollTarget::Show(self.selected_item)); self.selected_item = 0;
// self.attempt_resolve_selected_completion_documentation(project, cx); self.list.scroll_to(ScrollTarget::Show(self.selected_item));
// cx.notify(); self.attempt_resolve_selected_completion_documentation(project, cx);
// } cx.notify();
}
// fn pre_resolve_completion_documentation( fn select_prev(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
// &self, if self.selected_item > 0 {
// project: Option<Model<Project>>, self.selected_item -= 1;
// cx: &mut ViewContext<Editor>, } else {
self.selected_item = self.matches.len() - 1;
}
self.list.scroll_to(ScrollTarget::Show(self.selected_item));
self.attempt_resolve_selected_completion_documentation(project, cx);
cx.notify();
}
fn select_next(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
if self.selected_item + 1 < self.matches.len() {
self.selected_item += 1;
} else {
self.selected_item = 0;
}
self.list.scroll_to(ScrollTarget::Show(self.selected_item));
self.attempt_resolve_selected_completion_documentation(project, cx);
cx.notify();
}
fn select_last(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
self.selected_item = self.matches.len() - 1;
self.list.scroll_to(ScrollTarget::Show(self.selected_item));
self.attempt_resolve_selected_completion_documentation(project, cx);
cx.notify();
}
fn pre_resolve_completion_documentation(
&self,
project: Option<Model<Project>>,
cx: &mut ViewContext<Editor>,
) {
todo!("implementation below ");
}
// ) { // ) {
// let settings = settings::get::<EditorSettings>(cx); // let settings = EditorSettings::get_global(cx);
// if !settings.show_completion_documentation { // if !settings.show_completion_documentation {
// return; // return;
// } // }
@ -1031,86 +1056,88 @@ struct CompletionsMenu {
// .detach(); // .detach();
// } // }
// fn attempt_resolve_selected_completion_documentation( fn attempt_resolve_selected_completion_documentation(
// &mut self, &mut self,
// project: Option<&Model<Project>>, project: Option<&Model<Project>>,
// cx: &mut ViewContext<Editor>, cx: &mut ViewContext<Editor>,
// ) { ) {
// let settings = settings::get::<EditorSettings>(cx); let settings = EditorSettings::get_global(cx);
// if !settings.show_completion_documentation { if !settings.show_completion_documentation {
// return; return;
// } }
// let completion_index = self.matches[self.selected_item].candidate_id; let completion_index = self.matches[self.selected_item].candidate_id;
// let Some(project) = project else { let Some(project) = project else {
// return; return;
// }; };
// let language_registry = project.read(cx).languages().clone(); let language_registry = project.read(cx).languages().clone();
// let completions = self.completions.clone(); let completions = self.completions.clone();
// let completions_guard = completions.read(); let completions_guard = completions.read();
// let completion = &completions_guard[completion_index]; let completion = &completions_guard[completion_index];
// todo!()
// if completion.documentation.is_some() { // if completion.documentation.is_some() {
// return; // return;
// } // }
// let server_id = completion.server_id; let server_id = completion.server_id;
// let completion = completion.lsp_completion.clone(); let completion = completion.lsp_completion.clone();
// drop(completions_guard); drop(completions_guard);
// if project.read(cx).is_remote() { if project.read(cx).is_remote() {
// let Some(project_id) = project.read(cx).remote_id() else { let Some(project_id) = project.read(cx).remote_id() else {
// log::error!("Remote project without remote_id"); log::error!("Remote project without remote_id");
// return; return;
// }; };
// let client = project.read(cx).client(); let client = project.read(cx).client();
// cx.spawn(move |this, mut cx| async move { cx.spawn(move |this, mut cx| async move {
// Self::resolve_completion_documentation_remote( Self::resolve_completion_documentation_remote(
// project_id, project_id,
// server_id, server_id,
// completions.clone(), completions.clone(),
// completion_index, completion_index,
// completion, completion,
// client, client,
// language_registry.clone(), language_registry.clone(),
// ) )
// .await; .await;
// _ = this.update(&mut cx, |_, cx| cx.notify()); _ = this.update(&mut cx, |_, cx| cx.notify());
// }) })
// .detach(); .detach();
// } else { } else {
// let Some(server) = project.read(cx).language_server_for_id(server_id) else { let Some(server) = project.read(cx).language_server_for_id(server_id) else {
// return; return;
// }; };
// cx.spawn(move |this, mut cx| async move { cx.spawn(move |this, mut cx| async move {
// Self::resolve_completion_documentation_local( Self::resolve_completion_documentation_local(
// server, server,
// completions, completions,
// completion_index, completion_index,
// completion, completion,
// language_registry, language_registry,
// ) )
// .await; .await;
// _ = this.update(&mut cx, |_, cx| cx.notify()); _ = this.update(&mut cx, |_, cx| cx.notify());
// }) })
// .detach(); .detach();
// } }
// } }
// async fn resolve_completion_documentation_remote( async fn resolve_completion_documentation_remote(
// project_id: u64, project_id: u64,
// server_id: LanguageServerId, server_id: LanguageServerId,
// completions: Arc<RwLock<Box<[Completion]>>>, completions: Arc<RwLock<Box<[Completion]>>>,
// completion_index: usize, completion_index: usize,
// completion: lsp::CompletionItem, completion: lsp::CompletionItem,
// client: Arc<Client>, client: Arc<Client>,
// language_registry: Arc<LanguageRegistry>, language_registry: Arc<LanguageRegistry>,
// ) { ) {
todo!()
// let request = proto::ResolveCompletionDocumentation { // let request = proto::ResolveCompletionDocumentation {
// project_id, // project_id,
// language_server_id: server_id.0 as u64, // language_server_id: server_id.0 as u64,
@ -1145,15 +1172,16 @@ struct CompletionsMenu {
// let mut completions = completions.write(); // let mut completions = completions.write();
// let completion = &mut completions[completion_index]; // let completion = &mut completions[completion_index];
// completion.documentation = Some(documentation); // completion.documentation = Some(documentation);
// } }
// async fn resolve_completion_documentation_local( async fn resolve_completion_documentation_local(
// server: Arc<lsp::LanguageServer>, server: Arc<lsp::LanguageServer>,
// completions: Arc<RwLock<Box<[Completion]>>>, completions: Arc<RwLock<Box<[Completion]>>>,
// completion_index: usize, completion_index: usize,
// completion: lsp::CompletionItem, completion: lsp::CompletionItem,
// language_registry: Arc<LanguageRegistry>, language_registry: Arc<LanguageRegistry>,
// ) { ) {
todo!()
// let can_resolve = server // let can_resolve = server
// .capabilities() // .capabilities()
// .completion_provider // .completion_provider
@ -1185,21 +1213,24 @@ struct CompletionsMenu {
// let completion = &mut completions[completion_index]; // let completion = &mut completions[completion_index];
// completion.documentation = Some(Documentation::Undocumented); // completion.documentation = Some(Documentation::Undocumented);
// } // }
// } }
// fn visible(&self) -> bool { fn visible(&self) -> bool {
// !self.matches.is_empty() !self.matches.is_empty()
// } }
// fn render( fn render(
// &self, &self,
// style: EditorStyle, style: EditorStyle,
// workspace: Option<WeakView<Workspace>>, workspace: Option<WeakView<Workspace>>,
// cx: &mut ViewContext<Editor>, cx: &mut ViewContext<Editor>,
) {
todo!("old implementation below")
}
// ) -> AnyElement<Editor> { // ) -> AnyElement<Editor> {
// enum CompletionTag {} // enum CompletionTag {}
// let settings = settings::get::<EditorSettings>(cx); // let settings = EditorSettings>(cx);
// let show_completion_documentation = settings.show_completion_documentation; // let show_completion_documentation = settings.show_completion_documentation;
// let widest_completion_ix = self // let widest_completion_ix = self
@ -1396,122 +1427,124 @@ struct CompletionsMenu {
// .into_any() // .into_any()
// } // }
// pub async fn filter(&mut self, query: Option<&str>, executor: Arc<executor::Background>) { pub async fn filter(&mut self, query: Option<&str>, executor: BackgroundExecutor) {
// let mut matches = if let Some(query) = query { let mut matches = if let Some(query) = query {
// fuzzy::match_strings( fuzzy::match_strings(
// &self.match_candidates, &self.match_candidates,
// query, query,
// query.chars().any(|c| c.is_uppercase()), query.chars().any(|c| c.is_uppercase()),
// 100, 100,
// &Default::default(), &Default::default(),
// executor, executor,
// ) )
// .await .await
// } else { } else {
// self.match_candidates self.match_candidates
// .iter() .iter()
// .enumerate() .enumerate()
// .map(|(candidate_id, candidate)| StringMatch { .map(|(candidate_id, candidate)| StringMatch {
// candidate_id, candidate_id,
// score: Default::default(), score: Default::default(),
// positions: Default::default(), positions: Default::default(),
// string: candidate.string.clone(), string: candidate.string.clone(),
// }) })
// .collect() .collect()
// }; };
// // Remove all candidates where the query's start does not match the start of any word in the candidate // 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) = query {
// if let Some(query_start) = query.chars().next() { if let Some(query_start) = query.chars().next() {
// matches.retain(|string_match| { matches.retain(|string_match| {
// split_words(&string_match.string).any(|word| { split_words(&string_match.string).any(|word| {
// // Check that the first codepoint of the word as lowercase matches the first // Check that the first codepoint of the word as lowercase matches the first
// // codepoint of the query as lowercase // codepoint of the query as lowercase
// word.chars() word.chars()
// .flat_map(|codepoint| codepoint.to_lowercase()) .flat_map(|codepoint| codepoint.to_lowercase())
// .zip(query_start.to_lowercase()) .zip(query_start.to_lowercase())
// .all(|(word_cp, query_cp)| word_cp == query_cp) .all(|(word_cp, query_cp)| word_cp == query_cp)
// }) })
// }); });
// } }
// } }
// let completions = self.completions.read(); let completions = self.completions.read();
// matches.sort_unstable_by_key(|mat| { matches.sort_unstable_by_key(|mat| {
// let completion = &completions[mat.candidate_id]; let completion = &completions[mat.candidate_id];
// ( (
// completion.lsp_completion.sort_text.as_ref(), completion.lsp_completion.sort_text.as_ref(),
// Reverse(OrderedFloat(mat.score)), Reverse(OrderedFloat(mat.score)),
// completion.sort_key(), completion.sort_key(),
// ) )
// }); });
// drop(completions); drop(completions);
// for mat in &mut matches { for mat in &mut matches {
// let completions = self.completions.read(); let completions = self.completions.read();
// let filter_start = completions[mat.candidate_id].label.filter_range.start; let filter_start = completions[mat.candidate_id].label.filter_range.start;
// for position in &mut mat.positions { for position in &mut mat.positions {
// *position += filter_start; *position += filter_start;
// } }
// } }
// self.matches = matches.into(); self.matches = matches.into();
// self.selected_item = 0; self.selected_item = 0;
// } }
// } }
#[derive(Clone)] #[derive(Clone)]
struct CodeActionsMenu { struct CodeActionsMenu {
actions: Arc<[CodeAction]>, actions: Arc<[CodeAction]>,
buffer: Model<Buffer>, buffer: Model<Buffer>,
selected_item: usize, selected_item: usize,
// list: UniformListState, list: UniformListState,
deployed_from_indicator: bool, deployed_from_indicator: bool,
} }
// impl CodeActionsMenu { impl CodeActionsMenu {
// fn select_first(&mut self, cx: &mut ViewContext<Editor>) { fn select_first(&mut self, cx: &mut ViewContext<Editor>) {
// self.selected_item = 0; self.selected_item = 0;
// self.list.scroll_to(ScrollTarget::Show(self.selected_item)); self.list.scroll_to(ScrollTarget::Show(self.selected_item));
// cx.notify() cx.notify()
// } }
// fn select_prev(&mut self, cx: &mut ViewContext<Editor>) { fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
// if self.selected_item > 0 { if self.selected_item > 0 {
// self.selected_item -= 1; self.selected_item -= 1;
// } else { } else {
// self.selected_item = self.actions.len() - 1; self.selected_item = self.actions.len() - 1;
// } }
// self.list.scroll_to(ScrollTarget::Show(self.selected_item)); self.list.scroll_to(ScrollTarget::Show(self.selected_item));
// cx.notify(); cx.notify();
// } }
// fn select_next(&mut self, cx: &mut ViewContext<Editor>) { fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
// if self.selected_item + 1 < self.actions.len() { if self.selected_item + 1 < self.actions.len() {
// self.selected_item += 1; self.selected_item += 1;
// } else { } else {
// self.selected_item = 0; self.selected_item = 0;
// } }
// self.list.scroll_to(ScrollTarget::Show(self.selected_item)); self.list.scroll_to(ScrollTarget::Show(self.selected_item));
// cx.notify(); cx.notify();
// } }
// fn select_last(&mut self, cx: &mut ViewContext<Editor>) { fn select_last(&mut self, cx: &mut ViewContext<Editor>) {
// self.selected_item = self.actions.len() - 1; self.selected_item = self.actions.len() - 1;
// self.list.scroll_to(ScrollTarget::Show(self.selected_item)); self.list.scroll_to(ScrollTarget::Show(self.selected_item));
// cx.notify() cx.notify()
// } }
// fn visible(&self) -> bool { fn visible(&self) -> bool {
// !self.actions.is_empty() !self.actions.is_empty()
// } }
// fn render( fn render(
// &self, &self,
// mut cursor_position: DisplayPoint, mut cursor_position: DisplayPoint,
// style: EditorStyle, style: EditorStyle,
// cx: &mut ViewContext<Editor>, cx: &mut ViewContext<Editor>,
// ) -> (DisplayPoint, AnyElement<Editor>) { ) -> (DisplayPoint, AnyElement<Editor>) {
todo!("old version below")
}
// enum ActionTag {} // enum ActionTag {}
// let container_style = style.autocomplete.container; // let container_style = style.autocomplete.container;
@ -1584,7 +1617,7 @@ struct CodeActionsMenu {
// (cursor_position, element) // (cursor_position, element)
// } // }
// } }
pub struct CopilotState { pub struct CopilotState {
excerpt_id: Option<ExcerptId>, excerpt_id: Option<ExcerptId>,
@ -2018,7 +2051,8 @@ impl Editor {
// self.buffer().read(cx).title(cx) // self.buffer().read(cx).title(cx)
// } // }
// pub fn snapshot(&mut self, cx: &mut WindowContext) -> EditorSnapshot { pub fn snapshot(&mut self, cx: &mut WindowContext) -> EditorSnapshot {
todo!()
// EditorSnapshot { // EditorSnapshot {
// mode: self.mode, // mode: self.mode,
// show_gutter: self.show_gutter, // show_gutter: self.show_gutter,
@ -2031,7 +2065,7 @@ impl Editor {
// .upgrade(cx) // .upgrade(cx)
// .map_or(false, |handle| handle.is_focused(cx)), // .map_or(false, |handle| handle.is_focused(cx)),
// } // }
// } }
// pub fn language_at<'a, T: ToOffset>( // pub fn language_at<'a, T: ToOffset>(
// &self, // &self,
@ -2854,7 +2888,7 @@ impl Editor {
// let had_active_copilot_suggestion = this.has_active_copilot_suggestion(cx); // let had_active_copilot_suggestion = this.has_active_copilot_suggestion(cx);
// this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections)); // this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
// if !brace_inserted && settings::get::<EditorSettings>(cx).use_on_type_format { // if !brace_inserted && EditorSettings>(cx).use_on_type_format {
// if let Some(on_type_format_task) = // if let Some(on_type_format_task) =
// this.trigger_on_type_formatting(text.to_string(), cx) // this.trigger_on_type_formatting(text.to_string(), cx)
// { // {
@ -3173,7 +3207,7 @@ impl Editor {
// } // }
// fn trigger_completion_on_input(&mut self, text: &str, cx: &mut ViewContext<Self>) { // fn trigger_completion_on_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
// if !settings::get::<EditorSettings>(cx).show_completions_on_input { // if !EditorSettings>(cx).show_completions_on_input {
// return; // return;
// } // }
@ -3377,16 +3411,16 @@ impl Editor {
// } // }
// } // }
// fn visible_inlay_hints(&self, cx: &ViewContext<'_, '_, Editor>) -> Vec<Inlay> { fn visible_inlay_hints(&self, cx: &ViewContext<'_, Editor>) -> Vec<Inlay> {
// self.display_map self.display_map
// .read(cx) .read(cx)
// .current_inlays() .current_inlays()
// .filter(move |inlay| { .filter(move |inlay| {
// Some(inlay.id) != self.copilot_state.suggestion.as_ref().map(|h| h.id) Some(inlay.id) != self.copilot_state.suggestion.as_ref().map(|h| h.id)
// }) })
// .cloned() .cloned()
// .collect() .collect()
// } }
// pub fn excerpt_visible_offsets( // pub fn excerpt_visible_offsets(
// &self, // &self,
@ -7856,40 +7890,40 @@ impl Editor {
// Some(self.perform_format(project, FormatTrigger::Manual, cx)) // Some(self.perform_format(project, FormatTrigger::Manual, cx))
// } // }
// fn perform_format( fn perform_format(
// &mut self, &mut self,
// project: Model<Project>, project: Model<Project>,
// trigger: FormatTrigger, trigger: FormatTrigger,
// cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
// ) -> Task<Result<()>> { ) -> Task<Result<()>> {
// let buffer = self.buffer().clone(); let buffer = self.buffer().clone();
// let buffers = buffer.read(cx).all_buffers(); let buffers = buffer.read(cx).all_buffers();
// let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse(); let mut timeout = cx.background_executor().timer(FORMAT_TIMEOUT).fuse();
// let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx)); let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
// cx.spawn(|_, mut cx| async move { cx.spawn(|_, mut cx| async move {
// let transaction = futures::select_biased! { let transaction = futures::select_biased! {
// _ = timeout => { _ = timeout => {
// log::warn!("timed out waiting for formatting"); log::warn!("timed out waiting for formatting");
// None None
// } }
// transaction = format.log_err().fuse() => transaction, transaction = format.log_err().fuse() => transaction,
// }; };
// buffer.update(&mut cx, |buffer, cx| { buffer.update(&mut cx, |buffer, cx| {
// if let Some(transaction) = transaction { if let Some(transaction) = transaction {
// if !buffer.is_singleton() { if !buffer.is_singleton() {
// buffer.push_transaction(&transaction.0, cx); buffer.push_transaction(&transaction.0, cx);
// } }
// } }
// cx.notify(); cx.notify();
// }); });
// Ok(()) Ok(())
// }) })
// } }
// fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) { // fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
// if let Some(project) = self.project.clone() { // if let Some(project) = self.project.clone() {
@ -8162,42 +8196,42 @@ impl Editor {
// self.fold_ranges(ranges, true, cx); // self.fold_ranges(ranges, true, cx);
// } // }
// pub fn fold_ranges<T: ToOffset + Clone>( pub fn fold_ranges<T: ToOffset + Clone>(
// &mut self, &mut self,
// ranges: impl IntoIterator<Item = Range<T>>, ranges: impl IntoIterator<Item = Range<T>>,
// auto_scroll: bool, auto_scroll: bool,
// cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
// ) { ) {
// let mut ranges = ranges.into_iter().peekable(); let mut ranges = ranges.into_iter().peekable();
// if ranges.peek().is_some() { if ranges.peek().is_some() {
// self.display_map.update(cx, |map, cx| map.fold(ranges, cx)); self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
// if auto_scroll { if auto_scroll {
// self.request_autoscroll(Autoscroll::fit(), cx); self.request_autoscroll(Autoscroll::fit(), cx);
// } }
// cx.notify(); cx.notify();
// } }
// } }
// pub fn unfold_ranges<T: ToOffset + Clone>( pub fn unfold_ranges<T: ToOffset + Clone>(
// &mut self, &mut self,
// ranges: impl IntoIterator<Item = Range<T>>, ranges: impl IntoIterator<Item = Range<T>>,
// inclusive: bool, inclusive: bool,
// auto_scroll: bool, auto_scroll: bool,
// cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
// ) { ) {
// let mut ranges = ranges.into_iter().peekable(); let mut ranges = ranges.into_iter().peekable();
// if ranges.peek().is_some() { if ranges.peek().is_some() {
// self.display_map self.display_map
// .update(cx, |map, cx| map.unfold(ranges, inclusive, cx)); .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
// if auto_scroll { if auto_scroll {
// self.request_autoscroll(Autoscroll::fit(), cx); self.request_autoscroll(Autoscroll::fit(), cx);
// } }
// cx.notify(); cx.notify();
// } }
// } }
// pub fn gutter_hover( // pub fn gutter_hover(
// &mut self, // &mut self,
@ -8900,22 +8934,24 @@ impl Editor {
// telemetry.report_clickhouse_event(event, telemetry_settings); // telemetry.report_clickhouse_event(event, telemetry_settings);
// } // }
// #[cfg(any(test, feature = "test-support"))] #[cfg(any(test, feature = "test-support"))]
// fn report_editor_event( fn report_editor_event(
// &self, &self,
// _operation: &'static str, _operation: &'static str,
// _file_extension: Option<String>, _file_extension: Option<String>,
// _cx: &AppContext, _cx: &AppContext,
// ) { ) {
// } }
// #[cfg(not(any(test, feature = "test-support")))] #[cfg(not(any(test, feature = "test-support")))]
// fn report_editor_event( fn report_editor_event(
// &self, &self,
// operation: &'static str, operation: &'static str,
// file_extension: Option<String>, file_extension: Option<String>,
// cx: &AppContext, cx: &AppContext,
// ) { ) {
todo!("old version below");
}
// let Some(project) = &self.project else { return }; // let Some(project) = &self.project else { return };
// // If None, we are in a file without an extension // // If None, we are in a file without an extension
@ -9190,7 +9226,7 @@ impl EditorSnapshot {
self.placeholder_text.as_ref() self.placeholder_text.as_ref()
} }
pub fn scroll_position(&self) -> gpui::Point<Pixels> { pub fn scroll_position(&self) -> gpui::Point<f32> {
self.scroll_anchor.scroll_position(&self.display_snapshot) self.scroll_anchor.scroll_position(&self.display_snapshot)
} }
} }

View file

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

View file

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

View file

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

View file

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

View file

@ -7,7 +7,7 @@ use anyhow::{Context, Result};
use collections::HashSet; use collections::HashSet;
use futures::future::try_join_all; use futures::future::try_join_all;
use gpui::{ use gpui::{
point, AnyElement, AppContext, AsyncAppContext, Entity, Model, Pixels, SharedString, point, AnyElement, AppContext, AsyncAppContext, Entity, EntityId, Model, Pixels, SharedString,
Subscription, Task, View, ViewContext, WeakView, Subscription, Task, View, ViewContext, WeakView,
}; };
use language::{ use language::{
@ -26,6 +26,7 @@ use std::{
sync::Arc, sync::Arc,
}; };
use text::Selection; use text::Selection;
use theme::ThemeVariant;
use util::{paths::PathExt, ResultExt, TryFutureExt}; use util::{paths::PathExt, ResultExt, TryFutureExt};
use workspace::item::{BreadcrumbText, FollowableItemHandle}; use workspace::item::{BreadcrumbText, FollowableItemHandle};
use workspace::{ use workspace::{
@ -306,12 +307,15 @@ impl FollowableItem for Editor {
} }
} }
// async fn update_editor_from_message( async fn update_editor_from_message(
// this: WeakView<Editor>, this: WeakView<Editor>,
// project: Model<Project>, project: Model<Project>,
// message: proto::update_view::Editor, message: proto::update_view::Editor,
// cx: &mut AsyncAppContext, cx: &mut AsyncAppContext,
// ) -> Result<()> { ) -> Result<()> {
todo!()
}
// Previous implementation of the above
// // Open all of the buffers of which excerpts were added to the editor. // // Open all of the buffers of which excerpts were added to the editor.
// let inserted_excerpt_buffer_ids = message // let inserted_excerpt_buffer_ids = message
// .inserted_excerpts // .inserted_excerpts
@ -512,38 +516,39 @@ fn deserialize_anchor(buffer: &MultiBufferSnapshot, anchor: proto::EditorAnchor)
impl Item for Editor { impl Item for Editor {
fn navigate(&mut self, data: Box<dyn std::any::Any>, cx: &mut ViewContext<Self>) -> bool { fn navigate(&mut self, data: Box<dyn std::any::Any>, cx: &mut ViewContext<Self>) -> bool {
if let Ok(data) = data.downcast::<NavigationData>() { todo!();
let newest_selection = self.selections.newest::<Point>(cx); // if let Ok(data) = data.downcast::<NavigationData>() {
let buffer = self.buffer.read(cx).read(cx); // let newest_selection = self.selections.newest::<Point>(cx);
let offset = if buffer.can_resolve(&data.cursor_anchor) { // let buffer = self.buffer.read(cx).read(cx);
data.cursor_anchor.to_point(&buffer) // let offset = if buffer.can_resolve(&data.cursor_anchor) {
} else { // data.cursor_anchor.to_point(&buffer)
buffer.clip_point(data.cursor_position, Bias::Left) // } else {
}; // buffer.clip_point(data.cursor_position, Bias::Left)
// };
let mut scroll_anchor = data.scroll_anchor; // let mut scroll_anchor = data.scroll_anchor;
if !buffer.can_resolve(&scroll_anchor.anchor) { // if !buffer.can_resolve(&scroll_anchor.anchor) {
scroll_anchor.anchor = buffer.anchor_before( // scroll_anchor.anchor = buffer.anchor_before(
buffer.clip_point(Point::new(data.scroll_top_row, 0), Bias::Left), // buffer.clip_point(Point::new(data.scroll_top_row, 0), Bias::Left),
); // );
} // }
drop(buffer); // drop(buffer);
if newest_selection.head() == offset { // if newest_selection.head() == offset {
false // false
} else { // } else {
let nav_history = self.nav_history.take(); // let nav_history = self.nav_history.take();
self.set_scroll_anchor(scroll_anchor, cx); // self.set_scroll_anchor(scroll_anchor, cx);
self.change_selections(Some(Autoscroll::fit()), cx, |s| { // self.change_selections(Some(Autoscroll::fit()), cx, |s| {
s.select_ranges([offset..offset]) // s.select_ranges([offset..offset])
}); // });
self.nav_history = nav_history; // self.nav_history = nav_history;
true // true
} // }
} else { // } else {
false // false
} // }
} }
fn tab_tooltip_text(&self, cx: &AppContext) -> Option<SharedString> { 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> { fn tab_description<'a>(&'a self, detail: usize, cx: &'a AppContext) -> Option<SharedString> {
match path_for_buffer(&self.buffer, detail, true, cx)? { match path_for_buffer(&self.buffer, detail, true, cx)? {
Cow::Borrowed(path) => Some(path.to_string_lossy), Cow::Borrowed(path) => Some(path.to_string_lossy().into()),
Cow::Owned(path) => Some(path.to_string_lossy.to_string().into()), Cow::Owned(path) => Some(path.to_string_lossy().to_string().into()),
} }
} }
@ -590,10 +595,14 @@ impl Item for Editor {
// .into_any() // .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 self.buffer
.read(cx) .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 { fn is_singleton(&self, cx: &AppContext) -> bool {
@ -652,20 +661,24 @@ impl Item for Editor {
if buffers.len() == 1 { if buffers.len() == 1 {
project project
.update(&mut cx, |project, cx| project.save_buffers(buffers, cx)) .update(&mut cx, |project, cx| project.save_buffers(buffers, cx))?
.await?; .await?;
} else { } else {
// For multi-buffers, only save those ones that contain changes. For clean buffers // 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 // we simulate saving by calling `Buffer::did_save`, so that language servers or
// other downstream listeners of save events get notified. // other downstream listeners of save events get notified.
let (dirty_buffers, clean_buffers) = buffers.into_iter().partition(|buffer| { 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 project
.update(&mut cx, |project, cx| { .update(&mut cx, |project, cx| {
project.save_buffers(dirty_buffers, cx) project.save_buffers(dirty_buffers, cx)
}) })?
.await?; .await?;
for buffer in clean_buffers { for buffer in clean_buffers {
buffer.update(&mut cx, |buffer, cx| { buffer.update(&mut cx, |buffer, cx| {
@ -760,7 +773,7 @@ impl Item for Editor {
ToolbarItemLocation::PrimaryLeft { flex: None } ToolbarItemLocation::PrimaryLeft { flex: None }
} }
fn breadcrumbs(&self, cx: &AppContext) -> Option<Vec<BreadcrumbText>> { fn breadcrumbs(&self, variant: &ThemeVariant, cx: &AppContext) -> Option<Vec<BreadcrumbText>> {
todo!(); todo!();
// let cursor = self.selections.newest_anchor().head(); // let cursor = self.selections.newest_anchor().head();
// let multibuffer = &self.buffer().read(cx); // 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()) { if let Some(file) = buffer.read(cx).file().and_then(|file| file.as_local()) {
let path = file.abs_path(cx); let path = file.abs_path(cx);
cx.background() cx.background_executor()
.spawn(async move { .spawn(async move {
DB.save_path(item_id, workspace_id, path.clone()) DB.save_path(item_id, workspace_id, path.clone())
.await .await
@ -913,15 +926,17 @@ impl SearchableItem for Editor {
} }
fn clear_matches(&mut self, cx: &mut ViewContext<Self>) { 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>) { fn update_matches(&mut self, matches: Vec<Range<Anchor>>, cx: &mut ViewContext<Self>) {
self.highlight_background::<BufferSearchHighlights>( todo!()
matches, // self.highlight_background::<BufferSearchHighlights>(
|theme| theme.search.match_background, // matches,
cx, // |theme| theme.search.match_background,
); // cx,
// );
} }
fn query_suggestion(&mut self, cx: &mut ViewContext<Self>) -> String { fn query_suggestion(&mut self, cx: &mut ViewContext<Self>) -> String {
@ -952,20 +967,22 @@ impl SearchableItem for Editor {
matches: Vec<Range<Anchor>>, matches: Vec<Range<Anchor>>,
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) { ) {
self.unfold_ranges([matches[index].clone()], false, true, cx); todo!()
let range = self.range_for_match(&matches[index]); // self.unfold_ranges([matches[index].clone()], false, true, cx);
self.change_selections(Some(Autoscroll::fit()), cx, |s| { // let range = self.range_for_match(&matches[index]);
s.select_ranges([range]); // 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>) { fn select_matches(&mut self, matches: Vec<Self::Match>, cx: &mut ViewContext<Self>) {
self.unfold_ranges(matches.clone(), false, false, cx); todo!()
let mut ranges = Vec::new(); // self.unfold_ranges(matches.clone(), false, false, cx);
for m in &matches { // let mut ranges = Vec::new();
ranges.push(self.range_for_match(&m)) // for m in &matches {
} // ranges.push(self.range_for_match(&m))
self.change_selections(None, cx, |s| s.select_ranges(ranges)); // }
// self.change_selections(None, cx, |s| s.select_ranges(ranges));
} }
fn replace( fn replace(
&mut self, &mut self,
@ -1044,7 +1061,7 @@ impl SearchableItem for Editor {
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) -> Task<Vec<Range<Anchor>>> { ) -> Task<Vec<Range<Anchor>>> {
let buffer = self.buffer().read(cx).snapshot(cx); let buffer = self.buffer().read(cx).snapshot(cx);
cx.background().spawn(async move { cx.background_executor().spawn(async move {
let mut ranges = Vec::new(); let mut ranges = Vec::new();
if let Some((_, _, excerpt_buffer)) = buffer.as_singleton() { if let Some((_, _, excerpt_buffer)) = buffer.as_singleton() {
ranges.extend( ranges.extend(

View file

@ -170,170 +170,173 @@ pub fn update_inlay_link_and_hover_points(
shift_held: bool, shift_held: bool,
cx: &mut ViewContext<'_, Editor>, cx: &mut ViewContext<'_, Editor>,
) { ) {
let hovered_offset = if point_for_position.column_overshoot_after_line_end == 0 { todo!("old implementation below")
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 => {}
}
}
}
} }
// ) {
// 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 { // if !go_to_definition_updated {
update_go_to_definition_link(editor, None, cmd_held, shift_held, cx); // update_go_to_definition_link(editor, None, cmd_held, shift_held, cx);
} // }
if !hover_updated { // if !hover_updated {
hover_popover::hover_at(editor, None, cx); // hover_popover::hover_at(editor, None, cx);
} // }
} // }
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub enum LinkDefinitionKind { pub enum LinkDefinitionKind {
@ -570,34 +573,35 @@ fn go_to_fetched_definition_of_kind(
split: bool, split: bool,
cx: &mut ViewContext<Editor>, cx: &mut ViewContext<Editor>,
) { ) {
let cached_definitions = editor.link_go_to_definition_state.definitions.clone(); todo!();
hide_link_definition(editor, cx); // let cached_definitions = editor.link_go_to_definition_state.definitions.clone();
let cached_definitions_kind = editor.link_go_to_definition_state.kind; // 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); // let is_correct_kind = cached_definitions_kind == Some(kind);
if !cached_definitions.is_empty() && is_correct_kind { // if !cached_definitions.is_empty() && is_correct_kind {
if !editor.focused { // if !editor.focused {
cx.focus_self(); // cx.focus_self();
} // }
editor.navigate_to_definitions(cached_definitions, split, cx); // editor.navigate_to_definitions(cached_definitions, split, cx);
} else { // } else {
editor.select( // editor.select(
SelectPhase::Begin { // SelectPhase::Begin {
position: point.next_valid, // position: point.next_valid,
add: false, // add: false,
click_count: 1, // click_count: 1,
}, // },
cx, // cx,
); // );
if point.as_valid().is_some() { // if point.as_valid().is_some() {
match kind { // match kind {
LinkDefinitionKind::Symbol => editor.go_to_definition(&Default::default(), cx), // LinkDefinitionKind::Symbol => editor.go_to_definition(&Default::default(), cx),
LinkDefinitionKind::Type => editor.go_to_type_definition(&Default::default(), cx), // LinkDefinitionKind::Type => editor.go_to_type_definition(&Default::default(), cx),
} // }
} // }
} // }
} }
// #[cfg(test)] // #[cfg(test)]

View file

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

View file

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

View file

@ -9,7 +9,7 @@ use crate::{
Anchor, DisplayPoint, Editor, EditorMode, Event, InlayHintRefreshReason, MultiBufferSnapshot, Anchor, DisplayPoint, Editor, EditorMode, Event, InlayHintRefreshReason, MultiBufferSnapshot,
ToPoint, 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 language::{Bias, Point};
use std::{ use std::{
cmp::Ordering, cmp::Ordering,
@ -39,18 +39,18 @@ pub struct ScrollAnchor {
impl ScrollAnchor { impl ScrollAnchor {
fn new() -> Self { fn new() -> Self {
Self { Self {
offset: gpui::Point::zero(), offset: gpui::Point::default(),
anchor: Anchor::min(), 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; let mut scroll_position = self.offset;
if self.anchor != Anchor::min() { if self.anchor != Anchor::min() {
let scroll_top = self.anchor.to_display_point(snapshot).row() as f32; 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 { } else {
scroll_position.set_y(0.); scroll_position.y = 0.;
} }
scroll_position scroll_position
} }
@ -133,7 +133,7 @@ pub struct ScrollManager {
anchor: ScrollAnchor, anchor: ScrollAnchor,
ongoing: OngoingScroll, ongoing: OngoingScroll,
autoscroll_request: Option<(Autoscroll, bool)>, 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, show_scrollbars: bool,
hide_scrollbar_task: Option<Task<()>>, hide_scrollbar_task: Option<Task<()>>,
visible_line_count: Option<f32>, visible_line_count: Option<f32>,
@ -171,7 +171,7 @@ impl ScrollManager {
self.ongoing.axis = axis; 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) self.anchor.scroll_position(snapshot)
} }
@ -188,7 +188,7 @@ impl ScrollManager {
( (
ScrollAnchor { ScrollAnchor {
anchor: Anchor::min(), anchor: Anchor::min(),
offset: scroll_position.max(Point::zero()), offset: scroll_position.max(&gpui::Point::default()),
}, },
0, 0,
) )
@ -228,9 +228,9 @@ impl ScrollManager {
self.show_scrollbar(cx); self.show_scrollbar(cx);
self.autoscroll_request.take(); self.autoscroll_request.take();
if let Some(workspace_id) = workspace_id { 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 { .spawn(async move {
DB.save_scroll_position( DB.save_scroll_position(
item_id, item_id,
@ -255,7 +255,9 @@ impl ScrollManager {
if cx.default_global::<ScrollbarAutoHide>().0 { if cx.default_global::<ScrollbarAutoHide>().0 {
self.hide_scrollbar_task = Some(cx.spawn(|editor, mut cx| async move { 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 editor
.update(&mut cx, |editor, cx| { .update(&mut cx, |editor, cx| {
editor.scroll_manager.show_scrollbars = false; editor.scroll_manager.show_scrollbars = false;
@ -287,7 +289,7 @@ impl ScrollManager {
} }
// todo!() // todo!()
// impl Editor { impl Editor {
// pub fn vertical_scroll_margin(&mut self) -> usize { // pub fn vertical_scroll_margin(&mut self) -> usize {
// self.scroll_manager.vertical_scroll_margin as usize // self.scroll_manager.vertical_scroll_margin as usize
// } // }
@ -316,36 +318,37 @@ impl ScrollManager {
// } // }
// } // }
// pub fn set_scroll_position( pub fn set_scroll_position(
// &mut self, &mut self,
// scroll_position: gpui::Point<Pixels>, scroll_position: gpui::Point<f32>,
// cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
// ) { ) {
// self.set_scroll_position_internal(scroll_position, true, false, cx); self.set_scroll_position_internal(scroll_position, true, false, cx);
// } }
// pub(crate) fn set_scroll_position_internal( pub(crate) fn set_scroll_position_internal(
// &mut self, &mut self,
// scroll_position: gpui::Point<Pixels>, scroll_position: gpui::Point<f32>,
// local: bool, local: bool,
// autoscroll: bool, autoscroll: bool,
// cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
// ) { ) {
// let map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); let map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
// hide_hover(self, cx); hide_hover(self, cx);
// let workspace_id = self.workspace.as_ref().map(|workspace| workspace.1); let workspace_id = self.workspace.as_ref().map(|workspace| workspace.1);
// self.scroll_manager.set_scroll_position( self.scroll_manager.set_scroll_position(
// scroll_position, scroll_position,
// &map, &map,
// local, local,
// autoscroll, autoscroll,
// workspace_id, workspace_id,
// cx, cx,
// ); );
// todo!()
// self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx); // self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
// } }
// pub fn scroll_position(&self, cx: &mut ViewContext<Self>) -> gpui::Point<Pixels> { // 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)); // let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
@ -443,4 +446,4 @@ impl ScrollManager {
// self.set_scroll_anchor(scroll_anchor, cx); // self.set_scroll_anchor(scroll_anchor, cx);
// } // }
// } // }
// } }

View file

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

View file

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

View file

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

View file

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

View file

@ -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( #[derive(
Add, AddAssign, Clone, Copy, Default, Div, Eq, Hash, Ord, PartialEq, PartialOrd, Sub, SubAssign, Add, AddAssign, Clone, Copy, Default, Div, Eq, Hash, Ord, PartialEq, PartialOrd, Sub, SubAssign,
)] )]

View file

@ -411,6 +411,7 @@ impl MacTextSystemState {
descent: typographic_bounds.descent.into(), descent: typographic_bounds.descent.into(),
runs, runs,
font_size, font_size,
len: text.len(),
} }
} }

View file

@ -167,6 +167,15 @@ impl TextStyle {
Ok(self) 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 { pub fn to_run(&self, len: usize) -> TextRun {
TextRun { TextRun {
len, len,

View file

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

View file

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

View file

@ -16,6 +16,7 @@ pub struct LineLayout {
pub ascent: Pixels, pub ascent: Pixels,
pub descent: Pixels, pub descent: Pixels,
pub runs: Vec<ShapedRun>, pub runs: Vec<ShapedRun>,
pub len: usize,
} }
#[derive(Debug)] #[derive(Debug)]

View file

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

View file

@ -30,7 +30,7 @@ regex.workspace = true
[dev-dependencies] [dev-dependencies]
collections = { path = "../collections", features = ["test-support"] } 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"] } util = { path = "../util", features = ["test-support"] }
ctor.workspace = true ctor.workspace = true
env_logger.workspace = true env_logger.workspace = true

View file

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

View file

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