diff --git a/assets/keymaps/default-linux.json b/assets/keymaps/default-linux.json index c4c2cb2d0e..336ec8e8cc 100644 --- a/assets/keymaps/default-linux.json +++ b/assets/keymaps/default-linux.json @@ -3,10 +3,14 @@ { "bindings": { "up": "menu::SelectPrev", + "shift-tab": "menu::SelectPrev", + "home": "menu::SelectFirst", "pageup": "menu::SelectFirst", "shift-pageup": "menu::SelectFirst", "ctrl-p": "menu::SelectPrev", "down": "menu::SelectNext", + "tab": "menu::SelectNext", + "end": "menu::SelectLast", "pagedown": "menu::SelectLast", "shift-pagedown": "menu::SelectFirst", "ctrl-n": "menu::SelectNext", diff --git a/assets/keymaps/default-macos.json b/assets/keymaps/default-macos.json index 63c737e614..567cc1fc65 100644 --- a/assets/keymaps/default-macos.json +++ b/assets/keymaps/default-macos.json @@ -3,10 +3,14 @@ { "bindings": { "up": "menu::SelectPrev", + "shift-tab": "menu::SelectPrev", + "home": "menu::SelectFirst", "pageup": "menu::SelectFirst", "shift-pageup": "menu::SelectFirst", "ctrl-p": "menu::SelectPrev", "down": "menu::SelectNext", + "tab": "menu::SelectNext", + "end": "menu::SelectLast", "pagedown": "menu::SelectLast", "shift-pagedown": "menu::SelectFirst", "ctrl-n": "menu::SelectNext", diff --git a/crates/zed/src/zed/linux_prompts.rs b/crates/zed/src/zed/linux_prompts.rs index 949bba4936..7493f8c6f3 100644 --- a/crates/zed/src/zed/linux_prompts.rs +++ b/crates/zed/src/zed/linux_prompts.rs @@ -31,6 +31,7 @@ pub fn fallback_prompt_renderer( detail: detail.map(ToString::to_string), actions: actions.iter().map(ToString::to_string).collect(), focus: cx.focus_handle(), + active_action_id: actions.len() - 1, } }); @@ -44,10 +45,12 @@ pub struct FallbackPromptRenderer { detail: Option, actions: Vec, focus: FocusHandle, + active_action_id: usize, } + impl FallbackPromptRenderer { fn confirm(&mut self, _: &menu::Confirm, cx: &mut ViewContext) { - cx.emit(PromptResponse(0)); + cx.emit(PromptResponse(self.active_action_id)); } fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext) { @@ -55,7 +58,32 @@ impl FallbackPromptRenderer { cx.emit(PromptResponse(ix)); } } + + fn select_first(&mut self, _: &menu::SelectFirst, cx: &mut ViewContext) { + self.active_action_id = 0; + cx.notify(); + } + + fn select_last(&mut self, _: &menu::SelectLast, cx: &mut ViewContext) { + self.active_action_id = self.actions.len().saturating_sub(1); + cx.notify(); + } + + fn select_next(&mut self, _: &menu::SelectNext, cx: &mut ViewContext) { + self.active_action_id = (self.active_action_id + 1) % self.actions.len(); + cx.notify(); + } + + fn select_prev(&mut self, _: &menu::SelectPrev, cx: &mut ViewContext) { + if self.active_action_id > 0 { + self.active_action_id -= 1; + } else { + self.active_action_id = self.actions.len().saturating_sub(1); + } + cx.notify(); + } } + impl Render for FallbackPromptRenderer { fn render(&mut self, cx: &mut ViewContext) -> impl IntoElement { let settings = ThemeSettings::get_global(cx); @@ -66,6 +94,10 @@ impl Render for FallbackPromptRenderer { .track_focus(&self.focus) .on_action(cx.listener(Self::confirm)) .on_action(cx.listener(Self::cancel)) + .on_action(cx.listener(Self::select_next)) + .on_action(cx.listener(Self::select_prev)) + .on_action(cx.listener(Self::select_first)) + .on_action(cx.listener(Self::select_last)) .elevation_3(cx) .w_72() .overflow_hidden() @@ -87,11 +119,11 @@ impl Render for FallbackPromptRenderer { .child(detail) })) .child(h_flex().justify_end().gap_2().children( - self.actions.iter().enumerate().rev().map(|(ix, action)| { + self.actions.iter().rev().enumerate().map(|(ix, action)| { ui::Button::new(ix, action.clone()) .label_size(LabelSize::Large) .style(ButtonStyle::Filled) - .when(ix == 0, |el| { + .when(ix == self.active_action_id, |el| { el.style(ButtonStyle::Tinted(TintColor::Accent)) }) .layer(ElevationIndex::ModalSurface)