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

2
Cargo.lock generated
View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

View file

@ -553,17 +553,18 @@ impl InlayHintCache {
let mut resolved_hint = let mut resolved_hint =
resolved_hint_task.await.context("hint resolve task")?; resolved_hint_task.await.context("hint resolve task")?;
editor.update(&mut cx, |editor, _| { editor.update(&mut cx, |editor, _| {
if let Some(excerpt_hints) = todo!()
editor.inlay_hint_cache.hints.get(&excerpt_id) // if let Some(excerpt_hints) =
{ // editor.inlay_hint_cache.hints.get(&excerpt_id)
let mut guard = excerpt_hints.write(); // {
if let Some(cached_hint) = guard.hints_by_id.get_mut(&id) { // let mut guard = excerpt_hints.write();
if cached_hint.resolve_state == ResolveState::Resolving { // if let Some(cached_hint) = guard.hints_by_id.get_mut(&id) {
resolved_hint.resolve_state = ResolveState::Resolved; // if cached_hint.resolve_state == ResolveState::Resolving {
*cached_hint = resolved_hint; // resolved_hint.resolve_state = ResolveState::Resolved;
} // *cached_hint = resolved_hint;
} // }
} // }
// }
})?; })?;
} }
@ -584,89 +585,91 @@ fn spawn_new_update_tasks(
update_cache_version: usize, update_cache_version: usize,
cx: &mut ViewContext<'_, Editor>, cx: &mut ViewContext<'_, Editor>,
) { ) {
let visible_hints = Arc::new(editor.visible_inlay_hints(cx)); todo!("old version below");
for (excerpt_id, (excerpt_buffer, new_task_buffer_version, excerpt_visible_range)) in
excerpts_to_query
{
if excerpt_visible_range.is_empty() {
continue;
}
let buffer = excerpt_buffer.read(cx);
let buffer_id = buffer.remote_id();
let buffer_snapshot = buffer.snapshot();
if buffer_snapshot
.version()
.changed_since(&new_task_buffer_version)
{
continue;
}
let cached_excerpt_hints = editor.inlay_hint_cache.hints.get(&excerpt_id).cloned();
if let Some(cached_excerpt_hints) = &cached_excerpt_hints {
let cached_excerpt_hints = cached_excerpt_hints.read();
let cached_buffer_version = &cached_excerpt_hints.buffer_version;
if cached_excerpt_hints.version > update_cache_version
|| cached_buffer_version.changed_since(&new_task_buffer_version)
{
continue;
}
};
let (multi_buffer_snapshot, Some(query_ranges)) =
editor.buffer.update(cx, |multi_buffer, cx| {
(
multi_buffer.snapshot(cx),
determine_query_ranges(
multi_buffer,
excerpt_id,
&excerpt_buffer,
excerpt_visible_range,
cx,
),
)
})
else {
return;
};
let query = ExcerptQuery {
buffer_id,
excerpt_id,
cache_version: update_cache_version,
invalidate,
reason,
};
let new_update_task = |query_ranges| {
new_update_task(
query,
query_ranges,
multi_buffer_snapshot,
buffer_snapshot.clone(),
Arc::clone(&visible_hints),
cached_excerpt_hints,
Arc::clone(&editor.inlay_hint_cache.lsp_request_limiter),
cx,
)
};
match editor.inlay_hint_cache.update_tasks.entry(excerpt_id) {
hash_map::Entry::Occupied(mut o) => {
o.get_mut().update_cached_tasks(
&buffer_snapshot,
query_ranges,
invalidate,
new_update_task,
);
}
hash_map::Entry::Vacant(v) => {
v.insert(TasksForRanges::new(
query_ranges.clone(),
new_update_task(query_ranges),
));
}
}
}
} }
// let visible_hints = Arc::new(editor.visible_inlay_hints(cx));
// for (excerpt_id, (excerpt_buffer, new_task_buffer_version, excerpt_visible_range)) in
// excerpts_to_query
// {
// if excerpt_visible_range.is_empty() {
// continue;
// }
// let buffer = excerpt_buffer.read(cx);
// let buffer_id = buffer.remote_id();
// let buffer_snapshot = buffer.snapshot();
// if buffer_snapshot
// .version()
// .changed_since(&new_task_buffer_version)
// {
// continue;
// }
// let cached_excerpt_hints = editor.inlay_hint_cache.hints.get(&excerpt_id).cloned();
// if let Some(cached_excerpt_hints) = &cached_excerpt_hints {
// let cached_excerpt_hints = cached_excerpt_hints.read();
// let cached_buffer_version = &cached_excerpt_hints.buffer_version;
// if cached_excerpt_hints.version > update_cache_version
// || cached_buffer_version.changed_since(&new_task_buffer_version)
// {
// continue;
// }
// };
// let (multi_buffer_snapshot, Some(query_ranges)) =
// editor.buffer.update(cx, |multi_buffer, cx| {
// (
// multi_buffer.snapshot(cx),
// determine_query_ranges(
// multi_buffer,
// excerpt_id,
// &excerpt_buffer,
// excerpt_visible_range,
// cx,
// ),
// )
// })
// else {
// return;
// };
// let query = ExcerptQuery {
// buffer_id,
// excerpt_id,
// cache_version: update_cache_version,
// invalidate,
// reason,
// };
// let new_update_task = |query_ranges| {
// new_update_task(
// query,
// query_ranges,
// multi_buffer_snapshot,
// buffer_snapshot.clone(),
// Arc::clone(&visible_hints),
// cached_excerpt_hints,
// Arc::clone(&editor.inlay_hint_cache.lsp_request_limiter),
// cx,
// )
// };
// match editor.inlay_hint_cache.update_tasks.entry(excerpt_id) {
// hash_map::Entry::Occupied(mut o) => {
// o.get_mut().update_cached_tasks(
// &buffer_snapshot,
// query_ranges,
// invalidate,
// new_update_task,
// );
// }
// hash_map::Entry::Vacant(v) => {
// v.insert(TasksForRanges::new(
// query_ranges.clone(),
// new_update_task(query_ranges),
// ));
// }
// }
// }
// }
#[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 mut cached_inlays_changed = !new_update.remove_from_cache.is_empty();
cached_excerpt_hints
.ordered_hints
.retain(|hint_id| !new_update.remove_from_cache.contains(hint_id));
cached_excerpt_hints
.hints_by_id
.retain(|hint_id, _| !new_update.remove_from_cache.contains(hint_id));
let mut splice = InlaySplice {
to_remove: new_update.remove_from_visible,
to_insert: Vec::new(),
};
for new_hint in new_update.add_to_cache {
let insert_position = match cached_excerpt_hints
.ordered_hints
.binary_search_by(|probe| {
cached_excerpt_hints.hints_by_id[probe]
.position
.cmp(&new_hint.position, &buffer_snapshot)
}) {
Ok(i) => {
let mut insert_position = Some(i);
for id in &cached_excerpt_hints.ordered_hints[i..] {
let cached_hint = &cached_excerpt_hints.hints_by_id[id];
if new_hint
.position
.cmp(&cached_hint.position, &buffer_snapshot)
.is_gt()
{
break;
}
if cached_hint.text() == new_hint.text() {
insert_position = None;
break;
}
}
insert_position
}
Err(i) => Some(i),
};
if let Some(insert_position) = insert_position {
let new_inlay_id = post_inc(&mut editor.next_inlay_id);
if editor
.inlay_hint_cache
.allowed_hint_kinds
.contains(&new_hint.kind)
{
let new_hint_position =
multi_buffer_snapshot.anchor_in_excerpt(query.excerpt_id, new_hint.position);
splice
.to_insert
.push(Inlay::hint(new_inlay_id, new_hint_position, &new_hint));
}
let new_id = InlayId::Hint(new_inlay_id);
cached_excerpt_hints.hints_by_id.insert(new_id, new_hint);
cached_excerpt_hints
.ordered_hints
.insert(insert_position, new_id);
cached_inlays_changed = true;
}
}
cached_excerpt_hints.buffer_version = buffer_snapshot.version().clone();
drop(cached_excerpt_hints);
if invalidate {
let mut outdated_excerpt_caches = HashSet::default();
for (excerpt_id, excerpt_hints) in &editor.inlay_hint_cache().hints {
let excerpt_hints = excerpt_hints.read();
if excerpt_hints.buffer_id == query.buffer_id
&& excerpt_id != &query.excerpt_id
&& buffer_snapshot
.version()
.changed_since(&excerpt_hints.buffer_version)
{
outdated_excerpt_caches.insert(*excerpt_id);
splice
.to_remove
.extend(excerpt_hints.ordered_hints.iter().copied());
}
}
cached_inlays_changed |= !outdated_excerpt_caches.is_empty();
editor
.inlay_hint_cache
.hints
.retain(|excerpt_id, _| !outdated_excerpt_caches.contains(excerpt_id));
}
let InlaySplice {
to_remove,
to_insert,
} = splice;
let displayed_inlays_changed = !to_remove.is_empty() || !to_insert.is_empty();
if cached_inlays_changed || displayed_inlays_changed {
editor.inlay_hint_cache.version += 1;
}
if displayed_inlays_changed {
editor.splice_inlay_hints(to_remove, to_insert, cx)
}
} }
// let cached_excerpt_hints = editor
// .inlay_hint_cache
// .hints
// .entry(new_update.excerpt_id)
// .or_insert_with(|| {
// Arc::new(RwLock::new(CachedExcerptHints {
// version: query.cache_version,
// buffer_version: buffer_snapshot.version().clone(),
// buffer_id: query.buffer_id,
// ordered_hints: Vec::new(),
// hints_by_id: HashMap::default(),
// }))
// });
// let mut cached_excerpt_hints = cached_excerpt_hints.write();
// match query.cache_version.cmp(&cached_excerpt_hints.version) {
// cmp::Ordering::Less => return,
// cmp::Ordering::Greater | cmp::Ordering::Equal => {
// cached_excerpt_hints.version = query.cache_version;
// }
// }
// let mut cached_inlays_changed = !new_update.remove_from_cache.is_empty();
// cached_excerpt_hints
// .ordered_hints
// .retain(|hint_id| !new_update.remove_from_cache.contains(hint_id));
// cached_excerpt_hints
// .hints_by_id
// .retain(|hint_id, _| !new_update.remove_from_cache.contains(hint_id));
// let mut splice = InlaySplice {
// to_remove: new_update.remove_from_visible,
// to_insert: Vec::new(),
// };
// for new_hint in new_update.add_to_cache {
// let insert_position = match cached_excerpt_hints
// .ordered_hints
// .binary_search_by(|probe| {
// cached_excerpt_hints.hints_by_id[probe]
// .position
// .cmp(&new_hint.position, &buffer_snapshot)
// }) {
// Ok(i) => {
// let mut insert_position = Some(i);
// for id in &cached_excerpt_hints.ordered_hints[i..] {
// let cached_hint = &cached_excerpt_hints.hints_by_id[id];
// if new_hint
// .position
// .cmp(&cached_hint.position, &buffer_snapshot)
// .is_gt()
// {
// break;
// }
// if cached_hint.text() == new_hint.text() {
// insert_position = None;
// break;
// }
// }
// insert_position
// }
// Err(i) => Some(i),
// };
// if let Some(insert_position) = insert_position {
// let new_inlay_id = post_inc(&mut editor.next_inlay_id);
// if editor
// .inlay_hint_cache
// .allowed_hint_kinds
// .contains(&new_hint.kind)
// {
// let new_hint_position =
// multi_buffer_snapshot.anchor_in_excerpt(query.excerpt_id, new_hint.position);
// splice
// .to_insert
// .push(Inlay::hint(new_inlay_id, new_hint_position, &new_hint));
// }
// let new_id = InlayId::Hint(new_inlay_id);
// cached_excerpt_hints.hints_by_id.insert(new_id, new_hint);
// cached_excerpt_hints
// .ordered_hints
// .insert(insert_position, new_id);
// cached_inlays_changed = true;
// }
// }
// cached_excerpt_hints.buffer_version = buffer_snapshot.version().clone();
// drop(cached_excerpt_hints);
// if invalidate {
// let mut outdated_excerpt_caches = HashSet::default();
// for (excerpt_id, excerpt_hints) in &editor.inlay_hint_cache().hints {
// let excerpt_hints = excerpt_hints.read();
// if excerpt_hints.buffer_id == query.buffer_id
// && excerpt_id != &query.excerpt_id
// && buffer_snapshot
// .version()
// .changed_since(&excerpt_hints.buffer_version)
// {
// outdated_excerpt_caches.insert(*excerpt_id);
// splice
// .to_remove
// .extend(excerpt_hints.ordered_hints.iter().copied());
// }
// }
// cached_inlays_changed |= !outdated_excerpt_caches.is_empty();
// editor
// .inlay_hint_cache
// .hints
// .retain(|excerpt_id, _| !outdated_excerpt_caches.contains(excerpt_id));
// }
// let InlaySplice {
// to_remove,
// to_insert,
// } = splice;
// let displayed_inlays_changed = !to_remove.is_empty() || !to_insert.is_empty();
// if cached_inlays_changed || displayed_inlays_changed {
// editor.inlay_hint_cache.version += 1;
// }
// if displayed_inlays_changed {
// editor.splice_inlay_hints(to_remove, to_insert, cx)
// }
// }
// #[cfg(test)] // #[cfg(test)]
// pub mod tests { // pub mod tests {

View file

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

View file

@ -170,170 +170,173 @@ pub fn update_inlay_link_and_hover_points(
shift_held: bool, shift_held: bool,
cx: &mut ViewContext<'_, Editor>, cx: &mut ViewContext<'_, Editor>,
) { ) {
let hovered_offset = if point_for_position.column_overshoot_after_line_end == 0 { todo!("old implementation below")
Some(snapshot.display_point_to_inlay_offset(point_for_position.exact_unclipped, Bias::Left))
} else {
None
};
let mut go_to_definition_updated = false;
let mut hover_updated = false;
if let Some(hovered_offset) = hovered_offset {
let buffer_snapshot = editor.buffer().read(cx).snapshot(cx);
let previous_valid_anchor = buffer_snapshot.anchor_at(
point_for_position.previous_valid.to_point(snapshot),
Bias::Left,
);
let next_valid_anchor = buffer_snapshot.anchor_at(
point_for_position.next_valid.to_point(snapshot),
Bias::Right,
);
if let Some(hovered_hint) = editor
.visible_inlay_hints(cx)
.into_iter()
.skip_while(|hint| {
hint.position
.cmp(&previous_valid_anchor, &buffer_snapshot)
.is_lt()
})
.take_while(|hint| {
hint.position
.cmp(&next_valid_anchor, &buffer_snapshot)
.is_le()
})
.max_by_key(|hint| hint.id)
{
let inlay_hint_cache = editor.inlay_hint_cache();
let excerpt_id = previous_valid_anchor.excerpt_id;
if let Some(cached_hint) = inlay_hint_cache.hint_by_id(excerpt_id, hovered_hint.id) {
match cached_hint.resolve_state {
ResolveState::CanResolve(_, _) => {
if let Some(buffer_id) = previous_valid_anchor.buffer_id {
inlay_hint_cache.spawn_hint_resolve(
buffer_id,
excerpt_id,
hovered_hint.id,
cx,
);
}
}
ResolveState::Resolved => {
let mut extra_shift_left = 0;
let mut extra_shift_right = 0;
if cached_hint.padding_left {
extra_shift_left += 1;
extra_shift_right += 1;
}
if cached_hint.padding_right {
extra_shift_right += 1;
}
match cached_hint.label {
project::InlayHintLabel::String(_) => {
if let Some(tooltip) = cached_hint.tooltip {
hover_popover::hover_at_inlay(
editor,
InlayHover {
excerpt: excerpt_id,
tooltip: match tooltip {
InlayHintTooltip::String(text) => HoverBlock {
text,
kind: HoverBlockKind::PlainText,
},
InlayHintTooltip::MarkupContent(content) => {
HoverBlock {
text: content.value,
kind: content.kind,
}
}
},
range: InlayHighlight {
inlay: hovered_hint.id,
inlay_position: hovered_hint.position,
range: extra_shift_left
..hovered_hint.text.len() + extra_shift_right,
},
},
cx,
);
hover_updated = true;
}
}
project::InlayHintLabel::LabelParts(label_parts) => {
let hint_start =
snapshot.anchor_to_inlay_offset(hovered_hint.position);
if let Some((hovered_hint_part, part_range)) =
hover_popover::find_hovered_hint_part(
label_parts,
hint_start,
hovered_offset,
)
{
let highlight_start =
(part_range.start - hint_start).0 + extra_shift_left;
let highlight_end =
(part_range.end - hint_start).0 + extra_shift_right;
let highlight = InlayHighlight {
inlay: hovered_hint.id,
inlay_position: hovered_hint.position,
range: highlight_start..highlight_end,
};
if let Some(tooltip) = hovered_hint_part.tooltip {
hover_popover::hover_at_inlay(
editor,
InlayHover {
excerpt: excerpt_id,
tooltip: match tooltip {
InlayHintLabelPartTooltip::String(text) => {
HoverBlock {
text,
kind: HoverBlockKind::PlainText,
}
}
InlayHintLabelPartTooltip::MarkupContent(
content,
) => HoverBlock {
text: content.value,
kind: content.kind,
},
},
range: highlight.clone(),
},
cx,
);
hover_updated = true;
}
if let Some((language_server_id, location)) =
hovered_hint_part.location
{
go_to_definition_updated = true;
update_go_to_definition_link(
editor,
Some(GoToDefinitionTrigger::InlayHint(
highlight,
location,
language_server_id,
)),
cmd_held,
shift_held,
cx,
);
}
}
}
};
}
ResolveState::Resolving => {}
}
}
}
}
if !go_to_definition_updated {
update_go_to_definition_link(editor, None, cmd_held, shift_held, cx);
}
if !hover_updated {
hover_popover::hover_at(editor, None, cx);
}
} }
// ) {
// let hovered_offset = if point_for_position.column_overshoot_after_line_end == 0 {
// Some(snapshot.display_point_to_inlay_offset(point_for_position.exact_unclipped, Bias::Left))
// } else {
// None
// };
// let mut go_to_definition_updated = false;
// let mut hover_updated = false;
// if let Some(hovered_offset) = hovered_offset {
// let buffer_snapshot = editor.buffer().read(cx).snapshot(cx);
// let previous_valid_anchor = buffer_snapshot.anchor_at(
// point_for_position.previous_valid.to_point(snapshot),
// Bias::Left,
// );
// let next_valid_anchor = buffer_snapshot.anchor_at(
// point_for_position.next_valid.to_point(snapshot),
// Bias::Right,
// );
// if let Some(hovered_hint) = editor
// .visible_inlay_hints(cx)
// .into_iter()
// .skip_while(|hint| {
// hint.position
// .cmp(&previous_valid_anchor, &buffer_snapshot)
// .is_lt()
// })
// .take_while(|hint| {
// hint.position
// .cmp(&next_valid_anchor, &buffer_snapshot)
// .is_le()
// })
// .max_by_key(|hint| hint.id)
// {
// let inlay_hint_cache = editor.inlay_hint_cache();
// let excerpt_id = previous_valid_anchor.excerpt_id;
// if let Some(cached_hint) = inlay_hint_cache.hint_by_id(excerpt_id, hovered_hint.id) {
// match cached_hint.resolve_state {
// ResolveState::CanResolve(_, _) => {
// if let Some(buffer_id) = previous_valid_anchor.buffer_id {
// inlay_hint_cache.spawn_hint_resolve(
// buffer_id,
// excerpt_id,
// hovered_hint.id,
// cx,
// );
// }
// }
// ResolveState::Resolved => {
// let mut extra_shift_left = 0;
// let mut extra_shift_right = 0;
// if cached_hint.padding_left {
// extra_shift_left += 1;
// extra_shift_right += 1;
// }
// if cached_hint.padding_right {
// extra_shift_right += 1;
// }
// match cached_hint.label {
// project::InlayHintLabel::String(_) => {
// if let Some(tooltip) = cached_hint.tooltip {
// hover_popover::hover_at_inlay(
// editor,
// InlayHover {
// excerpt: excerpt_id,
// tooltip: match tooltip {
// InlayHintTooltip::String(text) => HoverBlock {
// text,
// kind: HoverBlockKind::PlainText,
// },
// InlayHintTooltip::MarkupContent(content) => {
// HoverBlock {
// text: content.value,
// kind: content.kind,
// }
// }
// },
// range: InlayHighlight {
// inlay: hovered_hint.id,
// inlay_position: hovered_hint.position,
// range: extra_shift_left
// ..hovered_hint.text.len() + extra_shift_right,
// },
// },
// cx,
// );
// hover_updated = true;
// }
// }
// project::InlayHintLabel::LabelParts(label_parts) => {
// let hint_start =
// snapshot.anchor_to_inlay_offset(hovered_hint.position);
// if let Some((hovered_hint_part, part_range)) =
// hover_popover::find_hovered_hint_part(
// label_parts,
// hint_start,
// hovered_offset,
// )
// {
// let highlight_start =
// (part_range.start - hint_start).0 + extra_shift_left;
// let highlight_end =
// (part_range.end - hint_start).0 + extra_shift_right;
// let highlight = InlayHighlight {
// inlay: hovered_hint.id,
// inlay_position: hovered_hint.position,
// range: highlight_start..highlight_end,
// };
// if let Some(tooltip) = hovered_hint_part.tooltip {
// hover_popover::hover_at_inlay(
// editor,
// InlayHover {
// excerpt: excerpt_id,
// tooltip: match tooltip {
// InlayHintLabelPartTooltip::String(text) => {
// HoverBlock {
// text,
// kind: HoverBlockKind::PlainText,
// }
// }
// InlayHintLabelPartTooltip::MarkupContent(
// content,
// ) => HoverBlock {
// text: content.value,
// kind: content.kind,
// },
// },
// range: highlight.clone(),
// },
// cx,
// );
// hover_updated = true;
// }
// if let Some((language_server_id, location)) =
// hovered_hint_part.location
// {
// go_to_definition_updated = true;
// update_go_to_definition_link(
// editor,
// Some(GoToDefinitionTrigger::InlayHint(
// highlight,
// location,
// language_server_id,
// )),
// cmd_held,
// shift_held,
// cx,
// );
// }
// }
// }
// };
// }
// ResolveState::Resolving => {}
// }
// }
// }
// }
// if !go_to_definition_updated {
// update_go_to_definition_link(editor, None, cmd_held, shift_held, cx);
// }
// if !hover_updated {
// hover_popover::hover_at(editor, None, cx);
// }
// }
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub enum LinkDefinitionKind { pub enum LinkDefinitionKind {
@ -570,34 +573,35 @@ fn go_to_fetched_definition_of_kind(
split: bool, split: bool,
cx: &mut ViewContext<Editor>, cx: &mut ViewContext<Editor>,
) { ) {
let cached_definitions = editor.link_go_to_definition_state.definitions.clone(); todo!();
hide_link_definition(editor, cx); // let cached_definitions = editor.link_go_to_definition_state.definitions.clone();
let cached_definitions_kind = editor.link_go_to_definition_state.kind; // hide_link_definition(editor, cx);
// let cached_definitions_kind = editor.link_go_to_definition_state.kind;
let is_correct_kind = cached_definitions_kind == Some(kind); // let is_correct_kind = cached_definitions_kind == Some(kind);
if !cached_definitions.is_empty() && is_correct_kind { // if !cached_definitions.is_empty() && is_correct_kind {
if !editor.focused { // if !editor.focused {
cx.focus_self(); // cx.focus_self();
} // }
editor.navigate_to_definitions(cached_definitions, split, cx); // editor.navigate_to_definitions(cached_definitions, split, cx);
} else { // } else {
editor.select( // editor.select(
SelectPhase::Begin { // SelectPhase::Begin {
position: point.next_valid, // position: point.next_valid,
add: false, // add: false,
click_count: 1, // click_count: 1,
}, // },
cx, // cx,
); // );
if point.as_valid().is_some() { // if point.as_valid().is_some() {
match kind { // match kind {
LinkDefinitionKind::Symbol => editor.go_to_definition(&Default::default(), cx), // LinkDefinitionKind::Symbol => editor.go_to_definition(&Default::default(), cx),
LinkDefinitionKind::Type => editor.go_to_type_definition(&Default::default(), cx), // LinkDefinitionKind::Type => editor.go_to_type_definition(&Default::default(), cx),
} // }
} // }
} // }
} }
// #[cfg(test)] // #[cfg(test)]

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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