diff --git a/Cargo.lock b/Cargo.lock index bef68c15b0..c60b84b877 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16424,6 +16424,7 @@ name = "zeta" version = "0.1.0" dependencies = [ "anyhow", + "arrayvec", "call", "client", "clock", diff --git a/crates/zeta/Cargo.toml b/crates/zeta/Cargo.toml index f80dfff5a0..fbd818e22a 100644 --- a/crates/zeta/Cargo.toml +++ b/crates/zeta/Cargo.toml @@ -18,6 +18,7 @@ test-support = [] [dependencies] anyhow.workspace = true +arrayvec.workspace = true client.workspace = true collections.workspace = true editor.workspace = true diff --git a/crates/zeta/src/zeta.rs b/crates/zeta/src/zeta.rs index 80b13011d0..0c135715bf 100644 --- a/crates/zeta/src/zeta.rs +++ b/crates/zeta/src/zeta.rs @@ -3,6 +3,7 @@ mod rate_completion_modal; pub use rate_completion_modal::*; use anyhow::{anyhow, Context as _, Result}; +use arrayvec::ArrayVec; use client::Client; use collections::{HashMap, HashSet, VecDeque}; use futures::AsyncReadExt; @@ -899,10 +900,15 @@ impl CurrentInlineCompletion { } } +struct PendingCompletion { + id: usize, + _task: Task>, +} + pub struct ZetaInlineCompletionProvider { zeta: Model, - first_pending_completion: Option>>, - last_pending_completion: Option>>, + pending_completions: ArrayVec, + next_pending_completion_id: usize, current_completion: Option, } @@ -912,8 +918,8 @@ impl ZetaInlineCompletionProvider { pub fn new(zeta: Model) -> Self { Self { zeta, - first_pending_completion: None, - last_pending_completion: None, + pending_completions: ArrayVec::new(), + next_pending_completion_id: 0, current_completion: None, } } @@ -944,7 +950,9 @@ impl inline_completion::InlineCompletionProvider for ZetaInlineCompletionProvide debounce: bool, cx: &mut ModelContext, ) { - let is_first = self.first_pending_completion.is_none(); + let pending_completion_id = self.next_pending_completion_id; + self.next_pending_completion_id += 1; + let task = cx.spawn(|this, mut cx| async move { if debounce { cx.background_executor().timer(Self::DEBOUNCE_TIMEOUT).await; @@ -965,9 +973,10 @@ impl inline_completion::InlineCompletionProvider for ZetaInlineCompletionProvide } this.update(&mut cx, |this, cx| { - this.first_pending_completion = None; - if !is_first { - this.last_pending_completion = None; + if this.pending_completions[0].id == pending_completion_id { + this.pending_completions.remove(0); + } else { + this.pending_completions.clear(); } if let Some(new_completion) = completion { @@ -993,10 +1002,19 @@ impl inline_completion::InlineCompletionProvider for ZetaInlineCompletionProvide }) }); - if is_first { - self.first_pending_completion = Some(task); - } else { - self.last_pending_completion = Some(task); + // We always maintain at most two pending completions. When we already + // have two, we replace the newest one. + if self.pending_completions.len() <= 1 { + self.pending_completions.push(PendingCompletion { + id: pending_completion_id, + _task: task, + }); + } else if self.pending_completions.len() == 2 { + self.pending_completions.pop(); + self.pending_completions.push(PendingCompletion { + id: pending_completion_id, + _task: task, + }); } } @@ -1011,13 +1029,11 @@ impl inline_completion::InlineCompletionProvider for ZetaInlineCompletionProvide } fn accept(&mut self, _cx: &mut ModelContext) { - self.first_pending_completion.take(); - self.last_pending_completion.take(); + self.pending_completions.clear(); } fn discard(&mut self, _cx: &mut ModelContext) { - self.first_pending_completion.take(); - self.last_pending_completion.take(); + self.pending_completions.clear(); self.current_completion.take(); }