Skip to main content

Module plugin

Module plugin 

Source
Expand description

Components from plugins (0.0.14 workstream 4): a PluginComponent that a plugin registered by name with PluginRegistrar::component, mounted as a Component beside the built-ins.

A plugin depends on rs-rich-plugin-api and core only, so its components speak that crate’s small contract: keys by name, text answers. A PluginView translates both ways. Its output is the text the plugin answers with; map it into a container’s output like any other child. Its keys are listed under the registered name, so a help overlay shows them and configuration rebinds them (counter.up = k).

A plugin component that panics does not take the app down: the view shows what went wrong, stops taking focus and ignores events.

use std::sync::Arc;

use rich_ext::plugin::component::{
    ComponentContext, ComponentEvent, ComponentFlow, ComponentView, PluginComponent,
};
use rich_ext::plugin::{Plugin, PluginError, PluginMetadata, PluginRegistrar};
use rich_ext::registry::ExtensionRegistry;
use rich_interact::compose::{ComponentExt, Split};
use rich_interact::plugin::PluginView;
use rich_interact::{headless, Flow, Outcome, Select};

#[derive(Default)]
struct Counter(u32);

impl PluginComponent for Counter {
    fn handle(&mut self, event: &ComponentEvent, _: &ComponentContext<'_>) -> ComponentFlow {
        match event.key() {
            Some("up") => self.0 += 1,
            Some("enter") => return ComponentFlow::Done(self.0.to_string()),
            _ => return ComponentFlow::Ignored,
        }
        ComponentFlow::Continue
    }
    fn render(&self, context: &ComponentContext<'_>) -> ComponentView {
        ComponentView::new(context.markup(&format!("count {}", self.0)))
    }
}

struct Counters;

impl Plugin for Counters {
    fn metadata(&self) -> PluginMetadata {
        PluginMetadata::new("counters", "Counters", "1.0.0")
    }
    fn register(&self, registrar: &mut dyn PluginRegistrar) -> Result<(), PluginError> {
        registrar.component("counter", Arc::new(|| Box::new(Counter::default())));
        Ok(())
    }
}

let mut registry = ExtensionRegistry::new();
registry.add_plugin(&Counters).unwrap();
let counter = PluginView::mount(&registry, "counter").unwrap();
let app = Split::horizontal(
    counter.map(Flow::Done),
    Select::new("Pick", ["a", "b"]).map(|pick| Flow::Done(pick.to_string())),
);
let script = headless::Script::new().keys("up up enter");
let (outcome, _) = headless::run(app, script, 40, 4);
assert_eq!(outcome.unwrap(), Outcome::Done("2".to_string()));

Structs§

PluginView
A plugin’s component as a Component whose answer is the plugin’s text. See the module.
UnknownComponent
No component is registered under a name, or its factory failed.