Merge pull request #773 from zed-industries/namespace-actions

Change how actions are declared so that they are always associated with a namespace
This commit is contained in:
Max Brunsfeld 2022-04-08 11:57:13 -07:00 committed by GitHub
commit 1778622960
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
34 changed files with 511 additions and 333 deletions

View file

@ -4,7 +4,7 @@ use client::{
}; };
use editor::Editor; use editor::Editor;
use gpui::{ use gpui::{
action, actions,
elements::*, elements::*,
keymap::Binding, keymap::Binding,
platform::CursorStyle, platform::CursorStyle,
@ -33,8 +33,7 @@ pub struct ChatPanel {
pub enum Event {} pub enum Event {}
action!(Send); actions!(chat_panel, [Send, LoadMoreMessages]);
action!(LoadMoreMessages);
pub fn init(cx: &mut MutableAppContext) { pub fn init(cx: &mut MutableAppContext) {
cx.add_action(ChatPanel::send); cx.add_action(ChatPanel::send);

View file

@ -13,7 +13,7 @@ use async_tungstenite::tungstenite::{
}; };
use futures::{future::LocalBoxFuture, FutureExt, StreamExt}; use futures::{future::LocalBoxFuture, FutureExt, StreamExt};
use gpui::{ use gpui::{
action, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AnyWeakViewHandle, AsyncAppContext, actions, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AnyWeakViewHandle, AsyncAppContext,
Entity, ModelContext, ModelHandle, MutableAppContext, Task, View, ViewContext, ViewHandle, Entity, ModelContext, ModelHandle, MutableAppContext, Task, View, ViewContext, ViewHandle,
}; };
use http::HttpClient; use http::HttpClient;
@ -50,7 +50,7 @@ lazy_static! {
.and_then(|s| if s.is_empty() { None } else { Some(s) }); .and_then(|s| if s.is_empty() { None } else { Some(s) });
} }
action!(Authenticate); actions!(client, [Authenticate]);
pub fn init(rpc: Arc<Client>, cx: &mut MutableAppContext) { pub fn init(rpc: Arc<Client>, cx: &mut MutableAppContext) {
cx.add_global_action(move |_: &Authenticate, cx| { cx.add_global_action(move |_: &Authenticate, cx| {

View file

@ -8,7 +8,7 @@ use editor::{
highlight_diagnostic_message, Editor, ExcerptId, MultiBuffer, ToOffset, highlight_diagnostic_message, Editor, ExcerptId, MultiBuffer, ToOffset,
}; };
use gpui::{ 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, ModelHandle, MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle,
WeakViewHandle, WeakViewHandle,
}; };
@ -28,7 +28,7 @@ use std::{
use util::TryFutureExt; use util::TryFutureExt;
use workspace::{ItemHandle as _, ItemNavHistory, Workspace}; use workspace::{ItemHandle as _, ItemNavHistory, Workspace};
action!(Deploy); actions!(diagnostics, [Deploy]);
const CONTEXT_LINE_COUNT: u32 = 1; const CONTEXT_LINE_COUNT: u32 = 1;

View file

@ -16,12 +16,13 @@ use display_map::*;
pub use element::*; pub use element::*;
use fuzzy::{StringMatch, StringMatchCandidate}; use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::{ use gpui::{
action, actions,
color::Color, color::Color,
elements::*, elements::*,
executor, executor,
fonts::{self, HighlightStyle, TextStyle}, fonts::{self, HighlightStyle, TextStyle},
geometry::vector::{vec2f, Vector2F}, geometry::vector::{vec2f, Vector2F},
impl_actions,
keymap::Binding, keymap::Binding,
platform::CursorStyle, platform::CursorStyle,
text_layout, AppContext, AsyncAppContext, ClipboardItem, Element, ElementBox, Entity, text_layout, AppContext, AsyncAppContext, ClipboardItem, Element, ElementBox, Entity,
@ -65,84 +66,132 @@ const MAX_LINE_LEN: usize = 1024;
const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10; const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
const MAX_SELECTION_HISTORY_LEN: usize = 1024; const MAX_SELECTION_HISTORY_LEN: usize = 1024;
action!(Cancel); #[derive(Clone)]
action!(Backspace); pub struct SelectNext(pub bool);
action!(Delete);
action!(Input, String); #[derive(Clone)]
action!(Newline); pub struct GoToDiagnostic(pub Direction);
action!(Tab, Direction);
action!(Indent); #[derive(Clone)]
action!(Outdent); pub struct Scroll(pub Vector2F);
action!(DeleteLine);
action!(DeleteToPreviousWordStart); #[derive(Clone)]
action!(DeleteToPreviousSubwordStart); pub struct Select(pub SelectPhase);
action!(DeleteToNextWordEnd);
action!(DeleteToNextSubwordEnd); #[derive(Clone)]
action!(DeleteToBeginningOfLine); pub struct Input(pub String);
action!(DeleteToEndOfLine);
action!(CutToEndOfLine); #[derive(Clone)]
action!(DuplicateLine); pub struct Tab(pub Direction);
action!(MoveLineUp);
action!(MoveLineDown); #[derive(Clone)]
action!(Cut); pub struct SelectToBeginningOfLine {
action!(Copy); stop_at_soft_wraps: bool,
action!(Paste); }
action!(Undo);
action!(Redo); #[derive(Clone)]
action!(MoveUp); pub struct SelectToEndOfLine {
action!(MoveDown); stop_at_soft_wraps: bool,
action!(MoveLeft); }
action!(MoveRight);
action!(MoveToPreviousWordStart); #[derive(Clone)]
action!(MoveToPreviousSubwordStart); pub struct ToggleCodeActions(pub bool);
action!(MoveToNextWordEnd);
action!(MoveToNextSubwordEnd); #[derive(Clone)]
action!(MoveToBeginningOfLine); pub struct ConfirmCompletion(pub Option<usize>);
action!(MoveToEndOfLine);
action!(MoveToBeginning); #[derive(Clone)]
action!(MoveToEnd); pub struct ConfirmCodeAction(pub Option<usize>);
action!(SelectUp);
action!(SelectDown); impl_actions!(
action!(SelectLeft); editor,
action!(SelectRight); [
action!(SelectToPreviousWordStart); SelectNext,
action!(SelectToPreviousSubwordStart); GoToDiagnostic,
action!(SelectToNextWordEnd); Scroll,
action!(SelectToNextSubwordEnd); Select,
action!(SelectToBeginningOfLine, bool); Input,
action!(SelectToEndOfLine, bool); Tab,
action!(SelectToBeginning); SelectToBeginningOfLine,
action!(SelectToEnd); SelectToEndOfLine,
action!(SelectAll); ToggleCodeActions,
action!(SelectLine); ConfirmCompletion,
action!(SplitSelectionIntoLines); ConfirmCodeAction,
action!(AddSelectionAbove); ]
action!(AddSelectionBelow); );
action!(SelectNext, bool);
action!(ToggleComments); actions!(
action!(SelectLargerSyntaxNode); editor,
action!(SelectSmallerSyntaxNode); [
action!(MoveToEnclosingBracket); Cancel,
action!(UndoSelection); Backspace,
action!(RedoSelection); Delete,
action!(GoToDiagnostic, Direction); Newline,
action!(GoToDefinition); Indent,
action!(FindAllReferences); Outdent,
action!(Rename); DeleteLine,
action!(ConfirmRename); DeleteToPreviousWordStart,
action!(PageUp); DeleteToPreviousSubwordStart,
action!(PageDown); DeleteToNextWordEnd,
action!(Fold); DeleteToNextSubwordEnd,
action!(UnfoldLines); DeleteToBeginningOfLine,
action!(FoldSelectedRanges); DeleteToEndOfLine,
action!(Scroll, Vector2F); CutToEndOfLine,
action!(Select, SelectPhase); DuplicateLine,
action!(ShowCompletions); MoveLineUp,
action!(ToggleCodeActions, bool); MoveLineDown,
action!(ConfirmCompletion, Option<usize>); Cut,
action!(ConfirmCodeAction, Option<usize>); Copy,
action!(OpenExcerpts); Paste,
action!(RestartLanguageServer); 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 DocumentHighlightRead {}
enum DocumentHighlightWrite {} enum DocumentHighlightWrite {}
@ -256,7 +305,9 @@ pub fn init(cx: &mut MutableAppContext) {
Binding::new("alt-shift-F", SelectToNextWordEnd, Some("Editor")), Binding::new("alt-shift-F", SelectToNextWordEnd, Some("Editor")),
Binding::new( Binding::new(
"cmd-shift-left", "cmd-shift-left",
SelectToBeginningOfLine(true), SelectToBeginningOfLine {
stop_at_soft_wraps: true,
},
Some("Editor"), Some("Editor"),
), ),
Binding::new( Binding::new(
@ -267,11 +318,25 @@ pub fn init(cx: &mut MutableAppContext) {
Binding::new("ctrl-alt-shift-F", SelectToNextSubwordEnd, Some("Editor")), Binding::new("ctrl-alt-shift-F", SelectToNextSubwordEnd, Some("Editor")),
Binding::new( Binding::new(
"ctrl-shift-A", "ctrl-shift-A",
SelectToBeginningOfLine(true), SelectToBeginningOfLine {
stop_at_soft_wraps: true,
},
Some("Editor"),
),
Binding::new(
"cmd-shift-right",
SelectToEndOfLine {
stop_at_soft_wraps: true,
},
Some("Editor"),
),
Binding::new(
"ctrl-shift-E",
SelectToEndOfLine {
stop_at_soft_wraps: true,
},
Some("Editor"), Some("Editor"),
), ),
Binding::new("cmd-shift-right", SelectToEndOfLine(true), Some("Editor")),
Binding::new("ctrl-shift-E", SelectToEndOfLine(true), Some("Editor")),
Binding::new("cmd-shift-up", SelectToBeginning, Some("Editor")), Binding::new("cmd-shift-up", SelectToBeginning, Some("Editor")),
Binding::new("cmd-shift-down", SelectToEnd, Some("Editor")), Binding::new("cmd-shift-down", SelectToEnd, Some("Editor")),
Binding::new("cmd-a", SelectAll, Some("Editor")), Binding::new("cmd-a", SelectAll, Some("Editor")),
@ -3860,12 +3925,12 @@ impl Editor {
pub fn select_to_beginning_of_line( pub fn select_to_beginning_of_line(
&mut self, &mut self,
SelectToBeginningOfLine(stop_at_soft_boundaries): &SelectToBeginningOfLine, action: &SelectToBeginningOfLine,
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) { ) {
self.move_selection_heads(cx, |map, head, _| { self.move_selection_heads(cx, |map, head, _| {
( (
movement::line_beginning(map, head, *stop_at_soft_boundaries), movement::line_beginning(map, head, action.stop_at_soft_wraps),
SelectionGoal::None, SelectionGoal::None,
) )
}); });
@ -3877,7 +3942,12 @@ impl Editor {
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) { ) {
self.transact(cx, |this, cx| { self.transact(cx, |this, cx| {
this.select_to_beginning_of_line(&SelectToBeginningOfLine(false), cx); this.select_to_beginning_of_line(
&SelectToBeginningOfLine {
stop_at_soft_wraps: false,
},
cx,
);
this.backspace(&Backspace, cx); this.backspace(&Backspace, cx);
}); });
} }
@ -3890,12 +3960,12 @@ impl Editor {
pub fn select_to_end_of_line( pub fn select_to_end_of_line(
&mut self, &mut self,
SelectToEndOfLine(stop_at_soft_boundaries): &SelectToEndOfLine, action: &SelectToEndOfLine,
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) { ) {
self.move_selection_heads(cx, |map, head, _| { self.move_selection_heads(cx, |map, head, _| {
( (
movement::line_end(map, head, *stop_at_soft_boundaries), movement::line_end(map, head, action.stop_at_soft_wraps),
SelectionGoal::None, SelectionGoal::None,
) )
}); });
@ -3903,14 +3973,24 @@ impl Editor {
pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) { pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
self.transact(cx, |this, cx| { self.transact(cx, |this, cx| {
this.select_to_end_of_line(&SelectToEndOfLine(false), cx); this.select_to_end_of_line(
&SelectToEndOfLine {
stop_at_soft_wraps: false,
},
cx,
);
this.delete(&Delete, cx); this.delete(&Delete, cx);
}); });
} }
pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) { pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
self.transact(cx, |this, cx| { self.transact(cx, |this, cx| {
this.select_to_end_of_line(&SelectToEndOfLine(false), cx); this.select_to_end_of_line(
&SelectToEndOfLine {
stop_at_soft_wraps: false,
},
cx,
);
this.cut(&Cut, cx); this.cut(&Cut, cx);
}); });
} }
@ -7251,7 +7331,12 @@ mod tests {
view.update(cx, |view, cx| { view.update(cx, |view, cx| {
view.move_left(&MoveLeft, cx); view.move_left(&MoveLeft, cx);
view.select_to_beginning_of_line(&SelectToBeginningOfLine(true), cx); view.select_to_beginning_of_line(
&SelectToBeginningOfLine {
stop_at_soft_wraps: true,
},
cx,
);
assert_eq!( assert_eq!(
view.selected_display_ranges(cx), view.selected_display_ranges(cx),
&[ &[
@ -7262,7 +7347,12 @@ mod tests {
}); });
view.update(cx, |view, cx| { view.update(cx, |view, cx| {
view.select_to_beginning_of_line(&SelectToBeginningOfLine(true), cx); view.select_to_beginning_of_line(
&SelectToBeginningOfLine {
stop_at_soft_wraps: true,
},
cx,
);
assert_eq!( assert_eq!(
view.selected_display_ranges(cx), view.selected_display_ranges(cx),
&[ &[
@ -7273,7 +7363,12 @@ mod tests {
}); });
view.update(cx, |view, cx| { view.update(cx, |view, cx| {
view.select_to_beginning_of_line(&SelectToBeginningOfLine(true), cx); view.select_to_beginning_of_line(
&SelectToBeginningOfLine {
stop_at_soft_wraps: true,
},
cx,
);
assert_eq!( assert_eq!(
view.selected_display_ranges(cx), view.selected_display_ranges(cx),
&[ &[
@ -7284,7 +7379,12 @@ mod tests {
}); });
view.update(cx, |view, cx| { view.update(cx, |view, cx| {
view.select_to_end_of_line(&SelectToEndOfLine(true), cx); view.select_to_end_of_line(
&SelectToEndOfLine {
stop_at_soft_wraps: true,
},
cx,
);
assert_eq!( assert_eq!(
view.selected_display_ranges(cx), view.selected_display_ranges(cx),
&[ &[

View file

@ -1,8 +1,9 @@
use editor::Editor; use editor::Editor;
use fuzzy::PathMatch; use fuzzy::PathMatch;
use gpui::{ use gpui::{
action, actions,
elements::*, elements::*,
impl_actions,
keymap::{self, Binding}, keymap::{self, Binding},
AppContext, Axis, Entity, ModelHandle, MutableAppContext, RenderContext, Task, View, AppContext, Axis, Entity, ModelHandle, MutableAppContext, RenderContext, Task, View,
ViewContext, ViewHandle, WeakViewHandle, ViewContext, ViewHandle, WeakViewHandle,
@ -37,8 +38,11 @@ pub struct FileFinder {
list_state: UniformListState, list_state: UniformListState,
} }
action!(Toggle); #[derive(Clone)]
action!(Select, ProjectPath); pub struct Select(pub ProjectPath);
impl_actions!(file_finder, [Select]);
actions!(file_finder, [Toggle]);
pub fn init(cx: &mut MutableAppContext) { pub fn init(cx: &mut MutableAppContext) {
cx.add_action(FileFinder::toggle); cx.add_action(FileFinder::toggle);

View file

@ -1,14 +1,13 @@
use editor::{display_map::ToDisplayPoint, Autoscroll, DisplayPoint, Editor}; use editor::{display_map::ToDisplayPoint, Autoscroll, DisplayPoint, Editor};
use gpui::{ 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, MutableAppContext, RenderContext, View, ViewContext, ViewHandle,
}; };
use settings::Settings; use settings::Settings;
use text::{Bias, Point}; use text::{Bias, Point};
use workspace::Workspace; use workspace::Workspace;
action!(Toggle); actions!(go_to_line, [Toggle, Confirm]);
action!(Confirm);
pub fn init(cx: &mut MutableAppContext) { pub fn init(cx: &mut MutableAppContext) {
cx.add_bindings([ cx.add_bindings([

View file

@ -1,3 +1,5 @@
pub mod action;
use crate::{ use crate::{
elements::ElementBox, elements::ElementBox,
executor::{self, Task}, executor::{self, Task},
@ -7,6 +9,7 @@ use crate::{
util::post_inc, util::post_inc,
AssetCache, AssetSource, ClipboardItem, FontCache, PathPromptOptions, TextLayoutCache, AssetCache, AssetSource, ClipboardItem, FontCache, PathPromptOptions, TextLayoutCache,
}; };
pub use action::*;
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use collections::btree_map; use collections::btree_map;
use keymap::MatchResult; use keymap::MatchResult;
@ -142,89 +145,6 @@ pub trait ElementStateContext: DerefMut<Target = MutableAppContext> {
} }
} }
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<dyn AnyAction>;
fn boxed_clone_as_any(&self) -> Box<dyn Any>;
}
#[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<dyn $crate::AnyAction> {
Box::new(self.clone())
}
fn boxed_clone_as_any(&self) -> Box<dyn std::any::Any> {
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<dyn $crate::AnyAction> {
Box::new(self.clone())
}
fn boxed_clone_as_any(&self) -> Box<dyn std::any::Any> {
Box::new(self.clone())
}
}
};
}
pub struct Menu<'a> { pub struct Menu<'a> {
pub name: &'a str, pub name: &'a str,
pub items: Vec<MenuItem<'a>>, pub items: Vec<MenuItem<'a>>,
@ -234,7 +154,7 @@ pub enum MenuItem<'a> {
Action { Action {
name: &'a str, name: &'a str,
keystroke: Option<&'a str>, keystroke: Option<&'a str>,
action: Box<dyn AnyAction>, action: Box<dyn Action>,
}, },
Separator, Separator,
} }
@ -787,8 +707,8 @@ impl ReadViewWith for TestAppContext {
} }
type ActionCallback = type ActionCallback =
dyn FnMut(&mut dyn AnyView, &dyn AnyAction, &mut MutableAppContext, usize, usize); dyn FnMut(&mut dyn AnyView, &dyn Action, &mut MutableAppContext, usize, usize);
type GlobalActionCallback = dyn FnMut(&dyn AnyAction, &mut MutableAppContext); type GlobalActionCallback = dyn FnMut(&dyn Action, &mut MutableAppContext);
type SubscriptionCallback = Box<dyn FnMut(&dyn Any, &mut MutableAppContext) -> bool>; type SubscriptionCallback = Box<dyn FnMut(&dyn Any, &mut MutableAppContext) -> bool>;
type GlobalSubscriptionCallback = Box<dyn FnMut(&dyn Any, &mut MutableAppContext)>; type GlobalSubscriptionCallback = Box<dyn FnMut(&dyn Any, &mut MutableAppContext)>;
@ -963,7 +883,7 @@ impl MutableAppContext {
{ {
let handler = Box::new( let handler = Box::new(
move |view: &mut dyn AnyView, move |view: &mut dyn AnyView,
action: &dyn AnyAction, action: &dyn Action,
cx: &mut MutableAppContext, cx: &mut MutableAppContext,
window_id: usize, window_id: usize,
view_id: usize| { view_id: usize| {
@ -1009,7 +929,7 @@ impl MutableAppContext {
A: Action, A: Action,
F: 'static + FnMut(&A, &mut MutableAppContext), 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(); let action = action.as_any().downcast_ref().unwrap();
handler(action, cx); handler(action, cx);
}); });
@ -1338,7 +1258,7 @@ impl MutableAppContext {
&mut self, &mut self,
window_id: usize, window_id: usize,
path: &[usize], path: &[usize],
action: &dyn AnyAction, action: &dyn Action,
) -> bool { ) -> bool {
self.update(|this| { self.update(|this| {
this.halt_action_dispatch = false; this.halt_action_dispatch = false;
@ -1398,7 +1318,7 @@ impl MutableAppContext {
self.dispatch_global_action_any(&action); 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| { self.update(|this| {
if let Some((name, mut handler)) = this.global_actions.remove_entry(&action.id()) { if let Some((name, mut handler)) = this.global_actions.remove_entry(&action.id()) {
handler(action, this); handler(action, this);
@ -4655,7 +4575,7 @@ impl RefCounts {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::elements::*; use crate::{elements::*, impl_actions};
use smol::future::poll_once; use smol::future::poll_once;
use std::{ use std::{
cell::Cell, 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())); let actions = Rc::new(RefCell::new(Vec::new()));
@ -5909,7 +5832,10 @@ mod tests {
#[crate::test(self)] #[crate::test(self)]
fn test_dispatch_keystroke(cx: &mut MutableAppContext) { 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 { struct View {
id: usize, id: usize,

View file

@ -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<dyn Action>;
fn boxed_clone_as_any(&self) -> Box<dyn Any>;
}
#[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<dyn $crate::action::Action> {
Box::new(self.clone())
}
fn boxed_clone_as_any(&self) -> Box<dyn std::any::Any> {
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),* ]);
};
}

View file

@ -1,3 +1,4 @@
use crate::Action;
use anyhow::anyhow; use anyhow::anyhow;
use std::{ use std::{
any::Any, any::Any,
@ -6,8 +7,6 @@ use std::{
}; };
use tree_sitter::{Language, Node, Parser}; use tree_sitter::{Language, Node, Parser};
use crate::{Action, AnyAction};
extern "C" { extern "C" {
fn tree_sitter_context_predicate() -> Language; fn tree_sitter_context_predicate() -> Language;
} }
@ -28,7 +27,7 @@ pub struct Keymap(Vec<Binding>);
pub struct Binding { pub struct Binding {
keystrokes: Vec<Keystroke>, keystrokes: Vec<Keystroke>,
action: Box<dyn AnyAction>, action: Box<dyn Action>,
context: Option<ContextPredicate>, context: Option<ContextPredicate>,
} }
@ -73,7 +72,7 @@ where
pub enum MatchResult { pub enum MatchResult {
None, None,
Pending, Pending,
Action(Box<dyn AnyAction>), Action(Box<dyn Action>),
} }
impl Debug for MatchResult { impl Debug for MatchResult {
@ -329,7 +328,7 @@ impl ContextPredicate {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::action; use crate::{actions, impl_actions};
use super::*; use super::*;
@ -420,9 +419,10 @@ mod tests {
#[test] #[test]
fn test_matcher() -> anyhow::Result<()> { fn test_matcher() -> anyhow::Result<()> {
action!(A, &'static str); #[derive(Clone)]
action!(B); pub struct A(pub &'static str);
action!(Ab); impl_actions!(test, [A]);
actions!(test, [B, Ab]);
impl PartialEq for A { impl PartialEq for A {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {

View file

@ -15,7 +15,7 @@ use crate::{
vector::Vector2F, vector::Vector2F,
}, },
text_layout::{LineLayout, RunStyle}, text_layout::{LineLayout, RunStyle},
AnyAction, ClipboardItem, Menu, Scene, Action, ClipboardItem, Menu, Scene,
}; };
use anyhow::Result; use anyhow::Result;
use async_task::Runnable; use async_task::Runnable;
@ -66,7 +66,7 @@ pub(crate) trait ForegroundPlatform {
fn on_open_files(&self, callback: Box<dyn FnMut(Vec<PathBuf>)>); fn on_open_files(&self, callback: Box<dyn FnMut(Vec<PathBuf>)>);
fn run(&self, on_finish_launching: Box<dyn FnOnce() -> ()>); fn run(&self, on_finish_launching: Box<dyn FnOnce() -> ()>);
fn on_menu_command(&self, callback: Box<dyn FnMut(&dyn AnyAction)>); fn on_menu_command(&self, callback: Box<dyn FnMut(&dyn Action)>);
fn set_menus(&self, menus: Vec<Menu>); fn set_menus(&self, menus: Vec<Menu>);
fn prompt_for_paths( fn prompt_for_paths(
&self, &self,

View file

@ -3,7 +3,7 @@ use crate::{
executor, executor,
keymap::Keystroke, keymap::Keystroke,
platform::{self, CursorStyle}, platform::{self, CursorStyle},
AnyAction, ClipboardItem, Event, Menu, MenuItem, Action, ClipboardItem, Event, Menu, MenuItem,
}; };
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use block::ConcreteBlock; use block::ConcreteBlock;
@ -107,10 +107,10 @@ pub struct MacForegroundPlatformState {
resign_active: Option<Box<dyn FnMut()>>, resign_active: Option<Box<dyn FnMut()>>,
quit: Option<Box<dyn FnMut()>>, quit: Option<Box<dyn FnMut()>>,
event: Option<Box<dyn FnMut(crate::Event) -> bool>>, event: Option<Box<dyn FnMut(crate::Event) -> bool>>,
menu_command: Option<Box<dyn FnMut(&dyn AnyAction)>>, menu_command: Option<Box<dyn FnMut(&dyn Action)>>,
open_files: Option<Box<dyn FnMut(Vec<PathBuf>)>>, open_files: Option<Box<dyn FnMut(Vec<PathBuf>)>>,
finish_launching: Option<Box<dyn FnOnce() -> ()>>, finish_launching: Option<Box<dyn FnOnce() -> ()>>,
menu_actions: Vec<Box<dyn AnyAction>>, menu_actions: Vec<Box<dyn Action>>,
} }
impl MacForegroundPlatform { impl MacForegroundPlatform {
@ -235,7 +235,7 @@ impl platform::ForegroundPlatform for MacForegroundPlatform {
} }
} }
fn on_menu_command(&self, callback: Box<dyn FnMut(&dyn AnyAction)>) { fn on_menu_command(&self, callback: Box<dyn FnMut(&dyn Action)>) {
self.0.borrow_mut().menu_command = Some(callback); self.0.borrow_mut().menu_command = Some(callback);
} }

View file

@ -1,7 +1,7 @@
use super::{CursorStyle, WindowBounds}; use super::{CursorStyle, WindowBounds};
use crate::{ use crate::{
geometry::vector::{vec2f, Vector2F}, geometry::vector::{vec2f, Vector2F},
AnyAction, ClipboardItem, Action, ClipboardItem,
}; };
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use parking_lot::Mutex; use parking_lot::Mutex;
@ -72,7 +72,7 @@ impl super::ForegroundPlatform for ForegroundPlatform {
unimplemented!() unimplemented!()
} }
fn on_menu_command(&self, _: Box<dyn FnMut(&dyn AnyAction)>) {} fn on_menu_command(&self, _: Box<dyn FnMut(&dyn Action)>) {}
fn set_menus(&self, _: Vec<crate::Menu>) {} fn set_menus(&self, _: Vec<crate::Menu>) {}

View file

@ -6,7 +6,7 @@ use crate::{
json::{self, ToJson}, json::{self, ToJson},
platform::Event, platform::Event,
text_layout::TextLayoutCache, text_layout::TextLayoutCache,
Action, AnyAction, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AssetCache, ElementBox, Action, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AssetCache, ElementBox,
ElementStateContext, Entity, FontSystem, ModelHandle, ReadModel, ReadView, Scene, ElementStateContext, Entity, FontSystem, ModelHandle, ReadModel, ReadView, Scene,
UpgradeModelHandle, UpgradeViewHandle, View, ViewHandle, WeakModelHandle, WeakViewHandle, UpgradeModelHandle, UpgradeViewHandle, View, ViewHandle, WeakModelHandle, WeakViewHandle,
}; };
@ -223,7 +223,7 @@ impl Presenter {
pub struct DispatchDirective { pub struct DispatchDirective {
pub path: Vec<usize>, pub path: Vec<usize>,
pub action: Box<dyn AnyAction>, pub action: Box<dyn Action>,
} }
pub struct LayoutContext<'a> { pub struct LayoutContext<'a> {

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
action, elements::*, AppContext, Entity, MutableAppContext, RenderContext, View, ViewContext, actions, elements::*, impl_actions, AppContext, Entity, MutableAppContext, RenderContext, View,
WeakViewHandle, ViewContext, WeakViewHandle,
}; };
pub struct Select { pub struct Select {
@ -25,8 +25,11 @@ pub enum ItemType {
Unselected, Unselected,
} }
action!(ToggleSelect); #[derive(Clone)]
action!(SelectItem, usize); pub struct SelectItem(pub usize);
actions!(select, [ToggleSelect]);
impl_actions!(select, [SelectItem]);
pub enum Event {} pub enum Event {}

View file

@ -1,11 +1,11 @@
use chrono::{Datelike, Local, Timelike}; use chrono::{Datelike, Local, Timelike};
use editor::{Autoscroll, Editor}; use editor::{Autoscroll, Editor};
use gpui::{action, keymap::Binding, MutableAppContext}; use gpui::{actions, keymap::Binding, MutableAppContext};
use std::{fs::OpenOptions, sync::Arc}; use std::{fs::OpenOptions, sync::Arc};
use util::TryFutureExt as _; use util::TryFutureExt as _;
use workspace::AppState; use workspace::AppState;
action!(NewJournalEntry); actions!(journal, [NewJournalEntry]);
pub fn init(app_state: Arc<AppState>, cx: &mut MutableAppContext) { pub fn init(app_state: Arc<AppState>, cx: &mut MutableAppContext) {
cx.add_bindings(vec![Binding::new("ctrl-alt-cmd-j", NewJournalEntry, None)]); cx.add_bindings(vec![Binding::new("ctrl-alt-cmd-j", NewJournalEntry, None)]);

View file

@ -4,7 +4,7 @@ use editor::{
}; };
use fuzzy::StringMatch; use fuzzy::StringMatch;
use gpui::{ use gpui::{
action, actions,
elements::*, elements::*,
geometry::vector::Vector2F, geometry::vector::Vector2F,
keymap::{self, Binding}, keymap::{self, Binding},
@ -20,7 +20,7 @@ use workspace::{
Workspace, Workspace,
}; };
action!(Toggle); actions!(outline, [Toggle]);
pub fn init(cx: &mut MutableAppContext) { pub fn init(cx: &mut MutableAppContext) {
cx.add_bindings([ cx.add_bindings([

View file

@ -1,9 +1,10 @@
use gpui::{ use gpui::{
action, actions,
elements::{ elements::{
Align, ConstrainedBox, Empty, Flex, Label, MouseEventHandler, ParentElement, ScrollTarget, Align, ConstrainedBox, Empty, Flex, Label, MouseEventHandler, ParentElement, ScrollTarget,
Svg, UniformList, UniformListState, Svg, UniformList, UniformListState,
}, },
impl_actions,
keymap::{self, Binding}, keymap::{self, Binding},
platform::CursorStyle, platform::CursorStyle,
AppContext, Element, ElementBox, Entity, ModelHandle, MutableAppContext, View, ViewContext, AppContext, Element, ElementBox, Entity, ModelHandle, MutableAppContext, View, ViewContext,
@ -46,10 +47,14 @@ struct EntryDetails {
is_selected: bool, is_selected: bool,
} }
action!(ExpandSelectedEntry); #[derive(Clone)]
action!(CollapseSelectedEntry); pub struct ToggleExpanded(pub ProjectEntryId);
action!(ToggleExpanded, ProjectEntryId);
action!(Open, 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) { pub fn init(cx: &mut MutableAppContext) {
cx.add_action(ProjectPanel::expand_selected_entry); cx.add_action(ProjectPanel::expand_selected_entry);

View file

@ -3,7 +3,7 @@ use editor::{
}; };
use fuzzy::{StringMatch, StringMatchCandidate}; use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::{ use gpui::{
action, actions,
elements::*, elements::*,
keymap::{self, Binding}, keymap::{self, Binding},
AppContext, Axis, Entity, ModelHandle, MutableAppContext, RenderContext, Task, View, AppContext, Axis, Entity, ModelHandle, MutableAppContext, RenderContext, Task, View,
@ -22,7 +22,7 @@ use workspace::{
Workspace, Workspace,
}; };
action!(Toggle); actions!(project_symbols, [Toggle]);
pub fn init(cx: &mut MutableAppContext) { pub fn init(cx: &mut MutableAppContext) {
cx.add_bindings([ cx.add_bindings([

View file

@ -2,7 +2,7 @@ use crate::{active_match_index, match_index_for_direction, Direction, SearchOpti
use collections::HashMap; use collections::HashMap;
use editor::{display_map::ToDisplayPoint, Anchor, Autoscroll, Bias, Editor}; use editor::{display_map::ToDisplayPoint, Anchor, Autoscroll, Bias, Editor};
use gpui::{ 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, MutableAppContext, RenderContext, Subscription, Task, View, ViewContext, ViewHandle,
WeakViewHandle, WeakViewHandle,
}; };
@ -12,10 +12,14 @@ use settings::Settings;
use std::ops::Range; use std::ops::Range;
use workspace::{ItemHandle, Pane, ToolbarItemLocation, ToolbarItemView}; use workspace::{ItemHandle, Pane, ToolbarItemLocation, ToolbarItemView};
action!(Deploy, bool); #[derive(Clone)]
action!(Dismiss); pub struct Deploy(pub bool);
action!(FocusEditor);
action!(ToggleSearchOption, SearchOption); #[derive(Clone)]
pub struct ToggleSearchOption(pub SearchOption);
actions!(buffer_search, [Dismiss, FocusEditor]);
impl_actions!(buffer_search, [Deploy, ToggleSearchOption]);
pub enum Event { pub enum Event {
UpdateLocation, UpdateLocation,

View file

@ -5,7 +5,7 @@ use crate::{
use collections::HashMap; use collections::HashMap;
use editor::{Anchor, Autoscroll, Editor, MultiBuffer, SelectAll}; use editor::{Anchor, Autoscroll, Editor, MultiBuffer, SelectAll};
use gpui::{ 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, ModelContext, ModelHandle, MutableAppContext, RenderContext, Subscription, Task, View,
ViewContext, ViewHandle, WeakModelHandle, WeakViewHandle, ViewContext, ViewHandle, WeakModelHandle, WeakViewHandle,
}; };
@ -19,10 +19,7 @@ use std::{
use util::ResultExt as _; use util::ResultExt as _;
use workspace::{Item, ItemNavHistory, Pane, ToolbarItemLocation, ToolbarItemView, Workspace}; use workspace::{Item, ItemNavHistory, Pane, ToolbarItemLocation, ToolbarItemView, Workspace};
action!(Deploy); actions!(project_search, [Deploy, Search, SearchInNew, ToggleFocus]);
action!(Search);
action!(SearchInNew);
action!(ToggleFocus);
const MAX_TAB_TITLE_LEN: usize = 24; const MAX_TAB_TITLE_LEN: usize = 24;

View file

@ -1,6 +1,6 @@
pub use buffer_search::BufferSearchBar; pub use buffer_search::BufferSearchBar;
use editor::{Anchor, MultiBufferSnapshot}; use editor::{Anchor, MultiBufferSnapshot};
use gpui::{action, MutableAppContext}; use gpui::{impl_actions, MutableAppContext};
pub use project_search::{ProjectSearchBar, ProjectSearchView}; pub use project_search::{ProjectSearchBar, ProjectSearchView};
use std::{ use std::{
cmp::{self, Ordering}, cmp::{self, Ordering},
@ -15,8 +15,13 @@ pub fn init(cx: &mut MutableAppContext) {
project_search::init(cx); project_search::init(cx);
} }
action!(ToggleSearchOption, SearchOption); #[derive(Clone)]
action!(SelectMatch, Direction); pub struct ToggleSearchOption(pub SearchOption);
#[derive(Clone)]
pub struct SelectMatch(pub Direction);
impl_actions!(search, [ToggleSearchOption, SelectMatch]);
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub enum SearchOption { pub enum SearchOption {

View file

@ -1118,7 +1118,7 @@ mod tests {
time::Duration, time::Duration,
}; };
use util::TryFutureExt; use util::TryFutureExt;
use workspace::{Item, SplitDirection, Workspace, WorkspaceParams}; use workspace::{Item, SplitDirection, ToggleFollow, Workspace, WorkspaceParams};
#[cfg(test)] #[cfg(test)]
#[ctor::ctor] #[ctor::ctor]
@ -4527,7 +4527,9 @@ mod tests {
editor_a2.update(cx_a, |editor, cx| editor.select_ranges([2..3], None, cx)); editor_a2.update(cx_a, |editor, cx| editor.select_ranges([2..3], None, cx));
workspace_b workspace_b
.update(cx_b, |workspace, cx| { .update(cx_b, |workspace, cx| {
workspace.toggle_follow(&client_a_id.into(), cx).unwrap() workspace
.toggle_follow(&ToggleFollow(client_a_id), cx)
.unwrap()
}) })
.await .await
.unwrap(); .unwrap();
@ -4627,7 +4629,9 @@ mod tests {
// Client A starts following client B. // Client A starts following client B.
workspace_a workspace_a
.update(cx_a, |workspace, cx| { .update(cx_a, |workspace, cx| {
workspace.toggle_follow(&client_b_id.into(), cx).unwrap() workspace
.toggle_follow(&ToggleFollow(client_b_id), cx)
.unwrap()
}) })
.await .await
.unwrap(); .unwrap();
@ -4856,7 +4860,9 @@ mod tests {
}); });
workspace_b workspace_b
.update(cx_b, |workspace, cx| { .update(cx_b, |workspace, cx| {
workspace.toggle_follow(&leader_id.into(), cx).unwrap() workspace
.toggle_follow(&ToggleFollow(leader_id), cx)
.unwrap()
}) })
.await .await
.unwrap(); .unwrap();
@ -4881,7 +4887,9 @@ mod tests {
workspace_b workspace_b
.update(cx_b, |workspace, cx| { .update(cx_b, |workspace, cx| {
workspace.toggle_follow(&leader_id.into(), cx).unwrap() workspace
.toggle_follow(&ToggleFollow(leader_id), cx)
.unwrap()
}) })
.await .await
.unwrap(); .unwrap();
@ -4899,7 +4907,9 @@ mod tests {
workspace_b workspace_b
.update(cx_b, |workspace, cx| { .update(cx_b, |workspace, cx| {
workspace.toggle_follow(&leader_id.into(), cx).unwrap() workspace
.toggle_follow(&ToggleFollow(leader_id), cx)
.unwrap()
}) })
.await .await
.unwrap(); .unwrap();
@ -4919,7 +4929,9 @@ mod tests {
workspace_b workspace_b
.update(cx_b, |workspace, cx| { .update(cx_b, |workspace, cx| {
workspace.toggle_follow(&leader_id.into(), cx).unwrap() workspace
.toggle_follow(&ToggleFollow(leader_id), cx)
.unwrap()
}) })
.await .await
.unwrap(); .unwrap();

View file

@ -1,15 +1,15 @@
use editor::Editor; use editor::Editor;
use fuzzy::{match_strings, StringMatch, StringMatchCandidate}; use fuzzy::{match_strings, StringMatch, StringMatchCandidate};
use gpui::{ use gpui::{
action,
elements::*, elements::*,
impl_actions,
keymap::{self, Binding}, keymap::{self, Binding},
AppContext, Axis, Element, ElementBox, Entity, MutableAppContext, RenderContext, View, AppContext, Axis, Element, ElementBox, Entity, MutableAppContext, RenderContext, View,
ViewContext, ViewHandle, ViewContext, ViewHandle,
}; };
use settings::Settings;
use std::{cmp, sync::Arc}; use std::{cmp, sync::Arc};
use theme::{Theme, ThemeRegistry}; use theme::{Theme, ThemeRegistry};
use settings::Settings;
use workspace::{ use workspace::{
menu::{Confirm, SelectNext, SelectPrev}, menu::{Confirm, SelectNext, SelectPrev},
Workspace, Workspace,
@ -25,8 +25,13 @@ pub struct ThemeSelector {
selection_completed: bool, selection_completed: bool,
} }
action!(Toggle, Arc<ThemeRegistry>); #[derive(Clone)]
action!(Reload, Arc<ThemeRegistry>); pub struct Toggle(pub Arc<ThemeRegistry>);
#[derive(Clone)]
pub struct Reload(pub Arc<ThemeRegistry>);
impl_actions!(theme_selector, [Toggle, Reload]);
pub fn init(themes: Arc<ThemeRegistry>, cx: &mut MutableAppContext) { pub fn init(themes: Arc<ThemeRegistry>, cx: &mut MutableAppContext) {
cx.add_action(ThemeSelector::confirm); cx.add_action(ThemeSelector::confirm);

View file

@ -1,11 +1,10 @@
use crate::{mode::Mode, SwitchMode, VimState};
use editor::Bias; use editor::Bias;
use gpui::{action, keymap::Binding, MutableAppContext, ViewContext}; use gpui::{actions, keymap::Binding, MutableAppContext, ViewContext};
use language::SelectionGoal; use language::SelectionGoal;
use workspace::Workspace; use workspace::Workspace;
use crate::{mode::Mode, SwitchMode, VimState}; actions!(vim, [NormalBefore]);
action!(NormalBefore);
pub fn init(cx: &mut MutableAppContext) { pub fn init(cx: &mut MutableAppContext) {
let context = Some("Editor && vim_mode == insert"); let context = Some("Editor && vim_mode == insert");

View file

@ -1,23 +1,42 @@
mod g_prefix; mod g_prefix;
use crate::{mode::NormalState, Mode, SwitchMode, VimState};
use editor::{char_kind, movement, Bias}; 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 language::SelectionGoal;
use workspace::Workspace; use workspace::Workspace;
use crate::{mode::NormalState, Mode, SwitchMode, VimState}; #[derive(Clone)]
struct MoveToNextWordStart(pub bool);
action!(GPrefix); #[derive(Clone)]
action!(MoveLeft); struct MoveToNextWordEnd(pub bool);
action!(MoveDown);
action!(MoveUp); #[derive(Clone)]
action!(MoveRight); struct MoveToPreviousWordStart(pub bool);
action!(MoveToStartOfLine);
action!(MoveToEndOfLine); impl_actions!(
action!(MoveToEnd); vim,
action!(MoveToNextWordStart, bool); [
action!(MoveToNextWordEnd, bool); MoveToNextWordStart,
action!(MoveToPreviousWordStart, bool); MoveToNextWordEnd,
MoveToPreviousWordStart,
]
);
actions!(
vim,
[
GPrefix,
MoveLeft,
MoveDown,
MoveUp,
MoveRight,
MoveToStartOfLine,
MoveToEndOfLine,
MoveToEnd,
]
);
pub fn init(cx: &mut MutableAppContext) { pub fn init(cx: &mut MutableAppContext) {
let context = Some("Editor && vim_mode == normal"); let context = Some("Editor && vim_mode == normal");

View file

@ -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 workspace::Workspace;
use crate::{mode::Mode, SwitchMode, VimState}; actions!(vim, [MoveToStart]);
action!(MoveToStart);
pub fn init(cx: &mut MutableAppContext) { pub fn init(cx: &mut MutableAppContext) {
let context = Some("Editor && vim_mode == normal && vim_submode == g"); let context = Some("Editor && vim_mode == normal && vim_submode == g");

View file

@ -7,13 +7,16 @@ mod vim_test_context;
use collections::HashMap; use collections::HashMap;
use editor::{CursorShape, Editor}; use editor::{CursorShape, Editor};
use gpui::{action, MutableAppContext, ViewContext, WeakViewHandle}; use gpui::{impl_actions, MutableAppContext, ViewContext, WeakViewHandle};
use mode::Mode; use mode::Mode;
use settings::Settings; use settings::Settings;
use workspace::{self, Workspace}; use workspace::{self, Workspace};
action!(SwitchMode, Mode); #[derive(Clone)]
pub struct SwitchMode(pub Mode);
impl_actions!(vim, [SwitchMode]);
pub fn init(cx: &mut MutableAppContext) { pub fn init(cx: &mut MutableAppContext) {
editor_events::init(cx); editor_events::init(cx);

View file

@ -1,9 +1,9 @@
use crate::{ItemHandle, StatusItemView}; use crate::{ItemHandle, StatusItemView};
use futures::StreamExt; use futures::StreamExt;
use gpui::AppContext; use gpui::{actions, AppContext};
use gpui::{ use gpui::{
action, elements::*, platform::CursorStyle, Entity, ModelHandle, MutableAppContext, elements::*, platform::CursorStyle, Entity, ModelHandle, MutableAppContext, RenderContext,
RenderContext, View, ViewContext, View, ViewContext,
}; };
use language::{LanguageRegistry, LanguageServerBinaryStatus}; use language::{LanguageRegistry, LanguageServerBinaryStatus};
use project::{LanguageServerProgress, Project}; use project::{LanguageServerProgress, Project};
@ -13,7 +13,7 @@ use std::cmp::Reverse;
use std::fmt::Write; use std::fmt::Write;
use std::sync::Arc; use std::sync::Arc;
action!(DismissErrorMessage); actions!(lsp_status, [DismissErrorMessage]);
pub struct LspStatus { pub struct LspStatus {
checking_for_update: Vec<String>, checking_for_update: Vec<String>,

View file

@ -1,10 +1,9 @@
use gpui::{action, keymap::Binding, MutableAppContext}; use gpui::{actions, keymap::Binding, MutableAppContext};
action!(Confirm); actions!(
action!(SelectPrev); menu,
action!(SelectNext); [Confirm, SelectPrev, SelectNext, SelectFirst, SelectLast,]
action!(SelectFirst); );
action!(SelectLast);
pub fn init(cx: &mut MutableAppContext) { pub fn init(cx: &mut MutableAppContext) {
cx.add_bindings([ cx.add_bindings([

View file

@ -4,9 +4,10 @@ use anyhow::Result;
use collections::{HashMap, VecDeque}; use collections::{HashMap, VecDeque};
use futures::StreamExt; use futures::StreamExt;
use gpui::{ use gpui::{
action, actions,
elements::*, elements::*,
geometry::{rect::RectF, vector::vec2f}, geometry::{rect::RectF, vector::vec2f},
impl_actions,
keymap::Binding, keymap::Binding,
platform::{CursorStyle, NavigationDirection}, platform::{CursorStyle, NavigationDirection},
AppContext, Entity, MutableAppContext, PromptLevel, Quad, RenderContext, Task, View, 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 std::{any::Any, cell::RefCell, cmp, mem, path::Path, rc::Rc};
use util::ResultExt; use util::ResultExt;
action!(Split, SplitDirection); actions!(
action!(ActivateItem, usize); pane,
action!(ActivatePrevItem); [
action!(ActivateNextItem); ActivatePrevItem,
action!(CloseActiveItem); ActivateNextItem,
action!(CloseInactiveItems); CloseActiveItem,
action!(CloseItem, CloseItemParams); CloseInactiveItems,
action!(GoBack, Option<WeakViewHandle<Pane>>); ]
action!(GoForward, Option<WeakViewHandle<Pane>>); );
#[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<WeakViewHandle<Pane>>);
#[derive(Clone)]
pub struct GoForward(pub Option<WeakViewHandle<Pane>>);
impl_actions!(pane, [Split, CloseItem, ActivateItem, GoBack, GoForward,]);
#[derive(Clone)] #[derive(Clone)]
pub struct CloseItemParams { pub struct CloseItemParams {

View file

@ -1,5 +1,5 @@
use super::Workspace; 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 std::{cell::RefCell, rc::Rc};
use theme::Theme; use theme::Theme;
@ -21,8 +21,13 @@ struct Item {
view: AnyViewHandle, view: AnyViewHandle,
} }
action!(ToggleSidebarItem, SidebarItemId); #[derive(Clone)]
action!(ToggleSidebarItemFocus, SidebarItemId); pub struct ToggleSidebarItem(pub SidebarItemId);
#[derive(Clone)]
pub struct ToggleSidebarItemFocus(pub SidebarItemId);
impl_actions!(workspace, [ToggleSidebarItem, ToggleSidebarItemFocus]);
#[derive(Clone)] #[derive(Clone)]
pub struct SidebarItemId { pub struct SidebarItemId {

View file

@ -13,10 +13,11 @@ use client::{
use clock::ReplicaId; use clock::ReplicaId;
use collections::{hash_map, HashMap, HashSet}; use collections::{hash_map, HashMap, HashSet};
use gpui::{ use gpui::{
action, actions,
color::Color, color::Color,
elements::*, elements::*,
geometry::{rect::RectF, vector::vec2f, PathBuilder}, geometry::{rect::RectF, vector::vec2f, PathBuilder},
impl_actions,
json::{self, to_string_pretty, ToJson}, json::{self, to_string_pretty, ToJson},
keymap::Binding, keymap::Binding,
platform::{CursorStyle, WindowOptions}, platform::{CursorStyle, WindowOptions},
@ -69,18 +70,41 @@ type FollowableItemBuilders = HashMap<
), ),
>; >;
action!(Open, Arc<AppState>); actions!(
action!(OpenNew, Arc<AppState>); workspace,
action!(OpenPaths, OpenParams); [
action!(ToggleShare); ToggleShare,
action!(ToggleFollow, PeerId); Unfollow,
action!(FollowNextCollaborator); Save,
action!(Unfollow); DebugElements,
action!(JoinProject, JoinProjectParams); ActivatePreviousPane,
action!(Save); ActivateNextPane,
action!(DebugElements); FollowNextCollaborator,
action!(ActivatePreviousPane); ]
action!(ActivateNextPane); );
#[derive(Clone)]
pub struct Open(pub Arc<AppState>);
#[derive(Clone)]
pub struct OpenNew(pub Arc<AppState>);
#[derive(Clone)]
pub struct OpenPaths {
pub paths: Vec<PathBuf>,
pub app_state: Arc<AppState>,
}
#[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<Client>, cx: &mut MutableAppContext) { pub fn init(client: &Arc<Client>, cx: &mut MutableAppContext) {
pane::init(cx); pane::init(cx);
@ -88,7 +112,7 @@ pub fn init(client: &Arc<Client>, cx: &mut MutableAppContext) {
cx.add_global_action(open); cx.add_global_action(open);
cx.add_global_action(move |action: &OpenPaths, cx: &mut MutableAppContext| { cx.add_global_action(move |action: &OpenPaths, cx: &mut MutableAppContext| {
open_paths(&action.0.paths, &action.0.app_state, cx).detach(); open_paths(&action.paths, &action.app_state, cx).detach();
}); });
cx.add_global_action(move |action: &OpenNew, cx: &mut MutableAppContext| { cx.add_global_action(move |action: &OpenNew, cx: &mut MutableAppContext| {
open_new(&action.0, cx) open_new(&action.0, cx)
@ -190,12 +214,6 @@ pub struct AppState {
) -> Workspace, ) -> Workspace,
} }
#[derive(Clone)]
pub struct OpenParams {
pub paths: Vec<PathBuf>,
pub app_state: Arc<AppState>,
}
#[derive(Clone)] #[derive(Clone)]
pub struct JoinProjectParams { pub struct JoinProjectParams {
pub project_id: u64, pub project_id: u64,
@ -2092,9 +2110,9 @@ impl Element for AvatarRibbon {
} }
} }
impl std::fmt::Debug for OpenParams { impl std::fmt::Debug for OpenPaths {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("OpenParams") f.debug_struct("OpenPaths")
.field("paths", &self.paths) .field("paths", &self.paths)
.finish() .finish()
} }
@ -2109,7 +2127,7 @@ fn open(action: &Open, cx: &mut MutableAppContext) {
}); });
cx.spawn(|mut cx| async move { cx.spawn(|mut cx| async move {
if let Some(paths) = paths.recv().await.flatten() { if let Some(paths) = paths.recv().await.flatten() {
cx.update(|cx| cx.dispatch_global_action(OpenPaths(OpenParams { paths, app_state }))); cx.update(|cx| cx.dispatch_global_action(OpenPaths { paths, app_state }));
} }
}) })
.detach(); .detach();

View file

@ -14,7 +14,7 @@ use smol::process::Command;
use std::{env, fs, path::PathBuf, sync::Arc}; use std::{env, fs, path::PathBuf, sync::Arc};
use theme::{ThemeRegistry, DEFAULT_THEME_NAME}; use theme::{ThemeRegistry, DEFAULT_THEME_NAME};
use util::ResultExt; use util::ResultExt;
use workspace::{self, AppState, OpenNew, OpenParams, OpenPaths}; use workspace::{self, AppState, OpenNew, OpenPaths};
use zed::{ use zed::{
self, self,
assets::Assets, assets::Assets,
@ -158,7 +158,7 @@ fn main() {
if paths.is_empty() { if paths.is_empty() {
cx.dispatch_global_action(OpenNew(app_state.clone())); cx.dispatch_global_action(OpenNew(app_state.clone()));
} else { } else {
cx.dispatch_global_action(OpenPaths(OpenParams { paths, app_state })); cx.dispatch_global_action(OpenPaths { paths, app_state });
} }
}); });
} }

View file

@ -12,8 +12,9 @@ pub use contacts_panel;
use contacts_panel::ContactsPanel; use contacts_panel::ContactsPanel;
pub use editor; pub use editor;
use gpui::{ use gpui::{
action, actions,
geometry::vector::vec2f, geometry::vector::vec2f,
impl_actions,
keymap::Binding, keymap::Binding,
platform::{WindowBounds, WindowOptions}, platform::{WindowBounds, WindowOptions},
ModelHandle, ViewContext, ModelHandle, ViewContext,
@ -29,10 +30,12 @@ use std::{path::PathBuf, sync::Arc};
pub use workspace; pub use workspace;
use workspace::{AppState, Workspace, WorkspaceParams}; use workspace::{AppState, Workspace, WorkspaceParams};
action!(About); actions!(zed, [About, Quit, OpenSettings]);
action!(Quit);
action!(OpenSettings); #[derive(Clone)]
action!(AdjustBufferFontSize, f32); pub struct AdjustBufferFontSize(pub f32);
impl_actions!(zed, [AdjustBufferFontSize]);
const MIN_FONT_SIZE: f32 = 6.0; const MIN_FONT_SIZE: f32 = 6.0;