Detailed changes
@@ -456,7 +456,7 @@
}
},
{
- "context": "Dock",
+ "context": "Dock > Pane",
"bindings": {
"shift-escape": "dock::HideDock",
"cmd-escape": "dock::RemoveTabFromDock"
@@ -475,17 +475,6 @@
"backspace": "project_panel::Delete"
}
},
- {
- "context": "ProjectPanel > Editor",
- "bindings": {
- "left": "editor::MoveLeft",
- "right": "editor::MoveRight",
- "backspace": "editor::Backspace",
- "cmd-x": "editor::Cut",
- "cmd-c": "editor::Copy",
- "cmd-v": "editor::Paste"
- }
- },
{
"context": "Terminal",
"bindings": {
@@ -1294,7 +1294,7 @@ impl View for ContactList {
fn keymap_context(&self, _: &AppContext) -> KeymapContext {
let mut cx = Self::default_keymap_context();
- cx.set.insert("menu".into());
+ cx.add_identifier("menu");
cx
}
@@ -82,7 +82,7 @@ impl View for ContextMenu {
fn keymap_context(&self, _: &AppContext) -> KeymapContext {
let mut cx = Self::default_keymap_context();
- cx.set.insert("menu".into());
+ cx.add_identifier("menu");
cx
}
@@ -6433,17 +6433,13 @@ impl View for Editor {
EditorMode::AutoHeight { .. } => "auto_height",
EditorMode::Full => "full",
};
- context.map.insert("mode".into(), mode.into());
+ context.add_key("mode", mode);
if self.pending_rename.is_some() {
- context.set.insert("renaming".into());
+ context.add_identifier("renaming");
}
match self.context_menu.as_ref() {
- Some(ContextMenu::Completions(_)) => {
- context.set.insert("showing_completions".into());
- }
- Some(ContextMenu::CodeActions(_)) => {
- context.set.insert("showing_code_actions".into());
- }
+ Some(ContextMenu::Completions(_)) => context.add_identifier("showing_completions"),
+ Some(ContextMenu::CodeActions(_)) => context.add_identifier("showing_code_actions"),
None => {}
}
@@ -86,7 +86,7 @@ pub trait View: Entity + Sized {
}
fn default_keymap_context() -> keymap_matcher::KeymapContext {
let mut cx = keymap_matcher::KeymapContext::default();
- cx.set.insert(Self::ui_name().into());
+ cx.add_identifier(Self::ui_name());
cx
}
fn debug_json(&self, _: &AppContext) -> serde_json::Value {
@@ -6639,12 +6639,12 @@ mod tests {
let mut view_1 = View::new(1);
let mut view_2 = View::new(2);
let mut view_3 = View::new(3);
- view_1.keymap_context.set.insert("a".into());
- view_2.keymap_context.set.insert("a".into());
- view_2.keymap_context.set.insert("b".into());
- view_3.keymap_context.set.insert("a".into());
- view_3.keymap_context.set.insert("b".into());
- view_3.keymap_context.set.insert("c".into());
+ view_1.keymap_context.add_identifier("a");
+ view_2.keymap_context.add_identifier("a");
+ view_2.keymap_context.add_identifier("b");
+ view_3.keymap_context.add_identifier("a");
+ view_3.keymap_context.add_identifier("b");
+ view_3.keymap_context.add_identifier("c");
let (window_id, view_1) = cx.add_window(Default::default(), |_| view_1);
let view_2 = cx.add_view(&view_1, |_| view_2);
@@ -89,6 +89,7 @@ impl KeymapMatcher {
self.contexts
.extend(dispatch_path.iter_mut().map(|e| std::mem::take(&mut e.1)));
+ dbg!(&self.contexts);
// Find the bindings which map the pending keystrokes and current context
for (i, (view_id, _)) in dispatch_path.iter().enumerate() {
// Don't require pending view entry if there are no pending keystrokes
@@ -234,10 +235,10 @@ mod tests {
actions!(test, [EditorAction, ProjectPanelAction]);
let mut editor = KeymapContext::default();
- editor.set.insert("Editor".into());
+ editor.add_identifier("Editor");
let mut project_panel = KeymapContext::default();
- project_panel.set.insert("ProjectPanel".into());
+ project_panel.add_identifier("ProjectPanel");
// Editor 'deeper' in than project panel
let dispatch_path = vec![(2, editor), (1, project_panel)];
@@ -266,10 +267,10 @@ mod tests {
actions!(test, [B, AB, C, D, DA, E, EF]);
let mut context1 = KeymapContext::default();
- context1.set.insert("1".into());
+ context1.add_identifier("1");
let mut context2 = KeymapContext::default();
- context2.set.insert("2".into());
+ context2.add_identifier("2");
let dispatch_path = vec![(2, context2), (1, context1)];
@@ -403,22 +404,22 @@ mod tests {
let predicate = KeymapContextPredicate::parse("a && b || c == d").unwrap();
let mut context = KeymapContext::default();
- context.set.insert("a".into());
+ context.add_identifier("a");
assert!(!predicate.eval(&[context]));
let mut context = KeymapContext::default();
- context.set.insert("a".into());
- context.set.insert("b".into());
+ context.add_identifier("a");
+ context.add_identifier("b");
assert!(predicate.eval(&[context]));
let mut context = KeymapContext::default();
- context.set.insert("a".into());
- context.map.insert("c".into(), "x".into());
+ context.add_identifier("a");
+ context.add_key("c", "x");
assert!(!predicate.eval(&[context]));
let mut context = KeymapContext::default();
- context.set.insert("a".into());
- context.map.insert("c".into(), "d".into());
+ context.add_identifier("a");
+ context.add_key("c", "d");
assert!(predicate.eval(&[context]));
let predicate = KeymapContextPredicate::parse("!a").unwrap();
@@ -458,10 +459,11 @@ mod tests {
assert!(!predicate.eval(&contexts[6..]));
fn context_set(names: &[&str]) -> KeymapContext {
- KeymapContext {
- set: names.iter().copied().map(str::to_string).collect(),
- ..Default::default()
- }
+ let mut keymap = KeymapContext::new();
+ names
+ .iter()
+ .for_each(|name| keymap.add_identifier(name.to_string()));
+ keymap
}
}
@@ -484,10 +486,10 @@ mod tests {
]);
let mut context_a = KeymapContext::default();
- context_a.set.insert("a".into());
+ context_a.add_identifier("a");
let mut context_b = KeymapContext::default();
- context_b.set.insert("b".into());
+ context_b.add_identifier("b");
let mut matcher = KeymapMatcher::new(keymap);
@@ -532,7 +534,7 @@ mod tests {
matcher.clear_pending();
let mut context_c = KeymapContext::default();
- context_c.set.insert("c".into());
+ context_c.add_identifier("c");
// Pending keystrokes are maintained per-view
assert_eq!(
@@ -1,13 +1,22 @@
+use std::borrow::Cow;
+
use anyhow::{anyhow, Result};
use collections::{HashMap, HashSet};
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct KeymapContext {
- pub set: HashSet<String>,
- pub map: HashMap<String, String>,
+ set: HashSet<Cow<'static, str>>,
+ map: HashMap<Cow<'static, str>, Cow<'static, str>>,
}
impl KeymapContext {
+ pub fn new() -> Self {
+ KeymapContext {
+ set: HashSet::default(),
+ map: HashMap::default(),
+ }
+ }
+
pub fn extend(&mut self, other: &Self) {
for v in &other.set {
self.set.insert(v.clone());
@@ -16,6 +25,18 @@ impl KeymapContext {
self.map.insert(k.clone(), v.clone());
}
}
+
+ pub fn add_identifier<I: Into<Cow<'static, str>>>(&mut self, identifier: I) {
+ self.set.insert(identifier.into());
+ }
+
+ pub fn add_key<S1: Into<Cow<'static, str>>, S2: Into<Cow<'static, str>>>(
+ &mut self,
+ key: S1,
+ value: S2,
+ ) {
+ self.map.insert(key.into(), value.into());
+ }
}
#[derive(Debug, Eq, PartialEq)]
@@ -46,12 +67,12 @@ impl KeymapContextPredicate {
Self::Identifier(name) => (&context.set).contains(name.as_str()),
Self::Equal(left, right) => context
.map
- .get(left)
+ .get(left.as_str())
.map(|value| value == right)
.unwrap_or(false),
Self::NotEqual(left, right) => context
.map
- .get(left)
+ .get(left.as_str())
.map(|value| value != right)
.unwrap_or(true),
Self::Not(pred) => !pred.eval(contexts),
@@ -126,7 +126,7 @@ impl<D: PickerDelegate> View for Picker<D> {
fn keymap_context(&self, _: &AppContext) -> KeymapContext {
let mut cx = Self::default_keymap_context();
- cx.set.insert("menu".into());
+ cx.add_identifier("menu");
cx
}
@@ -1314,7 +1314,7 @@ impl View for ProjectPanel {
fn keymap_context(&self, _: &AppContext) -> KeymapContext {
let mut cx = Self::default_keymap_context();
- cx.set.insert("menu".into());
+ cx.add_identifier("menu");
cx
}
}
@@ -469,53 +469,52 @@ impl View for TerminalView {
let mut context = Self::default_keymap_context();
let mode = self.terminal.read(cx).last_content.mode;
- context.map.insert(
- "screen".to_string(),
- (if mode.contains(TermMode::ALT_SCREEN) {
+ context.add_key(
+ "screen",
+ if mode.contains(TermMode::ALT_SCREEN) {
"alt"
} else {
"normal"
- })
- .to_string(),
+ },
);
if mode.contains(TermMode::APP_CURSOR) {
- context.set.insert("DECCKM".to_string());
+ context.add_identifier("DECCKM");
}
if mode.contains(TermMode::APP_KEYPAD) {
- context.set.insert("DECPAM".to_string());
+ context.add_identifier("DECPAM");
}
//Note the ! here
if !mode.contains(TermMode::APP_KEYPAD) {
- context.set.insert("DECPNM".to_string());
+ context.add_identifier("DECPNM");
}
if mode.contains(TermMode::SHOW_CURSOR) {
- context.set.insert("DECTCEM".to_string());
+ context.add_identifier("DECTCEM");
}
if mode.contains(TermMode::LINE_WRAP) {
- context.set.insert("DECAWM".to_string());
+ context.add_identifier("DECAWM");
}
if mode.contains(TermMode::ORIGIN) {
- context.set.insert("DECOM".to_string());
+ context.add_identifier("DECOM");
}
if mode.contains(TermMode::INSERT) {
- context.set.insert("IRM".to_string());
+ context.add_identifier("IRM");
}
//LNM is apparently the name for this. https://vt100.net/docs/vt510-rm/LNM.html
if mode.contains(TermMode::LINE_FEED_NEW_LINE) {
- context.set.insert("LNM".to_string());
+ context.add_identifier("LNM");
}
if mode.contains(TermMode::FOCUS_IN_OUT) {
- context.set.insert("report_focus".to_string());
+ context.add_identifier("report_focus");
}
if mode.contains(TermMode::ALTERNATE_SCROLL) {
- context.set.insert("alternate_scroll".to_string());
+ context.add_identifier("alternate_scroll");
}
if mode.contains(TermMode::BRACKETED_PASTE) {
- context.set.insert("bracketed_paste".to_string());
+ context.add_identifier("bracketed_paste");
}
if mode.intersects(TermMode::MOUSE_MODE) {
- context.set.insert("any_mouse_reporting".to_string());
+ context.add_identifier("any_mouse_reporting");
}
{
let mouse_reporting = if mode.contains(TermMode::MOUSE_REPORT_CLICK) {
@@ -527,9 +526,7 @@ impl View for TerminalView {
} else {
"off"
};
- context
- .map
- .insert("mouse_reporting".to_string(), mouse_reporting.to_string());
+ context.add_key("mouse_reporting", mouse_reporting);
}
{
let format = if mode.contains(TermMode::SGR_MOUSE) {
@@ -539,9 +536,7 @@ impl View for TerminalView {
} else {
"normal"
};
- context
- .map
- .insert("mouse_format".to_string(), format.to_string());
+ context.add_key("mouse_format", format);
}
context
}
@@ -73,34 +73,30 @@ impl VimState {
pub fn keymap_context_layer(&self) -> KeymapContext {
let mut context = KeymapContext::default();
- context.map.insert(
- "vim_mode".to_string(),
+ context.add_key(
+ "vim_mode",
match self.mode {
Mode::Normal => "normal",
Mode::Visual { .. } => "visual",
Mode::Insert => "insert",
- }
- .to_string(),
+ },
);
if self.vim_controlled() {
- context.set.insert("VimControl".to_string());
+ context.add_identifier("VimControl");
}
let active_operator = self.operator_stack.last();
if let Some(active_operator) = active_operator {
for context_flag in active_operator.context_flags().into_iter() {
- context.set.insert(context_flag.to_string());
+ context.add_identifier(*context_flag);
}
}
- context.map.insert(
- "vim_operator".to_string(),
- active_operator
- .map(|op| op.id())
- .unwrap_or_else(|| "none")
- .to_string(),
+ context.add_key(
+ "vim_operator",
+ active_operator.map(|op| op.id()).unwrap_or_else(|| "none"),
);
context
@@ -21,6 +21,7 @@ use gpui::{
vector::{vec2f, Vector2F},
},
impl_actions, impl_internal_actions,
+ keymap_matcher::KeymapContext,
platform::{CursorStyle, NavigationDirection},
Action, AnyViewHandle, AnyWeakViewHandle, AppContext, AsyncAppContext, Entity, EventContext,
ModelHandle, MouseButton, MutableAppContext, PromptLevel, Quad, RenderContext, Task, View,
@@ -1550,6 +1551,14 @@ impl View for Pane {
}
}
}
+
+ fn keymap_context(&self, _: &AppContext) -> KeymapContext {
+ let mut keymap = Self::default_keymap_context();
+ if self.docked.is_some() {
+ keymap.add_identifier("docked");
+ }
+ keymap
+ }
}
fn tab_bar_button<A: Action>(
@@ -2716,11 +2716,7 @@ impl View for Workspace {
}
fn keymap_context(&self, _: &AppContext) -> KeymapContext {
- let mut keymap = Self::default_keymap_context();
- if self.active_pane() == self.dock_pane() {
- keymap.set.insert("Dock".into());
- }
- keymap
+ Self::default_keymap_context()
}
}