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.