Restore impl_actions! and remove derive(Action)
This commit is contained in:
parent
4290c67b6a
commit
9ce7395b74
14 changed files with 147 additions and 236 deletions
|
@ -92,7 +92,7 @@ use theme::{ActiveTheme, ThemeSettings};
|
||||||
// channel_id: ChannelId,
|
// channel_id: ChannelId,
|
||||||
// }
|
// }
|
||||||
|
|
||||||
#[derive(Action, PartialEq, Debug, Clone, Serialize, Deserialize)]
|
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct OpenChannelNotes {
|
pub struct OpenChannelNotes {
|
||||||
pub channel_id: ChannelId,
|
pub channel_id: ChannelId,
|
||||||
}
|
}
|
||||||
|
@ -122,6 +122,8 @@ pub struct OpenChannelNotes {
|
||||||
// to: ChannelId,
|
// to: ChannelId,
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
impl_actions!(collab_panel, [OpenChannelNotes]);
|
||||||
|
|
||||||
actions!(
|
actions!(
|
||||||
collab_panel,
|
collab_panel,
|
||||||
[
|
[
|
||||||
|
@ -172,12 +174,12 @@ use editor::Editor;
|
||||||
use feature_flags::{ChannelsAlpha, FeatureFlagAppExt, FeatureFlagViewExt};
|
use feature_flags::{ChannelsAlpha, FeatureFlagAppExt, FeatureFlagViewExt};
|
||||||
use fuzzy::{match_strings, StringMatchCandidate};
|
use fuzzy::{match_strings, StringMatchCandidate};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, canvas, div, img, overlay, point, prelude::*, px, rems, serde_json, size, Action,
|
actions, canvas, div, img, impl_actions, overlay, point, prelude::*, px, rems, serde_json,
|
||||||
AppContext, AsyncWindowContext, Bounds, ClipboardItem, DismissEvent, Div, EventEmitter,
|
size, Action, AppContext, AsyncWindowContext, Bounds, ClipboardItem, DismissEvent, Div,
|
||||||
FocusHandle, Focusable, FocusableView, Hsla, InteractiveElement, IntoElement, Length, Model,
|
EventEmitter, FocusHandle, Focusable, FocusableView, Hsla, InteractiveElement, IntoElement,
|
||||||
MouseDownEvent, ParentElement, Pixels, Point, PromptLevel, Quad, Render, RenderOnce,
|
Length, Model, MouseDownEvent, ParentElement, Pixels, Point, PromptLevel, Quad, Render,
|
||||||
ScrollHandle, SharedString, Size, Stateful, Styled, Subscription, Task, View, ViewContext,
|
RenderOnce, ScrollHandle, SharedString, Size, Stateful, Styled, Subscription, Task, View,
|
||||||
VisualContext, WeakView,
|
ViewContext, VisualContext, WeakView,
|
||||||
};
|
};
|
||||||
use project::{Fs, Project};
|
use project::{Fs, Project};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
|
|
@ -49,7 +49,7 @@ impl CommandPalette {
|
||||||
.available_actions()
|
.available_actions()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|action| {
|
.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");
|
let namespace = name.split("::").next().unwrap_or("malformed action name");
|
||||||
if filter.is_some_and(|f| {
|
if filter.is_some_and(|f| {
|
||||||
f.hidden_namespaces.contains(namespace)
|
f.hidden_namespaces.contains(namespace)
|
||||||
|
|
|
@ -39,8 +39,8 @@ use futures::FutureExt;
|
||||||
use fuzzy::{StringMatch, StringMatchCandidate};
|
use fuzzy::{StringMatch, StringMatchCandidate};
|
||||||
use git::diff_hunk_to_display;
|
use git::diff_hunk_to_display;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, div, point, prelude::*, px, relative, rems, size, uniform_list, Action, AnyElement,
|
actions, div, impl_actions, point, prelude::*, px, relative, rems, size, uniform_list, Action,
|
||||||
AppContext, AsyncWindowContext, BackgroundExecutor, Bounds, ClipboardItem, Context,
|
AnyElement, AppContext, AsyncWindowContext, BackgroundExecutor, Bounds, ClipboardItem, Context,
|
||||||
DispatchPhase, Div, ElementId, EventEmitter, FocusHandle, FocusableView, FontFeatures,
|
DispatchPhase, Div, ElementId, EventEmitter, FocusHandle, FocusableView, FontFeatures,
|
||||||
FontStyle, FontWeight, HighlightStyle, Hsla, InputHandler, InteractiveText, KeyContext, Model,
|
FontStyle, FontWeight, HighlightStyle, Hsla, InputHandler, InteractiveText, KeyContext, Model,
|
||||||
MouseButton, ParentElement, Pixels, Render, RenderOnce, SharedString, Styled, StyledText,
|
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 {
|
pub struct SelectNext {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub replace_newest: bool,
|
pub replace_newest: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, Action)]
|
#[derive(PartialEq, Clone, Deserialize, Default)]
|
||||||
pub struct SelectPrevious {
|
pub struct SelectPrevious {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub replace_newest: bool,
|
pub replace_newest: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, Action)]
|
#[derive(PartialEq, Clone, Deserialize, Default)]
|
||||||
pub struct SelectAllMatches {
|
pub struct SelectAllMatches {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub replace_newest: bool,
|
pub replace_newest: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, Action)]
|
#[derive(PartialEq, Clone, Deserialize, Default)]
|
||||||
pub struct SelectToBeginningOfLine {
|
pub struct SelectToBeginningOfLine {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
stop_at_soft_wraps: bool,
|
stop_at_soft_wraps: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, Action)]
|
#[derive(PartialEq, Clone, Deserialize, Default)]
|
||||||
pub struct MovePageUp {
|
pub struct MovePageUp {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
center_cursor: bool,
|
center_cursor: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, Action)]
|
#[derive(PartialEq, Clone, Deserialize, Default)]
|
||||||
pub struct MovePageDown {
|
pub struct MovePageDown {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
center_cursor: bool,
|
center_cursor: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, Action)]
|
#[derive(PartialEq, Clone, Deserialize, Default)]
|
||||||
pub struct SelectToEndOfLine {
|
pub struct SelectToEndOfLine {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
stop_at_soft_wraps: bool,
|
stop_at_soft_wraps: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, Action)]
|
#[derive(PartialEq, Clone, Deserialize, Default)]
|
||||||
pub struct ToggleCodeActions {
|
pub struct ToggleCodeActions {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub deployed_from_indicator: bool,
|
pub deployed_from_indicator: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, Action)]
|
#[derive(PartialEq, Clone, Deserialize, Default)]
|
||||||
pub struct ConfirmCompletion {
|
pub struct ConfirmCompletion {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub item_ix: Option<usize>,
|
pub item_ix: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, Action)]
|
#[derive(PartialEq, Clone, Deserialize, Default)]
|
||||||
pub struct ConfirmCodeAction {
|
pub struct ConfirmCodeAction {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub item_ix: Option<usize>,
|
pub item_ix: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, Action)]
|
#[derive(PartialEq, Clone, Deserialize, Default)]
|
||||||
pub struct ToggleComments {
|
pub struct ToggleComments {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub advance_downwards: bool,
|
pub advance_downwards: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, Action)]
|
#[derive(PartialEq, Clone, Deserialize, Default)]
|
||||||
pub struct FoldAt {
|
pub struct FoldAt {
|
||||||
pub buffer_row: u32,
|
pub buffer_row: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, Action)]
|
#[derive(PartialEq, Clone, Deserialize, Default)]
|
||||||
pub struct UnfoldAt {
|
pub struct UnfoldAt {
|
||||||
pub buffer_row: u32,
|
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)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub enum InlayId {
|
pub enum InlayId {
|
||||||
Suggestion(usize),
|
Suggestion(usize),
|
||||||
|
|
|
@ -3,33 +3,32 @@ use anyhow::{anyhow, Context, Result};
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
pub use no_action::NoAction;
|
pub use no_action::NoAction;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::{
|
use std::any::{Any, TypeId};
|
||||||
any::{Any, TypeId},
|
|
||||||
ops::Deref,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Actions are used to implement keyboard-driven UI.
|
/// Actions are used to implement keyboard-driven UI.
|
||||||
/// When you declare an action, you can bind keys to the action in the keymap and
|
/// When you declare an action, you can bind keys to the action in the keymap and
|
||||||
/// listeners for that action in the element tree.
|
/// 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
|
/// 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
|
/// ```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
|
/// More complex data types can also be actions, providing they implement Clone, PartialEq, Debug,
|
||||||
/// it will be implemented and registered automatically.
|
/// 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 struct SelectNext {
|
||||||
/// pub replace_newest: bool,
|
/// 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]`
|
/// 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`.
|
/// macro, which only generates the code needed to register your action before `main`.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #[gpui::register_action]
|
|
||||||
/// #[derive(gpui::serde::Deserialize, std::cmp::PartialEq, std::clone::Clone, std::fmt::Debug)]
|
/// #[derive(gpui::serde::Deserialize, std::cmp::PartialEq, std::clone::Clone, std::fmt::Debug)]
|
||||||
/// pub struct Paste {
|
/// pub struct Paste {
|
||||||
/// pub content: SharedString,
|
/// pub content: SharedString,
|
||||||
|
@ -38,6 +37,7 @@ use std::{
|
||||||
/// impl gpui::Action for Paste {
|
/// impl gpui::Action for Paste {
|
||||||
/// ///...
|
/// ///...
|
||||||
/// }
|
/// }
|
||||||
|
/// register_action!(Paste);
|
||||||
/// ```
|
/// ```
|
||||||
pub trait Action: 'static {
|
pub trait Action: 'static {
|
||||||
fn boxed_clone(&self) -> Box<dyn Action>;
|
fn boxed_clone(&self) -> Box<dyn Action>;
|
||||||
|
@ -56,7 +56,7 @@ pub trait Action: 'static {
|
||||||
impl std::fmt::Debug for dyn Action {
|
impl std::fmt::Debug for dyn Action {
|
||||||
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("dyn Action")
|
f.debug_struct("dyn Action")
|
||||||
.field("type_name", &self.name())
|
.field("name", &self.name())
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ impl ActionRegistry {
|
||||||
for builder in __GPUI_ACTIONS {
|
for builder in __GPUI_ACTIONS {
|
||||||
let action = builder();
|
let action = builder();
|
||||||
//todo(remove)
|
//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.builders_by_name.insert(name.clone(), action.build);
|
||||||
self.names_by_type_id.insert(action.type_id, name.clone());
|
self.names_by_type_id.insert(action.type_id, name.clone());
|
||||||
self.all_names.push(name);
|
self.all_names.push(name);
|
||||||
|
@ -139,11 +139,9 @@ impl ActionRegistry {
|
||||||
name: &str,
|
name: &str,
|
||||||
params: Option<serde_json::Value>,
|
params: Option<serde_json::Value>,
|
||||||
) -> Result<Box<dyn Action>> {
|
) -> Result<Box<dyn Action>> {
|
||||||
//todo(remove)
|
|
||||||
let name = remove_the_2(name);
|
|
||||||
let build_action = self
|
let build_action = self
|
||||||
.builders_by_name
|
.builders_by_name
|
||||||
.get(name.deref())
|
.get(name)
|
||||||
.ok_or_else(|| anyhow!("no action type registered for {}", name))?;
|
.ok_or_else(|| anyhow!("no action type registered for {}", name))?;
|
||||||
(build_action)(params.unwrap_or_else(|| json!({})))
|
(build_action)(params.unwrap_or_else(|| json!({})))
|
||||||
.with_context(|| format!("Attempting to build action {}", name))
|
.with_context(|| format!("Attempting to build action {}", name))
|
||||||
|
@ -155,14 +153,13 @@ impl ActionRegistry {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Defines unit structs that can be used as actions.
|
/// 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_export]
|
||||||
macro_rules! actions {
|
macro_rules! actions {
|
||||||
($namespace:path, [ $($name:ident),* $(,)? ]) => {
|
($namespace:path, [ $($name:ident),* $(,)? ]) => {
|
||||||
$(
|
$(
|
||||||
#[derive(::std::cmp::PartialEq, ::std::clone::Clone, ::std::default::Default, gpui::serde_derive::Deserialize)]
|
#[derive(::std::cmp::PartialEq, ::std::clone::Clone, ::std::default::Default, gpui::serde_derive::Deserialize)]
|
||||||
#[serde(crate = "gpui::serde")]
|
#[serde(crate = "gpui::serde")]
|
||||||
#[gpui::register_action]
|
|
||||||
pub struct $name;
|
pub struct $name;
|
||||||
|
|
||||||
gpui::__impl_action!($namespace, $name,
|
gpui::__impl_action!($namespace, $name,
|
||||||
|
@ -170,6 +167,22 @@ macro_rules! actions {
|
||||||
Ok(Box::new(Self))
|
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 {
|
mod no_action {
|
||||||
use crate as gpui;
|
use crate as gpui;
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,23 @@
|
||||||
|
use gpui2::{actions, impl_actions};
|
||||||
|
use gpui2_macros::register_action;
|
||||||
use serde_derive::Deserialize;
|
use serde_derive::Deserialize;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_derive() {
|
fn test_action_macros() {
|
||||||
use gpui2 as gpui;
|
use gpui2 as gpui;
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, gpui2_macros::Action)]
|
actions!(test, [TestAction]);
|
||||||
|
|
||||||
|
#[derive(PartialEq, Clone, Deserialize)]
|
||||||
struct AnotherTestAction;
|
struct AnotherTestAction;
|
||||||
|
|
||||||
#[gpui2_macros::register_action]
|
impl_actions!(test, [AnotherTestAction]);
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, gpui::serde_derive::Deserialize)]
|
#[derive(PartialEq, Clone, gpui::serde_derive::Deserialize)]
|
||||||
struct RegisterableAction {}
|
struct RegisterableAction {}
|
||||||
|
|
||||||
|
register_action!(RegisterableAction);
|
||||||
|
|
||||||
impl gpui::Action for RegisterableAction {
|
impl gpui::Action for RegisterableAction {
|
||||||
fn boxed_clone(&self) -> Box<dyn gpui::Action> {
|
fn boxed_clone(&self) -> Box<dyn gpui::Action> {
|
||||||
todo!()
|
todo!()
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
|
@ -1,4 +1,3 @@
|
||||||
mod action;
|
|
||||||
mod derive_into_element;
|
mod derive_into_element;
|
||||||
mod register_action;
|
mod register_action;
|
||||||
mod style_helpers;
|
mod style_helpers;
|
||||||
|
@ -6,14 +5,9 @@ mod test;
|
||||||
|
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
|
|
||||||
#[proc_macro_derive(Action)]
|
#[proc_macro]
|
||||||
pub fn action(input: TokenStream) -> TokenStream {
|
pub fn register_action(ident: TokenStream) -> TokenStream {
|
||||||
action::action(input)
|
register_action::register_action_macro(ident)
|
||||||
}
|
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
|
||||||
pub fn register_action(attr: TokenStream, item: TokenStream) -> TokenStream {
|
|
||||||
register_action::register_action_macro(attr, item)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_derive(IntoElement)]
|
#[proc_macro_derive(IntoElement)]
|
||||||
|
|
|
@ -14,47 +14,13 @@
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use proc_macro2::Ident;
|
use proc_macro2::Ident;
|
||||||
use quote::{format_ident, quote};
|
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 {
|
pub fn register_action_macro(ident: TokenStream) -> TokenStream {
|
||||||
let input = parse_macro_input!(item as DeriveInput);
|
let name = parse_macro_input!(ident as Ident);
|
||||||
let registration = register_action(&input.ident);
|
let registration = register_action(&name);
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
TokenStream::from(quote! {
|
TokenStream::from(quote! {
|
||||||
#input
|
|
||||||
|
|
||||||
#registration
|
#registration
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
use std::{sync::Arc, time::Duration};
|
use std::{sync::Arc, time::Duration};
|
||||||
|
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use gpui::{Action, KeyBinding};
|
use gpui::{actions, KeyBinding};
|
||||||
use live_kit_client2::{
|
use live_kit_client2::{
|
||||||
LocalAudioTrack, LocalVideoTrack, RemoteAudioTrackUpdate, RemoteVideoTrackUpdate, Room,
|
LocalAudioTrack, LocalVideoTrack, RemoteAudioTrackUpdate, RemoteVideoTrackUpdate, Room,
|
||||||
};
|
};
|
||||||
use live_kit_server::token::{self, VideoGrant};
|
use live_kit_server::token::{self, VideoGrant};
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
use serde_derive::Deserialize;
|
|
||||||
use simplelog::SimpleLogger;
|
use simplelog::SimpleLogger;
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, Clone, Copy, PartialEq, Action)]
|
actions!(live_kit_client, [Quit]);
|
||||||
struct Quit;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
SimpleLogger::init(LevelFilter::Info, Default::default()).expect("could not initialize logger");
|
SimpleLogger::init(LevelFilter::Info, Default::default()).expect("could not initialize logger");
|
||||||
|
|
|
@ -10,7 +10,7 @@ use collections::HashMap;
|
||||||
use editor::{Editor, EditorMode};
|
use editor::{Editor, EditorMode};
|
||||||
use futures::channel::oneshot;
|
use futures::channel::oneshot;
|
||||||
use gpui::{
|
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,
|
InteractiveElement as _, IntoElement, KeyContext, ParentElement as _, Render, Styled,
|
||||||
Subscription, Task, View, ViewContext, VisualContext as _, WeakView, WindowContext,
|
Subscription, Task, View, ViewContext, VisualContext as _, WeakView, WindowContext,
|
||||||
};
|
};
|
||||||
|
@ -26,11 +26,13 @@ use workspace::{
|
||||||
ToolbarItemLocation, ToolbarItemView,
|
ToolbarItemLocation, ToolbarItemView,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize, Default, Action)]
|
#[derive(PartialEq, Clone, Deserialize)]
|
||||||
pub struct Deploy {
|
pub struct Deploy {
|
||||||
pub focus: bool,
|
pub focus: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_actions!(buffer_search, [Deploy]);
|
||||||
|
|
||||||
actions!(buffer_search, [Dismiss, FocusEditor]);
|
actions!(buffer_search, [Dismiss, FocusEditor]);
|
||||||
|
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
|
|
|
@ -9,10 +9,10 @@ pub mod terminal_panel;
|
||||||
// use crate::terminal_element::TerminalElement;
|
// use crate::terminal_element::TerminalElement;
|
||||||
use editor::{scroll::autoscroll::Autoscroll, Editor};
|
use editor::{scroll::autoscroll::Autoscroll, Editor};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, overlay, Action, AnyElement, AppContext, DismissEvent, Div, EventEmitter, FocusEvent,
|
div, impl_actions, overlay, AnyElement, AppContext, DismissEvent, Div, EventEmitter,
|
||||||
FocusHandle, Focusable, FocusableElement, FocusableView, KeyContext, KeyDownEvent, Keystroke,
|
FocusEvent, FocusHandle, Focusable, FocusableElement, FocusableView, KeyContext, KeyDownEvent,
|
||||||
Model, MouseButton, MouseDownEvent, Pixels, Render, Styled, Subscription, Task, View,
|
Keystroke, Model, MouseButton, MouseDownEvent, Pixels, Render, Styled, Subscription, Task,
|
||||||
VisualContext, WeakView,
|
View, VisualContext, WeakView,
|
||||||
};
|
};
|
||||||
use language::Bias;
|
use language::Bias;
|
||||||
use persistence::TERMINAL_DB;
|
use persistence::TERMINAL_DB;
|
||||||
|
@ -55,12 +55,14 @@ const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct ScrollTerminal(pub i32);
|
pub struct ScrollTerminal(pub i32);
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Action)]
|
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
|
||||||
pub struct SendText(String);
|
pub struct SendText(String);
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Action)]
|
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
|
||||||
pub struct SendKeystroke(String);
|
pub struct SendKeystroke(String);
|
||||||
|
|
||||||
|
impl_actions!(terminal_view, [SendText, SendKeystroke]);
|
||||||
|
|
||||||
pub fn init(cx: &mut AppContext) {
|
pub fn init(cx: &mut AppContext) {
|
||||||
terminal_panel::init(cx);
|
terminal_panel::init(cx);
|
||||||
terminal::init(cx);
|
terminal::init(cx);
|
||||||
|
|
|
@ -7,10 +7,10 @@ use crate::{
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use collections::{HashMap, HashSet, VecDeque};
|
use collections::{HashMap, HashSet, VecDeque};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, overlay, prelude::*, rems, Action, AnchorCorner, AnyWeakView, AppContext,
|
actions, impl_actions, overlay, prelude::*, rems, Action, AnchorCorner, AnyWeakView,
|
||||||
AsyncWindowContext, DismissEvent, Div, EntityId, EventEmitter, FocusHandle, Focusable,
|
AppContext, AsyncWindowContext, DismissEvent, Div, EntityId, EventEmitter, FocusHandle,
|
||||||
FocusableView, Model, MouseButton, NavigationDirection, Pixels, Point, PromptLevel, Render,
|
Focusable, FocusableView, Model, MouseButton, NavigationDirection, Pixels, Point, PromptLevel,
|
||||||
Task, View, ViewContext, VisualContext, WeakView, WindowContext,
|
Render, Task, View, ViewContext, VisualContext, WeakView, WindowContext,
|
||||||
};
|
};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use project::{Project, ProjectEntryId, ProjectPath};
|
use project::{Project, ProjectEntryId, ProjectPath};
|
||||||
|
@ -52,9 +52,7 @@ pub enum SaveIntent {
|
||||||
Skip,
|
Skip,
|
||||||
}
|
}
|
||||||
|
|
||||||
//todo!("Do we need the default bound on actions? Decide soon")
|
#[derive(Clone, Deserialize, PartialEq, Debug)]
|
||||||
// #[register_action]
|
|
||||||
#[derive(Action, Clone, Deserialize, PartialEq, Debug)]
|
|
||||||
pub struct ActivateItem(pub usize);
|
pub struct ActivateItem(pub usize);
|
||||||
|
|
||||||
// #[derive(Clone, PartialEq)]
|
// #[derive(Clone, PartialEq)]
|
||||||
|
@ -75,18 +73,20 @@ pub struct ActivateItem(pub usize);
|
||||||
// pub pane: WeakView<Pane>,
|
// pub pane: WeakView<Pane>,
|
||||||
// }
|
// }
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug, Deserialize, Default, Action)]
|
#[derive(Clone, PartialEq, Debug, Deserialize, Default)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct CloseActiveItem {
|
pub struct CloseActiveItem {
|
||||||
pub save_intent: Option<SaveIntent>,
|
pub save_intent: Option<SaveIntent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug, Deserialize, Default, Action)]
|
#[derive(Clone, PartialEq, Debug, Deserialize, Default)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct CloseAllItems {
|
pub struct CloseAllItems {
|
||||||
pub save_intent: Option<SaveIntent>,
|
pub save_intent: Option<SaveIntent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_actions!(pane, [CloseAllItems, CloseActiveItem, ActivateItem]);
|
||||||
|
|
||||||
actions!(
|
actions!(
|
||||||
pane,
|
pane,
|
||||||
[
|
[
|
||||||
|
|
|
@ -29,12 +29,12 @@ use futures::{
|
||||||
Future, FutureExt, StreamExt,
|
Future, FutureExt, StreamExt,
|
||||||
};
|
};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, div, point, size, Action, AnyModel, AnyView, AnyWeakView, AnyWindowHandle, AppContext,
|
actions, div, impl_actions, point, size, Action, AnyModel, AnyView, AnyWeakView,
|
||||||
AsyncAppContext, AsyncWindowContext, Bounds, Context, Div, Entity, EntityId, EventEmitter,
|
AnyWindowHandle, AppContext, AsyncAppContext, AsyncWindowContext, Bounds, Context, Div, Entity,
|
||||||
FocusHandle, FocusableView, GlobalPixels, InteractiveElement, KeyContext, ManagedView, Model,
|
EntityId, EventEmitter, FocusHandle, FocusableView, GlobalPixels, InteractiveElement,
|
||||||
ModelContext, ParentElement, PathPromptOptions, Point, PromptLevel, Render, Size, Styled,
|
KeyContext, ManagedView, Model, ModelContext, ParentElement, PathPromptOptions, Point,
|
||||||
Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowBounds, WindowContext,
|
PromptLevel, Render, Size, Styled, Subscription, Task, View, ViewContext, VisualContext,
|
||||||
WindowHandle, WindowOptions,
|
WeakView, WindowBounds, WindowContext, WindowHandle, WindowOptions,
|
||||||
};
|
};
|
||||||
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, ProjectItem};
|
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, ProjectItem};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
@ -125,36 +125,50 @@ pub struct OpenPaths {
|
||||||
pub paths: Vec<PathBuf>,
|
pub paths: Vec<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, PartialEq, Action)]
|
#[derive(Clone, Deserialize, PartialEq)]
|
||||||
pub struct ActivatePane(pub usize);
|
pub struct ActivatePane(pub usize);
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, PartialEq, Action)]
|
#[derive(Clone, Deserialize, PartialEq)]
|
||||||
pub struct ActivatePaneInDirection(pub SplitDirection);
|
pub struct ActivatePaneInDirection(pub SplitDirection);
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, PartialEq, Action)]
|
#[derive(Clone, Deserialize, PartialEq)]
|
||||||
pub struct SwapPaneInDirection(pub SplitDirection);
|
pub struct SwapPaneInDirection(pub SplitDirection);
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, PartialEq, Action)]
|
#[derive(Clone, Deserialize, PartialEq)]
|
||||||
pub struct NewFileInDirection(pub SplitDirection);
|
pub struct NewFileInDirection(pub SplitDirection);
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug, Deserialize, Action)]
|
#[derive(Clone, PartialEq, Debug, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct SaveAll {
|
pub struct SaveAll {
|
||||||
pub save_intent: Option<SaveIntent>,
|
pub save_intent: Option<SaveIntent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug, Deserialize, Action)]
|
#[derive(Clone, PartialEq, Debug, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct Save {
|
pub struct Save {
|
||||||
pub save_intent: Option<SaveIntent>,
|
pub save_intent: Option<SaveIntent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug, Deserialize, Default, Action)]
|
#[derive(Clone, PartialEq, Debug, Deserialize, Default)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct CloseAllItemsAndPanes {
|
pub struct CloseAllItemsAndPanes {
|
||||||
pub save_intent: Option<SaveIntent>,
|
pub save_intent: Option<SaveIntent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_actions!(
|
||||||
|
workspace,
|
||||||
|
[
|
||||||
|
ActivatePane,
|
||||||
|
ActivatePaneInDirection,
|
||||||
|
CloseAllItemsAndPanes,
|
||||||
|
NewFileInDirection,
|
||||||
|
OpenTerminal,
|
||||||
|
Save,
|
||||||
|
SaveAll,
|
||||||
|
SwapPaneInDirection,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct Toast {
|
pub struct Toast {
|
||||||
id: usize,
|
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 struct OpenTerminal {
|
||||||
pub working_directory: PathBuf,
|
pub working_directory: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use gpui::Action;
|
use gpui::impl_actions;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
// If the zed binary doesn't use anything in this crate, it will be optimized away
|
// 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
|
// https://github.com/mmastrac/rust-ctor/issues/280
|
||||||
pub fn init() {}
|
pub fn init() {}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Deserialize, Action)]
|
#[derive(Clone, PartialEq, Deserialize)]
|
||||||
pub struct OpenBrowser {
|
pub struct OpenBrowser {
|
||||||
pub url: String,
|
pub url: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Deserialize, Action)]
|
#[derive(Clone, PartialEq, Deserialize)]
|
||||||
pub struct OpenZedURL {
|
pub struct OpenZedURL {
|
||||||
pub url: String,
|
pub url: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_actions!(zed, [OpenBrowser, OpenZedURL]);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue