From 643146d768304f0625cce667d8a4ca48527832f3 Mon Sep 17 00:00:00 2001 From: Julia Date: Tue, 7 Nov 2023 11:00:30 -0500 Subject: [PATCH] Re-introduce a macro for defining actions for ease of use Co-Authored-By: Piotr Osiewicz Co-Authored-By: Conrad Irwin --- crates/client2/src/client2.rs | 13 ++----- crates/gpui2/src/action.rs | 52 ++++++++++++++++++++++++-- crates/gpui2/src/gpui2.rs | 1 + crates/gpui2/src/interactive.rs | 5 +-- crates/storybook2/src/stories/focus.rs | 14 ++----- 5 files changed, 57 insertions(+), 28 deletions(-) diff --git a/crates/client2/src/client2.rs b/crates/client2/src/client2.rs index 6494e0350bb3fe48e0fc5a477537bec058ee95ed..4a1c5f321c375a097a89252830bd17c572d0c648 100644 --- a/crates/client2/src/client2.rs +++ b/crates/client2/src/client2.rs @@ -15,8 +15,8 @@ use futures::{ TryStreamExt, }; use gpui::{ - serde_json, AnyModel, AnyWeakModel, AppContext, AsyncAppContext, Model, SemanticVersion, Task, - WeakModel, + actions, serde_json, AnyModel, AnyWeakModel, AppContext, AsyncAppContext, Model, + SemanticVersion, Task, WeakModel, }; use lazy_static::lazy_static; use parking_lot::RwLock; @@ -70,14 +70,7 @@ pub const ZED_SECRET_CLIENT_TOKEN: &str = "618033988749894"; pub const INITIAL_RECONNECTION_DELAY: Duration = Duration::from_millis(100); pub const CONNECTION_TIMEOUT: Duration = Duration::from_secs(5); -#[derive(Clone, Default, PartialEq, Deserialize)] -pub struct SignIn; - -#[derive(Clone, Default, PartialEq, Deserialize)] -pub struct SignOut; - -#[derive(Clone, Default, PartialEq, Deserialize)] -pub struct Reconnect; +actions!(SignIn, SignOut, Reconnect); pub fn init_settings(cx: &mut AppContext) { TelemetrySettings::register(cx); diff --git a/crates/gpui2/src/action.rs b/crates/gpui2/src/action.rs index 84843c98762572e591d76c774360fe48b21ee148..393a3feda6ba8a2a3ef1317f715ee08c8e12227e 100644 --- a/crates/gpui2/src/action.rs +++ b/crates/gpui2/src/action.rs @@ -4,7 +4,7 @@ use collections::{HashMap, HashSet}; use serde::Deserialize; use std::any::{type_name, Any}; -pub trait Action: 'static { +pub trait Action: std::fmt::Debug + 'static { fn qualified_name() -> SharedString where Self: Sized; @@ -17,12 +17,39 @@ pub trait Action: 'static { fn as_any(&self) -> &dyn Any; } +// actions defines structs that can be used as actions. +#[macro_export] +macro_rules! actions { + () => {}; + + ( $name:ident ) => { + #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug, ::std::cmp::PartialEq, $crate::serde::Deserialize)] + struct $name; + }; + + ( $name:ident { $($token:tt)* } ) => { + #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug, ::std::cmp::PartialEq, $crate::serde::Deserialize)] + struct $name { $($token)* } + }; + + ( $name:ident, $($rest:tt)* ) => { + actions!($name); + actions!($($rest)*); + }; + + ( $name:ident { $($token:tt)* }, $($rest:tt)* ) => { + actions!($name { $($token)* }); + actions!($($rest)*); + }; +} + impl Action for A where - A: for<'a> Deserialize<'a> + PartialEq + Clone + Default + 'static, + A: for<'a> Deserialize<'a> + PartialEq + Clone + Default + std::fmt::Debug + 'static, { fn qualified_name() -> SharedString { - type_name::().into() + // todo!() remove the 2 replacement when migration is done + type_name::().replace("2::", "::").into() } fn build(params: Option) -> Result> @@ -292,6 +319,25 @@ mod tests { use super::*; use DispatchContextPredicate::*; + #[test] + fn test_actions_definition() { + { + actions!(A, B { field: i32 }, C, D, E, F {}, G); + } + + { + actions!( + A, + B { field: i32 }, + C, + D, + E, + F {}, + G, // Don't wrap, test the trailing comma + ); + } + } + #[test] fn test_parse_context() { let mut expected = DispatchContext::default(); diff --git a/crates/gpui2/src/gpui2.rs b/crates/gpui2/src/gpui2.rs index 49cc3cebc23bf2d61f7615a02e48a77b7d11ba2a..348da17356dd3f48d1a507cfcb0c8d19a4413d2b 100644 --- a/crates/gpui2/src/gpui2.rs +++ b/crates/gpui2/src/gpui2.rs @@ -1,3 +1,4 @@ +#[macro_use] mod action; mod app; mod assets; diff --git a/crates/gpui2/src/interactive.rs b/crates/gpui2/src/interactive.rs index c6506f388e560d6ab4cdc2c473f67b7b2b53b2a1..0725a10aca05ef01a39144982146d36167bc366c 100644 --- a/crates/gpui2/src/interactive.rs +++ b/crates/gpui2/src/interactive.rs @@ -1233,8 +1233,6 @@ pub type KeyListener = Box< #[cfg(test)] mod test { - use serde_derive::Deserialize; - use crate::{ self as gpui, div, Div, FocusHandle, KeyBinding, Keystroke, ParentElement, Render, StatefulInteraction, StatelessInteractive, TestAppContext, VisualContext, @@ -1246,8 +1244,7 @@ mod test { focus_handle: FocusHandle, } - #[derive(PartialEq, Clone, Default, Deserialize)] - struct TestAction; + actions!(TestAction); impl Render for TestView { type Element = Div>; diff --git a/crates/storybook2/src/stories/focus.rs b/crates/storybook2/src/stories/focus.rs index 16c03f87d5421af9d9336e462692102c4cb632bb..0f580d0cbf171ef32b2c83465ad8601785304227 100644 --- a/crates/storybook2/src/stories/focus.rs +++ b/crates/storybook2/src/stories/focus.rs @@ -1,18 +1,10 @@ use gpui::{ - div, Div, FocusEnabled, Focusable, KeyBinding, ParentElement, Render, StatefulInteraction, - StatelessInteractive, Styled, View, VisualContext, WindowContext, + actions, div, Div, FocusEnabled, Focusable, KeyBinding, ParentElement, Render, + StatefulInteraction, StatelessInteractive, Styled, View, VisualContext, WindowContext, }; -use serde::Deserialize; use theme2::ActiveTheme; -#[derive(Clone, Default, PartialEq, Deserialize)] -struct ActionA; - -#[derive(Clone, Default, PartialEq, Deserialize)] -struct ActionB; - -#[derive(Clone, Default, PartialEq, Deserialize)] -struct ActionC; +actions!(ActionA, ActionB, ActionC); pub struct FocusStory {}