From b0acaed02fd2975abe6b276957351382e4f432a4 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 20 Oct 2023 11:08:24 +0200 Subject: [PATCH] Checkpoint --- crates/gpui3/src/action.rs | 56 +++++++++++++++++------------- crates/gpui3/src/interactive.rs | 15 +++++++- crates/gpui3/src/keymap/binding.rs | 6 ++-- crates/gpui3/src/keymap/keymap.rs | 5 +-- crates/gpui3/src/window.rs | 4 +++ 5 files changed, 55 insertions(+), 31 deletions(-) diff --git a/crates/gpui3/src/action.rs b/crates/gpui3/src/action.rs index 22546a1449e654149eecbe173e0db774a9a4928a..eb73de00de79a737ae3db6c7bac077e254c2e58b 100644 --- a/crates/gpui3/src/action.rs +++ b/crates/gpui3/src/action.rs @@ -23,6 +23,10 @@ impl DispatchContext { } } + pub fn is_empty(&self) -> bool { + self.set.is_empty() && self.map.is_empty() + } + pub fn clear(&mut self) { self.set.clear(); self.map.clear(); @@ -47,17 +51,17 @@ impl DispatchContext { } #[derive(Clone, Debug, Eq, PartialEq, Hash)] -pub enum ActionContextPredicate { +pub enum DispatchContextPredicate { Identifier(SharedString), Equal(SharedString, SharedString), NotEqual(SharedString, SharedString), - Child(Box, Box), - Not(Box), - And(Box, Box), - Or(Box, Box), + Child(Box, Box), + Not(Box), + And(Box, Box), + Or(Box, Box), } -impl ActionContextPredicate { +impl DispatchContextPredicate { pub fn parse(source: &str) -> Result { let source = Self::skip_whitespace(source); let (predicate, rest) = Self::parse_expr(source, 0)?; @@ -92,8 +96,10 @@ impl ActionContextPredicate { } fn parse_expr(mut source: &str, min_precedence: u32) -> anyhow::Result<(Self, &str)> { - type Op = - fn(ActionContextPredicate, ActionContextPredicate) -> Result; + type Op = fn( + DispatchContextPredicate, + DispatchContextPredicate, + ) -> Result; let (mut predicate, rest) = Self::parse_primary(source)?; source = rest; @@ -139,7 +145,7 @@ impl ActionContextPredicate { '!' => { let source = Self::skip_whitespace(&source[1..]); let (predicate, source) = Self::parse_expr(&source, PRECEDENCE_NOT)?; - Ok((ActionContextPredicate::Not(Box::new(predicate)), source)) + Ok((DispatchContextPredicate::Not(Box::new(predicate)), source)) } _ if next.is_alphanumeric() || next == '_' => { let len = source @@ -148,7 +154,7 @@ impl ActionContextPredicate { let (identifier, rest) = source.split_at(len); source = Self::skip_whitespace(rest); Ok(( - ActionContextPredicate::Identifier(identifier.to_string().into()), + DispatchContextPredicate::Identifier(identifier.to_string().into()), source, )) } @@ -200,17 +206,17 @@ const PRECEDENCE_NOT: u32 = 5; #[cfg(test)] mod tests { - use super::ActionContextPredicate::{self, *}; + use super::DispatchContextPredicate::{self, *}; #[test] fn test_parse_identifiers() { // Identifiers assert_eq!( - ActionContextPredicate::parse("abc12").unwrap(), + DispatchContextPredicate::parse("abc12").unwrap(), Identifier("abc12".into()) ); assert_eq!( - ActionContextPredicate::parse("_1a").unwrap(), + DispatchContextPredicate::parse("_1a").unwrap(), Identifier("_1a".into()) ); } @@ -218,11 +224,11 @@ mod tests { #[test] fn test_parse_negations() { assert_eq!( - ActionContextPredicate::parse("!abc").unwrap(), + DispatchContextPredicate::parse("!abc").unwrap(), Not(Box::new(Identifier("abc".into()))) ); assert_eq!( - ActionContextPredicate::parse(" ! ! abc").unwrap(), + DispatchContextPredicate::parse(" ! ! abc").unwrap(), Not(Box::new(Not(Box::new(Identifier("abc".into()))))) ); } @@ -230,15 +236,15 @@ mod tests { #[test] fn test_parse_equality_operators() { assert_eq!( - ActionContextPredicate::parse("a == b").unwrap(), + DispatchContextPredicate::parse("a == b").unwrap(), Equal("a".into(), "b".into()) ); assert_eq!( - ActionContextPredicate::parse("c!=d").unwrap(), + DispatchContextPredicate::parse("c!=d").unwrap(), NotEqual("c".into(), "d".into()) ); assert_eq!( - ActionContextPredicate::parse("c == !d") + DispatchContextPredicate::parse("c == !d") .unwrap_err() .to_string(), "operands must be identifiers" @@ -248,14 +254,14 @@ mod tests { #[test] fn test_parse_boolean_operators() { assert_eq!( - ActionContextPredicate::parse("a || b").unwrap(), + DispatchContextPredicate::parse("a || b").unwrap(), Or( Box::new(Identifier("a".into())), Box::new(Identifier("b".into())) ) ); assert_eq!( - ActionContextPredicate::parse("a || !b && c").unwrap(), + DispatchContextPredicate::parse("a || !b && c").unwrap(), Or( Box::new(Identifier("a".into())), Box::new(And( @@ -265,7 +271,7 @@ mod tests { ) ); assert_eq!( - ActionContextPredicate::parse("a && b || c&&d").unwrap(), + DispatchContextPredicate::parse("a && b || c&&d").unwrap(), Or( Box::new(And( Box::new(Identifier("a".into())), @@ -278,7 +284,7 @@ mod tests { ) ); assert_eq!( - ActionContextPredicate::parse("a == b && c || d == e && f").unwrap(), + DispatchContextPredicate::parse("a == b && c || d == e && f").unwrap(), Or( Box::new(And( Box::new(Equal("a".into(), "b".into())), @@ -291,7 +297,7 @@ mod tests { ) ); assert_eq!( - ActionContextPredicate::parse("a && b && c && d").unwrap(), + DispatchContextPredicate::parse("a && b && c && d").unwrap(), And( Box::new(And( Box::new(And( @@ -308,7 +314,7 @@ mod tests { #[test] fn test_parse_parenthesized_expressions() { assert_eq!( - ActionContextPredicate::parse("a && (b == c || d != e)").unwrap(), + DispatchContextPredicate::parse("a && (b == c || d != e)").unwrap(), And( Box::new(Identifier("a".into())), Box::new(Or( @@ -318,7 +324,7 @@ mod tests { ), ); assert_eq!( - ActionContextPredicate::parse(" ( a || b ) ").unwrap(), + DispatchContextPredicate::parse(" ( a || b ) ").unwrap(), Or( Box::new(Identifier("a".into())), Box::new(Identifier("b".into())), diff --git a/crates/gpui3/src/interactive.rs b/crates/gpui3/src/interactive.rs index d5c5239934f3616f8d2316aabdf5b0433ad0bdb9..ee8c69c911bd9d586c48af0e7a7878c3a4acbf5d 100644 --- a/crates/gpui3/src/interactive.rs +++ b/crates/gpui3/src/interactive.rs @@ -176,6 +176,14 @@ pub trait StatelessInteractive: Element { self } + fn context(mut self, context: impl Into) -> Self + where + Self: Sized, + { + self.stateless_interactivity().dispatch_context = context.into(); + self + } + fn on_action( mut self, listener: impl Fn(&mut Self::ViewState, &A, DispatchPhase, &mut ViewContext) @@ -320,7 +328,10 @@ pub trait ElementInteraction: 'static + Send + Sync { result }) } else { - cx.with_key_listeners(&self.as_stateless().key_listeners, f) + let stateless = self.as_stateless(); + cx.with_key_dispatch_context(stateless.dispatch_context.clone(), |cx| { + cx.with_key_listeners(&stateless.key_listeners, f) + }) } } @@ -519,6 +530,7 @@ where } pub struct StatelessInteraction { + pub dispatch_context: DispatchContext, pub mouse_down_listeners: SmallVec<[MouseDownListener; 2]>, pub mouse_up_listeners: SmallVec<[MouseUpListener; 2]>, pub mouse_move_listeners: SmallVec<[MouseMoveListener; 2]>, @@ -583,6 +595,7 @@ pub struct InteractiveElementState { impl Default for StatelessInteraction { fn default() -> Self { Self { + dispatch_context: DispatchContext::new(), mouse_down_listeners: SmallVec::new(), mouse_up_listeners: SmallVec::new(), mouse_move_listeners: SmallVec::new(), diff --git a/crates/gpui3/src/keymap/binding.rs b/crates/gpui3/src/keymap/binding.rs index 27289d0c674df508c49c4f2ab9c80e8027075718..418303bcff06b4474cef5fcd7e1f528164cceaa7 100644 --- a/crates/gpui3/src/keymap/binding.rs +++ b/crates/gpui3/src/keymap/binding.rs @@ -1,11 +1,11 @@ -use crate::{Action, ActionContextPredicate, DispatchContext, KeyMatch, Keystroke}; +use crate::{Action, DispatchContext, DispatchContextPredicate, KeyMatch, Keystroke}; use anyhow::Result; use smallvec::SmallVec; pub struct KeyBinding { action: Box, pub(super) keystrokes: SmallVec<[Keystroke; 2]>, - pub(super) context_predicate: Option, + pub(super) context_predicate: Option, } impl KeyBinding { @@ -15,7 +15,7 @@ impl KeyBinding { pub fn load(keystrokes: &str, action: Box, context: Option<&str>) -> Result { let context = if let Some(context) = context { - Some(ActionContextPredicate::parse(context)?) + Some(DispatchContextPredicate::parse(context)?) } else { None }; diff --git a/crates/gpui3/src/keymap/keymap.rs b/crates/gpui3/src/keymap/keymap.rs index fffd7d54846570271ea293c956609f4580368348..eda493a4607837783e830069931d617692feeb9f 100644 --- a/crates/gpui3/src/keymap/keymap.rs +++ b/crates/gpui3/src/keymap/keymap.rs @@ -1,4 +1,4 @@ -use crate::{ActionContextPredicate, KeyBinding, Keystroke}; +use crate::{DispatchContextPredicate, KeyBinding, Keystroke}; use collections::HashSet; use smallvec::SmallVec; use std::{any::TypeId, collections::HashMap}; @@ -10,7 +10,8 @@ pub struct KeymapVersion(usize); pub struct Keymap { bindings: Vec, binding_indices_by_action_id: HashMap>, - disabled_keystrokes: HashMap, HashSet>>, + disabled_keystrokes: + HashMap, HashSet>>, version: KeymapVersion, } diff --git a/crates/gpui3/src/window.rs b/crates/gpui3/src/window.rs index d1af98b667c331213bf87dbd4b2d3033640af81b..2652270ba1afcef409addf5837af40f663fae398 100644 --- a/crates/gpui3/src/window.rs +++ b/crates/gpui3/src/window.rs @@ -1388,6 +1388,10 @@ impl<'a, 'w, V: Send + Sync + 'static> ViewContext<'a, 'w, V> { context: DispatchContext, f: impl FnOnce(&mut Self) -> R, ) -> R { + if context.is_empty() { + return f(self); + } + if !self.window.freeze_key_dispatch_stack { self.window .key_dispatch_stack