@@ -26,8 +26,8 @@ use gpui::{
use items::BufferItemHandle;
use itertools::Itertools as _;
use language::{
- AnchorRangeExt as _, BracketPair, Buffer, Diagnostic, DiagnosticSeverity, Language, Point,
- Selection, SelectionGoal, TransactionId,
+ AnchorRangeExt as _, BracketPair, Buffer, Completion, Diagnostic, DiagnosticSeverity, Language,
+ Point, Selection, SelectionGoal, TransactionId,
};
use multi_buffer::MultiBufferChunks;
pub use multi_buffer::{
@@ -390,6 +390,7 @@ pub struct Editor {
highlighted_rows: Option<Range<u32>>,
highlighted_ranges: BTreeMap<TypeId, (Color, Vec<Range<Anchor>>)>,
nav_history: Option<ItemNavHistory>,
+ completion_state: Option<CompletionState>,
}
pub struct EditorSnapshot {
@@ -423,6 +424,11 @@ struct BracketPairState {
pair: BracketPair,
}
+struct CompletionState {
+ completions: Arc<[Completion]>,
+ list: UniformListState,
+}
+
#[derive(Debug)]
struct ActiveDiagnosticGroup {
primary_range: Range<Anchor>,
@@ -539,6 +545,7 @@ impl Editor {
highlighted_rows: None,
highlighted_ranges: Default::default(),
nav_history: None,
+ completion_state: None,
};
let selection = Selection {
id: post_inc(&mut this.next_selection_id),
@@ -1502,9 +1509,46 @@ impl Editor {
let position = self
.newest_selection::<usize>(&self.buffer.read(cx).read(cx))
.head();
- self.buffer
- .update(cx, |buffer, cx| buffer.completions(position, cx))
- .detach_and_log_err(cx);
+
+ let completions = self
+ .buffer
+ .update(cx, |buffer, cx| buffer.completions(position, cx));
+
+ cx.spawn_weak(|this, mut cx| async move {
+ let completions = completions.await?;
+ if let Some(this) = cx.read(|cx| this.upgrade(cx)) {
+ this.update(&mut cx, |this, cx| {
+ this.completion_state = Some(CompletionState {
+ completions: completions.into(),
+ list: Default::default(),
+ });
+ cx.notify();
+ });
+ }
+
+ Ok::<_, anyhow::Error>(())
+ })
+ .detach_and_log_err(cx);
+ }
+
+ pub fn render_completions(&self) -> Option<ElementBox> {
+ self.completion_state.as_ref().map(|state| {
+ let build_settings = self.build_settings.clone();
+ let completions = state.completions.clone();
+ UniformList::new(
+ state.list.clone(),
+ state.completions.len(),
+ move |range, items, cx| {
+ let settings = build_settings(cx);
+ for completion in &completions[range] {
+ items.push(
+ Label::new(completion.label().to_string(), settings.style.text.clone()).boxed(),
+ );
+ }
+ },
+ )
+ .boxed()
+ })
}
pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
@@ -836,6 +836,7 @@ impl Element for EditorElement {
max_row.saturating_sub(1) as f32,
);
+ let mut completions = None;
self.update_view(cx.app, |view, cx| {
let clamped = view.clamp_scroll_left(scroll_max.x());
let autoscrolled;
@@ -855,6 +856,8 @@ impl Element for EditorElement {
if clamped || autoscrolled {
snapshot = view.snapshot(cx);
}
+
+ completions = view.render_completions();
});
let blocks = self.layout_blocks(
@@ -891,6 +894,7 @@ impl Element for EditorElement {
em_width,
em_advance,
selections,
+ completions,
}),
)
}
@@ -1000,6 +1004,7 @@ pub struct LayoutState {
highlighted_ranges: Vec<(Range<DisplayPoint>, Color)>,
selections: HashMap<ReplicaId, Vec<text::Selection<DisplayPoint>>>,
text_offset: Vector2F,
+ completions: Option<ElementBox>,
}
fn layout_line(