Vim: enable sending multiple keystrokes from custom keybinding (#7965)
Release Notes: - Added `workspace::SendKeystrokes` to enable mapping from one key to a sequence of others ([#7033](https://github.com/zed-industries/zed/issues/7033)). Improves #7033. Big thank you to @ConradIrwin who did most of the heavy lifting on this one. This PR allows the user to send multiple keystrokes via custom keybinding. For example, the following keybinding would go down four lines and then right four characters. ```json [ { "context": "Editor && VimControl && !VimWaiting && !menu", "bindings": { "g z": [ "workspace::SendKeystrokes", "j j j j l l l l" ], } } ] ``` --------- Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
This commit is contained in:
parent
8f5d7db875
commit
8a73bc4c7d
13 changed files with 343 additions and 157 deletions
|
@ -4,7 +4,7 @@ use gpui::{
|
|||
FocusHandle, FocusableView, Length, ListState, MouseButton, MouseDownEvent, Render, Task,
|
||||
UniformListScrollHandle, View, ViewContext, WindowContext,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
use std::{sync::Arc, time::Duration};
|
||||
use ui::{prelude::*, v_flex, Color, Divider, Label, ListItem, ListItemSpacing};
|
||||
use workspace::ModalView;
|
||||
|
||||
|
@ -40,6 +40,19 @@ pub trait PickerDelegate: Sized + 'static {
|
|||
fn placeholder_text(&self) -> Arc<str>;
|
||||
fn update_matches(&mut self, query: String, cx: &mut ViewContext<Picker<Self>>) -> Task<()>;
|
||||
|
||||
// Delegates that support this method (e.g. the CommandPalette) can chose to block on any background
|
||||
// work for up to `duration` to try and get a result synchronously.
|
||||
// This avoids a flash of an empty command-palette on cmd-shift-p, and lets workspace::SendKeystrokes
|
||||
// mostly work when dismissing a palette.
|
||||
fn finalize_update_matches(
|
||||
&mut self,
|
||||
_query: String,
|
||||
_duration: Duration,
|
||||
_cx: &mut ViewContext<Picker<Self>>,
|
||||
) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn confirm(&mut self, secondary: bool, cx: &mut ViewContext<Picker<Self>>);
|
||||
fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>);
|
||||
|
||||
|
@ -98,6 +111,9 @@ impl<D: PickerDelegate> Picker<D> {
|
|||
is_modal: true,
|
||||
};
|
||||
this.update_matches("".to_string(), cx);
|
||||
// give the delegate 4ms to renderthe first set of suggestions.
|
||||
this.delegate
|
||||
.finalize_update_matches("".to_string(), Duration::from_millis(4), cx);
|
||||
this
|
||||
}
|
||||
|
||||
|
@ -197,15 +213,24 @@ impl<D: PickerDelegate> Picker<D> {
|
|||
}
|
||||
|
||||
fn confirm(&mut self, _: &menu::Confirm, cx: &mut ViewContext<Self>) {
|
||||
if self.pending_update_matches.is_some() {
|
||||
if self.pending_update_matches.is_some()
|
||||
&& !self
|
||||
.delegate
|
||||
.finalize_update_matches(self.query(cx), Duration::from_millis(16), cx)
|
||||
{
|
||||
self.confirm_on_update = Some(false)
|
||||
} else {
|
||||
self.pending_update_matches.take();
|
||||
self.delegate.confirm(false, cx);
|
||||
}
|
||||
}
|
||||
|
||||
fn secondary_confirm(&mut self, _: &menu::SecondaryConfirm, cx: &mut ViewContext<Self>) {
|
||||
if self.pending_update_matches.is_some() {
|
||||
if self.pending_update_matches.is_some()
|
||||
&& !self
|
||||
.delegate
|
||||
.finalize_update_matches(self.query(cx), Duration::from_millis(16), cx)
|
||||
{
|
||||
self.confirm_on_update = Some(true)
|
||||
} else {
|
||||
self.delegate.confirm(true, cx);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue