pub trait Action: Any + Send {
// Required methods
fn boxed_clone(&self) -> Box<dyn Action>;
fn partial_eq(&self, action: &dyn Action) -> bool;
fn name(&self) -> &'static str;
fn name_for_type() -> &'static str
where Self: Sized;
fn build(value: Value) -> Result<Box<dyn Action>>
where Self: Sized;
// Provided methods
fn action_json_schema(_: &mut SchemaGenerator) -> Option<Schema>
where Self: Sized { ... }
fn deprecated_aliases() -> &'static [&'static str]
where Self: Sized { ... }
fn deprecation_message() -> Option<&'static str>
where Self: Sized { ... }
fn documentation() -> Option<&'static str>
where Self: Sized { ... }
}Expand description
An action is a named command that the app can run, such as saving or moving the cursor up.
Declaring an action separates what the app can do from the keys that trigger it. A
KeyBinding maps keystrokes to an action, a menu or button can run the
same action, and InteractiveElement::on_action
handlers receive it. See keyboard input for
the dispatch order.
Declare unit actions with actions!, and actions with data with
#[derive(Action)]. The derive macro implements every method of this trait and registers the
action by name, so you rarely write an impl yourself.
§Examples
This action has a field, so the keymap entry carries a value. The handler runs when ctrl-r
is typed while the Counter element has focus:
use gpui::{Action, Context, FocusHandle, KeyBinding, TestApp, Window, div, prelude::*};
#[derive(Clone, PartialEq, serde::Deserialize, schemars::JsonSchema, Action)]
#[action(namespace = action_trait_docs)]
pub struct Repeat {
pub times: usize,
}
struct Counter {
focus_handle: FocusHandle,
total: usize,
}
impl Render for Counter {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div()
.key_context("Counter")
.track_focus(&self.focus_handle)
.on_action(cx.listener(|counter, action: &Repeat, _window, _cx| {
counter.total += action.times;
}))
}
}
let mut app = TestApp::new();
app.update(|cx| cx.bind_keys([KeyBinding::new("ctrl-r", Repeat { times: 2 }, Some("Counter"))]));
let mut window = app.open_window(|window, cx| {
let focus_handle = cx.focus_handle();
window.focus(&focus_handle, cx);
Counter { focus_handle, total: 0 }
});
window.simulate_keystrokes("ctrl-r");
assert_eq!(window.read(|counter, _| counter.total), 2);§Derive attributes
#[derive(Action)] requires Clone and PartialEq. A struct with fields also requires
serde::Deserialize and schemars::JsonSchema, which build the action from JSON and describe
its shape. A unit struct, or a type with no_json, needs neither.
Options go in #[action(...)], separated by commas:
namespace = identprefixes the name, sonamespace = editoronSavegiveseditor::Save. The value is an identifier, not a string.name = "Text"sets the name without a namespace. The name must not contain::.no_jsonmakesAction::buildalways return an error and makesAction::action_json_schemareturnNone. The type then doesn’t needDeserializeorJsonSchema.no_registerskips registration. The action can’t be invoked by name or built from JSON.deprecated_aliases = ["editor::OldName"]keeps old names working. Each old name must not be the name of a registered action.deprecated = "Message"attaches a deprecation message, whichAction::deprecation_messagereturns.
§Manual implementation
To control every method yourself, implement the trait and call
register_action!. It registers the action without the rest of the
derive.
use gpui::{SharedString, register_action};
#[derive(Clone, PartialEq, Eq, serde::Deserialize, schemars::JsonSchema)]
pub struct Paste {
pub content: SharedString,
}
impl gpui::Action for Paste {
}
register_action!(Paste);Required Methods§
Sourcefn boxed_clone(&self) -> Box<dyn Action>
fn boxed_clone(&self) -> Box<dyn Action>
Returns a boxed copy of this action.
Keymaps clone their bindings with this, so each binding owns its own action value.
Sourcefn partial_eq(&self, action: &dyn Action) -> bool
fn partial_eq(&self, action: &dyn Action) -> bool
Returns whether action is the same action type as self and has equal fields.
Returns false for an action of a different type.
Sourcefn name(&self) -> &'static str
fn name(&self) -> &'static str
Returns the action’s full name, such as editor::MoveUp.
Keymap files refer to actions by this name, and the name is what App::build_action
accepts.
Sourcefn name_for_type() -> &'static strwhere
Self: Sized,
fn name_for_type() -> &'static strwhere
Self: Sized,
Returns the same name as name, for the type rather than a value.
Sourcefn build(value: Value) -> Result<Box<dyn Action>>where
Self: Sized,
fn build(value: Value) -> Result<Box<dyn Action>>where
Self: Sized,
Builds this action from JSON, as a keymap entry supplies it.
value is {} for an action that takes no input. The derive macro reads value with
serde, so the JSON must match the type’s fields. Returns an error if it doesn’t match, and
always returns an error for an action declared with no_json. To build an action by name,
use App::build_action.
Provided Methods§
Sourcefn action_json_schema(_: &mut SchemaGenerator) -> Option<Schema>where
Self: Sized,
fn action_json_schema(_: &mut SchemaGenerator) -> Option<Schema>where
Self: Sized,
Returns the JSON schema of the input this action accepts, or None if it takes no input.
The derive macro fills this in from schemars::JsonSchema. Schema generation for keymap
files uses it.
Sourcefn deprecated_aliases() -> &'static [&'static str]where
Self: Sized,
fn deprecated_aliases() -> &'static [&'static str]where
Self: Sized,
Returns the old names that still invoke this action. They are set with the
deprecated_aliases option of #[action(...)].
Sourcefn deprecation_message() -> Option<&'static str>where
Self: Sized,
fn deprecation_message() -> Option<&'static str>where
Self: Sized,
Returns the deprecation message, or None if the action isn’t deprecated. It is set with
the deprecated option of #[action(...)].
Implementations§
Trait Implementations§
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".