@@ -117,7 +117,8 @@ action!(Unfold);
action!(FoldSelectedRanges);
action!(Scroll, Vector2F);
action!(Select, SelectPhase);
-action!(ShowAutocomplete);
+action!(ShowCompletions);
+action!(ConfirmCompletion);
pub fn init(cx: &mut MutableAppContext, path_openers: &mut Vec<Box<dyn PathOpener>>) {
path_openers.push(Box::new(items::BufferOpener));
@@ -133,6 +134,7 @@ pub fn init(cx: &mut MutableAppContext, path_openers: &mut Vec<Box<dyn PathOpene
Input("\n".into()),
Some("Editor && mode == auto_height"),
),
+ Binding::new("enter", ConfirmCompletion, Some("Editor && completing")),
Binding::new("tab", Tab, Some("Editor")),
Binding::new("shift-tab", Outdent, Some("Editor")),
Binding::new("ctrl-shift-K", DeleteLine, Some("Editor")),
@@ -225,7 +227,7 @@ pub fn init(cx: &mut MutableAppContext, path_openers: &mut Vec<Box<dyn PathOpene
Binding::new("alt-cmd-[", Fold, Some("Editor")),
Binding::new("alt-cmd-]", Unfold, Some("Editor")),
Binding::new("alt-cmd-f", FoldSelectedRanges, Some("Editor")),
- Binding::new("ctrl-space", ShowAutocomplete, Some("Editor")),
+ Binding::new("ctrl-space", ShowCompletions, Some("Editor")),
]);
cx.add_action(Editor::open_new);
@@ -290,6 +292,7 @@ pub fn init(cx: &mut MutableAppContext, path_openers: &mut Vec<Box<dyn PathOpene
cx.add_action(Editor::unfold);
cx.add_action(Editor::fold_selected_ranges);
cx.add_action(Editor::show_completions);
+ cx.add_action(Editor::confirm_completion);
}
trait SelectionExt {
@@ -425,7 +428,7 @@ struct BracketPairState {
}
struct CompletionState {
- completions: Arc<[Completion]>,
+ completions: Arc<[Completion<Anchor>]>,
selected_item: usize,
list: UniformListState,
}
@@ -1102,6 +1105,11 @@ impl Editor {
}
pub fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
+ if self.completion_state.take().is_some() {
+ cx.notify();
+ return;
+ }
+
if self.mode != EditorMode::Full {
cx.propagate_action();
return;
@@ -1506,7 +1514,7 @@ impl Editor {
}
}
- fn show_completions(&mut self, _: &ShowAutocomplete, cx: &mut ViewContext<Self>) {
+ fn show_completions(&mut self, _: &ShowCompletions, cx: &mut ViewContext<Self>) {
let position = self
.newest_selection::<usize>(&self.buffer.read(cx).read(cx))
.head();
@@ -1533,6 +1541,23 @@ impl Editor {
.detach_and_log_err(cx);
}
+ fn confirm_completion(&mut self, _: &ConfirmCompletion, cx: &mut ViewContext<Self>) {
+ if let Some(completion_state) = self.completion_state.take() {
+ if let Some(completion) = completion_state
+ .completions
+ .get(completion_state.selected_item)
+ {
+ self.buffer.update(cx, |buffer, cx| {
+ buffer.edit_with_autoindent(
+ [completion.old_range.clone()],
+ completion.new_text.clone(),
+ cx,
+ );
+ })
+ }
+ }
+ }
+
pub fn has_completions(&self) -> bool {
self.completion_state.is_some()
}
@@ -4180,6 +4205,9 @@ impl View for Editor {
EditorMode::Full => "full",
};
cx.map.insert("mode".into(), mode.into());
+ if self.completion_state.is_some() {
+ cx.set.insert("completing".into());
+ }
cx
}
}
@@ -852,12 +852,34 @@ impl MultiBuffer {
&self,
position: T,
cx: &mut ModelContext<Self>,
- ) -> Task<Result<Vec<Completion>>>
+ ) -> Task<Result<Vec<Completion<Anchor>>>>
where
T: ToOffset,
{
- let (buffer, text_anchor) = self.text_anchor_for_position(position, cx);
- buffer.update(cx, |buffer, cx| buffer.completions(text_anchor, cx))
+ let snapshot = self.snapshot(cx);
+ let anchor = snapshot.anchor_before(position);
+ let buffer = self.buffers.borrow()[&anchor.buffer_id].buffer.clone();
+ let completions =
+ buffer.update(cx, |buffer, cx| buffer.completions(anchor.text_anchor, cx));
+ cx.foreground().spawn(async move {
+ completions.await.map(|completions| {
+ completions
+ .into_iter()
+ .map(|completion| Completion {
+ old_range: snapshot.anchor_in_excerpt(
+ anchor.excerpt_id.clone(),
+ completion.old_range.start,
+ )
+ ..snapshot.anchor_in_excerpt(
+ anchor.excerpt_id.clone(),
+ completion.old_range.end,
+ ),
+ new_text: completion.new_text,
+ lsp_completion: completion.lsp_completion,
+ })
+ .collect()
+ })
+ })
}
pub fn language<'a>(&self, cx: &'a AppContext) -> Option<&'a Arc<Language>> {
@@ -114,10 +114,10 @@ pub struct Diagnostic {
pub is_disk_based: bool,
}
-pub struct Completion {
- old_range: Range<Anchor>,
- new_text: String,
- lsp_completion: lsp::CompletionItem,
+pub struct Completion<T> {
+ pub old_range: Range<T>,
+ pub new_text: String,
+ pub lsp_completion: lsp::CompletionItem,
}
struct LanguageServerState {
@@ -1622,7 +1622,7 @@ impl Buffer {
&self,
position: T,
cx: &mut ModelContext<Self>,
- ) -> Task<Result<Vec<Completion>>>
+ ) -> Task<Result<Vec<Completion<Anchor>>>>
where
T: ToOffset,
{
@@ -2424,7 +2424,7 @@ impl Default for Diagnostic {
}
}
-impl Completion {
+impl<T> Completion<T> {
pub fn label(&self) -> &str {
&self.lsp_completion.label
}