Switch from changing the meaning of the predicate to adding an additional match_dispatch_path_context API for UI elements

Mikayla Maki created

Change summary

crates/gpui/src/app.rs                           | 4 ++--
crates/gpui/src/keymap_matcher/binding.rs        | 9 +++++++++
crates/gpui/src/keymap_matcher/keymap_context.rs | 8 +-------
3 files changed, 12 insertions(+), 9 deletions(-)

Detailed changes

crates/gpui/src/app.rs 🔗

@@ -1248,7 +1248,7 @@ impl MutableAppContext {
         self.keystroke_matcher
             .bindings_for_action_type(action.as_any().type_id())
             .find_map(|b| {
-                if b.match_context(&contexts) {
+                if b.match_dispatch_path_context(&contexts) {
                     Some(b.keystrokes().into())
                 } else {
                     None
@@ -1283,7 +1283,7 @@ impl MutableAppContext {
                         deserialize("{}").ok()?,
                         self.keystroke_matcher
                             .bindings_for_action_type(*type_id)
-                            .filter(|b| b.match_context(&contexts))
+                            .filter(|b| b.match_dispatch_path_context(&contexts))
                             .collect(),
                     ))
                 } else {

crates/gpui/src/keymap_matcher/binding.rs 🔗

@@ -42,6 +42,15 @@ impl Binding {
             .unwrap_or(true)
     }
 
+    pub fn match_dispatch_path_context(&self, contexts: &[KeymapContext]) -> bool {
+        for i in 0..contexts.len() {
+            if self.match_context(&contexts[i..]) {
+                return true;
+            }
+        }
+        false
+    }
+
     pub fn match_keys_and_context(
         &self,
         pending_keystrokes: &Vec<Keystroke>,

crates/gpui/src/keymap_matcher/keymap_context.rs 🔗

@@ -64,13 +64,7 @@ impl KeymapContextPredicate {
     pub fn eval(&self, contexts: &[KeymapContext]) -> bool {
         let Some(context) = contexts.first() else { return false };
         match self {
-            Self::Identifier(name) => {
-                if (&context.set).contains(name.as_str()) {
-                    true
-                } else {
-                    self.eval(&contexts[1..])
-                }
-            }
+            Self::Identifier(name) => (&context.set).contains(name.as_str()),
             Self::Equal(left, right) => context
                 .map
                 .get(left.as_str())