diff --git a/crates/gpui/src/action.rs b/crates/gpui/src/action.rs index e335c4255e..b86dafe62c 100644 --- a/crates/gpui/src/action.rs +++ b/crates/gpui/src/action.rs @@ -114,14 +114,26 @@ impl ActionRegistry { pub(crate) fn load_actions(&mut self) { for builder in __GPUI_ACTIONS { let action = builder(); - //todo(remove) - let name: SharedString = action.name.into(); - self.builders_by_name.insert(name.clone(), action.build); - self.names_by_type_id.insert(action.type_id, name.clone()); - self.all_names.push(name); + self.insert_action(action); } } + #[cfg(test)] + pub(crate) fn load_action(&mut self) { + self.insert_action(ActionData { + name: A::debug_name(), + type_id: TypeId::of::(), + build: A::build, + }); + } + + fn insert_action(&mut self, action: ActionData) { + let name: SharedString = action.name.into(); + self.builders_by_name.insert(name.clone(), action.build); + self.names_by_type_id.insert(action.type_id, name.clone()); + self.all_names.push(name); + } + /// Construct an action based on its name and optional JSON parameters sourced from the keymap. pub fn build_action_type(&self, type_id: &TypeId) -> Result> { let name = self diff --git a/crates/gpui/src/key_dispatch.rs b/crates/gpui/src/key_dispatch.rs index 81f66746c5..c65b169596 100644 --- a/crates/gpui/src/key_dispatch.rs +++ b/crates/gpui/src/key_dispatch.rs @@ -192,8 +192,9 @@ impl DispatchTree { keymap .bindings_for_action(action) .filter(|binding| { - for i in 0..context_stack.len() { - let context = &context_stack[0..=i]; + for i in 1..context_stack.len() { + dbg!(i); + let context = &context_stack[0..i]; if keymap.binding_enabled(binding, context) { return true; } @@ -283,3 +284,86 @@ impl DispatchTree { *self.node_stack.last().unwrap() } } + +#[cfg(test)] +mod tests { + use std::{rc::Rc, sync::Arc}; + + use parking_lot::Mutex; + + use crate::{Action, ActionRegistry, DispatchTree, KeyBinding, KeyContext, Keymap}; + + #[derive(PartialEq, Eq)] + struct TestAction; + + impl Action for TestAction { + fn name(&self) -> &'static str { + "test::TestAction" + } + + fn debug_name() -> &'static str + where + Self: ::std::marker::Sized, + { + "test::TestAction" + } + + fn partial_eq(&self, action: &dyn Action) -> bool { + action + .as_any() + .downcast_ref::() + .map_or(false, |a| self == a) + } + + fn boxed_clone(&self) -> std::boxed::Box { + Box::new(TestAction) + } + + fn as_any(&self) -> &dyn ::std::any::Any { + self + } + + fn build(_value: serde_json::Value) -> anyhow::Result> + where + Self: Sized, + { + Ok(Box::new(TestAction)) + } + } + + #[test] + fn test_keybinding_for_action_bounds() { + dbg!("got here"); + + let keymap = Keymap::new(vec![KeyBinding::new( + "cmd-n", + TestAction, + Some("ProjectPanel"), + )]); + dbg!("got here"); + + let mut registry = ActionRegistry::default(); + dbg!("got here"); + + registry.load_action::(); + + dbg!("got here"); + + let keymap = Arc::new(Mutex::new(keymap)); + dbg!("got here"); + + let tree = DispatchTree::new(keymap, Rc::new(registry)); + + dbg!("got here"); + let keybinding = tree.bindings_for_action( + &TestAction, + &vec![ + KeyContext::parse(",").unwrap(), + KeyContext::parse("Workspace").unwrap(), + KeyContext::parse("ProjectPanel").unwrap(), + ], + ); + + assert!(keybinding[0].action.partial_eq(&TestAction)) + } +}