Runtime

use anathema::runtime::Runtime;
use anathema::backend::tui::TuiBackend;

let doc = Document::new("text 'hello world'");

let backend = TuiBackend::builder()
    .enable_alt_screen()
    .enable_raw_mode()
    .enable_mouse()
    .hide_cursor()
    .finish()
    .unwrap();

// finalize the backend (enable alt mode, ...)
backend.finalize();

let mut builder = Runtime::builder(doc, &backend);
runtime.fps(30); // default
runtime.finish(|rt| rt.run(&mut backend)).unwrap();

Registering components

Before components can be used in a template they have to be registered with the runtime.

let builder = Runtime::builder(document, &backend);

let component_id = builder.component(
    "my_comp",                                  // <- tag
    "template.aml",                             // <- template
    MyComponent,                                // <- component instance
    ComponentState,                             // <- state
);

You can use from_default if your component and its state implements Default. builder.from_default::<C>(comp, template) is equivalent to builder.component(comp, template, C::default(), C::State::default()).

File path vs embedded template

If the template is passed as a string it is assumed to be a path and hot reloading will be enabled by default.

To to pass a template (rather than a path to a template) call to_template on the template string:

static TEMPLATE: &str = include_str!("template.aml");

let component_id = builder.component(
    "my_comp",
    TEMPLATE.to_template(),
    MyComponent,
    ComponentState,
);

Hot reload

To disable hot reloading set the documents hot_reload = false.

let mut doc = Document::new("@index");
doc.hot_reload = false;

Multiple instances of a component

To repeatedly use a component in a template, e.g:

vstack
    @my_comp
    @my_comp
    @my_comp

The component has to be registered as a prototype using prototype (instead of component):

#![allow(unused)]
fn main() {
builder.prototype(
    "comp", 
    "text 'this is a template'",
    || MyComponent, 
    || ()
);
}

The main difference between registering a singular component vs a prototype is the closure creating an instance of the component and the state, rather than passing the actual component instance and state into the function.

Also note that prototypes does not have a component id and can not have messages emitted to them.

If your component and state is empty (zero-sized) and does not have any special functionality, you can also use template without passing the component and state closure. This is equivalent to builder.prototype(comp, template, || (), || ())

Global Events

You can register a global event handler on a runtime builder using the with_global_event_handler function, passing a closure to it that accepts 3 arguments and returns an Option<Event>. The arguments are of types Event, &mut TabIndex and &mut DeferredComponents.

You have to return the event that is supposed to be handled. When returning None, the event does not get handled. It is possible to change the event. You might want to do that if the event is a key event matching Ctrl + C, which can be checked using event.is_ctrl_c(). In that case you could return Some(Event::Stop) to shut down the runtime.

You can use the 2nd argument to change the currently selected element using the next and prev values.

Configuring the runtime

fps

Default: 30

The number of frames to (try to) render per second. Call this function with the number of fps.