From 919703e6a8e4c1a9f5b32889dd32b13f26b0aa56 Mon Sep 17 00:00:00 2001 From: Agus Zubiaga Date: Mon, 20 Jan 2025 19:11:13 -0300 Subject: [PATCH] Toggle inline completion menu from keyboard (#23380) --- assets/keymaps/default-linux.json | 4 +- assets/keymaps/default-macos.json | 5 +- .../src/inline_completion_button.rs | 57 ++++++++++++------- crates/ui/src/components/context_menu.rs | 2 +- crates/zed/src/zed.rs | 10 ++++ 5 files changed, 55 insertions(+), 23 deletions(-) diff --git a/assets/keymaps/default-linux.json b/assets/keymaps/default-linux.json index 26cff0e9ce..bfd2c95449 100644 --- a/assets/keymaps/default-linux.json +++ b/assets/keymaps/default-linux.json @@ -30,7 +30,9 @@ "ctrl-0": "zed::ResetBufferFontSize", "ctrl-,": "zed::OpenSettings", "ctrl-q": "zed::Quit", - "f11": "zed::ToggleFullScreen" + "f11": "zed::ToggleFullScreen", + "ctrl-alt-z": "zeta::RateCompletions", + "ctrl-shift-i": "inline_completion::ToggleMenu" } }, { diff --git a/assets/keymaps/default-macos.json b/assets/keymaps/default-macos.json index c5cd705438..843b94fe78 100644 --- a/assets/keymaps/default-macos.json +++ b/assets/keymaps/default-macos.json @@ -38,7 +38,9 @@ "alt-cmd-h": "zed::HideOthers", "cmd-m": "zed::Minimize", "fn-f": "zed::ToggleFullScreen", - "ctrl-cmd-f": "zed::ToggleFullScreen" + "ctrl-cmd-f": "zed::ToggleFullScreen", + "ctrl-shift-z": "zeta::RateCompletions", + "ctrl-shift-i": "inline_completion::ToggleMenu" } }, { @@ -68,7 +70,6 @@ "cmd-v": "editor::Paste", "cmd-z": "editor::Undo", "cmd-shift-z": "editor::Redo", - "ctrl-shift-z": "zeta::RateCompletions", "up": "editor::MoveUp", "ctrl-up": "editor::MoveToStartOfParagraph", "pageup": "editor::MovePageUp", diff --git a/crates/inline_completion_button/src/inline_completion_button.rs b/crates/inline_completion_button/src/inline_completion_button.rs index 1b11f988c2..21ba92231d 100644 --- a/crates/inline_completion_button/src/inline_completion_button.rs +++ b/crates/inline_completion_button/src/inline_completion_button.rs @@ -18,10 +18,7 @@ use language::{ use settings::{update_settings_file, Settings, SettingsStore}; use std::{path::Path, sync::Arc, time::Duration}; use supermaven::{AccountStatus, Supermaven}; -use ui::{ - ActiveTheme as _, ButtonLike, Color, FluentBuilder as _, Icon, IconWithIndicator, Indicator, - PopoverMenuHandle, -}; +use ui::{prelude::*, ButtonLike, Color, Icon, IconWithIndicator, Indicator, PopoverMenuHandle}; use workspace::{ create_and_open_local_file, item::ItemHandle, @@ -36,6 +33,7 @@ use zed_predict_tos::ZedPredictTos; use zeta::RateCompletionModal; actions!(zeta, [RateCompletions]); +actions!(inline_completion, [ToggleMenu]); const COPILOT_SETTINGS_URL: &str = "https://github.com/settings/copilot"; @@ -50,7 +48,7 @@ pub struct InlineCompletionButton { fs: Arc, workspace: WeakView, user_store: Model, - zeta_popover_menu_handle: PopoverMenuHandle, + popover_menu_handle: PopoverMenuHandle, } enum SupermavenButtonStatus { @@ -118,7 +116,7 @@ impl Render for InlineCompletionButton { .ok(); } })) - .tooltip(|cx| Tooltip::text("GitHub Copilot", cx)), + .tooltip(|cx| Tooltip::for_action("GitHub Copilot", &ToggleMenu, cx)), ); } let this = cx.view().clone(); @@ -135,9 +133,11 @@ impl Render for InlineCompletionButton { }) .anchor(Corner::BottomRight) .trigger( - IconButton::new("copilot-icon", icon) - .tooltip(|cx| Tooltip::text("GitHub Copilot", cx)), - ), + IconButton::new("copilot-icon", icon).tooltip(|cx| { + Tooltip::for_action("GitHub Copilot", &ToggleMenu, cx) + }), + ) + .with_handle(self.popover_menu_handle.clone()), ) } @@ -170,6 +170,7 @@ impl Render for InlineCompletionButton { let icon = status.to_icon(); let tooltip_text = status.to_tooltip(); + let has_menu = status.has_menu(); let this = cx.view().clone(); let fs = self.fs.clone(); @@ -202,10 +203,14 @@ impl Render for InlineCompletionButton { _ => None, }) .anchor(Corner::BottomRight) - .trigger( - IconButton::new("supermaven-icon", icon) - .tooltip(move |cx| Tooltip::text(tooltip_text.clone(), cx)), - ), + .trigger(IconButton::new("supermaven-icon", icon).tooltip(move |cx| { + if has_menu { + Tooltip::for_action(tooltip_text.clone(), &ToggleMenu, cx) + } else { + Tooltip::text(tooltip_text.clone(), cx) + } + })) + .with_handle(self.popover_menu_handle.clone()), ); } @@ -254,10 +259,12 @@ impl Render for InlineCompletionButton { } let this = cx.view().clone(); - let button = IconButton::new("zeta", IconName::ZedPredict) - .when(!self.zeta_popover_menu_handle.is_deployed(), |button| { - button.tooltip(|cx| Tooltip::text("Edit Prediction", cx)) - }); + let button = IconButton::new("zeta", IconName::ZedPredict).when( + !self.popover_menu_handle.is_deployed(), + |button| { + button.tooltip(|cx| Tooltip::for_action("Edit Prediction", &ToggleMenu, cx)) + }, + ); let is_refreshing = self .inline_completion_provider @@ -269,7 +276,7 @@ impl Render for InlineCompletionButton { Some(this.update(cx, |this, cx| this.build_zeta_context_menu(cx))) }) .anchor(Corner::BottomRight) - .with_handle(self.zeta_popover_menu_handle.clone()); + .with_handle(self.popover_menu_handle.clone()); if is_refreshing { popover_menu = popover_menu.trigger( @@ -296,6 +303,7 @@ impl InlineCompletionButton { workspace: WeakView, fs: Arc, user_store: Model, + popover_menu_handle: PopoverMenuHandle, cx: &mut ViewContext, ) -> Self { if let Some(copilot) = Copilot::global(cx) { @@ -311,7 +319,7 @@ impl InlineCompletionButton { language: None, file: None, inline_completion_provider: None, - zeta_popover_menu_handle: PopoverMenuHandle::default(), + popover_menu_handle, workspace, fs, user_store, @@ -470,6 +478,10 @@ impl InlineCompletionButton { cx.notify() } + + pub fn toggle_menu(&mut self, cx: &mut ViewContext) { + self.popover_menu_handle.toggle(cx); + } } impl StatusItemView for InlineCompletionButton { @@ -507,6 +519,13 @@ impl SupermavenButtonStatus { SupermavenButtonStatus::Initializing => "Supermaven initializing".to_string(), } } + + fn has_menu(&self) -> bool { + match self { + SupermavenButtonStatus::Ready | SupermavenButtonStatus::NeedsActivation(_) => true, + SupermavenButtonStatus::Errored(_) | SupermavenButtonStatus::Initializing => false, + } + } } async fn configure_disabled_globs( diff --git a/crates/ui/src/components/context_menu.rs b/crates/ui/src/components/context_menu.rs index 38d151c8b0..e4357a8ccd 100644 --- a/crates/ui/src/components/context_menu.rs +++ b/crates/ui/src/components/context_menu.rs @@ -145,7 +145,7 @@ impl ContextMenu { delayed: false, clicked: false, _on_blur_subscription, - keep_open_on_confirm: true, + keep_open_on_confirm: false, }, cx, ) diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 5e0e4a9f9f..79f62e7f9d 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -48,6 +48,7 @@ use std::rc::Rc; use std::{borrow::Cow, ops::Deref, path::Path, sync::Arc}; use terminal_view::terminal_panel::{self, TerminalPanel}; use theme::{ActiveTheme, ThemeSettings}; +use ui::PopoverMenuHandle; use util::markdown::MarkdownString; use util::{asset_str, ResultExt}; use uuid::Uuid; @@ -164,15 +165,24 @@ pub fn initialize_workspace( show_software_emulation_warning_if_needed(specs, cx); } + let popover_menu_handle = PopoverMenuHandle::default(); + let inline_completion_button = cx.new_view(|cx| { inline_completion_button::InlineCompletionButton::new( workspace.weak_handle(), app_state.fs.clone(), app_state.user_store.clone(), + popover_menu_handle.clone(), cx, ) }); + workspace.register_action({ + move |_, _: &inline_completion_button::ToggleMenu, cx| { + popover_menu_handle.toggle(cx); + } + }); + let diagnostic_summary = cx.new_view(|cx| diagnostics::items::DiagnosticIndicator::new(workspace, cx)); let activity_indicator =