Insert completion text on enter

Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
Max Brunsfeld 2022-01-31 13:46:50 -08:00
parent 071a55a7ab
commit 8d2b7ba032
4 changed files with 64 additions and 14 deletions

View file

@ -117,7 +117,8 @@ action!(Unfold);
action!(FoldSelectedRanges); action!(FoldSelectedRanges);
action!(Scroll, Vector2F); action!(Scroll, Vector2F);
action!(Select, SelectPhase); action!(Select, SelectPhase);
action!(ShowAutocomplete); action!(ShowCompletions);
action!(ConfirmCompletion);
pub fn init(cx: &mut MutableAppContext, path_openers: &mut Vec<Box<dyn PathOpener>>) { pub fn init(cx: &mut MutableAppContext, path_openers: &mut Vec<Box<dyn PathOpener>>) {
path_openers.push(Box::new(items::BufferOpener)); 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()), Input("\n".into()),
Some("Editor && mode == auto_height"), Some("Editor && mode == auto_height"),
), ),
Binding::new("enter", ConfirmCompletion, Some("Editor && completing")),
Binding::new("tab", Tab, Some("Editor")), Binding::new("tab", Tab, Some("Editor")),
Binding::new("shift-tab", Outdent, Some("Editor")), Binding::new("shift-tab", Outdent, Some("Editor")),
Binding::new("ctrl-shift-K", DeleteLine, 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-[", Fold, Some("Editor")),
Binding::new("alt-cmd-]", Unfold, Some("Editor")), Binding::new("alt-cmd-]", Unfold, Some("Editor")),
Binding::new("alt-cmd-f", FoldSelectedRanges, 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); 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::unfold);
cx.add_action(Editor::fold_selected_ranges); cx.add_action(Editor::fold_selected_ranges);
cx.add_action(Editor::show_completions); cx.add_action(Editor::show_completions);
cx.add_action(Editor::confirm_completion);
} }
trait SelectionExt { trait SelectionExt {
@ -425,7 +428,7 @@ struct BracketPairState {
} }
struct CompletionState { struct CompletionState {
completions: Arc<[Completion]>, completions: Arc<[Completion<Anchor>]>,
selected_item: usize, selected_item: usize,
list: UniformListState, list: UniformListState,
} }
@ -1102,6 +1105,11 @@ impl Editor {
} }
pub fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) { 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 { if self.mode != EditorMode::Full {
cx.propagate_action(); cx.propagate_action();
return; 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 let position = self
.newest_selection::<usize>(&self.buffer.read(cx).read(cx)) .newest_selection::<usize>(&self.buffer.read(cx).read(cx))
.head(); .head();
@ -1533,6 +1541,23 @@ impl Editor {
.detach_and_log_err(cx); .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 { pub fn has_completions(&self) -> bool {
self.completion_state.is_some() self.completion_state.is_some()
} }
@ -4180,6 +4205,9 @@ impl View for Editor {
EditorMode::Full => "full", EditorMode::Full => "full",
}; };
cx.map.insert("mode".into(), mode.into()); cx.map.insert("mode".into(), mode.into());
if self.completion_state.is_some() {
cx.set.insert("completing".into());
}
cx cx
} }
} }

View file

@ -852,12 +852,34 @@ impl MultiBuffer {
&self, &self,
position: T, position: T,
cx: &mut ModelContext<Self>, cx: &mut ModelContext<Self>,
) -> Task<Result<Vec<Completion>>> ) -> Task<Result<Vec<Completion<Anchor>>>>
where where
T: ToOffset, T: ToOffset,
{ {
let (buffer, text_anchor) = self.text_anchor_for_position(position, cx); let snapshot = self.snapshot(cx);
buffer.update(cx, |buffer, cx| buffer.completions(text_anchor, 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>> { pub fn language<'a>(&self, cx: &'a AppContext) -> Option<&'a Arc<Language>> {

View file

@ -114,10 +114,10 @@ pub struct Diagnostic {
pub is_disk_based: bool, pub is_disk_based: bool,
} }
pub struct Completion { pub struct Completion<T> {
old_range: Range<Anchor>, pub old_range: Range<T>,
new_text: String, pub new_text: String,
lsp_completion: lsp::CompletionItem, pub lsp_completion: lsp::CompletionItem,
} }
struct LanguageServerState { struct LanguageServerState {
@ -1622,7 +1622,7 @@ impl Buffer {
&self, &self,
position: T, position: T,
cx: &mut ModelContext<Self>, cx: &mut ModelContext<Self>,
) -> Task<Result<Vec<Completion>>> ) -> Task<Result<Vec<Completion<Anchor>>>>
where where
T: ToOffset, T: ToOffset,
{ {
@ -2424,7 +2424,7 @@ impl Default for Diagnostic {
} }
} }
impl Completion { impl<T> Completion<T> {
pub fn label(&self) -> &str { pub fn label(&self) -> &str {
&self.lsp_completion.label &self.lsp_completion.label
} }

View file

@ -2,6 +2,7 @@ mod admin;
mod api; mod api;
mod assets; mod assets;
mod auth; mod auth;
mod careers;
mod community; mod community;
mod db; mod db;
mod env; mod env;
@ -12,7 +13,6 @@ mod home;
mod releases; mod releases;
mod rpc; mod rpc;
mod team; mod team;
mod careers;
use self::errors::TideResultExt as _; use self::errors::TideResultExt as _;
use ::rpc::Peer; use ::rpc::Peer;