gpui: Simplify bindings_for_action
API (#34857)
Closes #ISSUE Simplifies the API to no longer have a variant that returns indices. The downside is that a few places that used to call `bindings_for_action_with_indices` now compare `Box<dyn Action>` instead of indices, however the result is the removal of wrapper code and index handling that is largely unnecessary Release Notes: - N/A *or* Added/Fixed/Improved ... Co-authored-by: Conrad <conrad@zed.dev>
This commit is contained in:
parent
2eeab5b0bf
commit
1a76a6b0bf
2 changed files with 31 additions and 61 deletions
|
@ -50,8 +50,8 @@
|
||||||
/// KeyBinding::new("cmd-k left", pane::SplitLeft, Some("Pane"))
|
/// KeyBinding::new("cmd-k left", pane::SplitLeft, Some("Pane"))
|
||||||
///
|
///
|
||||||
use crate::{
|
use crate::{
|
||||||
Action, ActionRegistry, App, BindingIndex, DispatchPhase, EntityId, FocusId, KeyBinding,
|
Action, ActionRegistry, App, DispatchPhase, EntityId, FocusId, KeyBinding, KeyContext, Keymap,
|
||||||
KeyContext, Keymap, Keystroke, ModifiersChangedEvent, Window,
|
Keystroke, ModifiersChangedEvent, Window,
|
||||||
};
|
};
|
||||||
use collections::FxHashMap;
|
use collections::FxHashMap;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
@ -406,16 +406,11 @@ impl DispatchTree {
|
||||||
// methods, but this can't be done very cleanly since keymap must be borrowed.
|
// methods, but this can't be done very cleanly since keymap must be borrowed.
|
||||||
let keymap = self.keymap.borrow();
|
let keymap = self.keymap.borrow();
|
||||||
keymap
|
keymap
|
||||||
.bindings_for_action_with_indices(action)
|
.bindings_for_action(action)
|
||||||
.filter(|(binding_index, binding)| {
|
.filter(|binding| {
|
||||||
Self::binding_matches_predicate_and_not_shadowed(
|
Self::binding_matches_predicate_and_not_shadowed(&keymap, &binding, context_stack)
|
||||||
&keymap,
|
|
||||||
*binding_index,
|
|
||||||
&binding.keystrokes,
|
|
||||||
context_stack,
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
.map(|(_, binding)| binding.clone())
|
.cloned()
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,28 +423,22 @@ impl DispatchTree {
|
||||||
) -> Option<KeyBinding> {
|
) -> Option<KeyBinding> {
|
||||||
let keymap = self.keymap.borrow();
|
let keymap = self.keymap.borrow();
|
||||||
keymap
|
keymap
|
||||||
.bindings_for_action_with_indices(action)
|
.bindings_for_action(action)
|
||||||
.rev()
|
.rev()
|
||||||
.find_map(|(binding_index, binding)| {
|
.find(|binding| {
|
||||||
let found = Self::binding_matches_predicate_and_not_shadowed(
|
Self::binding_matches_predicate_and_not_shadowed(&keymap, &binding, context_stack)
|
||||||
&keymap,
|
|
||||||
binding_index,
|
|
||||||
&binding.keystrokes,
|
|
||||||
context_stack,
|
|
||||||
);
|
|
||||||
if found { Some(binding.clone()) } else { None }
|
|
||||||
})
|
})
|
||||||
|
.cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn binding_matches_predicate_and_not_shadowed(
|
fn binding_matches_predicate_and_not_shadowed(
|
||||||
keymap: &Keymap,
|
keymap: &Keymap,
|
||||||
binding_index: BindingIndex,
|
binding: &KeyBinding,
|
||||||
keystrokes: &[Keystroke],
|
|
||||||
context_stack: &[KeyContext],
|
context_stack: &[KeyContext],
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let (bindings, _) = keymap.bindings_for_input_with_indices(&keystrokes, context_stack);
|
let (bindings, _) = keymap.bindings_for_input(&binding.keystrokes, context_stack);
|
||||||
if let Some((highest_precedence_index, _)) = bindings.iter().next() {
|
if let Some(found) = bindings.iter().next() {
|
||||||
binding_index == *highest_precedence_index
|
found.action.partial_eq(binding.action.as_ref())
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,15 +77,6 @@ impl Keymap {
|
||||||
&'a self,
|
&'a self,
|
||||||
action: &'a dyn Action,
|
action: &'a dyn Action,
|
||||||
) -> impl 'a + DoubleEndedIterator<Item = &'a KeyBinding> {
|
) -> impl 'a + DoubleEndedIterator<Item = &'a KeyBinding> {
|
||||||
self.bindings_for_action_with_indices(action)
|
|
||||||
.map(|(_, binding)| binding)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Like `bindings_for_action_with_indices`, but also returns the binding indices.
|
|
||||||
pub fn bindings_for_action_with_indices<'a>(
|
|
||||||
&'a self,
|
|
||||||
action: &'a dyn Action,
|
|
||||||
) -> impl 'a + DoubleEndedIterator<Item = (BindingIndex, &'a KeyBinding)> {
|
|
||||||
let action_id = action.type_id();
|
let action_id = action.type_id();
|
||||||
let binding_indices = self
|
let binding_indices = self
|
||||||
.binding_indices_by_action_id
|
.binding_indices_by_action_id
|
||||||
|
@ -118,7 +109,7 @@ impl Keymap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Some((BindingIndex(*ix), binding))
|
Some(binding)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,22 +144,8 @@ impl Keymap {
|
||||||
input: &[Keystroke],
|
input: &[Keystroke],
|
||||||
context_stack: &[KeyContext],
|
context_stack: &[KeyContext],
|
||||||
) -> (SmallVec<[KeyBinding; 1]>, bool) {
|
) -> (SmallVec<[KeyBinding; 1]>, bool) {
|
||||||
let (bindings, pending) = self.bindings_for_input_with_indices(input, context_stack);
|
let mut matched_bindings = SmallVec::<[(usize, BindingIndex, &KeyBinding); 1]>::new();
|
||||||
let bindings = bindings
|
let mut pending_bindings = SmallVec::<[(BindingIndex, &KeyBinding); 1]>::new();
|
||||||
.into_iter()
|
|
||||||
.map(|(_, binding)| binding)
|
|
||||||
.collect::<SmallVec<[KeyBinding; 1]>>();
|
|
||||||
(bindings, pending)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Like `bindings_for_input`, but also returns the binding indices.
|
|
||||||
pub fn bindings_for_input_with_indices(
|
|
||||||
&self,
|
|
||||||
input: &[Keystroke],
|
|
||||||
context_stack: &[KeyContext],
|
|
||||||
) -> (SmallVec<[(BindingIndex, KeyBinding); 1]>, bool) {
|
|
||||||
let mut bindings: SmallVec<[(usize, BindingIndex, &KeyBinding); 1]> = SmallVec::new();
|
|
||||||
let mut pending_bindings: SmallVec<[(BindingIndex, &KeyBinding); 1]> = SmallVec::new();
|
|
||||||
|
|
||||||
for (ix, binding) in self.bindings().enumerate().rev() {
|
for (ix, binding) in self.bindings().enumerate().rev() {
|
||||||
let Some(depth) = self.binding_enabled(binding, &context_stack) else {
|
let Some(depth) = self.binding_enabled(binding, &context_stack) else {
|
||||||
|
@ -179,26 +156,30 @@ impl Keymap {
|
||||||
};
|
};
|
||||||
|
|
||||||
if !pending {
|
if !pending {
|
||||||
bindings.push((depth, BindingIndex(ix), binding))
|
matched_bindings.push((depth, BindingIndex(ix), binding));
|
||||||
} else {
|
} else {
|
||||||
pending_bindings.push((BindingIndex(ix), binding))
|
pending_bindings.push((BindingIndex(ix), binding));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bindings.sort_by(|(depth_a, ix_a, _), (depth_b, ix_b, _)| {
|
matched_bindings.sort_by(|(depth_a, ix_a, _), (depth_b, ix_b, _)| {
|
||||||
depth_b.cmp(depth_a).then(ix_b.cmp(ix_a))
|
depth_b.cmp(depth_a).then(ix_b.cmp(ix_a))
|
||||||
});
|
});
|
||||||
|
|
||||||
let bindings: SmallVec<[_; 1]> = bindings
|
let mut bindings: SmallVec<[_; 1]> = SmallVec::new();
|
||||||
.into_iter()
|
let mut first_binding_index = None;
|
||||||
.take_while(|(_, _, binding)| !is_no_action(&*binding.action))
|
for (_, ix, binding) in matched_bindings {
|
||||||
.map(|(_, ix, binding)| (ix, binding.clone()))
|
if is_no_action(&*binding.action) {
|
||||||
.collect();
|
break;
|
||||||
|
}
|
||||||
|
bindings.push(binding.clone());
|
||||||
|
first_binding_index.get_or_insert(ix);
|
||||||
|
}
|
||||||
|
|
||||||
let mut pending = HashSet::default();
|
let mut pending = HashSet::default();
|
||||||
for (ix, binding) in pending_bindings.into_iter().rev() {
|
for (ix, binding) in pending_bindings.into_iter().rev() {
|
||||||
if let Some((binding_ix, _)) = bindings.first()
|
if let Some(binding_ix) = first_binding_index
|
||||||
&& *binding_ix > ix
|
&& binding_ix > ix
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue