From 606d5e36e1016d473f15869757a1efb39c7f45cf Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 15 May 2023 16:44:09 -0700 Subject: [PATCH] Add events for copilot suggestion accepting and discarding --- crates/copilot/src/copilot.rs | 36 ++++++++++++++++++++++++++++++++++- crates/editor/src/editor.rs | 16 ++++++++++++++-- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/crates/copilot/src/copilot.rs b/crates/copilot/src/copilot.rs index 9ccd9c445d..55c4c70f65 100644 --- a/crates/copilot/src/copilot.rs +++ b/crates/copilot/src/copilot.rs @@ -47,6 +47,10 @@ pub fn init(http: Arc, node_runtime: Arc, cx: &mut }); cx.set_global(copilot.clone()); + ////////////////////////////////////// + // SUBSCRIBE TO COPILOT EVENTS HERE // + ////////////////////////////////////// + cx.observe(&copilot, |handle, cx| { let status = handle.read(cx).status(); cx.update_default_global::(move |filter, _cx| { @@ -270,8 +274,19 @@ pub struct Copilot { buffers: HashMap>, } +pub enum Event { + CompletionAccepted { + uuid: String, + file_type: Option>, + }, + CompletionDiscarded { + uuids: Vec, + file_type: Option>, + }, +} + impl Entity for Copilot { - type Event = (); + type Event = Event; fn app_will_quit( &mut self, @@ -737,18 +752,26 @@ impl Copilot { pub fn accept_completion( &mut self, completion: &Completion, + file_type: Option>, cx: &mut ModelContext, ) -> Task> { let server = match self.server.as_authenticated() { Ok(server) => server, Err(error) => return Task::ready(Err(error)), }; + + cx.emit(Event::CompletionAccepted { + uuid: completion.uuid.clone(), + file_type, + }); + let request = server .lsp .request::(request::NotifyAcceptedParams { uuid: completion.uuid.clone(), }); + cx.background().spawn(async move { request.await?; Ok(()) @@ -758,12 +781,22 @@ impl Copilot { pub fn discard_completions( &mut self, completions: &[Completion], + file_type: Option>, cx: &mut ModelContext, ) -> Task> { let server = match self.server.as_authenticated() { Ok(server) => server, Err(error) => return Task::ready(Err(error)), }; + + cx.emit(Event::CompletionDiscarded { + uuids: completions + .iter() + .map(|completion| completion.uuid.clone()) + .collect(), + file_type: file_type.clone(), + }); + let request = server .lsp @@ -773,6 +806,7 @@ impl Copilot { .map(|completion| completion.uuid.clone()) .collect(), }); + cx.background().spawn(async move { request.await?; Ok(()) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index b6d44397a9..221e94370e 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -3094,8 +3094,14 @@ impl Editor { if let Some((copilot, completion)) = Copilot::global(cx).zip(self.copilot_state.active_completion()) { + let language = self + .language_at(completion.range.start.offset, cx) + .map(|language| language.name()); + copilot - .update(cx, |copilot, cx| copilot.accept_completion(completion, cx)) + .update(cx, |copilot, cx| { + copilot.accept_completion(completion, language, cx) + }) .detach_and_log_err(cx); } self.insert_with_autoindent_mode(&suggestion.text.to_string(), None, cx); @@ -3109,9 +3115,15 @@ impl Editor { fn discard_copilot_suggestion(&mut self, cx: &mut ViewContext) -> bool { if self.has_active_copilot_suggestion(cx) { if let Some(copilot) = Copilot::global(cx) { + let file_type = self.copilot_state + .completions + .get(0) + .and_then(|completion| self.language_at(completion.range.start.offset, cx)) + .map(|language| language.name()); + copilot .update(cx, |copilot, cx| { - copilot.discard_completions(&self.copilot_state.completions, cx) + copilot.discard_completions(&self.copilot_state.completions, file_type, cx) }) .detach_and_log_err(cx); }