From 5242a3a6dcf1faf93dbcfc85406a15a906f017e2 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 7 Apr 2022 16:20:49 -0700 Subject: [PATCH] Restructure action macro to assign a namespace to every action Also, allow arbitrary types to be used as Actions via the impl_actions macro Co-authored-by: Nathan Sobo Co-authored-by: Keith Simmons --- crates/chat_panel/src/chat_panel.rs | 5 +- crates/client/src/client.rs | 4 +- crates/diagnostics/src/diagnostics.rs | 4 +- crates/editor/src/editor.rs | 203 +++++++++++------- crates/file_finder/src/file_finder.rs | 10 +- crates/go_to_line/src/go_to_line.rs | 5 +- crates/gpui/src/app.rs | 112 ++-------- crates/gpui/src/app/action.rs | 56 +++++ crates/gpui/src/keymap.rs | 16 +- crates/gpui/src/platform.rs | 4 +- crates/gpui/src/platform/mac/platform.rs | 8 +- crates/gpui/src/platform/test.rs | 4 +- crates/gpui/src/presenter.rs | 4 +- crates/gpui/src/views/select.rs | 11 +- crates/journal/src/journal.rs | 4 +- crates/outline/src/outline.rs | 4 +- crates/project_panel/src/project_panel.rs | 15 +- crates/project_symbols/src/project_symbols.rs | 4 +- crates/search/src/buffer_search.rs | 14 +- crates/search/src/project_search.rs | 7 +- crates/search/src/search.rs | 11 +- crates/server/src/rpc.rs | 26 ++- crates/theme_selector/src/theme_selector.rs | 13 +- crates/vim/src/insert.rs | 7 +- crates/vim/src/normal.rs | 45 ++-- crates/vim/src/normal/g_prefix.rs | 7 +- crates/vim/src/vim.rs | 7 +- crates/workspace/src/lsp_status.rs | 8 +- crates/workspace/src/menu.rs | 11 +- crates/workspace/src/pane.rs | 38 +++- crates/workspace/src/sidebar.rs | 11 +- crates/workspace/src/workspace.rs | 47 ++-- crates/zed/src/zed.rs | 13 +- 33 files changed, 432 insertions(+), 306 deletions(-) create mode 100644 crates/gpui/src/app/action.rs diff --git a/crates/chat_panel/src/chat_panel.rs b/crates/chat_panel/src/chat_panel.rs index 9d575768a6..3e432f98c1 100644 --- a/crates/chat_panel/src/chat_panel.rs +++ b/crates/chat_panel/src/chat_panel.rs @@ -4,7 +4,7 @@ use client::{ }; use editor::Editor; use gpui::{ - action, + actions, elements::*, keymap::Binding, platform::CursorStyle, @@ -33,8 +33,7 @@ pub struct ChatPanel { pub enum Event {} -action!(Send); -action!(LoadMoreMessages); +actions!(chat_panel, [Send, LoadMoreMessages]); pub fn init(cx: &mut MutableAppContext) { cx.add_action(ChatPanel::send); diff --git a/crates/client/src/client.rs b/crates/client/src/client.rs index 1bae6cd49e..2a563914c9 100644 --- a/crates/client/src/client.rs +++ b/crates/client/src/client.rs @@ -13,7 +13,7 @@ use async_tungstenite::tungstenite::{ }; use futures::{future::LocalBoxFuture, FutureExt, StreamExt}; use gpui::{ - action, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AnyWeakViewHandle, AsyncAppContext, + actions, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AnyWeakViewHandle, AsyncAppContext, Entity, ModelContext, ModelHandle, MutableAppContext, Task, View, ViewContext, ViewHandle, }; use http::HttpClient; @@ -50,7 +50,7 @@ lazy_static! { .and_then(|s| if s.is_empty() { None } else { Some(s) }); } -action!(Authenticate); +actions!(client, [Authenticate]); pub fn init(rpc: Arc, cx: &mut MutableAppContext) { cx.add_global_action(move |_: &Authenticate, cx| { diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index 55a41a4468..ba5a518673 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -8,7 +8,7 @@ use editor::{ highlight_diagnostic_message, Editor, ExcerptId, MultiBuffer, ToOffset, }; use gpui::{ - action, elements::*, fonts::TextStyle, keymap::Binding, AnyViewHandle, AppContext, Entity, + actions, elements::*, fonts::TextStyle, keymap::Binding, AnyViewHandle, AppContext, Entity, ModelHandle, MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle, WeakViewHandle, }; @@ -28,7 +28,7 @@ use std::{ use util::TryFutureExt; use workspace::{ItemHandle as _, ItemNavHistory, Workspace}; -action!(Deploy); +actions!(diagnostics, [Deploy]); const CONTEXT_LINE_COUNT: u32 = 1; diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 030fcb5d83..e201f5f366 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -16,12 +16,13 @@ use display_map::*; pub use element::*; use fuzzy::{StringMatch, StringMatchCandidate}; use gpui::{ - action, + actions, color::Color, elements::*, executor, fonts::{self, HighlightStyle, TextStyle}, geometry::vector::{vec2f, Vector2F}, + impl_actions, keymap::Binding, platform::CursorStyle, text_layout, AppContext, AsyncAppContext, ClipboardItem, Element, ElementBox, Entity, @@ -65,84 +66,128 @@ const MAX_LINE_LEN: usize = 1024; const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10; const MAX_SELECTION_HISTORY_LEN: usize = 1024; -action!(Cancel); -action!(Backspace); -action!(Delete); -action!(Input, String); -action!(Newline); -action!(Tab, Direction); -action!(Indent); -action!(Outdent); -action!(DeleteLine); -action!(DeleteToPreviousWordStart); -action!(DeleteToPreviousSubwordStart); -action!(DeleteToNextWordEnd); -action!(DeleteToNextSubwordEnd); -action!(DeleteToBeginningOfLine); -action!(DeleteToEndOfLine); -action!(CutToEndOfLine); -action!(DuplicateLine); -action!(MoveLineUp); -action!(MoveLineDown); -action!(Cut); -action!(Copy); -action!(Paste); -action!(Undo); -action!(Redo); -action!(MoveUp); -action!(MoveDown); -action!(MoveLeft); -action!(MoveRight); -action!(MoveToPreviousWordStart); -action!(MoveToPreviousSubwordStart); -action!(MoveToNextWordEnd); -action!(MoveToNextSubwordEnd); -action!(MoveToBeginningOfLine); -action!(MoveToEndOfLine); -action!(MoveToBeginning); -action!(MoveToEnd); -action!(SelectUp); -action!(SelectDown); -action!(SelectLeft); -action!(SelectRight); -action!(SelectToPreviousWordStart); -action!(SelectToPreviousSubwordStart); -action!(SelectToNextWordEnd); -action!(SelectToNextSubwordEnd); -action!(SelectToBeginningOfLine, bool); -action!(SelectToEndOfLine, bool); -action!(SelectToBeginning); -action!(SelectToEnd); -action!(SelectAll); -action!(SelectLine); -action!(SplitSelectionIntoLines); -action!(AddSelectionAbove); -action!(AddSelectionBelow); -action!(SelectNext, bool); -action!(ToggleComments); -action!(SelectLargerSyntaxNode); -action!(SelectSmallerSyntaxNode); -action!(MoveToEnclosingBracket); -action!(UndoSelection); -action!(RedoSelection); -action!(GoToDiagnostic, Direction); -action!(GoToDefinition); -action!(FindAllReferences); -action!(Rename); -action!(ConfirmRename); -action!(PageUp); -action!(PageDown); -action!(Fold); -action!(UnfoldLines); -action!(FoldSelectedRanges); -action!(Scroll, Vector2F); -action!(Select, SelectPhase); -action!(ShowCompletions); -action!(ToggleCodeActions, bool); -action!(ConfirmCompletion, Option); -action!(ConfirmCodeAction, Option); -action!(OpenExcerpts); -action!(RestartLanguageServer); +#[derive(Clone)] +pub struct SelectNext(pub bool); + +#[derive(Clone)] +pub struct GoToDiagnostic(pub Direction); + +#[derive(Clone)] +pub struct Scroll(pub Vector2F); + +#[derive(Clone)] +pub struct Select(pub SelectPhase); + +#[derive(Clone)] +pub struct Input(pub String); + +#[derive(Clone)] +pub struct Tab(pub Direction); + +#[derive(Clone)] +pub struct SelectToBeginningOfLine(pub bool); + +#[derive(Clone)] +pub struct SelectToEndOfLine(pub bool); + +#[derive(Clone)] +pub struct ToggleCodeActions(pub bool); + +#[derive(Clone)] +pub struct ConfirmCompletion(pub Option); + +#[derive(Clone)] +pub struct ConfirmCodeAction(pub Option); + +impl_actions!( + editor, + [ + SelectNext, + GoToDiagnostic, + Scroll, + Select, + Input, + Tab, + SelectToBeginningOfLine, + SelectToEndOfLine, + ToggleCodeActions, + ConfirmCompletion, + ConfirmCodeAction, + ] +); + +actions!( + editor, + [ + Cancel, + Backspace, + Delete, + Newline, + Indent, + Outdent, + DeleteLine, + DeleteToPreviousWordStart, + DeleteToPreviousSubwordStart, + DeleteToNextWordEnd, + DeleteToNextSubwordEnd, + DeleteToBeginningOfLine, + DeleteToEndOfLine, + CutToEndOfLine, + DuplicateLine, + MoveLineUp, + MoveLineDown, + Cut, + Copy, + Paste, + Undo, + Redo, + MoveUp, + MoveDown, + MoveLeft, + MoveRight, + MoveToPreviousWordStart, + MoveToPreviousSubwordStart, + MoveToNextWordEnd, + MoveToNextSubwordEnd, + MoveToBeginningOfLine, + MoveToEndOfLine, + MoveToBeginning, + MoveToEnd, + SelectUp, + SelectDown, + SelectLeft, + SelectRight, + SelectToPreviousWordStart, + SelectToPreviousSubwordStart, + SelectToNextWordEnd, + SelectToNextSubwordEnd, + SelectToBeginning, + SelectToEnd, + SelectAll, + SelectLine, + SplitSelectionIntoLines, + AddSelectionAbove, + AddSelectionBelow, + ToggleComments, + SelectLargerSyntaxNode, + SelectSmallerSyntaxNode, + MoveToEnclosingBracket, + UndoSelection, + RedoSelection, + GoToDefinition, + FindAllReferences, + Rename, + ConfirmRename, + PageUp, + PageDown, + Fold, + UnfoldLines, + FoldSelectedRanges, + ShowCompletions, + OpenExcerpts, + RestartLanguageServer, + ] +); enum DocumentHighlightRead {} enum DocumentHighlightWrite {} diff --git a/crates/file_finder/src/file_finder.rs b/crates/file_finder/src/file_finder.rs index 7c4bfbd93d..af9fd910b5 100644 --- a/crates/file_finder/src/file_finder.rs +++ b/crates/file_finder/src/file_finder.rs @@ -1,8 +1,9 @@ use editor::Editor; use fuzzy::PathMatch; use gpui::{ - action, + actions, elements::*, + impl_actions, keymap::{self, Binding}, AppContext, Axis, Entity, ModelHandle, MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle, WeakViewHandle, @@ -37,8 +38,11 @@ pub struct FileFinder { list_state: UniformListState, } -action!(Toggle); -action!(Select, ProjectPath); +#[derive(Clone)] +pub struct Select(pub ProjectPath); + +impl_actions!(file_finder, [Select]); +actions!(file_finder, [Toggle]); pub fn init(cx: &mut MutableAppContext) { cx.add_action(FileFinder::toggle); diff --git a/crates/go_to_line/src/go_to_line.rs b/crates/go_to_line/src/go_to_line.rs index 19b43d5721..9995736550 100644 --- a/crates/go_to_line/src/go_to_line.rs +++ b/crates/go_to_line/src/go_to_line.rs @@ -1,14 +1,13 @@ use editor::{display_map::ToDisplayPoint, Autoscroll, DisplayPoint, Editor}; use gpui::{ - action, elements::*, geometry::vector::Vector2F, keymap::Binding, Axis, Entity, + actions, elements::*, geometry::vector::Vector2F, keymap::Binding, Axis, Entity, MutableAppContext, RenderContext, View, ViewContext, ViewHandle, }; use settings::Settings; use text::{Bias, Point}; use workspace::Workspace; -action!(Toggle); -action!(Confirm); +actions!(go_to_line, [Toggle, Confirm]); pub fn init(cx: &mut MutableAppContext) { cx.add_bindings([ diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index dcdd325eae..3fc5652791 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -1,3 +1,5 @@ +pub mod action; + use crate::{ elements::ElementBox, executor::{self, Task}, @@ -7,6 +9,7 @@ use crate::{ util::post_inc, AssetCache, AssetSource, ClipboardItem, FontCache, PathPromptOptions, TextLayoutCache, }; +pub use action::*; use anyhow::{anyhow, Result}; use collections::btree_map; use keymap::MatchResult; @@ -142,89 +145,6 @@ pub trait ElementStateContext: DerefMut { } } -pub trait Action: 'static + AnyAction { - type Argument: 'static + Clone; -} - -pub trait AnyAction { - fn id(&self) -> TypeId; - fn name(&self) -> &'static str; - fn as_any(&self) -> &dyn Any; - fn boxed_clone(&self) -> Box; - fn boxed_clone_as_any(&self) -> Box; -} - -#[macro_export] -macro_rules! action { - ($name:ident, $arg:ty) => { - #[derive(Clone)] - pub struct $name(pub $arg); - - impl $crate::Action for $name { - type Argument = $arg; - } - - impl $crate::AnyAction for $name { - fn id(&self) -> std::any::TypeId { - std::any::TypeId::of::<$name>() - } - - fn name(&self) -> &'static str { - stringify!($name) - } - - fn as_any(&self) -> &dyn std::any::Any { - self - } - - fn boxed_clone(&self) -> Box { - Box::new(self.clone()) - } - - fn boxed_clone_as_any(&self) -> Box { - Box::new(self.clone()) - } - } - - impl From<$arg> for $name { - fn from(arg: $arg) -> Self { - Self(arg) - } - } - }; - - ($name:ident) => { - #[derive(Clone, Debug, Eq, PartialEq)] - pub struct $name; - - impl $crate::Action for $name { - type Argument = (); - } - - impl $crate::AnyAction for $name { - fn id(&self) -> std::any::TypeId { - std::any::TypeId::of::<$name>() - } - - fn name(&self) -> &'static str { - stringify!($name) - } - - fn as_any(&self) -> &dyn std::any::Any { - self - } - - fn boxed_clone(&self) -> Box { - Box::new(self.clone()) - } - - fn boxed_clone_as_any(&self) -> Box { - Box::new(self.clone()) - } - } - }; -} - pub struct Menu<'a> { pub name: &'a str, pub items: Vec>, @@ -234,7 +154,7 @@ pub enum MenuItem<'a> { Action { name: &'a str, keystroke: Option<&'a str>, - action: Box, + action: Box, }, Separator, } @@ -787,8 +707,8 @@ impl ReadViewWith for TestAppContext { } type ActionCallback = - dyn FnMut(&mut dyn AnyView, &dyn AnyAction, &mut MutableAppContext, usize, usize); -type GlobalActionCallback = dyn FnMut(&dyn AnyAction, &mut MutableAppContext); + dyn FnMut(&mut dyn AnyView, &dyn Action, &mut MutableAppContext, usize, usize); +type GlobalActionCallback = dyn FnMut(&dyn Action, &mut MutableAppContext); type SubscriptionCallback = Box bool>; type GlobalSubscriptionCallback = Box; @@ -963,7 +883,7 @@ impl MutableAppContext { { let handler = Box::new( move |view: &mut dyn AnyView, - action: &dyn AnyAction, + action: &dyn Action, cx: &mut MutableAppContext, window_id: usize, view_id: usize| { @@ -1009,7 +929,7 @@ impl MutableAppContext { A: Action, F: 'static + FnMut(&A, &mut MutableAppContext), { - let handler = Box::new(move |action: &dyn AnyAction, cx: &mut MutableAppContext| { + let handler = Box::new(move |action: &dyn Action, cx: &mut MutableAppContext| { let action = action.as_any().downcast_ref().unwrap(); handler(action, cx); }); @@ -1338,7 +1258,7 @@ impl MutableAppContext { &mut self, window_id: usize, path: &[usize], - action: &dyn AnyAction, + action: &dyn Action, ) -> bool { self.update(|this| { this.halt_action_dispatch = false; @@ -1398,7 +1318,7 @@ impl MutableAppContext { self.dispatch_global_action_any(&action); } - fn dispatch_global_action_any(&mut self, action: &dyn AnyAction) -> bool { + fn dispatch_global_action_any(&mut self, action: &dyn Action) -> bool { self.update(|this| { if let Some((name, mut handler)) = this.global_actions.remove_entry(&action.id()) { handler(action, this); @@ -4655,7 +4575,7 @@ impl RefCounts { #[cfg(test)] mod tests { use super::*; - use crate::elements::*; + use crate::{elements::*, impl_actions}; use smol::future::poll_once; use std::{ cell::Cell, @@ -5801,7 +5721,10 @@ mod tests { } } - action!(Action, &'static str); + #[derive(Clone)] + pub struct Action(pub &'static str); + + impl_actions!(test, [Action]); let actions = Rc::new(RefCell::new(Vec::new())); @@ -5909,7 +5832,10 @@ mod tests { #[crate::test(self)] fn test_dispatch_keystroke(cx: &mut MutableAppContext) { - action!(Action, &'static str); + #[derive(Clone)] + pub struct Action(pub &'static str); + + impl_actions!(test, [Action]); struct View { id: usize, diff --git a/crates/gpui/src/app/action.rs b/crates/gpui/src/app/action.rs new file mode 100644 index 0000000000..79606feee7 --- /dev/null +++ b/crates/gpui/src/app/action.rs @@ -0,0 +1,56 @@ +use std::any::{Any, TypeId}; + +pub trait Action: 'static { + fn id(&self) -> TypeId; + fn namespace(&self) -> &'static str; + fn name(&self) -> &'static str; + fn as_any(&self) -> &dyn Any; + fn boxed_clone(&self) -> Box; + fn boxed_clone_as_any(&self) -> Box; +} + +#[macro_export] +macro_rules! impl_actions { + ($namespace:path, [ $($name:ident),* $(,)? ]) => { + $( + impl $crate::action::Action for $name { + fn id(&self) -> std::any::TypeId { + std::any::TypeId::of::<$name>() + } + + fn namespace(&self) -> &'static str { + stringify!($namespace) + } + + fn name(&self) -> &'static str { + stringify!($name) + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn boxed_clone(&self) -> Box { + Box::new(self.clone()) + } + + fn boxed_clone_as_any(&self) -> Box { + Box::new(self.clone()) + } + } + )* + }; +} + +#[macro_export] +macro_rules! actions { + ($namespace:path, [ $($name:ident),* $(,)? ]) => { + + $( + #[derive(Clone, Debug, Default, PartialEq, Eq)] + pub struct $name; + )* + + $crate::impl_actions!($namespace, [ $($name),* ]); + }; +} diff --git a/crates/gpui/src/keymap.rs b/crates/gpui/src/keymap.rs index 37223d77d1..f286265964 100644 --- a/crates/gpui/src/keymap.rs +++ b/crates/gpui/src/keymap.rs @@ -1,3 +1,4 @@ +use crate::Action; use anyhow::anyhow; use std::{ any::Any, @@ -6,8 +7,6 @@ use std::{ }; use tree_sitter::{Language, Node, Parser}; -use crate::{Action, AnyAction}; - extern "C" { fn tree_sitter_context_predicate() -> Language; } @@ -28,7 +27,7 @@ pub struct Keymap(Vec); pub struct Binding { keystrokes: Vec, - action: Box, + action: Box, context: Option, } @@ -73,7 +72,7 @@ where pub enum MatchResult { None, Pending, - Action(Box), + Action(Box), } impl Debug for MatchResult { @@ -329,7 +328,7 @@ impl ContextPredicate { #[cfg(test)] mod tests { - use crate::action; + use crate::{actions, impl_actions}; use super::*; @@ -420,9 +419,10 @@ mod tests { #[test] fn test_matcher() -> anyhow::Result<()> { - action!(A, &'static str); - action!(B); - action!(Ab); + #[derive(Clone)] + pub struct A(pub &'static str); + impl_actions!(test, [A]); + actions!(test, [B, Ab]); impl PartialEq for A { fn eq(&self, other: &Self) -> bool { diff --git a/crates/gpui/src/platform.rs b/crates/gpui/src/platform.rs index 66bd44b26f..6afdfb4637 100644 --- a/crates/gpui/src/platform.rs +++ b/crates/gpui/src/platform.rs @@ -15,7 +15,7 @@ use crate::{ vector::Vector2F, }, text_layout::{LineLayout, RunStyle}, - AnyAction, ClipboardItem, Menu, Scene, + Action, ClipboardItem, Menu, Scene, }; use anyhow::Result; use async_task::Runnable; @@ -66,7 +66,7 @@ pub(crate) trait ForegroundPlatform { fn on_open_files(&self, callback: Box)>); fn run(&self, on_finish_launching: Box ()>); - fn on_menu_command(&self, callback: Box); + fn on_menu_command(&self, callback: Box); fn set_menus(&self, menus: Vec); fn prompt_for_paths( &self, diff --git a/crates/gpui/src/platform/mac/platform.rs b/crates/gpui/src/platform/mac/platform.rs index 0b612c978c..d8969e7957 100644 --- a/crates/gpui/src/platform/mac/platform.rs +++ b/crates/gpui/src/platform/mac/platform.rs @@ -3,7 +3,7 @@ use crate::{ executor, keymap::Keystroke, platform::{self, CursorStyle}, - AnyAction, ClipboardItem, Event, Menu, MenuItem, + Action, ClipboardItem, Event, Menu, MenuItem, }; use anyhow::{anyhow, Result}; use block::ConcreteBlock; @@ -107,10 +107,10 @@ pub struct MacForegroundPlatformState { resign_active: Option>, quit: Option>, event: Option bool>>, - menu_command: Option>, + menu_command: Option>, open_files: Option)>>, finish_launching: Option ()>>, - menu_actions: Vec>, + menu_actions: Vec>, } impl MacForegroundPlatform { @@ -235,7 +235,7 @@ impl platform::ForegroundPlatform for MacForegroundPlatform { } } - fn on_menu_command(&self, callback: Box) { + fn on_menu_command(&self, callback: Box) { self.0.borrow_mut().menu_command = Some(callback); } diff --git a/crates/gpui/src/platform/test.rs b/crates/gpui/src/platform/test.rs index 706439a955..a18f52a4f6 100644 --- a/crates/gpui/src/platform/test.rs +++ b/crates/gpui/src/platform/test.rs @@ -1,7 +1,7 @@ use super::{CursorStyle, WindowBounds}; use crate::{ geometry::vector::{vec2f, Vector2F}, - AnyAction, ClipboardItem, + Action, ClipboardItem, }; use anyhow::{anyhow, Result}; use parking_lot::Mutex; @@ -72,7 +72,7 @@ impl super::ForegroundPlatform for ForegroundPlatform { unimplemented!() } - fn on_menu_command(&self, _: Box) {} + fn on_menu_command(&self, _: Box) {} fn set_menus(&self, _: Vec) {} diff --git a/crates/gpui/src/presenter.rs b/crates/gpui/src/presenter.rs index 8546bed00f..ee840bd1e7 100644 --- a/crates/gpui/src/presenter.rs +++ b/crates/gpui/src/presenter.rs @@ -6,7 +6,7 @@ use crate::{ json::{self, ToJson}, platform::Event, text_layout::TextLayoutCache, - Action, AnyAction, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AssetCache, ElementBox, + Action, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AssetCache, ElementBox, ElementStateContext, Entity, FontSystem, ModelHandle, ReadModel, ReadView, Scene, UpgradeModelHandle, UpgradeViewHandle, View, ViewHandle, WeakModelHandle, WeakViewHandle, }; @@ -223,7 +223,7 @@ impl Presenter { pub struct DispatchDirective { pub path: Vec, - pub action: Box, + pub action: Box, } pub struct LayoutContext<'a> { diff --git a/crates/gpui/src/views/select.rs b/crates/gpui/src/views/select.rs index 944f45f0d4..14b098c472 100644 --- a/crates/gpui/src/views/select.rs +++ b/crates/gpui/src/views/select.rs @@ -1,6 +1,6 @@ use crate::{ - action, elements::*, AppContext, Entity, MutableAppContext, RenderContext, View, ViewContext, - WeakViewHandle, + actions, elements::*, impl_actions, AppContext, Entity, MutableAppContext, RenderContext, View, + ViewContext, WeakViewHandle, }; pub struct Select { @@ -25,8 +25,11 @@ pub enum ItemType { Unselected, } -action!(ToggleSelect); -action!(SelectItem, usize); +#[derive(Clone)] +pub struct SelectItem(pub usize); + +actions!(select, [ToggleSelect]); +impl_actions!(select, [SelectItem]); pub enum Event {} diff --git a/crates/journal/src/journal.rs b/crates/journal/src/journal.rs index 460423f6dc..de9945d10e 100644 --- a/crates/journal/src/journal.rs +++ b/crates/journal/src/journal.rs @@ -1,11 +1,11 @@ use chrono::{Datelike, Local, Timelike}; use editor::{Autoscroll, Editor}; -use gpui::{action, keymap::Binding, MutableAppContext}; +use gpui::{actions, keymap::Binding, MutableAppContext}; use std::{fs::OpenOptions, sync::Arc}; use util::TryFutureExt as _; use workspace::AppState; -action!(NewJournalEntry); +actions!(journal, [NewJournalEntry]); pub fn init(app_state: Arc, cx: &mut MutableAppContext) { cx.add_bindings(vec![Binding::new("ctrl-alt-cmd-j", NewJournalEntry, None)]); diff --git a/crates/outline/src/outline.rs b/crates/outline/src/outline.rs index af22b87ee6..5386657ef2 100644 --- a/crates/outline/src/outline.rs +++ b/crates/outline/src/outline.rs @@ -4,7 +4,7 @@ use editor::{ }; use fuzzy::StringMatch; use gpui::{ - action, + actions, elements::*, geometry::vector::Vector2F, keymap::{self, Binding}, @@ -20,7 +20,7 @@ use workspace::{ Workspace, }; -action!(Toggle); +actions!(outline, [Toggle]); pub fn init(cx: &mut MutableAppContext) { cx.add_bindings([ diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 6ae81fcb5e..3534fa186f 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -1,9 +1,10 @@ use gpui::{ - action, + actions, elements::{ Align, ConstrainedBox, Empty, Flex, Label, MouseEventHandler, ParentElement, ScrollTarget, Svg, UniformList, UniformListState, }, + impl_actions, keymap::{self, Binding}, platform::CursorStyle, AppContext, Element, ElementBox, Entity, ModelHandle, MutableAppContext, View, ViewContext, @@ -46,10 +47,14 @@ struct EntryDetails { is_selected: bool, } -action!(ExpandSelectedEntry); -action!(CollapseSelectedEntry); -action!(ToggleExpanded, ProjectEntryId); -action!(Open, ProjectEntryId); +#[derive(Clone)] +pub struct ToggleExpanded(pub ProjectEntryId); + +#[derive(Clone)] +pub struct Open(pub ProjectEntryId); + +actions!(project_panel, [ExpandSelectedEntry, CollapseSelectedEntry]); +impl_actions!(project_panel, [Open, ToggleExpanded]); pub fn init(cx: &mut MutableAppContext) { cx.add_action(ProjectPanel::expand_selected_entry); diff --git a/crates/project_symbols/src/project_symbols.rs b/crates/project_symbols/src/project_symbols.rs index f707aa30f7..689f579b81 100644 --- a/crates/project_symbols/src/project_symbols.rs +++ b/crates/project_symbols/src/project_symbols.rs @@ -3,7 +3,7 @@ use editor::{ }; use fuzzy::{StringMatch, StringMatchCandidate}; use gpui::{ - action, + actions, elements::*, keymap::{self, Binding}, AppContext, Axis, Entity, ModelHandle, MutableAppContext, RenderContext, Task, View, @@ -22,7 +22,7 @@ use workspace::{ Workspace, }; -action!(Toggle); +actions!(project_symbols, [Toggle]); pub fn init(cx: &mut MutableAppContext) { cx.add_bindings([ diff --git a/crates/search/src/buffer_search.rs b/crates/search/src/buffer_search.rs index c87a3a2391..ffaf8e368d 100644 --- a/crates/search/src/buffer_search.rs +++ b/crates/search/src/buffer_search.rs @@ -2,7 +2,7 @@ use crate::{active_match_index, match_index_for_direction, Direction, SearchOpti use collections::HashMap; use editor::{display_map::ToDisplayPoint, Anchor, Autoscroll, Bias, Editor}; use gpui::{ - action, elements::*, keymap::Binding, platform::CursorStyle, AppContext, Entity, + actions, elements::*, impl_actions, keymap::Binding, platform::CursorStyle, AppContext, Entity, MutableAppContext, RenderContext, Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle, }; @@ -12,10 +12,14 @@ use settings::Settings; use std::ops::Range; use workspace::{ItemHandle, Pane, ToolbarItemLocation, ToolbarItemView}; -action!(Deploy, bool); -action!(Dismiss); -action!(FocusEditor); -action!(ToggleSearchOption, SearchOption); +#[derive(Clone)] +pub struct Deploy(pub bool); + +#[derive(Clone)] +pub struct ToggleSearchOption(pub SearchOption); + +actions!(buffer_search, [Dismiss, FocusEditor]); +impl_actions!(buffer_search, [Deploy, ToggleSearchOption]); pub enum Event { UpdateLocation, diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index 9009dfee79..f96e3c84d1 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -5,7 +5,7 @@ use crate::{ use collections::HashMap; use editor::{Anchor, Autoscroll, Editor, MultiBuffer, SelectAll}; use gpui::{ - action, elements::*, keymap::Binding, platform::CursorStyle, AppContext, ElementBox, Entity, + actions, elements::*, keymap::Binding, platform::CursorStyle, AppContext, ElementBox, Entity, ModelContext, ModelHandle, MutableAppContext, RenderContext, Subscription, Task, View, ViewContext, ViewHandle, WeakModelHandle, WeakViewHandle, }; @@ -19,10 +19,7 @@ use std::{ use util::ResultExt as _; use workspace::{Item, ItemNavHistory, Pane, ToolbarItemLocation, ToolbarItemView, Workspace}; -action!(Deploy); -action!(Search); -action!(SearchInNew); -action!(ToggleFocus); +actions!(project_search, [Deploy, Search, SearchInNew, ToggleFocus]); const MAX_TAB_TITLE_LEN: usize = 24; diff --git a/crates/search/src/search.rs b/crates/search/src/search.rs index 38d3a5fce8..83e5a259d2 100644 --- a/crates/search/src/search.rs +++ b/crates/search/src/search.rs @@ -1,6 +1,6 @@ pub use buffer_search::BufferSearchBar; use editor::{Anchor, MultiBufferSnapshot}; -use gpui::{action, MutableAppContext}; +use gpui::{impl_actions, MutableAppContext}; pub use project_search::{ProjectSearchBar, ProjectSearchView}; use std::{ cmp::{self, Ordering}, @@ -15,8 +15,13 @@ pub fn init(cx: &mut MutableAppContext) { project_search::init(cx); } -action!(ToggleSearchOption, SearchOption); -action!(SelectMatch, Direction); +#[derive(Clone)] +pub struct ToggleSearchOption(pub SearchOption); + +#[derive(Clone)] +pub struct SelectMatch(pub Direction); + +impl_actions!(search, [ToggleSearchOption, SelectMatch]); #[derive(Clone, Copy)] pub enum SearchOption { diff --git a/crates/server/src/rpc.rs b/crates/server/src/rpc.rs index 51c7807660..a8cb863935 100644 --- a/crates/server/src/rpc.rs +++ b/crates/server/src/rpc.rs @@ -1118,7 +1118,7 @@ mod tests { }, time::Duration, }; - use workspace::{Item, SplitDirection, Workspace, WorkspaceParams}; + use workspace::{Item, SplitDirection, ToggleFollow, Workspace, WorkspaceParams}; #[cfg(test)] #[ctor::ctor] @@ -4527,7 +4527,9 @@ mod tests { editor_a2.update(cx_a, |editor, cx| editor.select_ranges([2..3], None, cx)); workspace_b .update(cx_b, |workspace, cx| { - workspace.toggle_follow(&client_a_id.into(), cx).unwrap() + workspace + .toggle_follow(&ToggleFollow(client_a_id), cx) + .unwrap() }) .await .unwrap(); @@ -4627,7 +4629,9 @@ mod tests { // Client A starts following client B. workspace_a .update(cx_a, |workspace, cx| { - workspace.toggle_follow(&client_b_id.into(), cx).unwrap() + workspace + .toggle_follow(&ToggleFollow(client_b_id), cx) + .unwrap() }) .await .unwrap(); @@ -4856,7 +4860,9 @@ mod tests { }); workspace_b .update(cx_b, |workspace, cx| { - workspace.toggle_follow(&leader_id.into(), cx).unwrap() + workspace + .toggle_follow(&ToggleFollow(leader_id), cx) + .unwrap() }) .await .unwrap(); @@ -4881,7 +4887,9 @@ mod tests { workspace_b .update(cx_b, |workspace, cx| { - workspace.toggle_follow(&leader_id.into(), cx).unwrap() + workspace + .toggle_follow(&ToggleFollow(leader_id), cx) + .unwrap() }) .await .unwrap(); @@ -4899,7 +4907,9 @@ mod tests { workspace_b .update(cx_b, |workspace, cx| { - workspace.toggle_follow(&leader_id.into(), cx).unwrap() + workspace + .toggle_follow(&ToggleFollow(leader_id), cx) + .unwrap() }) .await .unwrap(); @@ -4919,7 +4929,9 @@ mod tests { workspace_b .update(cx_b, |workspace, cx| { - workspace.toggle_follow(&leader_id.into(), cx).unwrap() + workspace + .toggle_follow(&ToggleFollow(leader_id), cx) + .unwrap() }) .await .unwrap(); diff --git a/crates/theme_selector/src/theme_selector.rs b/crates/theme_selector/src/theme_selector.rs index 5bcbd62e09..b69552d02b 100644 --- a/crates/theme_selector/src/theme_selector.rs +++ b/crates/theme_selector/src/theme_selector.rs @@ -1,15 +1,15 @@ use editor::Editor; use fuzzy::{match_strings, StringMatch, StringMatchCandidate}; use gpui::{ - action, elements::*, + impl_actions, keymap::{self, Binding}, AppContext, Axis, Element, ElementBox, Entity, MutableAppContext, RenderContext, View, ViewContext, ViewHandle, }; +use settings::Settings; use std::{cmp, sync::Arc}; use theme::{Theme, ThemeRegistry}; -use settings::Settings; use workspace::{ menu::{Confirm, SelectNext, SelectPrev}, Workspace, @@ -25,8 +25,13 @@ pub struct ThemeSelector { selection_completed: bool, } -action!(Toggle, Arc); -action!(Reload, Arc); +#[derive(Clone)] +pub struct Toggle(pub Arc); + +#[derive(Clone)] +pub struct Reload(pub Arc); + +impl_actions!(theme_selector, [Toggle, Reload]); pub fn init(themes: Arc, cx: &mut MutableAppContext) { cx.add_action(ThemeSelector::confirm); diff --git a/crates/vim/src/insert.rs b/crates/vim/src/insert.rs index 9c1e36a90e..749ae7c5d3 100644 --- a/crates/vim/src/insert.rs +++ b/crates/vim/src/insert.rs @@ -1,11 +1,10 @@ +use crate::{mode::Mode, SwitchMode, VimState}; use editor::Bias; -use gpui::{action, keymap::Binding, MutableAppContext, ViewContext}; +use gpui::{actions, keymap::Binding, MutableAppContext, ViewContext}; use language::SelectionGoal; use workspace::Workspace; -use crate::{mode::Mode, SwitchMode, VimState}; - -action!(NormalBefore); +actions!(vim, [NormalBefore]); pub fn init(cx: &mut MutableAppContext) { let context = Some("Editor && vim_mode == insert"); diff --git a/crates/vim/src/normal.rs b/crates/vim/src/normal.rs index 5bf1a3c417..ce5305e8bf 100644 --- a/crates/vim/src/normal.rs +++ b/crates/vim/src/normal.rs @@ -1,23 +1,42 @@ mod g_prefix; +use crate::{mode::NormalState, Mode, SwitchMode, VimState}; use editor::{char_kind, movement, Bias}; -use gpui::{action, keymap::Binding, MutableAppContext, ViewContext}; +use gpui::{actions, impl_actions, keymap::Binding, MutableAppContext, ViewContext}; use language::SelectionGoal; use workspace::Workspace; -use crate::{mode::NormalState, Mode, SwitchMode, VimState}; +#[derive(Clone)] +struct MoveToNextWordStart(pub bool); -action!(GPrefix); -action!(MoveLeft); -action!(MoveDown); -action!(MoveUp); -action!(MoveRight); -action!(MoveToStartOfLine); -action!(MoveToEndOfLine); -action!(MoveToEnd); -action!(MoveToNextWordStart, bool); -action!(MoveToNextWordEnd, bool); -action!(MoveToPreviousWordStart, bool); +#[derive(Clone)] +struct MoveToNextWordEnd(pub bool); + +#[derive(Clone)] +struct MoveToPreviousWordStart(pub bool); + +impl_actions!( + vim, + [ + MoveToNextWordStart, + MoveToNextWordEnd, + MoveToPreviousWordStart, + ] +); + +actions!( + vim, + [ + GPrefix, + MoveLeft, + MoveDown, + MoveUp, + MoveRight, + MoveToStartOfLine, + MoveToEndOfLine, + MoveToEnd, + ] +); pub fn init(cx: &mut MutableAppContext) { let context = Some("Editor && vim_mode == normal"); diff --git a/crates/vim/src/normal/g_prefix.rs b/crates/vim/src/normal/g_prefix.rs index 5b71089245..79c48a686e 100644 --- a/crates/vim/src/normal/g_prefix.rs +++ b/crates/vim/src/normal/g_prefix.rs @@ -1,9 +1,8 @@ -use gpui::{action, keymap::Binding, MutableAppContext, ViewContext}; +use crate::{mode::Mode, SwitchMode, VimState}; +use gpui::{actions, keymap::Binding, MutableAppContext, ViewContext}; use workspace::Workspace; -use crate::{mode::Mode, SwitchMode, VimState}; - -action!(MoveToStart); +actions!(vim, [MoveToStart]); pub fn init(cx: &mut MutableAppContext) { let context = Some("Editor && vim_mode == normal && vim_submode == g"); diff --git a/crates/vim/src/vim.rs b/crates/vim/src/vim.rs index 16ee1612d5..2d76831076 100644 --- a/crates/vim/src/vim.rs +++ b/crates/vim/src/vim.rs @@ -7,13 +7,16 @@ mod vim_test_context; use collections::HashMap; use editor::{CursorShape, Editor}; -use gpui::{action, MutableAppContext, ViewContext, WeakViewHandle}; +use gpui::{impl_actions, MutableAppContext, ViewContext, WeakViewHandle}; use mode::Mode; use settings::Settings; use workspace::{self, Workspace}; -action!(SwitchMode, Mode); +#[derive(Clone)] +pub struct SwitchMode(pub Mode); + +impl_actions!(vim, [SwitchMode]); pub fn init(cx: &mut MutableAppContext) { editor_events::init(cx); diff --git a/crates/workspace/src/lsp_status.rs b/crates/workspace/src/lsp_status.rs index cf920b108d..1accbcad3c 100644 --- a/crates/workspace/src/lsp_status.rs +++ b/crates/workspace/src/lsp_status.rs @@ -1,9 +1,9 @@ use crate::{ItemHandle, StatusItemView}; use futures::StreamExt; -use gpui::AppContext; +use gpui::{actions, AppContext}; use gpui::{ - action, elements::*, platform::CursorStyle, Entity, ModelHandle, MutableAppContext, - RenderContext, View, ViewContext, + elements::*, platform::CursorStyle, Entity, ModelHandle, MutableAppContext, RenderContext, + View, ViewContext, }; use language::{LanguageRegistry, LanguageServerBinaryStatus}; use project::{LanguageServerProgress, Project}; @@ -13,7 +13,7 @@ use std::cmp::Reverse; use std::fmt::Write; use std::sync::Arc; -action!(DismissErrorMessage); +actions!(lsp_status, [DismissErrorMessage]); pub struct LspStatus { checking_for_update: Vec, diff --git a/crates/workspace/src/menu.rs b/crates/workspace/src/menu.rs index e4ce82276a..e2412db741 100644 --- a/crates/workspace/src/menu.rs +++ b/crates/workspace/src/menu.rs @@ -1,10 +1,9 @@ -use gpui::{action, keymap::Binding, MutableAppContext}; +use gpui::{actions, keymap::Binding, MutableAppContext}; -action!(Confirm); -action!(SelectPrev); -action!(SelectNext); -action!(SelectFirst); -action!(SelectLast); +actions!( + menu, + [Confirm, SelectPrev, SelectNext, SelectFirst, SelectLast,] +); pub fn init(cx: &mut MutableAppContext) { cx.add_bindings([ diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 7f41624f6c..6459e46fca 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -4,9 +4,10 @@ use anyhow::Result; use collections::{HashMap, VecDeque}; use futures::StreamExt; use gpui::{ - action, + actions, elements::*, geometry::{rect::RectF, vector::vec2f}, + impl_actions, keymap::Binding, platform::{CursorStyle, NavigationDirection}, AppContext, Entity, MutableAppContext, PromptLevel, Quad, RenderContext, Task, View, @@ -17,15 +18,32 @@ use settings::Settings; use std::{any::Any, cell::RefCell, cmp, mem, path::Path, rc::Rc}; use util::ResultExt; -action!(Split, SplitDirection); -action!(ActivateItem, usize); -action!(ActivatePrevItem); -action!(ActivateNextItem); -action!(CloseActiveItem); -action!(CloseInactiveItems); -action!(CloseItem, CloseItemParams); -action!(GoBack, Option>); -action!(GoForward, Option>); +actions!( + pane, + [ + ActivatePrevItem, + ActivateNextItem, + CloseActiveItem, + CloseInactiveItems, + ] +); + +#[derive(Clone)] +pub struct Split(pub SplitDirection); + +#[derive(Clone)] +pub struct CloseItem(pub CloseItemParams); + +#[derive(Clone)] +pub struct ActivateItem(pub usize); + +#[derive(Clone)] +pub struct GoBack(pub Option>); + +#[derive(Clone)] +pub struct GoForward(pub Option>); + +impl_actions!(pane, [Split, CloseItem, ActivateItem, GoBack, GoForward,]); #[derive(Clone)] pub struct CloseItemParams { diff --git a/crates/workspace/src/sidebar.rs b/crates/workspace/src/sidebar.rs index 7a7ad4e272..49852d16f2 100644 --- a/crates/workspace/src/sidebar.rs +++ b/crates/workspace/src/sidebar.rs @@ -1,5 +1,5 @@ use super::Workspace; -use gpui::{action, elements::*, platform::CursorStyle, AnyViewHandle, RenderContext}; +use gpui::{elements::*, impl_actions, platform::CursorStyle, AnyViewHandle, RenderContext}; use std::{cell::RefCell, rc::Rc}; use theme::Theme; @@ -21,8 +21,13 @@ struct Item { view: AnyViewHandle, } -action!(ToggleSidebarItem, SidebarItemId); -action!(ToggleSidebarItemFocus, SidebarItemId); +#[derive(Clone)] +pub struct ToggleSidebarItem(pub SidebarItemId); + +#[derive(Clone)] +pub struct ToggleSidebarItemFocus(pub SidebarItemId); + +impl_actions!(workspace, [ToggleSidebarItem, ToggleSidebarItemFocus]); #[derive(Clone)] pub struct SidebarItemId { diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index b49b6f601f..a320dca23c 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -13,10 +13,11 @@ use client::{ use clock::ReplicaId; use collections::{hash_map, HashMap, HashSet}; use gpui::{ - action, + actions, color::Color, elements::*, geometry::{rect::RectF, vector::vec2f, PathBuilder}, + impl_actions, json::{self, to_string_pretty, ToJson}, keymap::Binding, platform::{CursorStyle, WindowOptions}, @@ -69,18 +70,38 @@ type FollowableItemBuilders = HashMap< ), >; -action!(Open, Arc); -action!(OpenNew, Arc); -action!(OpenPaths, OpenParams); -action!(ToggleShare); -action!(ToggleFollow, PeerId); -action!(FollowNextCollaborator); -action!(Unfollow); -action!(JoinProject, JoinProjectParams); -action!(Save); -action!(DebugElements); -action!(ActivatePreviousPane); -action!(ActivateNextPane); +actions!( + workspace, + [ + ToggleShare, + Unfollow, + Save, + DebugElements, + ActivatePreviousPane, + ActivateNextPane, + FollowNextCollaborator, + ] +); + +#[derive(Clone)] +pub struct Open(pub Arc); + +#[derive(Clone)] +pub struct OpenNew(pub Arc); + +#[derive(Clone)] +pub struct OpenPaths(pub OpenParams); + +#[derive(Clone)] +pub struct ToggleFollow(pub PeerId); + +#[derive(Clone)] +pub struct JoinProject(pub JoinProjectParams); + +impl_actions!( + workspace, + [Open, OpenNew, OpenPaths, ToggleFollow, JoinProject] +); pub fn init(client: &Arc, cx: &mut MutableAppContext) { pane::init(cx); diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 86a059e6fd..6fca5247fc 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -12,8 +12,9 @@ pub use contacts_panel; use contacts_panel::ContactsPanel; pub use editor; use gpui::{ - action, + actions, geometry::vector::vec2f, + impl_actions, keymap::Binding, platform::{WindowBounds, WindowOptions}, ModelHandle, ViewContext, @@ -29,10 +30,12 @@ use std::{path::PathBuf, sync::Arc}; pub use workspace; use workspace::{AppState, Workspace, WorkspaceParams}; -action!(About); -action!(Quit); -action!(OpenSettings); -action!(AdjustBufferFontSize, f32); +actions!(zed, [About, Quit, OpenSettings]); + +#[derive(Clone)] +pub struct AdjustBufferFontSize(pub f32); + +impl_actions!(zed, [AdjustBufferFontSize]); const MIN_FONT_SIZE: f32 = 6.0;