ratatui_action/lib.rs
1#![warn(missing_docs)]
2#![warn(rustdoc::broken_intra_doc_links)]
3
4//! Semantic action descriptions for Ratatui applications.
5//!
6//! `ratatui-action` is the action-model half of the command palette experiment
7//! in `ratatui-labs`. It gives an application a way to name the capabilities it
8//! already has, attach user-facing metadata, describe simple required inputs,
9//! and receive resolved invocation requests from UI surfaces.
10//!
11//! The crate is intentionally surface-agnostic. A command palette, keybinding
12//! table, menu, help screen, toolbar, context menu, or automation layer can all
13//! read the same [`ActionSpec`](spec::ActionSpec) values and return
14//! [`ActionInvocation`](invocation::ActionInvocation) requests for the
15//! application to dispatch.
16//!
17//! The action model deliberately does not store callbacks. Applications keep
18//! ownership of state mutation, side effects, permissions, and error handling.
19//! This keeps the API usable by applications with very different state models
20//! and avoids turning the experiment into an application framework.
21//!
22//! The API is experimental. Callers can rely on the behavior documented here
23//! while experimenting, but names, module boundaries, and storage choices may
24//! change before any release with compatibility commitments.
25//!
26//! # Crate Model
27//!
28//! The primary types are:
29//!
30//! - [`ActionId`](id::ActionId) and [`InputId`](id::InputId) for stable identifiers.
31//! - [`ActionSpec`](spec::ActionSpec) and [`Availability`](spec::Availability) for describing
32//! actions and whether they can be invoked.
33//! - [`ActionInput`](input::ActionInput) and [`ActionChoice`](input::ActionChoice) for declaring
34//! values a UI surface must collect.
35//! - [`ActionArgs`](invocation::ActionArgs), [`ActionInvocation`](invocation::ActionInvocation),
36//! and [`InvocationSource`](invocation::InvocationSource) for returning resolved work to the
37//! application.
38//!
39//! A UI surface should treat action specs as input data and invocations as
40//! output data. The application remains the only place that knows how to perform
41//! an action.
42//!
43//! Module map:
44//!
45//! - [`id`] defines stable [`ActionId`](id::ActionId) and [`InputId`](id::InputId) keys.
46//! - [`spec`] defines [`ActionSpec`](spec::ActionSpec) and [`Availability`](spec::Availability).
47//! - [`input`] defines [`ActionInput`](input::ActionInput) and
48//! [`ActionChoice`](input::ActionChoice).
49//! - [`invocation`] defines [`ActionArgs`](invocation::ActionArgs),
50//! [`ActionInvocation`](invocation::ActionInvocation), and
51//! [`InvocationSource`](invocation::InvocationSource).
52//!
53//! # Basic Flow
54//!
55//! A typical integration builds a list of [`spec::ActionSpec`] values, passes
56//! them to a UI surface, and dispatches the returned
57//! [`invocation::ActionInvocation`].
58//!
59//! ```
60//! use ratatui_action::invocation::{ActionInvocation, InvocationSource};
61//! use ratatui_action::spec::ActionSpec;
62//!
63//! let action = ActionSpec::new("document.open", "Open document");
64//! let invocation = ActionInvocation::new(action.id().clone(), InvocationSource::Palette);
65//!
66//! match invocation.id().as_str() {
67//! "document.open" => {
68//! // Open the document in application-owned state.
69//! }
70//! _ => {}
71//! }
72//! ```
73//!
74//! # Inputs And Arguments
75//!
76//! Actions can declare simple inputs. The UI surface collects values for those
77//! inputs and returns them as [`invocation::ActionArgs`].
78//!
79//! ```
80//! use ratatui_action::id::InputId;
81//! use ratatui_action::input::{ActionChoice, ActionInput};
82//! use ratatui_action::invocation::{ActionArgs, ActionInvocation, InvocationSource};
83//! use ratatui_action::spec::ActionSpec;
84//!
85//! let action = ActionSpec::new("theme.switch", "Switch theme").with_input(ActionInput::Choice {
86//! id: InputId::new("theme"),
87//! label: "Theme".into(),
88//! choices: vec![ActionChoice::new("github-dark", "GitHub Dark")],
89//! });
90//!
91//! let mut args = ActionArgs::new();
92//! args.insert("theme", "github-dark");
93//! let invocation =
94//! ActionInvocation::with_args(action.id().clone(), args, InvocationSource::Palette);
95//!
96//! assert_eq!(
97//! invocation.args().get(&InputId::new("theme")),
98//! Some("github-dark")
99//! );
100//! ```
101//!
102//! # Compatibility Boundary
103//!
104//! Public structs use constructors, accessors, and builder-style modifiers
105//! instead of public fields. That keeps the experimental API flexible enough to
106//! add validation, change storage, or introduce borrowed view data before
107//! publication. Prefer matching on stable identifiers at the application
108//! dispatch boundary rather than depending on current struct layout.
109//!
110//! # Modules
111//!
112//! - [`id`] owns stable action and input identifiers.
113//! - [`spec`] owns action metadata and availability.
114//! - [`input`] owns input declarations and choice values.
115//! - [`invocation`] owns resolved arguments and invocation requests.
116//!
117//! # Related Crates
118//!
119//! `ratatui-command-palette` consumes these action specs and provides command
120//! palette state, view data, and rendering. The `ratatui-labs` crate re-exports
121//! this crate under `ratatui_labs::action` as a convenience namespace while the
122//! experiment is being evaluated.
123
124pub mod id;
125pub mod input;
126pub mod invocation;
127pub mod spec;