Compare commits
1 Commits
editor/tog
...
lw/gpui-op
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f21f4e8bb |
@@ -26,8 +26,8 @@ use dap::{
|
||||
};
|
||||
use futures::{SinkExt, channel::mpsc};
|
||||
use gpui::{
|
||||
Action as _, AnyView, AppContext, Axis, Entity, EntityId, EventEmitter, FocusHandle, Focusable,
|
||||
NoAction, Pixels, Point, Subscription, Task, WeakEntity,
|
||||
AnyView, AppContext, Axis, Entity, EntityId, EventEmitter, FocusHandle, Focusable, Pixels,
|
||||
Point, Subscription, Task, WeakEntity,
|
||||
};
|
||||
use language::Buffer;
|
||||
use loaded_source_list::LoadedSourceList;
|
||||
@@ -385,7 +385,7 @@ pub(crate) fn new_debugger_pane(
|
||||
project.clone(),
|
||||
Default::default(),
|
||||
None,
|
||||
NoAction.boxed_clone(),
|
||||
None,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use anyhow::{Context as _, Result};
|
||||
use collections::HashMap;
|
||||
pub use gpui_macros::Action;
|
||||
pub use no_action::{NoAction, is_no_action};
|
||||
|
||||
use serde_json::json;
|
||||
use std::{
|
||||
any::{Any, TypeId},
|
||||
@@ -419,22 +419,3 @@ pub fn generate_list_of_all_registered_actions() -> impl Iterator<Item = MacroAc
|
||||
.into_iter()
|
||||
.map(|builder| builder.0())
|
||||
}
|
||||
|
||||
mod no_action {
|
||||
use crate as gpui;
|
||||
use std::any::Any as _;
|
||||
|
||||
actions!(
|
||||
zed,
|
||||
[
|
||||
/// Action with special handling which unbinds the keybinding this is associated with,
|
||||
/// if it is the highest precedence match.
|
||||
NoAction
|
||||
]
|
||||
);
|
||||
|
||||
/// Returns whether or not this action represents a removed key binding.
|
||||
pub fn is_no_action(action: &dyn gpui::Action) -> bool {
|
||||
action.as_any().type_id() == (NoAction {}).type_id()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,7 +438,11 @@ impl DispatchTree {
|
||||
) -> bool {
|
||||
let (bindings, _) = keymap.bindings_for_input(&binding.keystrokes, context_stack);
|
||||
if let Some(found) = bindings.iter().next() {
|
||||
found.action.partial_eq(binding.action.as_ref())
|
||||
match (found.action.as_deref(), binding.action.as_deref()) {
|
||||
(None, None) => true,
|
||||
(Some(f), Some(b)) => f.partial_eq(b),
|
||||
(None, Some(_)) | (Some(_), None) => false,
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
@@ -677,7 +681,12 @@ mod tests {
|
||||
|
||||
let keybinding = tree.bindings_for_action(&TestAction, &contexts);
|
||||
|
||||
assert!(keybinding[0].action.partial_eq(&TestAction))
|
||||
assert!(
|
||||
keybinding[0]
|
||||
.action
|
||||
.as_deref()
|
||||
.is_some_and(|it| it.partial_eq(&TestAction))
|
||||
);
|
||||
}
|
||||
|
||||
#[crate::test]
|
||||
|
||||
@@ -4,7 +4,7 @@ mod context;
|
||||
pub use binding::*;
|
||||
pub use context::*;
|
||||
|
||||
use crate::{Action, AsKeystroke, Keystroke, is_no_action};
|
||||
use crate::{Action, AsKeystroke, Keystroke};
|
||||
use collections::{HashMap, HashSet};
|
||||
use smallvec::SmallVec;
|
||||
use std::any::TypeId;
|
||||
@@ -43,14 +43,14 @@ impl Keymap {
|
||||
/// Add more bindings to the keymap.
|
||||
pub fn add_bindings<T: IntoIterator<Item = KeyBinding>>(&mut self, bindings: T) {
|
||||
for binding in bindings {
|
||||
let action_id = binding.action().as_any().type_id();
|
||||
if is_no_action(&*binding.action) {
|
||||
self.no_action_binding_indices.push(self.bindings.len());
|
||||
} else {
|
||||
if let Some(action) = binding.action.as_deref() {
|
||||
let action_id = action.type_id();
|
||||
self.binding_indices_by_action_id
|
||||
.entry(action_id)
|
||||
.or_default()
|
||||
.push(self.bindings.len());
|
||||
} else {
|
||||
self.no_action_binding_indices.push(self.bindings.len());
|
||||
}
|
||||
self.bindings.push(binding);
|
||||
}
|
||||
@@ -86,7 +86,10 @@ impl Keymap {
|
||||
|
||||
binding_indices.filter_map(|ix| {
|
||||
let binding = &self.bindings[*ix];
|
||||
if !binding.action().partial_eq(action) {
|
||||
if binding
|
||||
.action()
|
||||
.is_none_or(|action| !action.partial_eq(action))
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -170,7 +173,7 @@ impl Keymap {
|
||||
let mut first_binding_index = None;
|
||||
|
||||
for (_, ix, binding) in matched_bindings {
|
||||
if is_no_action(&*binding.action) {
|
||||
if binding.action.is_none() {
|
||||
// Only break if this is a user-defined NoAction binding
|
||||
// This allows user keymaps to override base keymap NoAction bindings
|
||||
if let Some(meta) = binding.meta {
|
||||
@@ -195,7 +198,7 @@ impl Keymap {
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if is_no_action(&*binding.action) {
|
||||
if binding.action.is_none() {
|
||||
pending.remove(&&binding.keystrokes);
|
||||
continue;
|
||||
}
|
||||
@@ -204,8 +207,9 @@ impl Keymap {
|
||||
|
||||
(bindings, !pending.is_empty())
|
||||
}
|
||||
|
||||
/// Check if the given binding is enabled, given a certain key context.
|
||||
/// Returns the deepest depth at which the binding matches, or None if it doesn't match.
|
||||
/// Returns the deepest depth at which the binding matches, or [`None`] if it doesn't match.
|
||||
fn binding_enabled(&self, binding: &KeyBinding, contexts: &[KeyContext]) -> Option<usize> {
|
||||
if let Some(predicate) = &binding.context_predicate {
|
||||
predicate.depth_of(contexts)
|
||||
@@ -219,7 +223,6 @@ impl Keymap {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate as gpui;
|
||||
use gpui::NoAction;
|
||||
|
||||
actions!(
|
||||
test_only,
|
||||
@@ -287,8 +290,18 @@ mod tests {
|
||||
|
||||
assert!(!pending);
|
||||
assert_eq!(result.len(), 2);
|
||||
assert!(result[0].action.partial_eq(&ActionGamma {}));
|
||||
assert!(result[1].action.partial_eq(&ActionBeta {}));
|
||||
assert!(
|
||||
result[0]
|
||||
.action
|
||||
.as_deref()
|
||||
.is_some_and(|it| it.partial_eq(&ActionGamma {}))
|
||||
);
|
||||
assert!(
|
||||
result[1]
|
||||
.action
|
||||
.as_deref()
|
||||
.is_some_and(|it| it.partial_eq(&ActionBeta {}))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -296,8 +309,8 @@ mod tests {
|
||||
let bindings = [
|
||||
KeyBinding::new("ctrl-a", ActionAlpha {}, Some("editor")),
|
||||
KeyBinding::new("ctrl-b", ActionAlpha {}, Some("editor")),
|
||||
KeyBinding::new("ctrl-a", NoAction {}, Some("editor && mode==full")),
|
||||
KeyBinding::new("ctrl-b", NoAction {}, None),
|
||||
KeyBinding::new_no_action("ctrl-a", Some("editor && mode==full")),
|
||||
KeyBinding::new_no_action("ctrl-b", None),
|
||||
];
|
||||
|
||||
let mut keymap = Keymap::default();
|
||||
@@ -351,7 +364,7 @@ mod tests {
|
||||
fn test_multiple_keystroke_binding_disabled() {
|
||||
let bindings = [
|
||||
KeyBinding::new("space w w", ActionAlpha {}, Some("workspace")),
|
||||
KeyBinding::new("space w w", NoAction {}, Some("editor")),
|
||||
KeyBinding::new_no_action("space w w", Some("editor")),
|
||||
];
|
||||
|
||||
let mut keymap = Keymap::default();
|
||||
@@ -403,7 +416,7 @@ mod tests {
|
||||
// that should result in pending
|
||||
let bindings = [
|
||||
KeyBinding::new("space w w", ActionAlpha {}, Some("workspace")),
|
||||
KeyBinding::new("space w w", NoAction {}, Some("editor")),
|
||||
KeyBinding::new_no_action("space w w", Some("editor")),
|
||||
KeyBinding::new("space w x", ActionAlpha {}, Some("editor")),
|
||||
];
|
||||
let mut keymap = Keymap::default();
|
||||
@@ -418,7 +431,7 @@ mod tests {
|
||||
let bindings = [
|
||||
KeyBinding::new("space w w", ActionAlpha {}, Some("workspace")),
|
||||
KeyBinding::new("space w x", ActionAlpha {}, Some("editor")),
|
||||
KeyBinding::new("space w w", NoAction {}, Some("editor")),
|
||||
KeyBinding::new_no_action("space w w", Some("editor")),
|
||||
];
|
||||
let mut keymap = Keymap::default();
|
||||
keymap.add_bindings(bindings);
|
||||
@@ -432,7 +445,7 @@ mod tests {
|
||||
let bindings = [
|
||||
KeyBinding::new("space w w", ActionAlpha {}, Some("workspace")),
|
||||
KeyBinding::new("space w x", ActionAlpha {}, Some("workspace")),
|
||||
KeyBinding::new("space w w", NoAction {}, Some("editor")),
|
||||
KeyBinding::new_no_action("space w w", Some("editor")),
|
||||
];
|
||||
let mut keymap = Keymap::default();
|
||||
keymap.add_bindings(bindings);
|
||||
@@ -446,7 +459,7 @@ mod tests {
|
||||
fn test_override_multikey() {
|
||||
let bindings = [
|
||||
KeyBinding::new("ctrl-w left", ActionAlpha {}, Some("editor")),
|
||||
KeyBinding::new("ctrl-w", NoAction {}, Some("editor")),
|
||||
KeyBinding::new_no_action("ctrl-w", Some("editor")),
|
||||
];
|
||||
|
||||
let mut keymap = Keymap::default();
|
||||
@@ -481,7 +494,7 @@ mod tests {
|
||||
fn test_simple_disable() {
|
||||
let bindings = [
|
||||
KeyBinding::new("ctrl-x", ActionAlpha {}, Some("editor")),
|
||||
KeyBinding::new("ctrl-x", NoAction {}, Some("editor")),
|
||||
KeyBinding::new_no_action("ctrl-x", Some("editor")),
|
||||
];
|
||||
|
||||
let mut keymap = Keymap::default();
|
||||
@@ -501,7 +514,7 @@ mod tests {
|
||||
// disabled at the wrong level
|
||||
let bindings = [
|
||||
KeyBinding::new("ctrl-x", ActionAlpha {}, Some("editor")),
|
||||
KeyBinding::new("ctrl-x", NoAction {}, Some("workspace")),
|
||||
KeyBinding::new_no_action("ctrl-x", Some("workspace")),
|
||||
];
|
||||
|
||||
let mut keymap = Keymap::default();
|
||||
@@ -523,7 +536,7 @@ mod tests {
|
||||
fn test_disable_deeper() {
|
||||
let bindings = [
|
||||
KeyBinding::new("ctrl-x", ActionAlpha {}, Some("workspace")),
|
||||
KeyBinding::new("ctrl-x", NoAction {}, Some("editor")),
|
||||
KeyBinding::new_no_action("ctrl-x", Some("editor")),
|
||||
];
|
||||
|
||||
let mut keymap = Keymap::default();
|
||||
@@ -560,7 +573,12 @@ mod tests {
|
||||
.map(Result::unwrap),
|
||||
);
|
||||
assert_eq!(matched.0.len(), 1);
|
||||
assert!(matched.0[0].action.partial_eq(&ActionBeta));
|
||||
assert!(
|
||||
matched.0[0]
|
||||
.action
|
||||
.as_deref()
|
||||
.is_some_and(|it| it.partial_eq(&ActionBeta))
|
||||
);
|
||||
assert!(matched.1);
|
||||
}
|
||||
|
||||
@@ -568,7 +586,7 @@ mod tests {
|
||||
fn test_pending_match_enabled_extended() {
|
||||
let bindings = [
|
||||
KeyBinding::new("ctrl-x", ActionBeta, Some("vim_mode == normal")),
|
||||
KeyBinding::new("ctrl-x 0", NoAction, Some("Workspace")),
|
||||
KeyBinding::new_no_action("ctrl-x 0", Some("Workspace")),
|
||||
];
|
||||
let mut keymap = Keymap::default();
|
||||
keymap.add_bindings(bindings);
|
||||
@@ -583,11 +601,16 @@ mod tests {
|
||||
.map(Result::unwrap),
|
||||
);
|
||||
assert_eq!(matched.0.len(), 1);
|
||||
assert!(matched.0[0].action.partial_eq(&ActionBeta));
|
||||
assert!(
|
||||
matched.0[0]
|
||||
.action
|
||||
.as_deref()
|
||||
.is_some_and(|it| it.partial_eq(&ActionBeta))
|
||||
);
|
||||
assert!(!matched.1);
|
||||
let bindings = [
|
||||
KeyBinding::new("ctrl-x", ActionBeta, Some("Workspace")),
|
||||
KeyBinding::new("ctrl-x 0", NoAction, Some("vim_mode == normal")),
|
||||
KeyBinding::new_no_action("ctrl-x 0", Some("vim_mode == normal")),
|
||||
];
|
||||
let mut keymap = Keymap::default();
|
||||
keymap.add_bindings(bindings);
|
||||
@@ -602,7 +625,12 @@ mod tests {
|
||||
.map(Result::unwrap),
|
||||
);
|
||||
assert_eq!(matched.0.len(), 1);
|
||||
assert!(matched.0[0].action.partial_eq(&ActionBeta));
|
||||
assert!(
|
||||
matched.0[0]
|
||||
.action
|
||||
.as_deref()
|
||||
.is_some_and(|it| it.partial_eq(&ActionBeta))
|
||||
);
|
||||
assert!(!matched.1);
|
||||
}
|
||||
|
||||
@@ -625,7 +653,12 @@ mod tests {
|
||||
.map(Result::unwrap),
|
||||
);
|
||||
assert_eq!(matched.0.len(), 1);
|
||||
assert!(matched.0[0].action.partial_eq(&ActionBeta));
|
||||
assert!(
|
||||
matched.0[0]
|
||||
.action
|
||||
.as_deref()
|
||||
.is_some_and(|it| it.partial_eq(&ActionBeta))
|
||||
);
|
||||
assert!(!matched.1);
|
||||
}
|
||||
|
||||
@@ -652,8 +685,18 @@ mod tests {
|
||||
|
||||
// Both bindings should be returned, but Editor binding should be first (highest precedence)
|
||||
assert_eq!(result.len(), 2);
|
||||
assert!(result[0].action.partial_eq(&ActionBeta {})); // Editor binding first
|
||||
assert!(result[1].action.partial_eq(&ActionAlpha {})); // Workspace binding second
|
||||
assert!(
|
||||
result[0]
|
||||
.action
|
||||
.as_deref()
|
||||
.is_some_and(|it| it.partial_eq(&ActionBeta {}))
|
||||
); // Editor binding first
|
||||
assert!(
|
||||
result[1]
|
||||
.action
|
||||
.as_deref()
|
||||
.is_some_and(|it| it.partial_eq(&ActionAlpha {}))
|
||||
); // Workspace binding second
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -662,8 +705,8 @@ mod tests {
|
||||
KeyBinding::new("ctrl-a", ActionAlpha {}, Some("pane")),
|
||||
KeyBinding::new("ctrl-b", ActionBeta {}, Some("editor && mode == full")),
|
||||
KeyBinding::new("ctrl-c", ActionGamma {}, Some("workspace")),
|
||||
KeyBinding::new("ctrl-a", NoAction {}, Some("pane && active")),
|
||||
KeyBinding::new("ctrl-b", NoAction {}, Some("editor")),
|
||||
KeyBinding::new_no_action("ctrl-a", Some("pane && active")),
|
||||
KeyBinding::new_no_action("ctrl-b", Some("editor")),
|
||||
];
|
||||
|
||||
let mut keymap = Keymap::default();
|
||||
@@ -707,7 +750,17 @@ mod tests {
|
||||
|
||||
// User binding should take precedence over default binding
|
||||
assert_eq!(result.len(), 2);
|
||||
assert!(result[0].action.partial_eq(&ActionBeta {}));
|
||||
assert!(result[1].action.partial_eq(&ActionAlpha {}));
|
||||
assert!(
|
||||
result[0]
|
||||
.action
|
||||
.as_deref()
|
||||
.is_some_and(|it| it.partial_eq(&ActionBeta {}))
|
||||
);
|
||||
assert!(
|
||||
result[1]
|
||||
.action
|
||||
.as_deref()
|
||||
.is_some_and(|it| it.partial_eq(&ActionAlpha {}))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ use smallvec::SmallVec;
|
||||
|
||||
/// A keybinding and its associated metadata, from the keymap.
|
||||
pub struct KeyBinding {
|
||||
pub(crate) action: Box<dyn Action>,
|
||||
pub(crate) action: Option<Box<dyn Action>>,
|
||||
pub(crate) keystrokes: SmallVec<[KeybindingKeystroke; 2]>,
|
||||
pub(crate) context_predicate: Option<Rc<KeyBindingContextPredicate>>,
|
||||
pub(crate) meta: Option<KeyBindingMetaIndex>,
|
||||
@@ -19,7 +19,7 @@ pub struct KeyBinding {
|
||||
impl Clone for KeyBinding {
|
||||
fn clone(&self) -> Self {
|
||||
KeyBinding {
|
||||
action: self.action.boxed_clone(),
|
||||
action: self.action.as_ref().map(|action| action.boxed_clone()),
|
||||
keystrokes: self.keystrokes.clone(),
|
||||
context_predicate: self.context_predicate.clone(),
|
||||
meta: self.meta,
|
||||
@@ -35,7 +35,22 @@ impl KeyBinding {
|
||||
context.map(|context| KeyBindingContextPredicate::parse(context).unwrap().into());
|
||||
Self::load(
|
||||
keystrokes,
|
||||
Box::new(action),
|
||||
Some(Box::new(action) as Box<dyn Action>),
|
||||
context_predicate,
|
||||
false,
|
||||
None,
|
||||
&DummyKeyboardMapper,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// Construct a new keybinding from the given data with no action associated to it. Panics on parse error.
|
||||
pub fn new_no_action(keystrokes: &str, context: Option<&str>) -> Self {
|
||||
let context_predicate =
|
||||
context.map(|context| KeyBindingContextPredicate::parse(context).unwrap().into());
|
||||
Self::load(
|
||||
keystrokes,
|
||||
None,
|
||||
context_predicate,
|
||||
false,
|
||||
None,
|
||||
@@ -47,7 +62,7 @@ impl KeyBinding {
|
||||
/// Load a keybinding from the given raw data.
|
||||
pub fn load(
|
||||
keystrokes: &str,
|
||||
action: Box<dyn Action>,
|
||||
action: impl Into<Option<Box<dyn Action>>>,
|
||||
context_predicate: Option<Rc<KeyBindingContextPredicate>>,
|
||||
use_key_equivalents: bool,
|
||||
action_input: Option<SharedString>,
|
||||
@@ -67,7 +82,7 @@ impl KeyBinding {
|
||||
|
||||
Ok(Self {
|
||||
keystrokes,
|
||||
action,
|
||||
action: action.into(),
|
||||
context_predicate,
|
||||
meta: None,
|
||||
action_input,
|
||||
@@ -106,8 +121,8 @@ impl KeyBinding {
|
||||
}
|
||||
|
||||
/// Get the action associated with this binding
|
||||
pub fn action(&self) -> &dyn Action {
|
||||
self.action.as_ref()
|
||||
pub fn action(&self) -> Option<&dyn Action> {
|
||||
self.action.as_deref()
|
||||
}
|
||||
|
||||
/// Get the predicate used to match this binding
|
||||
@@ -131,7 +146,10 @@ impl std::fmt::Debug for KeyBinding {
|
||||
f.debug_struct("KeyBinding")
|
||||
.field("keystrokes", &self.keystrokes)
|
||||
.field("context_predicate", &self.context_predicate)
|
||||
.field("action", &self.action.name())
|
||||
.field(
|
||||
"action",
|
||||
&self.action.as_deref().map_or("null", |it| it.name()),
|
||||
)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3800,11 +3800,13 @@ impl Window {
|
||||
}
|
||||
|
||||
for binding in match_result.bindings {
|
||||
self.dispatch_action_on_node(node_id, binding.action.as_ref(), cx);
|
||||
if let Some(action) = binding.action.as_deref() {
|
||||
self.dispatch_action_on_node(node_id, action, cx);
|
||||
}
|
||||
if !cx.propagate_event {
|
||||
self.dispatch_keystroke_observers(
|
||||
event,
|
||||
Some(binding.action),
|
||||
binding.action,
|
||||
match_result.context_stack,
|
||||
cx,
|
||||
);
|
||||
@@ -3922,14 +3924,11 @@ impl Window {
|
||||
|
||||
cx.propagate_event = true;
|
||||
for binding in replay.bindings {
|
||||
self.dispatch_action_on_node(node_id, binding.action.as_ref(), cx);
|
||||
if let Some(action) = binding.action.as_deref() {
|
||||
self.dispatch_action_on_node(node_id, action, cx);
|
||||
}
|
||||
if !cx.propagate_event {
|
||||
self.dispatch_keystroke_observers(
|
||||
&event,
|
||||
Some(binding.action),
|
||||
Vec::default(),
|
||||
cx,
|
||||
);
|
||||
self.dispatch_keystroke_observers(&event, binding.action, Vec::default(), cx);
|
||||
continue 'replay;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -677,6 +677,9 @@ impl KeymapEditor {
|
||||
let mut string_match_candidates = Vec::new();
|
||||
|
||||
for key_binding in key_bindings {
|
||||
let Some(action) = key_binding.action() else {
|
||||
continue;
|
||||
};
|
||||
let source = key_binding
|
||||
.meta()
|
||||
.map(KeybindSource::from_meta)
|
||||
@@ -696,7 +699,7 @@ impl KeymapEditor {
|
||||
})
|
||||
.unwrap_or(KeybindContextString::Global);
|
||||
|
||||
let action_name = key_binding.action().name();
|
||||
let action_name = action.name();
|
||||
unmapped_action_names.remove(&action_name);
|
||||
|
||||
let action_arguments = key_binding
|
||||
@@ -1814,7 +1817,7 @@ impl Render for KeymapEditor {
|
||||
let action = div()
|
||||
.id(("keymap action", index))
|
||||
.child({
|
||||
if action_name != gpui::NoAction.name() {
|
||||
if !action_name.is_empty() {
|
||||
binding
|
||||
.action()
|
||||
.humanized_name
|
||||
|
||||
@@ -62,7 +62,7 @@ impl KeyContextView {
|
||||
.map(|binding| {
|
||||
let match_state = if let Some(predicate) = binding.predicate() {
|
||||
if this.matches(&predicate) {
|
||||
if this.action_matches(&e.action, binding.action()) {
|
||||
if this.action_matches(e.action.as_deref(), binding.action()) {
|
||||
Some(true)
|
||||
} else {
|
||||
Some(false)
|
||||
@@ -70,7 +70,7 @@ impl KeyContextView {
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else if this.action_matches(&e.action, binding.action()) {
|
||||
} else if this.action_matches(e.action.as_deref(), binding.action()) {
|
||||
Some(true)
|
||||
} else {
|
||||
Some(false)
|
||||
@@ -80,10 +80,7 @@ impl KeyContextView {
|
||||
} else {
|
||||
"".to_string()
|
||||
};
|
||||
let mut name = binding.action().name();
|
||||
if name == "zed::NoAction" {
|
||||
name = "(null)"
|
||||
}
|
||||
let name = binding.action().map_or("(null)", |action| action.name());
|
||||
|
||||
(
|
||||
name.to_owned().into(),
|
||||
@@ -130,12 +127,8 @@ impl KeyContextView {
|
||||
predicate.depth_of(&self.context_stack).is_some()
|
||||
}
|
||||
|
||||
fn action_matches(&self, a: &Option<Box<dyn Action>>, b: &dyn Action) -> bool {
|
||||
if let Some(last_action) = a {
|
||||
last_action.partial_eq(b)
|
||||
} else {
|
||||
b.name() == "zed::NoAction"
|
||||
}
|
||||
fn action_matches(&self, a: Option<&dyn Action>, b: Option<&dyn Action>) -> bool {
|
||||
a.zip(b).is_some_and(|(a, b)| a.partial_eq(b))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,9 +2,8 @@ use anyhow::{Context as _, Result};
|
||||
use collections::{BTreeMap, HashMap, IndexMap};
|
||||
use fs::Fs;
|
||||
use gpui::{
|
||||
Action, ActionBuildError, App, InvalidKeystrokeError, KEYSTROKE_PARSE_EXPECTED_MESSAGE,
|
||||
KeyBinding, KeyBindingContextPredicate, KeyBindingMetaIndex, KeybindingKeystroke, Keystroke,
|
||||
NoAction, SharedString,
|
||||
ActionBuildError, App, InvalidKeystrokeError, KEYSTROKE_PARSE_EXPECTED_MESSAGE, KeyBinding,
|
||||
KeyBindingContextPredicate, KeyBindingMetaIndex, KeybindingKeystroke, Keystroke, SharedString,
|
||||
};
|
||||
use schemars::{JsonSchema, json_schema};
|
||||
use serde::Deserialize;
|
||||
@@ -350,12 +349,12 @@ impl KeymapFile {
|
||||
let action_input = items[1].clone();
|
||||
let action_input_string = action_input.to_string();
|
||||
(
|
||||
cx.build_action(name, Some(action_input)),
|
||||
cx.build_action(name, Some(action_input)).map(Some),
|
||||
Some(action_input_string),
|
||||
)
|
||||
}
|
||||
Value::String(name) => (cx.build_action(name, None), None),
|
||||
Value::Null => (Ok(NoAction.boxed_clone()), None),
|
||||
Value::String(name) => (cx.build_action(name, None).map(Some), None),
|
||||
Value::Null => (Ok(None), None),
|
||||
_ => {
|
||||
return Err(format!(
|
||||
"expected two-element array of `[name, input]`. \
|
||||
@@ -410,7 +409,9 @@ impl KeymapFile {
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(validator) = KEY_BINDING_VALIDATORS.get(&key_binding.action().type_id()) {
|
||||
if let Some(action) = key_binding.action()
|
||||
&& let Some(validator) = KEY_BINDING_VALIDATORS.get(&action.type_id())
|
||||
{
|
||||
match validator.validate(&key_binding) {
|
||||
Ok(()) => Ok(key_binding),
|
||||
Err(error) => Err(error.0),
|
||||
@@ -502,7 +503,7 @@ impl KeymapFile {
|
||||
|
||||
let mut empty_schema_action_names = vec![];
|
||||
for (name, action_schema) in action_schemas.into_iter() {
|
||||
let deprecation = if name == NoAction.name() {
|
||||
let deprecation = if name.is_empty() {
|
||||
Some("null")
|
||||
} else {
|
||||
deprecations.get(name).copied()
|
||||
@@ -635,7 +636,7 @@ impl KeymapFile {
|
||||
target_keybind_source,
|
||||
} if target_keybind_source != KeybindSource::User => {
|
||||
let mut source = target.clone();
|
||||
source.action_name = gpui::NoAction.name();
|
||||
source.action_name = "";
|
||||
source.action_arguments.take();
|
||||
operation = KeybindUpdateOperation::Add {
|
||||
source,
|
||||
@@ -930,7 +931,7 @@ pub struct KeybindUpdateTarget<'a> {
|
||||
|
||||
impl<'a> KeybindUpdateTarget<'a> {
|
||||
fn action_value(&self) -> Result<Value> {
|
||||
if self.action_name == gpui::NoAction.name() {
|
||||
if self.action_name.is_empty() {
|
||||
return Ok(Value::Null);
|
||||
}
|
||||
let action_name: Value = self.action_name.into();
|
||||
|
||||
@@ -1040,7 +1040,7 @@ pub fn new_terminal_pane(
|
||||
project.clone(),
|
||||
Default::default(),
|
||||
None,
|
||||
NewTerminal.boxed_clone(),
|
||||
Some(NewTerminal.boxed_clone()),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
|
||||
@@ -528,7 +528,7 @@ impl Component for KeyBinding {
|
||||
single_example(
|
||||
"Default",
|
||||
KeyBinding::new_from_gpui(
|
||||
gpui::KeyBinding::new("ctrl-s", gpui::NoAction, None),
|
||||
gpui::KeyBinding::new_no_action("ctrl-s", None),
|
||||
cx,
|
||||
)
|
||||
.into_any_element(),
|
||||
@@ -536,7 +536,7 @@ impl Component for KeyBinding {
|
||||
single_example(
|
||||
"Mac Style",
|
||||
KeyBinding::new_from_gpui(
|
||||
gpui::KeyBinding::new("cmd-s", gpui::NoAction, None),
|
||||
gpui::KeyBinding::new_no_action("cmd-s", None),
|
||||
cx,
|
||||
)
|
||||
.platform_style(PlatformStyle::Mac)
|
||||
@@ -545,7 +545,7 @@ impl Component for KeyBinding {
|
||||
single_example(
|
||||
"Windows Style",
|
||||
KeyBinding::new_from_gpui(
|
||||
gpui::KeyBinding::new("ctrl-s", gpui::NoAction, None),
|
||||
gpui::KeyBinding::new_no_action("ctrl-s", None),
|
||||
cx,
|
||||
)
|
||||
.platform_style(PlatformStyle::Windows)
|
||||
@@ -558,7 +558,7 @@ impl Component for KeyBinding {
|
||||
vec![single_example(
|
||||
"Vim Mode Enabled",
|
||||
KeyBinding::new_from_gpui(
|
||||
gpui::KeyBinding::new("dd", gpui::NoAction, None),
|
||||
gpui::KeyBinding::new_no_action("dd", None),
|
||||
cx,
|
||||
)
|
||||
.vim_mode(true)
|
||||
@@ -571,7 +571,7 @@ impl Component for KeyBinding {
|
||||
single_example(
|
||||
"Multiple Keys",
|
||||
KeyBinding::new_from_gpui(
|
||||
gpui::KeyBinding::new("ctrl-k ctrl-b", gpui::NoAction, None),
|
||||
gpui::KeyBinding::new_no_action("ctrl-k ctrl-b", None),
|
||||
cx,
|
||||
)
|
||||
.into_any_element(),
|
||||
@@ -579,7 +579,7 @@ impl Component for KeyBinding {
|
||||
single_example(
|
||||
"With Shift",
|
||||
KeyBinding::new_from_gpui(
|
||||
gpui::KeyBinding::new("shift-cmd-p", gpui::NoAction, None),
|
||||
gpui::KeyBinding::new_no_action("shift-cmd-p", None),
|
||||
cx,
|
||||
)
|
||||
.into_any_element(),
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use gpui::NoAction;
|
||||
use gpui::Render;
|
||||
use itertools::Itertools;
|
||||
use story::Story;
|
||||
@@ -8,7 +7,7 @@ use crate::{KeyBinding, prelude::*};
|
||||
pub struct KeybindingStory;
|
||||
|
||||
pub fn binding(key: &str) -> gpui::KeyBinding {
|
||||
gpui::KeyBinding::new(key, NoAction {}, None)
|
||||
gpui::KeyBinding::new_no_action(key, None)
|
||||
}
|
||||
|
||||
impl Render for KeybindingStory {
|
||||
@@ -42,7 +41,7 @@ impl Render for KeybindingStory {
|
||||
.py_3()
|
||||
.children(chunk.map(|permutation| {
|
||||
KeyBinding::new_from_gpui(
|
||||
binding(&(permutation.join("-") + "-x")),
|
||||
binding(&(permutation.into_iter().join("-") + "-x")),
|
||||
cx,
|
||||
)
|
||||
}))
|
||||
|
||||
@@ -1244,14 +1244,14 @@ fn generate_commands(_: &App) -> Vec<VimCommand> {
|
||||
.range(act_on_range),
|
||||
VimCommand::str(("rev", "ert"), "git::Restore").range(act_on_range),
|
||||
VimCommand::new(("d", "elete"), VisualDeleteLine).range(select_range),
|
||||
VimCommand::new(("y", "ank"), gpui::NoAction).range(|_, range| {
|
||||
Some(
|
||||
YankCommand {
|
||||
range: range.clone(),
|
||||
}
|
||||
.boxed_clone(),
|
||||
)
|
||||
}),
|
||||
// VimCommand::new(("y", "ank"), gpui::NoAction).range(|_, range| {
|
||||
// Some(
|
||||
// YankCommand {
|
||||
// range: range.clone(),
|
||||
// }
|
||||
// .boxed_clone(),
|
||||
// )
|
||||
// }),
|
||||
VimCommand::new(("reg", "isters"), ToggleRegistersView).bang(ToggleRegistersView),
|
||||
VimCommand::new(("di", "splay"), ToggleRegistersView).bang(ToggleRegistersView),
|
||||
VimCommand::new(("marks", ""), ToggleMarksView).bang(ToggleMarksView),
|
||||
|
||||
@@ -370,7 +370,7 @@ pub struct Pane {
|
||||
/// Is None if navigation buttons are permanently turned off (and should not react to setting changes).
|
||||
/// Otherwise, when `display_nav_history_buttons` is Some, it determines whether nav buttons should be displayed.
|
||||
display_nav_history_buttons: Option<bool>,
|
||||
double_click_dispatch_action: Box<dyn Action>,
|
||||
double_click_dispatch_action: Option<Box<dyn Action>>,
|
||||
save_modals_spawned: HashSet<EntityId>,
|
||||
close_pane_if_empty: bool,
|
||||
pub new_item_context_menu_handle: PopoverMenuHandle<ContextMenu>,
|
||||
@@ -458,7 +458,7 @@ impl Pane {
|
||||
project: Entity<Project>,
|
||||
next_timestamp: Arc<AtomicUsize>,
|
||||
can_drop_predicate: Option<Arc<dyn Fn(&dyn Any, &mut Window, &mut App) -> bool + 'static>>,
|
||||
double_click_dispatch_action: Box<dyn Action>,
|
||||
double_click_dispatch_action: Option<Box<dyn Action>>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Self {
|
||||
@@ -3066,10 +3066,14 @@ impl Pane {
|
||||
}))
|
||||
.on_click(cx.listener(move |this, event: &ClickEvent, window, cx| {
|
||||
if event.click_count() == 2 {
|
||||
window.dispatch_action(
|
||||
this.double_click_dispatch_action.boxed_clone(),
|
||||
cx,
|
||||
);
|
||||
if let Some(double_click_dispatch_action) =
|
||||
&this.double_click_dispatch_action
|
||||
{
|
||||
window.dispatch_action(
|
||||
double_click_dispatch_action.boxed_clone(),
|
||||
cx,
|
||||
);
|
||||
}
|
||||
}
|
||||
})),
|
||||
),
|
||||
@@ -3744,10 +3748,14 @@ impl Render for Pane {
|
||||
.on_click(cx.listener(
|
||||
move |this, event: &ClickEvent, window, cx| {
|
||||
if event.click_count() == 2 {
|
||||
window.dispatch_action(
|
||||
this.double_click_dispatch_action.boxed_clone(),
|
||||
cx,
|
||||
);
|
||||
if let Some(double_click_dispatch_action) =
|
||||
&this.double_click_dispatch_action
|
||||
{
|
||||
window.dispatch_action(
|
||||
double_click_dispatch_action.boxed_clone(),
|
||||
cx,
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
));
|
||||
|
||||
@@ -1306,7 +1306,7 @@ impl Workspace {
|
||||
project.clone(),
|
||||
pane_history_timestamp.clone(),
|
||||
None,
|
||||
NewFile.boxed_clone(),
|
||||
Some(NewFile.boxed_clone()),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
@@ -3187,7 +3187,7 @@ impl Workspace {
|
||||
self.project.clone(),
|
||||
self.pane_history_timestamp.clone(),
|
||||
None,
|
||||
NewFile.boxed_clone(),
|
||||
Some(NewFile.boxed_clone()),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user