@@ -1015,15 +1015,17 @@ impl CodeActionsMenu {
pub struct CopilotState {
excerpt_id: Option<ExcerptId>,
pending_refresh: Task<Option<()>>,
+ pending_cycling_refresh: Task<Option<()>>,
+ cycled: bool,
completions: Vec<copilot::Completion>,
active_completion_index: usize,
- cycled: bool,
}
impl Default for CopilotState {
fn default() -> Self {
Self {
excerpt_id: None,
+ pending_cycling_refresh: Task::ready(Some(())),
pending_refresh: Task::ready(Some(())),
completions: Default::default(),
active_completion_index: 0,
@@ -1071,6 +1073,22 @@ impl CopilotState {
}
}
+ fn cycle_completions(&mut self, direction: Direction) {
+ match direction {
+ Direction::Prev => {
+ self.active_completion_index = if self.active_completion_index == 0 {
+ self.completions.len() - 1
+ } else {
+ self.active_completion_index - 1
+ };
+ }
+ Direction::Next => {
+ self.active_completion_index =
+ (self.active_completion_index + 1) % self.completions.len();
+ }
+ }
+ }
+
fn push_completion(&mut self, new_completion: copilot::Completion) {
for completion in &self.completions {
if *completion == new_completion {
@@ -2029,13 +2047,13 @@ impl Editor {
this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
if had_active_copilot_suggestion {
- this.refresh_copilot_suggestions(false, cx);
+ this.refresh_copilot_suggestions(cx);
if !this.has_active_copilot_suggestion(cx) {
this.trigger_completion_on_input(&text, cx);
}
} else {
this.trigger_completion_on_input(&text, cx);
- this.refresh_copilot_suggestions(false, cx);
+ this.refresh_copilot_suggestions(cx);
}
});
}
@@ -2117,7 +2135,7 @@ impl Editor {
.collect();
this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
- this.refresh_copilot_suggestions(false, cx);
+ this.refresh_copilot_suggestions(cx);
});
}
@@ -2515,7 +2533,7 @@ impl Editor {
});
}
- this.refresh_copilot_suggestions(false, cx);
+ this.refresh_copilot_suggestions(cx);
});
let project = self.project.clone()?;
@@ -2808,11 +2826,7 @@ impl Editor {
None
}
- fn refresh_copilot_suggestions(
- &mut self,
- cycling: bool,
- cx: &mut ViewContext<Self>,
- ) -> Option<()> {
+ fn refresh_copilot_suggestions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
let copilot = Copilot::global(cx)?;
if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
self.clear_copilot_suggestions(cx);
@@ -2838,30 +2852,31 @@ impl Editor {
let mut completions = Vec::new();
- let completions_iter = if cycling {
- copilot
- .update(&mut cx, |copilot, cx| {
- copilot.completions(&buffer, buffer_position, cx)
- })
- .await
- } else {
- copilot
- .update(&mut cx, |copilot, cx| {
- copilot.completions_cycling(&buffer, buffer_position, cx)
- })
- .await
- };
+ // let completions_iter = if cycling {
+ let completions_iter = copilot
+ .update(&mut cx, |copilot, cx| {
+ copilot.completions(&buffer, buffer_position, cx)
+ })
+ .await;
+ // } else {
+ // copilot
+ // .update(&mut cx, |copilot, cx| {
+ // copilot.completions_cycling(&buffer, buffer_position, cx)
+ // })
+ // .await
+ // };
completions.extend(completions_iter.log_err().into_iter().flatten());
this.upgrade(&cx)?.update(&mut cx, |this, cx| {
if !completions.is_empty() {
+ this.copilot_state.cycled = false;
+ this.copilot_state.pending_cycling_refresh = Task::ready(None);
this.copilot_state.completions.clear();
this.copilot_state.active_completion_index = 0;
this.copilot_state.excerpt_id = Some(cursor.excerpt_id);
for completion in completions {
this.copilot_state.push_completion(completion);
}
- this.copilot_state.cycled = cycling;
this.update_visible_copilot_suggestion(cx);
}
});
@@ -2872,9 +2887,49 @@ impl Editor {
Some(())
}
+ fn cycle_suggestions(
+ &mut self,
+ direction: Direction,
+ cx: &mut ViewContext<Self>,
+ ) -> Option<()> {
+ let copilot = Copilot::global(cx)?;
+ if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
+ return None;
+ }
+
+ if self.copilot_state.cycled {
+ self.copilot_state.cycle_completions(direction);
+ self.update_visible_copilot_suggestion(cx);
+ } else {
+ let cursor = self.selections.newest_anchor().head();
+ let (buffer, buffer_position) =
+ self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
+ self.copilot_state.pending_cycling_refresh = cx.spawn_weak(|this, mut cx| async move {
+ let completions = copilot
+ .update(&mut cx, |copilot, cx| {
+ copilot.completions_cycling(&buffer, buffer_position, cx)
+ })
+ .await;
+
+ this.upgrade(&cx)?.update(&mut cx, |this, cx| {
+ this.copilot_state.cycled = true;
+ for completion in completions.log_err().into_iter().flatten() {
+ this.copilot_state.push_completion(completion);
+ }
+ this.copilot_state.cycle_completions(direction);
+ this.update_visible_copilot_suggestion(cx);
+ });
+
+ Some(())
+ });
+ }
+
+ Some(())
+ }
+
fn copilot_suggest(&mut self, _: &copilot::Suggest, cx: &mut ViewContext<Self>) {
if !self.has_active_copilot_suggestion(cx) {
- self.refresh_copilot_suggestions(false, cx);
+ self.refresh_copilot_suggestions(cx);
return;
}
@@ -2882,14 +2937,11 @@ impl Editor {
}
fn next_copilot_suggestion(&mut self, _: &copilot::NextSuggestion, cx: &mut ViewContext<Self>) {
- if !self.has_active_copilot_suggestion(cx) || !self.copilot_state.cycled {
- self.refresh_copilot_suggestions(true, cx);
- return;
+ if self.has_active_copilot_suggestion(cx) {
+ self.cycle_suggestions(Direction::Next, cx);
+ } else {
+ self.refresh_copilot_suggestions(cx);
}
-
- self.copilot_state.active_completion_index =
- (self.copilot_state.active_completion_index + 1) % self.copilot_state.completions.len();
- self.update_visible_copilot_suggestion(cx);
}
fn previous_copilot_suggestion(
@@ -2897,18 +2949,11 @@ impl Editor {
_: &copilot::PreviousSuggestion,
cx: &mut ViewContext<Self>,
) {
- if !self.has_active_copilot_suggestion(cx) || !self.copilot_state.cycled {
- self.refresh_copilot_suggestions(true, cx);
- return;
+ if self.has_active_copilot_suggestion(cx) {
+ self.cycle_suggestions(Direction::Prev, cx);
+ } else {
+ self.refresh_copilot_suggestions(cx);
}
-
- self.copilot_state.active_completion_index =
- if self.copilot_state.active_completion_index == 0 {
- self.copilot_state.completions.len() - 1
- } else {
- self.copilot_state.active_completion_index - 1
- };
- self.update_visible_copilot_suggestion(cx);
}
fn accept_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
@@ -3255,7 +3300,7 @@ impl Editor {
this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
this.insert("", cx);
- this.refresh_copilot_suggestions(false, cx);
+ this.refresh_copilot_suggestions(cx);
});
}
@@ -3271,7 +3316,7 @@ impl Editor {
})
});
this.insert("", cx);
- this.refresh_copilot_suggestions(false, cx);
+ this.refresh_copilot_suggestions(cx);
});
}
@@ -3367,7 +3412,7 @@ impl Editor {
self.transact(cx, |this, cx| {
this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
- this.refresh_copilot_suggestions(false, cx);
+ this.refresh_copilot_suggestions(cx);
});
}
@@ -4047,7 +4092,7 @@ impl Editor {
}
self.request_autoscroll(Autoscroll::fit(), cx);
self.unmark_text(cx);
- self.refresh_copilot_suggestions(false, cx);
+ self.refresh_copilot_suggestions(cx);
cx.emit(Event::Edited);
}
}
@@ -4062,7 +4107,7 @@ impl Editor {
}
self.request_autoscroll(Autoscroll::fit(), cx);
self.unmark_text(cx);
- self.refresh_copilot_suggestions(false, cx);
+ self.refresh_copilot_suggestions(cx);
cx.emit(Event::Edited);
}
}
@@ -6524,7 +6569,7 @@ impl Editor {
}
fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
- self.refresh_copilot_suggestions(false, cx);
+ self.refresh_copilot_suggestions(cx);
}
pub fn set_searchable(&mut self, searchable: bool) {