Add initial vim mode mode switching

Co-authored-by: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
Keith Simmons 2022-03-24 19:24:36 -07:00
parent ccc276da7a
commit bb9b36dccd
16 changed files with 683 additions and 49 deletions

View file

@ -442,13 +442,32 @@ impl TestAppContext {
}
pub fn dispatch_keystroke(
&self,
&mut self,
window_id: usize,
responder_chain: Vec<usize>,
keystroke: &Keystroke,
) -> Result<bool> {
let mut state = self.cx.borrow_mut();
state.dispatch_keystroke(window_id, responder_chain, keystroke)
keystroke: Keystroke,
input: Option<String>,
is_held: bool,
) {
self.cx.borrow_mut().update(|cx| {
let presenter = cx
.presenters_and_platform_windows
.get(&window_id)
.unwrap()
.0
.clone();
let responder_chain = presenter.borrow().dispatch_path(cx.as_ref());
if !cx.dispatch_keystroke(window_id, responder_chain, &keystroke) {
presenter.borrow_mut().dispatch_event(
Event::KeyDown {
keystroke,
input,
is_held,
},
cx,
);
}
});
}
pub fn add_model<T, F>(&mut self, build_model: F) -> ModelHandle<T>
@ -503,7 +522,7 @@ impl TestAppContext {
pub fn update<T, F: FnOnce(&mut MutableAppContext) -> T>(&mut self, callback: F) -> T {
let mut state = self.cx.borrow_mut();
// Don't increment pending flushes in order to effects to be flushed before the callback
// Don't increment pending flushes in order for effects to be flushed before the callback
// completes, which is helpful in tests.
let result = callback(&mut *state);
// Flush effects after the callback just in case there are any. This can happen in edge
@ -1250,9 +1269,9 @@ impl MutableAppContext {
}
}
fn defer(&mut self, callback: Box<dyn FnOnce(&mut MutableAppContext)>) {
pub fn defer(&mut self, callback: impl 'static + FnOnce(&mut MutableAppContext)) {
self.pending_effects.push_back(Effect::Deferred {
callback,
callback: Box::new(callback),
after_window_update: false,
})
}
@ -1379,17 +1398,15 @@ impl MutableAppContext {
window_id: usize,
responder_chain: Vec<usize>,
keystroke: &Keystroke,
) -> Result<bool> {
) -> bool {
let mut context_chain = Vec::new();
for view_id in &responder_chain {
if let Some(view) = self.cx.views.get(&(window_id, *view_id)) {
context_chain.push(view.keymap_context(self.as_ref()));
} else {
return Err(anyhow!(
"View {} in responder chain does not exist",
view_id
));
}
let view = self
.cx
.views
.get(&(window_id, *view_id))
.expect("view in responder chain does not exist");
context_chain.push(view.keymap_context(self.as_ref()));
}
let mut pending = false;
@ -1404,13 +1421,13 @@ impl MutableAppContext {
if self.dispatch_action_any(window_id, &responder_chain[0..=i], action.as_ref())
{
self.keystroke_matcher.clear_pending();
return Ok(true);
return true;
}
}
}
}
Ok(pending)
pending
}
pub fn default_global<T: 'static + Default>(&mut self) -> &T {
@ -1540,14 +1557,11 @@ impl MutableAppContext {
window.on_event(Box::new(move |event| {
app.update(|cx| {
if let Event::KeyDown { keystroke, .. } = &event {
if cx
.dispatch_keystroke(
window_id,
presenter.borrow().dispatch_path(cx.as_ref()),
keystroke,
)
.unwrap()
{
if cx.dispatch_keystroke(
window_id,
presenter.borrow().dispatch_path(cx.as_ref()),
keystroke,
) {
return;
}
}
@ -2711,11 +2725,11 @@ impl<'a, T: Entity> ModelContext<'a, T> {
pub fn defer(&mut self, callback: impl 'static + FnOnce(&mut T, &mut ModelContext<T>)) {
let handle = self.handle();
self.app.defer(Box::new(move |cx| {
self.app.defer(move |cx| {
handle.update(cx, |model, cx| {
callback(model, cx);
})
}))
})
}
pub fn emit(&mut self, payload: T::Event) {
@ -3064,11 +3078,11 @@ impl<'a, T: View> ViewContext<'a, T> {
pub fn defer(&mut self, callback: impl 'static + FnOnce(&mut T, &mut ViewContext<T>)) {
let handle = self.handle();
self.app.defer(Box::new(move |cx| {
self.app.defer(move |cx| {
handle.update(cx, |view, cx| {
callback(view, cx);
})
}))
})
}
pub fn after_window_update(
@ -3678,9 +3692,9 @@ impl<T: View> ViewHandle<T> {
F: 'static + FnOnce(&mut T, &mut ViewContext<T>),
{
let this = self.clone();
cx.as_mut().defer(Box::new(move |cx| {
cx.as_mut().defer(move |cx| {
this.update(cx, |view, cx| update(view, cx));
}));
});
}
pub fn is_focused(&self, cx: &AppContext) -> bool {
@ -5921,8 +5935,7 @@ mod tests {
window_id,
vec![view_1.id(), view_2.id(), view_3.id()],
&Keystroke::parse("a").unwrap(),
)
.unwrap();
);
assert_eq!(&*actions.borrow(), &["2 a"]);
@ -5931,8 +5944,7 @@ mod tests {
window_id,
vec![view_1.id(), view_2.id(), view_3.id()],
&Keystroke::parse("b").unwrap(),
)
.unwrap();
);
assert_eq!(&*actions.borrow(), &["3 b", "2 b", "1 b", "global b"]);
}