Re-entrant SendKeystrokes (#20277)
Release Notes: - Improved `workspace::SendKeystrokes` to support re-binding keys. For example you can now do: `"x": ["workspace::SendKeystrokes", "\" _ x"]` in vim mode to ensure that `x` does not clobber your clipboard. - Improved key binding documentation
This commit is contained in:
parent
50069a2153
commit
38b1940251
4 changed files with 137 additions and 475 deletions
|
@ -1403,6 +1403,32 @@ async fn test_remap_nested_pineapple(cx: &mut gpui::TestAppContext) {
|
|||
cx.shared_state().await.assert_eq("🍍ˇ");
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_remap_recursion(cx: &mut gpui::TestAppContext) {
|
||||
let mut cx = NeovimBackedTestContext::new(cx).await;
|
||||
cx.update(|cx| {
|
||||
cx.bind_keys([KeyBinding::new(
|
||||
"x",
|
||||
workspace::SendKeystrokes("\" _ x".to_string()),
|
||||
Some("VimControl"),
|
||||
)]);
|
||||
cx.bind_keys([KeyBinding::new(
|
||||
"y",
|
||||
workspace::SendKeystrokes("2 x".to_string()),
|
||||
Some("VimControl"),
|
||||
)])
|
||||
});
|
||||
cx.neovim.exec("noremap x \"_x").await;
|
||||
cx.neovim.exec("map y 2x").await;
|
||||
|
||||
cx.set_shared_state("ˇhello").await;
|
||||
cx.simulate_shared_keystrokes("d l").await;
|
||||
cx.shared_clipboard().await.assert_eq("h");
|
||||
cx.simulate_shared_keystrokes("y").await;
|
||||
cx.shared_clipboard().await.assert_eq("h");
|
||||
cx.shared_state().await.assert_eq("ˇlo");
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_escape_while_waiting(cx: &mut gpui::TestAppContext) {
|
||||
let mut cx = NeovimBackedTestContext::new(cx).await;
|
||||
|
|
11
crates/vim/test_data/test_remap_recursion.json
Normal file
11
crates/vim/test_data/test_remap_recursion.json
Normal file
|
@ -0,0 +1,11 @@
|
|||
{"Exec":{"command":"noremap x \"_x"}}
|
||||
{"Exec":{"command":"map y 2x"}}
|
||||
{"Put":{"state":"ˇhello"}}
|
||||
{"Key":"d"}
|
||||
{"Key":"l"}
|
||||
{"Get":{"state":"ˇello","mode":"Normal"}}
|
||||
{"ReadRegister":{"name":"\"","value":"h"}}
|
||||
{"Key":"y"}
|
||||
{"Get":{"state":"ˇlo","mode":"Normal"}}
|
||||
{"ReadRegister":{"name":"\"","value":"h"}}
|
||||
{"Get":{"state":"ˇlo","mode":"Normal"}}
|
|
@ -752,7 +752,7 @@ pub struct Workspace {
|
|||
leader_updates_tx: mpsc::UnboundedSender<(PeerId, proto::UpdateFollowers)>,
|
||||
database_id: Option<WorkspaceId>,
|
||||
app_state: Arc<AppState>,
|
||||
dispatching_keystrokes: Rc<RefCell<Vec<Keystroke>>>,
|
||||
dispatching_keystrokes: Rc<RefCell<(HashSet<String>, Vec<Keystroke>)>>,
|
||||
_subscriptions: Vec<Subscription>,
|
||||
_apply_leader_updates: Task<Result<()>>,
|
||||
_observe_current_user: Task<Result<()>>,
|
||||
|
@ -1784,6 +1784,11 @@ impl Workspace {
|
|||
}
|
||||
|
||||
fn send_keystrokes(&mut self, action: &SendKeystrokes, cx: &mut ViewContext<Self>) {
|
||||
let mut state = self.dispatching_keystrokes.borrow_mut();
|
||||
if !state.0.insert(action.0.clone()) {
|
||||
cx.propagate();
|
||||
return;
|
||||
}
|
||||
let mut keystrokes: Vec<Keystroke> = action
|
||||
.0
|
||||
.split(' ')
|
||||
|
@ -1791,16 +1796,16 @@ impl Workspace {
|
|||
.collect();
|
||||
keystrokes.reverse();
|
||||
|
||||
self.dispatching_keystrokes
|
||||
.borrow_mut()
|
||||
.append(&mut keystrokes);
|
||||
state.1.append(&mut keystrokes);
|
||||
drop(state);
|
||||
|
||||
let keystrokes = self.dispatching_keystrokes.clone();
|
||||
cx.window_context()
|
||||
.spawn(|mut cx| async move {
|
||||
// limit to 100 keystrokes to avoid infinite recursion.
|
||||
for _ in 0..100 {
|
||||
let Some(keystroke) = keystrokes.borrow_mut().pop() else {
|
||||
let Some(keystroke) = keystrokes.borrow_mut().1.pop() else {
|
||||
keystrokes.borrow_mut().0.clear();
|
||||
return Ok(());
|
||||
};
|
||||
cx.update(|cx| {
|
||||
|
@ -1817,7 +1822,8 @@ impl Workspace {
|
|||
}
|
||||
})?;
|
||||
}
|
||||
keystrokes.borrow_mut().clear();
|
||||
|
||||
*keystrokes.borrow_mut() = Default::default();
|
||||
Err(anyhow!("over 100 keystrokes passed to send_keystrokes"))
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue