WIP
This commit is contained in:
parent
a731f8fb1e
commit
f3b8a9d8c2
26 changed files with 1782 additions and 1665 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -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",
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// }
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.),
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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>),
|
||||||
|
|
|
@ -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,
|
||||||
)]
|
)]
|
||||||
|
|
|
@ -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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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>,
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue