@@ -497,6 +497,23 @@ struct InlineCompletionState {
invalidation_range: Range<Anchor>,
}
+enum EditPredictionSettings {
+ Disabled,
+ Enabled {
+ show_in_menu: bool,
+ preview_requires_modifier: bool,
+ },
+}
+
+impl EditPredictionSettings {
+ pub fn is_enabled(&self) -> bool {
+ match self {
+ EditPredictionSettings::Disabled => false,
+ EditPredictionSettings::Enabled { .. } => true,
+ }
+ }
+}
+
enum InlineCompletionHighlight {}
pub enum MenuInlineCompletionsPolicy {
@@ -683,6 +700,7 @@ pub struct Editor {
active_inline_completion: Option<InlineCompletionState>,
/// Used to prevent flickering as the user types while the menu is open
stale_inline_completion_in_menu: Option<InlineCompletionState>,
+ edit_prediction_settings: EditPredictionSettings,
inline_completions_hidden_for_vim_mode: bool,
show_inline_completions_override: Option<bool>,
menu_inline_completions_policy: MenuInlineCompletionsPolicy,
@@ -1395,6 +1413,7 @@ impl Editor {
inline_completions_hidden_for_vim_mode: false,
show_inline_completions_override: None,
menu_inline_completions_policy: MenuInlineCompletionsPolicy::ByProvider,
+ edit_prediction_settings: EditPredictionSettings::Disabled,
custom_context_menu: None,
show_git_blame_gutter: false,
show_git_blame_inline: false,
@@ -1530,7 +1549,7 @@ impl Editor {
key_context.add("copilot_suggestion");
key_context.add("edit_prediction");
- if showing_completions || self.edit_prediction_requires_modifier(cx) {
+ if showing_completions || self.edit_prediction_requires_modifier() {
key_context.add(EDIT_PREDICTION_REQUIRES_MODIFIER_KEY_CONTEXT);
}
}
@@ -1886,23 +1905,14 @@ impl Editor {
cx: &mut Context<Self>,
) {
if self.show_inline_completions_override.is_some() {
- self.set_show_inline_completions(None, window, cx);
+ self.set_show_edit_predictions(None, window, cx);
} else {
- let cursor = self.selections.newest_anchor().head();
- if let Some((buffer, cursor_buffer_position)) =
- self.buffer.read(cx).text_anchor_for_position(cursor, cx)
- {
- let show_inline_completions = !self.should_show_inline_completions_in_buffer(
- &buffer,
- cursor_buffer_position,
- cx,
- );
- self.set_show_inline_completions(Some(show_inline_completions), window, cx);
- }
+ let show_edit_predictions = !self.edit_predictions_enabled();
+ self.set_show_edit_predictions(Some(show_edit_predictions), window, cx);
}
}
- pub fn set_show_inline_completions(
+ pub fn set_show_edit_predictions(
&mut self,
show_edit_predictions: Option<bool>,
window: &mut Window,
@@ -3019,7 +3029,7 @@ impl Editor {
}
let trigger_in_words =
- this.show_edit_predictions_in_menu(cx) || !had_active_inline_completion;
+ this.show_edit_predictions_in_menu() || !had_active_inline_completion;
this.trigger_completion_on_input(&text, trigger_in_words, window, cx);
linked_editing_ranges::refresh_linked_ranges(this, window, cx);
this.refresh_inline_completion(true, false, window, cx);
@@ -3912,7 +3922,7 @@ impl Editor {
*editor.context_menu.borrow_mut() =
Some(CodeContextMenu::Completions(menu));
- if editor.show_edit_predictions_in_menu(cx) {
+ if editor.show_edit_predictions_in_menu() {
editor.update_visible_inline_completion(window, cx);
} else {
editor.discard_inline_completion(false, cx);
@@ -3926,7 +3936,7 @@ impl Editor {
// If it was already hidden and we don't show inline
// completions in the menu, we should also show the
// inline-completion when available.
- if was_hidden && editor.show_edit_predictions_in_menu(cx) {
+ if was_hidden && editor.show_edit_predictions_in_menu() {
editor.update_visible_inline_completion(window, cx);
}
}
@@ -3976,7 +3986,7 @@ impl Editor {
let entries = completions_menu.entries.borrow();
let mat = entries.get(item_ix.unwrap_or(completions_menu.selected_item))?;
- if self.show_edit_predictions_in_menu(cx) {
+ if self.show_edit_predictions_in_menu() {
self.discard_inline_completion(true, cx);
}
let candidate_id = mat.candidate_id;
@@ -4668,7 +4678,7 @@ impl Editor {
}
if !user_requested
- && (!self.should_show_inline_completions_in_buffer(&buffer, cursor_buffer_position, cx)
+ && (!self.should_show_edit_predictions()
|| !self.is_focused(window)
|| buffer.read(cx).is_empty())
{
@@ -4687,58 +4697,79 @@ impl Editor {
Some(())
}
- pub fn should_show_inline_completions(&self, cx: &App) -> bool {
- let cursor = self.selections.newest_anchor().head();
- if let Some((buffer, cursor_position)) =
- self.buffer.read(cx).text_anchor_for_position(cursor, cx)
- {
- self.should_show_inline_completions_in_buffer(&buffer, cursor_position, cx)
- } else {
- false
+ fn show_edit_predictions_in_menu(&self) -> bool {
+ match self.edit_prediction_settings {
+ EditPredictionSettings::Disabled => false,
+ EditPredictionSettings::Enabled { show_in_menu, .. } => show_in_menu,
}
}
- fn edit_prediction_requires_modifier(&self, cx: &App) -> bool {
- let cursor = self.selections.newest_anchor().head();
+ pub fn edit_predictions_enabled(&self) -> bool {
+ match self.edit_prediction_settings {
+ EditPredictionSettings::Disabled => false,
+ EditPredictionSettings::Enabled { .. } => true,
+ }
+ }
- self.buffer
- .read(cx)
- .text_anchor_for_position(cursor, cx)
- .map(|(buffer, _)| {
- all_language_settings(buffer.read(cx).file(), cx).inline_completions_preview_mode()
- == InlineCompletionPreviewMode::WhenHoldingModifier
- })
- .unwrap_or(false)
+ fn edit_prediction_requires_modifier(&self) -> bool {
+ match self.edit_prediction_settings {
+ EditPredictionSettings::Disabled => false,
+ EditPredictionSettings::Enabled {
+ preview_requires_modifier,
+ ..
+ } => preview_requires_modifier,
+ }
}
- fn should_show_inline_completions_in_buffer(
+ fn edit_prediction_settings_at_position(
&self,
buffer: &Entity<Buffer>,
buffer_position: language::Anchor,
cx: &App,
- ) -> bool {
- if !self.snippet_stack.is_empty() {
- return false;
+ ) -> EditPredictionSettings {
+ if self.mode != EditorMode::Full
+ || !self.show_inline_completions_override.unwrap_or(true)
+ || self.inline_completions_disabled_in_scope(buffer, buffer_position, cx)
+ {
+ return EditPredictionSettings::Disabled;
}
- if self.inline_completions_disabled_in_scope(buffer, buffer_position, cx) {
- return false;
- }
+ let buffer = buffer.read(cx);
- if let Some(show_inline_completions) = self.show_inline_completions_override {
- show_inline_completions
- } else {
- let buffer = buffer.read(cx);
- self.mode == EditorMode::Full
- && language_settings(
- buffer.language_at(buffer_position).map(|l| l.name()),
- buffer.file(),
- cx,
- )
- .show_edit_predictions
+ let file = buffer.file();
+
+ if !language_settings(buffer.language().map(|l| l.name()), file, cx).show_edit_predictions {
+ return EditPredictionSettings::Disabled;
+ };
+
+ let by_provider = matches!(
+ self.menu_inline_completions_policy,
+ MenuInlineCompletionsPolicy::ByProvider
+ );
+
+ let show_in_menu = by_provider
+ && EditorSettings::get_global(cx).show_edit_predictions_in_menu
+ && self
+ .edit_prediction_provider
+ .as_ref()
+ .map_or(false, |provider| {
+ provider.provider.show_completions_in_menu()
+ });
+
+ let preview_requires_modifier = all_language_settings(file, cx)
+ .inline_completions_preview_mode()
+ == InlineCompletionPreviewMode::WhenHoldingModifier;
+
+ EditPredictionSettings::Enabled {
+ show_in_menu,
+ preview_requires_modifier,
}
}
+ fn should_show_edit_predictions(&self) -> bool {
+ self.snippet_stack.is_empty() && self.edit_predictions_enabled()
+ }
+
pub fn inline_completions_enabled(&self, cx: &App) -> bool {
let cursor = self.selections.newest_anchor().head();
if let Some((buffer, cursor_position)) =
@@ -4781,9 +4812,7 @@ impl Editor {
let cursor = self.selections.newest_anchor().head();
let (buffer, cursor_buffer_position) =
self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
- if self.inline_completions_hidden_for_vim_mode
- || !self.should_show_inline_completions_in_buffer(&buffer, cursor_buffer_position, cx)
- {
+ if self.inline_completions_hidden_for_vim_mode || !self.should_show_edit_predictions() {
return None;
}
@@ -4889,7 +4918,7 @@ impl Editor {
}
}
- if self.show_edit_predictions_in_menu(cx) {
+ if self.show_edit_predictions_in_menu() {
self.hide_context_menu(window, cx);
}
@@ -5076,14 +5105,10 @@ impl Editor {
/// Returns true when we're displaying the inline completion popover below the cursor
/// like we are not previewing and the LSP autocomplete menu is visible
/// or we are in `when_holding_modifier` mode.
- pub fn inline_completion_visible_in_cursor_popover(
- &self,
- has_completion: bool,
- cx: &App,
- ) -> bool {
+ pub fn edit_prediction_visible_in_cursor_popover(&self, has_completion: bool) -> bool {
if self.previewing_inline_completion
- || !self.show_edit_predictions_in_menu(cx)
- || !self.should_show_inline_completions(cx)
+ || !self.show_edit_predictions_in_menu()
+ || !self.edit_predictions_enabled()
{
return false;
}
@@ -5092,7 +5117,7 @@ impl Editor {
return true;
}
- has_completion && self.edit_prediction_requires_modifier(cx)
+ has_completion && self.edit_prediction_requires_modifier()
}
fn handle_modifiers_changed(
@@ -5102,7 +5127,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
- if self.show_edit_predictions_in_menu(cx) {
+ if self.show_edit_predictions_in_menu() {
let accept_binding =
AcceptEditPredictionBinding::resolve(self.focus_handle(cx), window);
if let Some(accept_keystroke) = accept_binding.keystroke() {
@@ -5140,10 +5165,11 @@ impl Editor {
let offset_selection = selection.map(|endpoint| endpoint.to_offset(&multibuffer));
let excerpt_id = cursor.excerpt_id;
- let show_in_menu = self.show_edit_predictions_in_menu(cx);
+ let show_in_menu = self.show_edit_predictions_in_menu();
let completions_menu_has_precedence = !show_in_menu
&& (self.context_menu.borrow().is_some()
|| (!self.completion_tasks.is_empty() && !self.has_active_inline_completion()));
+
if completions_menu_has_precedence
|| !offset_selection.is_empty()
|| self
@@ -5160,11 +5186,22 @@ impl Editor {
}
self.take_active_inline_completion(cx);
- let provider = self.edit_prediction_provider()?;
+ let Some(provider) = self.edit_prediction_provider() else {
+ self.edit_prediction_settings = EditPredictionSettings::Disabled;
+ return None;
+ };
let (buffer, cursor_buffer_position) =
self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
+ self.edit_prediction_settings =
+ self.edit_prediction_settings_at_position(&buffer, cursor_buffer_position, cx);
+
+ if !self.edit_prediction_settings.is_enabled() {
+ self.discard_inline_completion(false, cx);
+ return None;
+ }
+
let inline_completion = provider.suggest(&buffer, cursor_buffer_position, cx)?;
let edits = inline_completion
.edits
@@ -5223,8 +5260,7 @@ impl Editor {
snapshot,
}
} else {
- let show_completions_in_buffer = !self
- .inline_completion_visible_in_cursor_popover(true, cx)
+ let show_completions_in_buffer = !self.edit_prediction_visible_in_cursor_popover(true)
&& !self.inline_completions_hidden_for_vim_mode;
if show_completions_in_buffer {
if edits
@@ -5300,19 +5336,6 @@ impl Editor {
Some(self.edit_prediction_provider.as_ref()?.provider.clone())
}
- fn show_edit_predictions_in_menu(&self, cx: &App) -> bool {
- let by_provider = matches!(
- self.menu_inline_completions_policy,
- MenuInlineCompletionsPolicy::ByProvider
- );
-
- by_provider
- && EditorSettings::get_global(cx).show_edit_predictions_in_menu
- && self
- .edit_prediction_provider()
- .map_or(false, |provider| provider.show_completions_in_menu())
- }
-
fn render_code_actions_indicator(
&self,
_style: &EditorStyle,