@@ -5,6 +5,7 @@ pub(crate) mod typed;
55pub use dap::*;
66use helix_vcs::Hunk;
77pub use lsp::*;
8+use tokio::sync::oneshot;
89use tui::widgets::Row;
910pub use typed::*;
1011
@@ -4171,6 +4172,24 @@ pub fn completion(cx: &mut Context) {
41714172 None => return,
41724173 };
41734174
4175+ // setup a chanel that allows the request to be canceled
4176+ let (tx, rx) = oneshot::channel();
4177+ // set completion_request so that this request can be canceled
4178+ // by setting completion_request, the old channel stored there is dropped
4179+ // and the associated request is automatically dropped
4180+ cx.editor.completion_request_handle = Some(tx);
4181+ let future = async move {
4182+ tokio::select! {
4183+ biased;
4184+ _ = rx => {
4185+ Ok(serde_json::Value::Null)
4186+ }
4187+ res = future => {
4188+ res
4189+ }
4190+ }
4191+ };
4192+
41744193 let trigger_offset = cursor;
41754194
41764195 // TODO: trigger_offset should be the cursor offset but we also need a starting offset from where we want to apply
@@ -4183,11 +4202,19 @@ pub fn completion(cx: &mut Context) {
41834202 let start_offset = cursor.saturating_sub(offset);
41844203 let savepoint = doc.savepoint(view);
41854204
4205+ let trigger_doc = doc.id();
4206+ let trigger_view = view.id;
4207+
41864208 cx.callback(
41874209 future,
41884210 move |editor, compositor, response: Option<lsp::CompletionResponse>| {
4189− if editor.mode != Mode::Insert {
4190− // we're not in insert mode anymore
4211+ let (view, doc) = current_ref!(editor);
4212+ // check if the completion request is stale.
4213+ //
4214+ // Completions are completed asynchrounsly and therefore the user could
4215+ //switch document/view or leave insert mode. In all of thoise cases the
4216+ // completion should be discarded
4217+ if editor.mode != Mode::Insert || view.id != trigger_view || doc.id() != trigger_doc {
41914218 return;
41924219 }
41934220