Expand description
Write Standard Code plugins in Rust.
Every plugin is a wasm component against the WIT package
standard:plugin@2.0.0, built for wasm32-wasip2. This crate wraps the
generated bindings in a safe API:
- UI plugins (
UiPlugin,#[ui]) run in every viewer and paintSurfaces in the cell model (Cells) or the graphics model (Pixels). They are side-effect free: effects that must happen once go throughclaimsor a companion daemon (calls), andview::is_drivingsays whether the user is controlling this viewer. - Daemon plugins (
daemon::DaemonPlugin,#[daemon]) run insidestandarddwith an asyncrunloop on a small executor.
The account interfaces (values, live, events, calls,
config, secrets, account) are shared by both. Every call the
plugin’s manifest grants do not cover returns Error::GrantDenied.
A UI plugin is #![no_std] (the std library would import the WASI CLI
world, which a viewer does not offer); alloc is available and this
crate’s default runtime feature supplies the allocator and panic
handler. A UI plugin, in full:
//! A sidebar card: the time since the viewer started and a bar of the
//! seconds. It repaints once a second and only while the card is visible.
//!
//! Manifest (`bundle/standard-plugin.json`):
//!
//! ```json
//! {
//! "apiVersion": 2, "kind": "ui", "id": "clock-card", "version": "0.1.0",
//! "module": "clock_card.wasm",
//! "surfaces": [{ "id": "card", "anchor": "sidebar.card", "model": "cells", "height": 2 }],
//! "grants": {}
//! }
//! ```
#![no_std]
use standard_plugin::prelude::*;
#[standard_plugin::ui]
struct ClockCard {
card: Surface<Cells>,
shown: Option<u64>,
}
impl UiPlugin for ClockCard {
fn activate(_cx: &mut Context) -> Self {
Self {
card: Surface::new("card"),
shown: None,
}
}
fn frame(&mut self, frame: &Frame) {
let second = frame.now_ms() / 1000;
if self.shown != Some(second) {
self.shown = Some(second);
let (cols, _) = self.card.size();
let time = format!(
"{:02}:{:02}:{:02}",
second / 3600 % 24,
second / 60 % 60,
second % 60
);
self.card.text(0, 0, &time, Style::fg(Colour::FG).bold());
let fraction = (second % 60) as f32 / 60.0;
let track = Style::fg(Colour::RECEDE_FG);
self.card.bar(
Area::new(0, 1, cols, 1),
fraction,
Style::fg(Colour::ACCENT),
track,
);
// Publishes only the cells that changed.
let _ = self.card.commit();
}
// The next second boundary: an idle viewer wakes once a second.
frame.wake_at((second + 1) * 1000);
}
fn event(&mut self, event: Event, _cx: &mut Context) {
if let Event::Resize { .. } = event {
// The card has a new, empty buffer: repaint on the next frame.
self.shown = None;
}
}
}More: the guide pages (the same Markdown files are this crate’s
docs/ directory, and standard-plugin guide prints them), and the
compiled examples in this crate’s examples/ directory. testing (on
non-wasm targets) runs a plugin against an in-process host in ordinary
cargo test.
Re-exports§
pub use api::Json;pub use api::Target;pub use api::account;pub use api::calls;pub use api::calls;pub use api::capabilities;pub use api::claims;pub use api::claims;pub use api::config;pub use api::events;pub use api::events;pub use api::health;pub use api::live;pub use api::live;pub use api::secrets;pub use api::url;pub use api::values;pub use api::values;pub use api::view;pub use draw::Area;pub use draw::Image;pub use draw::Shapes;pub use draw::font;pub use surface::AnySurface;pub use surface::AnySurfaceMut;pub use surface::Cell;pub use surface::Cells;pub use surface::Instances;pub use surface::Pixels;pub use surface::Surface;pub use libm;
Modules§
- api
- The account interfaces shared by UI and daemon plugins, and the viewer interfaces of UI plugins.
- daemon
- Daemon plugins: run inside
standarddon the machines the plugin is enabled on, never render, and may reach the machine through granted system interfaces (process,watch,panes; with thewasifeature, files, sockets and HTTP). - draw
- Vector shapes drawn into a plugin’s own surface buffer, in either model.
- guide
- The guides, as pages of this documentation. The same Markdown files are
this crate’s
docs/directory, where links between guides resolve, andstandard-plugin guideprints them for the SDK version a plugin’sCargo.lockresolves. - prelude
- What most plugins import:
use standard_plugin::prelude::*;. - sources
- The sources this SDK version is built from, for tools: the
standard-pluginCLI checks components againstsources::WITand scaffolds new plugins from the examples, so both always match the SDK the new plugin depends on. - surface
- Surfaces: typed views over the double-buffered shared buffer a UI plugin paints and the viewer samples.
- testing
- Run a plugin under
cargo test, against an in-process host.
Structs§
- Attrs
- Cell attribute bits.
- Context
- What a plugin is called with besides a frame: its configuration, and handles to every interface.
- Frame
- One frame callback.
- Geometry
- The size a surface currently has.
cols/rowsare cells;px_w/px_hthe pixel size of the graphics model (zero while the viewer has no pixel geometry);cell_px_w/cell_px_hthe pixel size of one cell. - Key
- A key on the surface with input focus.
- Modifiers
- Modifier keys held during a key or pointer event.
- Pointer
- The pointer over one of the plugin’s surfaces.
- Rect
- A rectangle in cells (cell model) or pixels (graphics model).
- Rgba
- One RGBA8 pixel of the graphics model (straight, not premultiplied,
alpha). In the buffer: the bytes
r, g, b, a. - Style
- How a cell paints: foreground, background, attributes.
- Theme
Slot - A theme colour slot: the viewer resolves it to its current theme, so a plugin follows the user’s terminal colours and “receded” (grayed out) text stays readable on every background.
Enums§
- Button
- Colour
- A cell colour. Encoded in the buffer as a
u32whose top byte is the model: - Error
- Why a host call or a surface operation did not run.
- Event
- What the host tells a plugin besides frames.
- KeyCode
- Which key. A character key is the character it types; the named keys are the WIT’s vocabulary. Escape never arrives: it closes the surface.
- KeyPhase
- Pointer
Kind - Power
- Whether the viewer’s machine is saving power.
Traits§
- UiPlugin
- A UI plugin: one instance runs in every viewer on the account.
Functions§
- recede
rgbblendedpercentof the way towardtoward(both0xRRGGBB), channel by channel: the viewer’s recede. With the theme’s background astowardit is “grayed out” (seecrate::view::Theme::recede).
Type Aliases§
- Result
Result<T, Error>.
Attribute Macros§
- daemon
- Exports the annotated type, which implements
daemon::DaemonPlugin, as the component’sdaemon-pluginworld. Exports the annotated type, which implementsstandard_plugin::daemon::DaemonPlugin, as the plugin’sdaemon-pluginworld. - ui
- Exports the annotated type, which implements
UiPlugin, as the component’sui-pluginworld. Put it on the plugin’s struct or enum, or on itsimpl UiPlugin for ...block; once per plugin crate. Exports the annotated type, which implementsstandard_plugin::UiPlugin, as the plugin’sui-pluginworld.