Restore impl_actions! and remove derive(Action)

This commit is contained in:
Conrad Irwin 2023-12-10 19:33:38 -07:00
parent 4290c67b6a
commit 9ce7395b74
14 changed files with 147 additions and 236 deletions

View File

@ -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};

View File

@ -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)

View File

@ -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<usize>,
}
#[derive(PartialEq, Clone, Deserialize, Default, Action)]
#[derive(PartialEq, Clone, Deserialize, Default)]
pub struct ConfirmCodeAction {
#[serde(default)]
pub item_ix: Option<usize>,
}
#[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),

View File

@ -3,33 +3,32 @@ 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, Debug,
/// 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, Debug)]
/// 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)]
/// 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<dyn Action>;
@ -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<serde_json::Value>,
) -> Result<Box<dyn Action>> {
//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<dyn gpui::Action>> {
Ok(std::boxed::Box::new(gpui::serde_json::from_value::<Self>(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;

View File

@ -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<dyn gpui::Action> {
todo!()

View File

@ -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::<Self>(value)?))
}
};
let register_action = register_action(&name);
let output = quote! {
const _: fn() = || {
fn assert_impl<T: ?Sized + for<'a> 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<dyn gpui::Action>>
where
Self: ::std::marker::Sized {
#build_impl
}
fn partial_eq(&self, action: &dyn gpui::Action) -> bool {
action
.as_any()
.downcast_ref::<Self>()
.map_or(false, |a| self == a)
}
fn boxed_clone(&self) -> std::boxed::Box<dyn gpui::Action> {
::std::boxed::Box::new(self.clone())
}
fn as_any(&self) -> &dyn ::std::any::Any {
self
}
}
#register_action
};
TokenStream::from(output)
}

View File

@ -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)]

View File

@ -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
})
}

View File

@ -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");

View File

@ -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 {

View File

@ -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);

View File

@ -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<Pane>,
// }
#[derive(Clone, PartialEq, Debug, Deserialize, Default, Action)]
#[derive(Clone, PartialEq, Debug, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct CloseActiveItem {
pub save_intent: Option<SaveIntent>,
}
#[derive(Clone, PartialEq, Debug, Deserialize, Default, Action)]
#[derive(Clone, PartialEq, Debug, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct CloseAllItems {
pub save_intent: Option<SaveIntent>,
}
impl_actions!(pane, [CloseAllItems, CloseActiveItem, ActivateItem]);
actions!(
pane,
[

View File

@ -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<PathBuf>,
}
#[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<SaveIntent>,
}
#[derive(Clone, PartialEq, Debug, Deserialize, Action)]
#[derive(Clone, PartialEq, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Save {
pub save_intent: Option<SaveIntent>,
}
#[derive(Clone, PartialEq, Debug, Deserialize, Default, Action)]
#[derive(Clone, PartialEq, Debug, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct CloseAllItemsAndPanes {
pub save_intent: Option<SaveIntent>,
}
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,
}

View File

@ -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]);