diff --git a/assets/keymaps/default-linux.json b/assets/keymaps/default-linux.json index 3787f97a8d69bdd95d61e9488476852d63080f2b..f52ddfcc26000060dd10b2c54ef35a48cd9d64a2 100644 --- a/assets/keymaps/default-linux.json +++ b/assets/keymaps/default-linux.json @@ -468,13 +468,21 @@ }, { "context": "Editor && showing_completions", + "use_key_equivalents": true, + "bindings": { + "enter": "editor::ConfirmCompletion" + } + }, + { + "context": "Editor && !inline_completion && showing_completions", + "use_key_equivalents": true, "bindings": { - "enter": "editor::ConfirmCompletion", "tab": "editor::ComposeCompletion" } }, { - "context": "Editor && inline_completion && !showing_completions", + "context": "Editor && inline_completion", + "use_key_equivalents": true, "bindings": { "tab": "editor::AcceptInlineCompletion" } diff --git a/assets/keymaps/default-macos.json b/assets/keymaps/default-macos.json index 0e281079e97846e6211950decfdbfce27783e313..1ec898a84b81d6035bcc0d5a6b5360e025e2874b 100644 --- a/assets/keymaps/default-macos.json +++ b/assets/keymaps/default-macos.json @@ -541,12 +541,18 @@ "context": "Editor && showing_completions", "use_key_equivalents": true, "bindings": { - "enter": "editor::ConfirmCompletion", + "enter": "editor::ConfirmCompletion" + } + }, + { + "context": "Editor && !inline_completion && showing_completions", + "use_key_equivalents": true, + "bindings": { "tab": "editor::ComposeCompletion" } }, { - "context": "Editor && inline_completion && !showing_completions", + "context": "Editor && inline_completion", "use_key_equivalents": true, "bindings": { "tab": "editor::AcceptInlineCompletion" diff --git a/crates/copilot/src/copilot_completion_provider.rs b/crates/copilot/src/copilot_completion_provider.rs index 8d664e22899c493b3a694e802e30bc4e3b0714ce..949e2178a6f76dc87f482c4a847357b245aec970 100644 --- a/crates/copilot/src/copilot_completion_provider.rs +++ b/crates/copilot/src/copilot_completion_provider.rs @@ -296,7 +296,6 @@ mod tests { editor.set_inline_completion_provider(Some(copilot_provider), cx) }); - // When inserting, ensure autocompletion is favored over Copilot suggestions. cx.set_state(indoc! {" oneˇ two @@ -323,8 +322,9 @@ mod tests { ); executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); cx.update_editor(|editor, cx| { + // We want to show both: the inline completion and the completion menu assert!(editor.context_menu_visible()); - assert!(!editor.has_active_inline_completion()); + assert!(editor.has_active_inline_completion()); // Confirming a completion inserts it and hides the context menu, without showing // the copilot suggestion afterwards. @@ -338,40 +338,7 @@ mod tests { assert_eq!(editor.display_text(cx), "one.completion_a\ntwo\nthree\n"); }); - // Ensure Copilot suggestions are shown right away if no autocompletion is available. - cx.set_state(indoc! {" - oneˇ - two - three - "}); - cx.simulate_keystroke("."); - drop(handle_completion_request( - &mut cx, - indoc! {" - one.|<> - two - three - "}, - vec![], - )); - handle_copilot_completion_request( - &copilot_lsp, - vec![crate::request::Completion { - text: "one.copilot1".into(), - range: lsp::Range::new(lsp::Position::new(0, 0), lsp::Position::new(0, 4)), - ..Default::default() - }], - vec![], - ); - executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); - cx.update_editor(|editor, cx| { - assert!(!editor.context_menu_visible()); - assert!(editor.has_active_inline_completion()); - assert_eq!(editor.display_text(cx), "one.copilot1\ntwo\nthree\n"); - assert_eq!(editor.text(cx), "one.\ntwo\nthree\n"); - }); - - // Reset editor, and ensure autocompletion is still favored over Copilot suggestions. + // Reset editor and test that accepting completions works cx.set_state(indoc! {" oneˇ two @@ -399,17 +366,12 @@ mod tests { executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); cx.update_editor(|editor, cx| { assert!(editor.context_menu_visible()); - assert!(!editor.has_active_inline_completion()); - - // When hiding the context menu, the Copilot suggestion becomes visible. - editor.cancel(&Default::default(), cx); - assert!(!editor.context_menu_visible()); assert!(editor.has_active_inline_completion()); assert_eq!(editor.display_text(cx), "one.copilot1\ntwo\nthree\n"); assert_eq!(editor.text(cx), "one.\ntwo\nthree\n"); }); - // Ensure existing completion is interpolated when inserting again. + // Ensure existing inline completion is interpolated when inserting again. cx.simulate_keystroke("c"); executor.run_until_parked(); cx.update_editor(|editor, cx| { @@ -880,7 +842,7 @@ mod tests { cx.update_editor(|editor, cx| editor.next_inline_completion(&Default::default(), cx)); executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); cx.update_editor(|editor, cx| { - assert!(!editor.context_menu_visible(), "Even there are some completions available, those are not triggered when active copilot suggestion is present"); + assert!(!editor.context_menu_visible()); assert!(editor.has_active_inline_completion()); assert_eq!(editor.display_text(cx), "one\ntwo.foo()\nthree\n"); assert_eq!(editor.text(cx), "one\ntw\nthree\n"); @@ -934,15 +896,9 @@ mod tests { ); executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); cx.update_editor(|editor, cx| { - assert!( - editor.context_menu_visible(), - "On completion trigger input, the completions should be fetched and visible" - ); - assert!( - !editor.has_active_inline_completion(), - "On completion trigger input, copilot suggestion should be dismissed" - ); - assert_eq!(editor.display_text(cx), "one\ntwo.\nthree\n"); + assert!(editor.context_menu_visible()); + assert!(editor.has_active_inline_completion(),); + assert_eq!(editor.display_text(cx), "one\ntwo.foo()\nthree\n"); assert_eq!(editor.text(cx), "one\ntwo.\nthree\n"); }); } diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 1336a76f22194518bdfb3065fc3038fdde6f44cc..97eb4ee6bffef65454ad9901a7b567681ded43d0 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -3687,16 +3687,13 @@ impl Editor { menu.resolve_visible_completions(editor.completion_provider.as_deref(), cx); *context_menu = Some(CodeContextMenu::Completions(menu)); drop(context_menu); - editor.discard_inline_completion(false, cx); cx.notify(); } else if editor.completion_tasks.len() <= 1 { // If there are no more completion tasks and the last menu was // empty, we should hide it. If it was already hidden, we should // also show the copilot completion when available. drop(context_menu); - if editor.hide_context_menu(cx).is_none() { - editor.update_visible_inline_completion(cx); - } + editor.hide_context_menu(cx); } })?; @@ -3732,6 +3729,7 @@ impl Editor { ) -> Option>> { use language::ToOffset as _; + self.discard_inline_completion(true, cx); let completions_menu = if let CodeContextMenu::Completions(menu) = self.hide_context_menu(cx)? { menu @@ -4475,6 +4473,8 @@ impl Editor { _: &AcceptInlineCompletion, cx: &mut ViewContext, ) { + self.hide_context_menu(cx); + let Some(active_inline_completion) = self.active_inline_completion.as_ref() else { return; }; @@ -4629,9 +4629,7 @@ impl Editor { let offset_selection = selection.map(|endpoint| endpoint.to_offset(&multibuffer)); let excerpt_id = cursor.excerpt_id; - if self.context_menu.read().is_some() - || (!self.completion_tasks.is_empty() && !self.has_active_inline_completion()) - || !offset_selection.is_empty() + if !offset_selection.is_empty() || self .active_inline_completion .as_ref() @@ -4978,11 +4976,7 @@ impl Editor { fn hide_context_menu(&mut self, cx: &mut ViewContext) -> Option { cx.notify(); self.completion_tasks.clear(); - let context_menu = self.context_menu.write().take(); - if context_menu.is_some() { - self.update_visible_inline_completion(cx); - } - context_menu + self.context_menu.write().take() } fn show_snippet_choices(