@@ -406,6 +406,129 @@ pub fn init_settings(cx: &mut AppContext) {
pub fn init(cx: &mut AppContext) {
init_settings(cx);
+ // cx.register_action_type(Editor::new_file);
+ // cx.register_action_type(Editor::new_file_in_direction);
+ // cx.register_action_type(Editor::cancel);
+ // cx.register_action_type(Editor::newline);
+ // cx.register_action_type(Editor::newline_above);
+ // cx.register_action_type(Editor::newline_below);
+ // cx.register_action_type(Editor::backspace);
+ // cx.register_action_type(Editor::delete);
+ // cx.register_action_type(Editor::tab);
+ // cx.register_action_type(Editor::tab_prev);
+ // cx.register_action_type(Editor::indent);
+ // cx.register_action_type(Editor::outdent);
+ // cx.register_action_type(Editor::delete_line);
+ // cx.register_action_type(Editor::join_lines);
+ // cx.register_action_type(Editor::sort_lines_case_sensitive);
+ // cx.register_action_type(Editor::sort_lines_case_insensitive);
+ // cx.register_action_type(Editor::reverse_lines);
+ // cx.register_action_type(Editor::shuffle_lines);
+ // cx.register_action_type(Editor::convert_to_upper_case);
+ // cx.register_action_type(Editor::convert_to_lower_case);
+ // cx.register_action_type(Editor::convert_to_title_case);
+ // cx.register_action_type(Editor::convert_to_snake_case);
+ // cx.register_action_type(Editor::convert_to_kebab_case);
+ // cx.register_action_type(Editor::convert_to_upper_camel_case);
+ // cx.register_action_type(Editor::convert_to_lower_camel_case);
+ // cx.register_action_type(Editor::delete_to_previous_word_start);
+ // cx.register_action_type(Editor::delete_to_previous_subword_start);
+ // cx.register_action_type(Editor::delete_to_next_word_end);
+ // cx.register_action_type(Editor::delete_to_next_subword_end);
+ // cx.register_action_type(Editor::delete_to_beginning_of_line);
+ // cx.register_action_type(Editor::delete_to_end_of_line);
+ // cx.register_action_type(Editor::cut_to_end_of_line);
+ // cx.register_action_type(Editor::duplicate_line);
+ // cx.register_action_type(Editor::move_line_up);
+ // cx.register_action_type(Editor::move_line_down);
+ // cx.register_action_type(Editor::transpose);
+ // cx.register_action_type(Editor::cut);
+ // cx.register_action_type(Editor::copy);
+ // cx.register_action_type(Editor::paste);
+ // cx.register_action_type(Editor::undo);
+ // cx.register_action_type(Editor::redo);
+ // cx.register_action_type(Editor::move_page_up);
+ // cx.register_action_type::<MoveDown>();
+ // cx.register_action_type(Editor::move_page_down);
+ // cx.register_action_type(Editor::next_screen);
+ // cx.register_action_type::<MoveLeft>();
+ // cx.register_action_type::<MoveRight>();
+ // cx.register_action_type(Editor::move_to_previous_word_start);
+ // cx.register_action_type(Editor::move_to_previous_subword_start);
+ // cx.register_action_type(Editor::move_to_next_word_end);
+ // cx.register_action_type(Editor::move_to_next_subword_end);
+ // cx.register_action_type(Editor::move_to_beginning_of_line);
+ // cx.register_action_type(Editor::move_to_end_of_line);
+ // cx.register_action_type(Editor::move_to_start_of_paragraph);
+ // cx.register_action_type(Editor::move_to_end_of_paragraph);
+ // cx.register_action_type(Editor::move_to_beginning);
+ // cx.register_action_type(Editor::move_to_end);
+ // cx.register_action_type(Editor::select_up);
+ // cx.register_action_type(Editor::select_down);
+ // cx.register_action_type(Editor::select_left);
+ // cx.register_action_type(Editor::select_right);
+ // cx.register_action_type(Editor::select_to_previous_word_start);
+ // cx.register_action_type(Editor::select_to_previous_subword_start);
+ // cx.register_action_type(Editor::select_to_next_word_end);
+ // cx.register_action_type(Editor::select_to_next_subword_end);
+ // cx.register_action_type(Editor::select_to_beginning_of_line);
+ // cx.register_action_type(Editor::select_to_end_of_line);
+ // cx.register_action_type(Editor::select_to_start_of_paragraph);
+ // cx.register_action_type(Editor::select_to_end_of_paragraph);
+ // cx.register_action_type(Editor::select_to_beginning);
+ // cx.register_action_type(Editor::select_to_end);
+ // cx.register_action_type(Editor::select_all);
+ // cx.register_action_type(Editor::select_all_matches);
+ // cx.register_action_type(Editor::select_line);
+ // cx.register_action_type(Editor::split_selection_into_lines);
+ // cx.register_action_type(Editor::add_selection_above);
+ // cx.register_action_type(Editor::add_selection_below);
+ // cx.register_action_type(Editor::select_next);
+ // cx.register_action_type(Editor::select_previous);
+ // cx.register_action_type(Editor::toggle_comments);
+ // cx.register_action_type(Editor::select_larger_syntax_node);
+ // cx.register_action_type(Editor::select_smaller_syntax_node);
+ // cx.register_action_type(Editor::move_to_enclosing_bracket);
+ // cx.register_action_type(Editor::undo_selection);
+ // cx.register_action_type(Editor::redo_selection);
+ // cx.register_action_type(Editor::go_to_diagnostic);
+ // cx.register_action_type(Editor::go_to_prev_diagnostic);
+ // cx.register_action_type(Editor::go_to_hunk);
+ // cx.register_action_type(Editor::go_to_prev_hunk);
+ // cx.register_action_type(Editor::go_to_definition);
+ // cx.register_action_type(Editor::go_to_definition_split);
+ // cx.register_action_type(Editor::go_to_type_definition);
+ // cx.register_action_type(Editor::go_to_type_definition_split);
+ // cx.register_action_type(Editor::fold);
+ // cx.register_action_type(Editor::fold_at);
+ // cx.register_action_type(Editor::unfold_lines);
+ // cx.register_action_type(Editor::unfold_at);
+ // cx.register_action_type(Editor::gutter_hover);
+ // cx.register_action_type(Editor::fold_selected_ranges);
+ // cx.register_action_type(Editor::show_completions);
+ // cx.register_action_type(Editor::toggle_code_actions);
+ // cx.register_action_type(Editor::open_excerpts);
+ // cx.register_action_type(Editor::toggle_soft_wrap);
+ // cx.register_action_type(Editor::toggle_inlay_hints);
+ // cx.register_action_type(Editor::reveal_in_finder);
+ // cx.register_action_type(Editor::copy_path);
+ // cx.register_action_type(Editor::copy_relative_path);
+ // cx.register_action_type(Editor::copy_highlight_json);
+ // cx.add_async_action(Editor::format);
+ // cx.register_action_type(Editor::restart_language_server);
+ // cx.register_action_type(Editor::show_character_palette);
+ // cx.add_async_action(Editor::confirm_completion);
+ // cx.add_async_action(Editor::confirm_code_action);
+ // cx.add_async_action(Editor::rename);
+ // cx.add_async_action(Editor::confirm_rename);
+ // cx.add_async_action(Editor::find_all_references);
+ // cx.register_action_type(Editor::next_copilot_suggestion);
+ // cx.register_action_type(Editor::previous_copilot_suggestion);
+ // cx.register_action_type(Editor::copilot_suggest);
+ // cx.register_action_type(Editor::context_menu_first);
+ // cx.register_action_type(Editor::context_menu_prev);
+ // cx.register_action_type(Editor::context_menu_next);
+ // cx.register_action_type(Editor::context_menu_last);
hover_popover::init(cx);
scroll::actions::init(cx);
@@ -6,6 +6,49 @@ use parking_lot::{MappedRwLockReadGuard, RwLock, RwLockReadGuard};
use serde::Deserialize;
use std::any::{type_name, Any};
+/// 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.
+/// ```rust
+/// actions!(MoveUp, MoveDown, MoveLeft, MoveRight, Newline);
+/// ```
+/// More complex data types can also be actions. If you annotate your type with the `#[action]` proc macro,
+/// it will automatically
+/// ```
+/// #[action]
+/// pub struct SelectNext {
+/// pub replace_newest: bool,
+/// }
+///
+/// Any type A that satisfies the following bounds is automatically an action:
+///
+/// ```
+/// A: for<'a> Deserialize<'a> + PartialEq + Clone + Default + std::fmt::Debug + 'static,
+/// ```
+///
+/// The `#[action]` annotation will derive these implementations for your struct automatically. If you
+/// want to control them manually, you can use the lower-level `#[register_action]` macro, which only
+/// generates the code needed to register your action before `main`. Then you'll need to implement all
+/// the traits manually.
+///
+/// ```
+/// #[gpui::register_action]
+/// #[derive(gpui::serde::Deserialize, std::cmp::PartialEq, std::clone::Clone, std::fmt::Debug)]
+/// pub struct Paste {
+/// pub content: SharedString,
+/// }
+///
+/// impl std::default::Default for Paste {
+/// fn default() -> Self {
+/// Self {
+/// content: SharedString::from("🍝"),
+/// }
+/// }
+/// }
+/// ```
pub trait Action: std::fmt::Debug + 'static {
fn qualified_name() -> SharedString
where
@@ -19,6 +62,44 @@ pub trait Action: std::fmt::Debug + 'static {
fn as_any(&self) -> &dyn Any;
}
+// Types become actions by satisfying a list of trait bounds.
+impl<A> Action for A
+where
+ A: for<'a> Deserialize<'a> + PartialEq + Clone + Default + std::fmt::Debug + 'static,
+{
+ fn qualified_name() -> SharedString {
+ // todo!() remove the 2 replacement when migration is done
+ type_name::<A>().replace("2::", "::").into()
+ }
+
+ fn build(params: Option<serde_json::Value>) -> Result<Box<dyn Action>>
+ where
+ Self: Sized,
+ {
+ let action = if let Some(params) = params {
+ serde_json::from_value(params).context("failed to deserialize action")?
+ } else {
+ Self::default()
+ };
+ Ok(Box::new(action))
+ }
+
+ fn partial_eq(&self, action: &dyn Action) -> bool {
+ action
+ .as_any()
+ .downcast_ref::<Self>()
+ .map_or(false, |a| self == a)
+ }
+
+ fn boxed_clone(&self) -> Box<dyn Action> {
+ Box::new(self.clone())
+ }
+
+ fn as_any(&self) -> &dyn Any {
+ self
+ }
+}
+
type ActionBuilder = fn(json: Option<serde_json::Value>) -> anyhow::Result<Box<dyn Action>>;
lazy_static! {
@@ -84,43 +165,6 @@ macro_rules! actions {
};
}
-impl<A> Action for A
-where
- A: for<'a> Deserialize<'a> + PartialEq + Clone + Default + std::fmt::Debug + 'static,
-{
- fn qualified_name() -> SharedString {
- // todo!() remove the 2 replacement when migration is done
- type_name::<A>().replace("2::", "::").into()
- }
-
- fn build(params: Option<serde_json::Value>) -> Result<Box<dyn Action>>
- where
- Self: Sized,
- {
- let action = if let Some(params) = params {
- serde_json::from_value(params).context("failed to deserialize action")?
- } else {
- Self::default()
- };
- Ok(Box::new(action))
- }
-
- fn partial_eq(&self, action: &dyn Action) -> bool {
- action
- .as_any()
- .downcast_ref::<Self>()
- .map_or(false, |a| self == a)
- }
-
- fn boxed_clone(&self) -> Box<dyn Action> {
- Box::new(self.clone())
- }
-
- fn as_any(&self) -> &dyn Any {
- self
- }
-}
-
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct DispatchContext {
set: HashSet<SharedString>,