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:
Conrad Irwin 2024-11-05 21:18:16 -07:00 committed by GitHub
parent 50069a2153
commit 38b1940251
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 137 additions and 475 deletions

View file

@ -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);