diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index 1892fc6fa960344e74756aab19e814cb2869314e..0b917d72b0beb4bf797641836e0f0989c0c7327f 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -92,7 +92,7 @@ use theme::{ActiveTheme, ThemeSettings}; // channel_id: ChannelId, // } -#[derive(Action, PartialEq, Debug, Clone, Serialize, Deserialize)] +#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)] pub struct OpenChannelNotes { pub channel_id: ChannelId, } @@ -122,6 +122,8 @@ pub struct OpenChannelNotes { // to: ChannelId, // } +impl_actions!(collab_panel, [OpenChannelNotes]); + actions!( collab_panel, [ @@ -172,12 +174,12 @@ use editor::Editor; use feature_flags::{ChannelsAlpha, FeatureFlagAppExt, FeatureFlagViewExt}; use fuzzy::{match_strings, StringMatchCandidate}; use gpui::{ - actions, canvas, div, img, overlay, point, prelude::*, px, rems, serde_json, size, Action, - AppContext, AsyncWindowContext, Bounds, ClipboardItem, DismissEvent, Div, EventEmitter, - FocusHandle, Focusable, FocusableView, Hsla, InteractiveElement, IntoElement, Length, Model, - MouseDownEvent, ParentElement, Pixels, Point, PromptLevel, Quad, Render, RenderOnce, - ScrollHandle, SharedString, Size, Stateful, Styled, Subscription, Task, View, ViewContext, - VisualContext, WeakView, + actions, canvas, div, img, impl_actions, overlay, point, prelude::*, px, rems, serde_json, + size, Action, AppContext, AsyncWindowContext, Bounds, ClipboardItem, DismissEvent, Div, + EventEmitter, FocusHandle, Focusable, FocusableView, Hsla, InteractiveElement, IntoElement, + Length, Model, MouseDownEvent, ParentElement, Pixels, Point, PromptLevel, Quad, Render, + RenderOnce, ScrollHandle, SharedString, Size, Stateful, Styled, Subscription, Task, View, + ViewContext, VisualContext, WeakView, }; use project::{Fs, Project}; use serde_derive::{Deserialize, Serialize}; diff --git a/crates/command_palette2/src/command_palette.rs b/crates/command_palette2/src/command_palette.rs index 4827b137516dafe71d07f08645b1cbe7305a50f6..018d8bc878242bb4a6c8c1fe25afcb3ab4913bce 100644 --- a/crates/command_palette2/src/command_palette.rs +++ b/crates/command_palette2/src/command_palette.rs @@ -49,7 +49,7 @@ impl CommandPalette { .available_actions() .into_iter() .filter_map(|action| { - let name = gpui::remove_the_2(action.name()); + let name = action.name(); let namespace = name.split("::").next().unwrap_or("malformed action name"); if filter.is_some_and(|f| { f.hidden_namespaces.contains(namespace) diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index 913b8993128f4a60c3a7bfe900a2a54f877f30b3..4912e1aa117a6566224986df7c8fb2dfb3c88446 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -39,8 +39,8 @@ use futures::FutureExt; use fuzzy::{StringMatch, StringMatchCandidate}; use git::diff_hunk_to_display; use gpui::{ - actions, div, point, prelude::*, px, relative, rems, size, uniform_list, Action, AnyElement, - AppContext, AsyncWindowContext, BackgroundExecutor, Bounds, ClipboardItem, Context, + actions, div, impl_actions, point, prelude::*, px, relative, rems, size, uniform_list, Action, + AnyElement, AppContext, AsyncWindowContext, BackgroundExecutor, Bounds, ClipboardItem, Context, DispatchPhase, Div, ElementId, EventEmitter, FocusHandle, FocusableView, FontFeatures, FontStyle, FontWeight, HighlightStyle, Hsla, InputHandler, InteractiveText, KeyContext, Model, MouseButton, ParentElement, Pixels, Render, RenderOnce, SharedString, Styled, StyledText, @@ -185,82 +185,101 @@ pub fn render_parsed_markdown( }) } -#[derive(PartialEq, Clone, Deserialize, Default, Action)] +#[derive(PartialEq, Clone, Deserialize, Default)] pub struct SelectNext { #[serde(default)] pub replace_newest: bool, } -#[derive(PartialEq, Clone, Deserialize, Default, Action)] +#[derive(PartialEq, Clone, Deserialize, Default)] pub struct SelectPrevious { #[serde(default)] pub replace_newest: bool, } -#[derive(PartialEq, Clone, Deserialize, Default, Action)] +#[derive(PartialEq, Clone, Deserialize, Default)] pub struct SelectAllMatches { #[serde(default)] pub replace_newest: bool, } -#[derive(PartialEq, Clone, Deserialize, Default, Action)] +#[derive(PartialEq, Clone, Deserialize, Default)] pub struct SelectToBeginningOfLine { #[serde(default)] stop_at_soft_wraps: bool, } -#[derive(PartialEq, Clone, Deserialize, Default, Action)] +#[derive(PartialEq, Clone, Deserialize, Default)] pub struct MovePageUp { #[serde(default)] center_cursor: bool, } -#[derive(PartialEq, Clone, Deserialize, Default, Action)] +#[derive(PartialEq, Clone, Deserialize, Default)] pub struct MovePageDown { #[serde(default)] center_cursor: bool, } -#[derive(PartialEq, Clone, Deserialize, Default, Action)] +#[derive(PartialEq, Clone, Deserialize, Default)] pub struct SelectToEndOfLine { #[serde(default)] stop_at_soft_wraps: bool, } -#[derive(PartialEq, Clone, Deserialize, Default, Action)] +#[derive(PartialEq, Clone, Deserialize, Default)] pub struct ToggleCodeActions { #[serde(default)] pub deployed_from_indicator: bool, } -#[derive(PartialEq, Clone, Deserialize, Default, Action)] +#[derive(PartialEq, Clone, Deserialize, Default)] pub struct ConfirmCompletion { #[serde(default)] pub item_ix: Option, } -#[derive(PartialEq, Clone, Deserialize, Default, Action)] +#[derive(PartialEq, Clone, Deserialize, Default)] pub struct ConfirmCodeAction { #[serde(default)] pub item_ix: Option, } -#[derive(PartialEq, Clone, Deserialize, Default, Action)] +#[derive(PartialEq, Clone, Deserialize, Default)] pub struct ToggleComments { #[serde(default)] pub advance_downwards: bool, } -#[derive(PartialEq, Clone, Deserialize, Default, Action)] +#[derive(PartialEq, Clone, Deserialize, Default)] pub struct FoldAt { pub buffer_row: u32, } -#[derive(PartialEq, Clone, Deserialize, Default, Action)] +#[derive(PartialEq, Clone, Deserialize, Default)] pub struct UnfoldAt { pub buffer_row: u32, } +impl_actions!( + editor, + [ + SelectNext, + SelectPrevious, + SelectAllMatches, + SelectToBeginningOfLine, + MovePageUp, + MovePageDown, + SelectToEndOfLine, + ToggleCodeActions, + ConfirmCompletion, + ConfirmCodeAction, + ToggleComments, + FoldAt, + UnfoldAt + ] +); + #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum InlayId { Suggestion(usize), diff --git a/crates/gpui2/src/action.rs b/crates/gpui2/src/action.rs index ce01fbaf22d2140049577faf2d976e5b23111423..bf03c87ae92bf56f158dd646f2a5848e5097ac92 100644 --- a/crates/gpui2/src/action.rs +++ b/crates/gpui2/src/action.rs @@ -3,34 +3,33 @@ use anyhow::{anyhow, Context, Result}; use collections::HashMap; pub use no_action::NoAction; use serde_json::json; -use std::{ - any::{Any, TypeId}, - ops::Deref, -}; +use std::any::{Any, TypeId}; /// Actions are used to implement keyboard-driven UI. /// When you declare an action, you can bind keys to the action in the keymap and /// listeners for that action in the element tree. /// /// To declare a list of simple actions, you can use the actions! macro, which defines a simple unit struct -/// action for each listed action name. +/// action for each listed action name in the given namespace. /// ```rust -/// actions!(MoveUp, MoveDown, MoveLeft, MoveRight, Newline); +/// actions!(editor, [MoveUp, MoveDown, MoveLeft, MoveRight, Newline]); /// ``` -/// More complex data types can also be actions. If you annotate your type with the action derive macro -/// it will be implemented and registered automatically. +/// More complex data types can also be actions, providing they implement Clone, PartialEq, +/// and serde_derive::Deserialize. +/// Use `impl_actions!` to automatically implement the action in the given namespace. /// ``` -/// #[derive(Clone, PartialEq, serde_derive::Deserialize, Action)] +/// #[derive(Clone, PartialEq, serde_derive::Deserialize)] /// pub struct SelectNext { /// pub replace_newest: bool, /// } +/// impl_actions!(editor, [SelectNext]); +/// ``` /// /// If you want to control the behavior of the action trait manually, you can use the lower-level `#[register_action]` /// macro, which only generates the code needed to register your action before `main`. /// /// ``` -/// #[gpui::register_action] -/// #[derive(gpui::serde::Deserialize, std::cmp::PartialEq, std::clone::Clone, std::fmt::Debug)] +/// #[derive(gpui::serde::Deserialize, std::cmp::PartialEq, std::clone::Clone)] /// pub struct Paste { /// pub content: SharedString, /// } @@ -38,6 +37,7 @@ use std::{ /// impl gpui::Action for Paste { /// ///... /// } +/// register_action!(Paste); /// ``` pub trait Action: 'static { fn boxed_clone(&self) -> Box; @@ -56,7 +56,7 @@ pub trait Action: 'static { impl std::fmt::Debug for dyn Action { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("dyn Action") - .field("type_name", &self.name()) + .field("name", &self.name()) .finish() } } @@ -115,7 +115,7 @@ impl ActionRegistry { for builder in __GPUI_ACTIONS { let action = builder(); //todo(remove) - let name: SharedString = remove_the_2(action.name).into(); + let name: SharedString = action.name.into(); self.builders_by_name.insert(name.clone(), action.build); self.names_by_type_id.insert(action.type_id, name.clone()); self.all_names.push(name); @@ -139,11 +139,9 @@ impl ActionRegistry { name: &str, params: Option, ) -> Result> { - //todo(remove) - let name = remove_the_2(name); let build_action = self .builders_by_name - .get(name.deref()) + .get(name) .ok_or_else(|| anyhow!("no action type registered for {}", name))?; (build_action)(params.unwrap_or_else(|| json!({}))) .with_context(|| format!("Attempting to build action {}", name)) @@ -155,14 +153,13 @@ impl ActionRegistry { } /// Defines unit structs that can be used as actions. -/// To use more complex data types as actions, annotate your type with the #[action] macro. +/// To use more complex data types as actions, use `impl_actions!` #[macro_export] macro_rules! actions { ($namespace:path, [ $($name:ident),* $(,)? ]) => { $( #[derive(::std::cmp::PartialEq, ::std::clone::Clone, ::std::default::Default, gpui::serde_derive::Deserialize)] #[serde(crate = "gpui::serde")] - #[gpui::register_action] pub struct $name; gpui::__impl_action!($namespace, $name, @@ -170,6 +167,22 @@ macro_rules! actions { Ok(Box::new(Self)) } ); + + gpui::register_action!($name); + )* + }; +} + +/// Implements the Action trait for any struct that implements Clone, Default, PartialEq, and serde_deserialize::Deserialize +#[macro_export] +macro_rules! impl_actions { + ($namespace:path, [ $($name:ident),* $(,)? ]) => { + $( + gpui::__impl_action!($namespace, $name, + fn build(value: gpui::serde_json::Value) -> gpui::Result<::std::boxed::Box> { + Ok(std::boxed::Box::new(gpui::serde_json::from_value::(value)?)) + } + ); )* }; } @@ -220,17 +233,6 @@ macro_rules! __impl_action { }; } -//todo!(remove) -pub fn remove_the_2(action_name: &str) -> String { - let mut separator_matches = action_name.rmatch_indices("::"); - separator_matches.next().unwrap(); - let name_start_ix = separator_matches.next().map_or(0, |(ix, _)| ix + 2); - // todo!() remove the 2 replacement when migration is done - action_name[name_start_ix..] - .replace("2::", "::") - .to_string() -} - mod no_action { use crate as gpui; diff --git a/crates/gpui2/tests/action_macros.rs b/crates/gpui2/tests/action_macros.rs index 49064ffd86e371e0fcc4547e8ba34dad3843a6df..758b33fbfafc215acfff1179db22bc7923a32da3 100644 --- a/crates/gpui2/tests/action_macros.rs +++ b/crates/gpui2/tests/action_macros.rs @@ -1,16 +1,23 @@ +use gpui2::{actions, impl_actions}; +use gpui2_macros::register_action; use serde_derive::Deserialize; #[test] -fn test_derive() { +fn test_action_macros() { use gpui2 as gpui; - #[derive(PartialEq, Clone, Deserialize, gpui2_macros::Action)] + actions!(test, [TestAction]); + + #[derive(PartialEq, Clone, Deserialize)] struct AnotherTestAction; - #[gpui2_macros::register_action] + impl_actions!(test, [AnotherTestAction]); + #[derive(PartialEq, Clone, gpui::serde_derive::Deserialize)] struct RegisterableAction {} + register_action!(RegisterableAction); + impl gpui::Action for RegisterableAction { fn boxed_clone(&self) -> Box { todo!() diff --git a/crates/gpui2_macros/src/action.rs b/crates/gpui2_macros/src/action.rs deleted file mode 100644 index 296e3f08b12b5fe0ede78d9ec1be0df96dd85735..0000000000000000000000000000000000000000 --- a/crates/gpui2_macros/src/action.rs +++ /dev/null @@ -1,97 +0,0 @@ -// Input: -// -// #[action] -// struct Foo { -// bar: String, -// } - -// Output: -// -// #[gpui::register_action] -// #[derive(gpui::serde::Deserialize, std::cmp::PartialEq, std::clone::Clone, std::default::Default, std::fmt::Debug)] -// struct Foo { -// bar: String, -// } - -use proc_macro::TokenStream; -use quote::quote; -use syn::{parse_macro_input, DeriveInput, Error}; - -use crate::register_action::register_action; - -pub fn action(input: TokenStream) -> TokenStream { - let input = parse_macro_input!(input as DeriveInput); - - let name = &input.ident; - - if input.generics.lt_token.is_some() { - return Error::new(name.span(), "Actions must be a concrete type") - .into_compile_error() - .into(); - } - - let is_unit_struct = match input.data { - syn::Data::Struct(struct_data) => struct_data.fields.is_empty(), - syn::Data::Enum(_) => false, - syn::Data::Union(_) => false, - }; - - let build_impl = if is_unit_struct { - quote! { - let _ = value; - Ok(std::boxed::Box::new(Self {})) - } - } else { - quote! { - Ok(std::boxed::Box::new(gpui::serde_json::from_value::(value)?)) - } - }; - - let register_action = register_action(&name); - - let output = quote! { - const _: fn() = || { - fn assert_impl gpui::serde::Deserialize<'a> + ::std::cmp::PartialEq + ::std::clone::Clone>() {} - assert_impl::<#name>(); - }; - - impl gpui::Action for #name { - fn name(&self) -> &'static str - { - ::std::any::type_name::<#name>() - } - - fn debug_name() -> &'static str - where - Self: ::std::marker::Sized - { - ::std::any::type_name::<#name>() - } - - fn build(value: gpui::serde_json::Value) -> gpui::Result<::std::boxed::Box> - where - Self: ::std::marker::Sized { - #build_impl - } - - fn partial_eq(&self, action: &dyn gpui::Action) -> bool { - action - .as_any() - .downcast_ref::() - .map_or(false, |a| self == a) - } - - fn boxed_clone(&self) -> std::boxed::Box { - ::std::boxed::Box::new(self.clone()) - } - - fn as_any(&self) -> &dyn ::std::any::Any { - self - } - } - - #register_action - }; - - TokenStream::from(output) -} diff --git a/crates/gpui2_macros/src/gpui2_macros.rs b/crates/gpui2_macros/src/gpui2_macros.rs index a7fb363d366d1852be188607cd4899388712dde2..a56d80b86d0ec92c523eb9dcbcb185f4b2d11049 100644 --- a/crates/gpui2_macros/src/gpui2_macros.rs +++ b/crates/gpui2_macros/src/gpui2_macros.rs @@ -1,4 +1,3 @@ -mod action; mod derive_into_element; mod register_action; mod style_helpers; @@ -6,14 +5,9 @@ mod test; use proc_macro::TokenStream; -#[proc_macro_derive(Action)] -pub fn action(input: TokenStream) -> TokenStream { - action::action(input) -} - -#[proc_macro_attribute] -pub fn register_action(attr: TokenStream, item: TokenStream) -> TokenStream { - register_action::register_action_macro(attr, item) +#[proc_macro] +pub fn register_action(ident: TokenStream) -> TokenStream { + register_action::register_action_macro(ident) } #[proc_macro_derive(IntoElement)] diff --git a/crates/gpui2_macros/src/register_action.rs b/crates/gpui2_macros/src/register_action.rs index f25f867a74e2aa1e0a44f81b2eee74cf5ff7968d..9e3a473843df734b58190675e6f4fb78110b5c6f 100644 --- a/crates/gpui2_macros/src/register_action.rs +++ b/crates/gpui2_macros/src/register_action.rs @@ -14,47 +14,13 @@ use proc_macro::TokenStream; use proc_macro2::Ident; use quote::{format_ident, quote}; -use syn::{parse_macro_input, DeriveInput, Error}; +use syn::parse_macro_input; -pub fn register_action_macro(_attr: TokenStream, item: TokenStream) -> TokenStream { - let input = parse_macro_input!(item as DeriveInput); - let registration = register_action(&input.ident); - - let has_action_derive = input - .attrs - .iter() - .find(|attr| { - (|| { - let meta = attr.parse_meta().ok()?; - meta.path().is_ident("derive").then(|| match meta { - syn::Meta::Path(_) => None, - syn::Meta::NameValue(_) => None, - syn::Meta::List(list) => list - .nested - .iter() - .find(|list| match list { - syn::NestedMeta::Meta(meta) => meta.path().is_ident("Action"), - syn::NestedMeta::Lit(_) => false, - }) - .map(|_| true), - })? - })() - .unwrap_or(false) - }) - .is_some(); - - if has_action_derive { - return Error::new( - input.ident.span(), - "The Action derive macro has already registered this action", - ) - .into_compile_error() - .into(); - } +pub fn register_action_macro(ident: TokenStream) -> TokenStream { + let name = parse_macro_input!(ident as Ident); + let registration = register_action(&name); TokenStream::from(quote! { - #input - #registration }) } diff --git a/crates/live_kit_client2/examples/test_app2.rs b/crates/live_kit_client2/examples/test_app2.rs index 00aec53baff83478d59365d2aed4d896e99e87f7..fc2c8deb716e3238b3cec53feeb5863e488ba3e8 100644 --- a/crates/live_kit_client2/examples/test_app2.rs +++ b/crates/live_kit_client2/examples/test_app2.rs @@ -1,17 +1,15 @@ use std::{sync::Arc, time::Duration}; use futures::StreamExt; -use gpui::{Action, KeyBinding}; +use gpui::{actions, KeyBinding}; use live_kit_client2::{ LocalAudioTrack, LocalVideoTrack, RemoteAudioTrackUpdate, RemoteVideoTrackUpdate, Room, }; use live_kit_server::token::{self, VideoGrant}; use log::LevelFilter; -use serde_derive::Deserialize; use simplelog::SimpleLogger; -#[derive(Deserialize, Debug, Clone, Copy, PartialEq, Action)] -struct Quit; +actions!(live_kit_client, [Quit]); fn main() { SimpleLogger::init(LevelFilter::Info, Default::default()).expect("could not initialize logger"); diff --git a/crates/search2/src/buffer_search.rs b/crates/search2/src/buffer_search.rs index 33f246ef35730e818208c1a6ab767d8ec270c6c1..14c046e0d4781819253ca2cd428a5ffa82117049 100644 --- a/crates/search2/src/buffer_search.rs +++ b/crates/search2/src/buffer_search.rs @@ -10,7 +10,7 @@ use collections::HashMap; use editor::{Editor, EditorMode}; use futures::channel::oneshot; use gpui::{ - actions, div, red, Action, AppContext, Div, EventEmitter, FocusableView, + actions, div, impl_actions, red, Action, AppContext, Div, EventEmitter, FocusableView, InteractiveElement as _, IntoElement, KeyContext, ParentElement as _, Render, Styled, Subscription, Task, View, ViewContext, VisualContext as _, WeakView, WindowContext, }; @@ -26,11 +26,13 @@ use workspace::{ ToolbarItemLocation, ToolbarItemView, }; -#[derive(PartialEq, Clone, Deserialize, Default, Action)] +#[derive(PartialEq, Clone, Deserialize)] pub struct Deploy { pub focus: bool, } +impl_actions!(buffer_search, [Deploy]); + actions!(buffer_search, [Dismiss, FocusEditor]); pub enum Event { diff --git a/crates/terminal_view2/src/terminal_view.rs b/crates/terminal_view2/src/terminal_view.rs index 83c7779d2e05f9a83a0de1d246131df95684bf59..be33e0c2ec5fa1815f35a268d4e56f967333bf96 100644 --- a/crates/terminal_view2/src/terminal_view.rs +++ b/crates/terminal_view2/src/terminal_view.rs @@ -9,10 +9,10 @@ pub mod terminal_panel; // use crate::terminal_element::TerminalElement; use editor::{scroll::autoscroll::Autoscroll, Editor}; use gpui::{ - div, overlay, Action, AnyElement, AppContext, DismissEvent, Div, EventEmitter, FocusEvent, - FocusHandle, Focusable, FocusableElement, FocusableView, KeyContext, KeyDownEvent, Keystroke, - Model, MouseButton, MouseDownEvent, Pixels, Render, Styled, Subscription, Task, View, - VisualContext, WeakView, + div, impl_actions, overlay, AnyElement, AppContext, DismissEvent, Div, EventEmitter, + FocusEvent, FocusHandle, Focusable, FocusableElement, FocusableView, KeyContext, KeyDownEvent, + Keystroke, Model, MouseButton, MouseDownEvent, Pixels, Render, Styled, Subscription, Task, + View, VisualContext, WeakView, }; use language::Bias; use persistence::TERMINAL_DB; @@ -55,12 +55,14 @@ const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500); #[derive(Clone, Debug, PartialEq)] pub struct ScrollTerminal(pub i32); -#[derive(Clone, Debug, Default, Deserialize, PartialEq, Action)] +#[derive(Clone, Debug, Default, Deserialize, PartialEq)] pub struct SendText(String); -#[derive(Clone, Debug, Default, Deserialize, PartialEq, Action)] +#[derive(Clone, Debug, Default, Deserialize, PartialEq)] pub struct SendKeystroke(String); +impl_actions!(terminal_view, [SendText, SendKeystroke]); + pub fn init(cx: &mut AppContext) { terminal_panel::init(cx); terminal::init(cx); diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index 3c81e6aa2641ca8155284be32634d5c994b9f47e..38e0706fb1896b6e4bd90dcc141063d22def0b04 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -7,10 +7,10 @@ use crate::{ use anyhow::Result; use collections::{HashMap, HashSet, VecDeque}; use gpui::{ - actions, overlay, prelude::*, rems, Action, AnchorCorner, AnyWeakView, AppContext, - AsyncWindowContext, DismissEvent, Div, EntityId, EventEmitter, FocusHandle, Focusable, - FocusableView, Model, MouseButton, NavigationDirection, Pixels, Point, PromptLevel, Render, - Task, View, ViewContext, VisualContext, WeakView, WindowContext, + actions, impl_actions, overlay, prelude::*, rems, Action, AnchorCorner, AnyWeakView, + AppContext, AsyncWindowContext, DismissEvent, Div, EntityId, EventEmitter, FocusHandle, + Focusable, FocusableView, Model, MouseButton, NavigationDirection, Pixels, Point, PromptLevel, + Render, Task, View, ViewContext, VisualContext, WeakView, WindowContext, }; use parking_lot::Mutex; use project::{Project, ProjectEntryId, ProjectPath}; @@ -52,9 +52,7 @@ pub enum SaveIntent { Skip, } -//todo!("Do we need the default bound on actions? Decide soon") -// #[register_action] -#[derive(Action, Clone, Deserialize, PartialEq, Debug)] +#[derive(Clone, Deserialize, PartialEq, Debug)] pub struct ActivateItem(pub usize); // #[derive(Clone, PartialEq)] @@ -75,18 +73,20 @@ pub struct ActivateItem(pub usize); // pub pane: WeakView, // } -#[derive(Clone, PartialEq, Debug, Deserialize, Default, Action)] +#[derive(Clone, PartialEq, Debug, Deserialize, Default)] #[serde(rename_all = "camelCase")] pub struct CloseActiveItem { pub save_intent: Option, } -#[derive(Clone, PartialEq, Debug, Deserialize, Default, Action)] +#[derive(Clone, PartialEq, Debug, Deserialize, Default)] #[serde(rename_all = "camelCase")] pub struct CloseAllItems { pub save_intent: Option, } +impl_actions!(pane, [CloseAllItems, CloseActiveItem, ActivateItem]); + actions!( pane, [ diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index f0f39f6f6bd632f873e9fb15002e2dccd0f4b93f..eb846fbea8b81917351c4e36b881c52521ae790b 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -29,12 +29,12 @@ use futures::{ Future, FutureExt, StreamExt, }; use gpui::{ - actions, div, point, size, Action, AnyModel, AnyView, AnyWeakView, AnyWindowHandle, AppContext, - AsyncAppContext, AsyncWindowContext, Bounds, Context, Div, Entity, EntityId, EventEmitter, - FocusHandle, FocusableView, GlobalPixels, InteractiveElement, KeyContext, ManagedView, Model, - ModelContext, ParentElement, PathPromptOptions, Point, PromptLevel, Render, Size, Styled, - Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowBounds, WindowContext, - WindowHandle, WindowOptions, + actions, div, impl_actions, point, size, Action, AnyModel, AnyView, AnyWeakView, + AnyWindowHandle, AppContext, AsyncAppContext, AsyncWindowContext, Bounds, Context, Div, Entity, + EntityId, EventEmitter, FocusHandle, FocusableView, GlobalPixels, InteractiveElement, + KeyContext, ManagedView, Model, ModelContext, ParentElement, PathPromptOptions, Point, + PromptLevel, Render, Size, Styled, Subscription, Task, View, ViewContext, VisualContext, + WeakView, WindowBounds, WindowContext, WindowHandle, WindowOptions, }; use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, ProjectItem}; use itertools::Itertools; @@ -125,36 +125,50 @@ pub struct OpenPaths { pub paths: Vec, } -#[derive(Clone, Deserialize, PartialEq, Action)] +#[derive(Clone, Deserialize, PartialEq)] pub struct ActivatePane(pub usize); -#[derive(Clone, Deserialize, PartialEq, Action)] +#[derive(Clone, Deserialize, PartialEq)] pub struct ActivatePaneInDirection(pub SplitDirection); -#[derive(Clone, Deserialize, PartialEq, Action)] +#[derive(Clone, Deserialize, PartialEq)] pub struct SwapPaneInDirection(pub SplitDirection); -#[derive(Clone, Deserialize, PartialEq, Action)] +#[derive(Clone, Deserialize, PartialEq)] pub struct NewFileInDirection(pub SplitDirection); -#[derive(Clone, PartialEq, Debug, Deserialize, Action)] +#[derive(Clone, PartialEq, Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct SaveAll { pub save_intent: Option, } -#[derive(Clone, PartialEq, Debug, Deserialize, Action)] +#[derive(Clone, PartialEq, Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Save { pub save_intent: Option, } -#[derive(Clone, PartialEq, Debug, Deserialize, Default, Action)] +#[derive(Clone, PartialEq, Debug, Deserialize, Default)] #[serde(rename_all = "camelCase")] pub struct CloseAllItemsAndPanes { pub save_intent: Option, } +impl_actions!( + workspace, + [ + ActivatePane, + ActivatePaneInDirection, + CloseAllItemsAndPanes, + NewFileInDirection, + OpenTerminal, + Save, + SaveAll, + SwapPaneInDirection, + ] +); + #[derive(Deserialize)] pub struct Toast { id: usize, @@ -200,7 +214,7 @@ impl Clone for Toast { } } -#[derive(Debug, Default, Clone, Deserialize, PartialEq, Action)] +#[derive(Debug, Default, Clone, Deserialize, PartialEq)] pub struct OpenTerminal { pub working_directory: PathBuf, } diff --git a/crates/zed_actions2/src/lib.rs b/crates/zed_actions2/src/lib.rs index 456d1f5973ba5ef628fa8e969e6696d647596776..91a935c1f2da257e856887a239087ce6cb571ddd 100644 --- a/crates/zed_actions2/src/lib.rs +++ b/crates/zed_actions2/src/lib.rs @@ -1,4 +1,4 @@ -use gpui::Action; +use gpui::impl_actions; use serde::Deserialize; // If the zed binary doesn't use anything in this crate, it will be optimized away @@ -10,12 +10,14 @@ use serde::Deserialize; // https://github.com/mmastrac/rust-ctor/issues/280 pub fn init() {} -#[derive(Clone, PartialEq, Deserialize, Action)] +#[derive(Clone, PartialEq, Deserialize)] pub struct OpenBrowser { pub url: String, } -#[derive(Clone, PartialEq, Deserialize, Action)] +#[derive(Clone, PartialEq, Deserialize)] pub struct OpenZedURL { pub url: String, } + +impl_actions!(zed, [OpenBrowser, OpenZedURL]);