Skip to main content

Crate tuirealm_derive

Crate tuirealm_derive 

Source
Expand description

§tuirealm_derive

tuirealm_derive provides the derive macro which automatically implements Component for a tui-realm component.

tuirealm_derive is a crate which implements the procedural macro Component which can be used to automatically implement the Component trait for a tui-realm AppComponent. Indeed, as you already know if you’re a tui-realm user, you’ve got two kind of component entities:

  • Component: generic graphic component which is not bridged to the application and is “reusable”
  • AppComponent: which uses a Component as “backend” and is bridged to the application using the Event -> Msg system.

The AppComponent wraps the Component along with additional states. Since AppComponent MUST implement Component, we need to implement the Component trait too, which in most of the cases it will just call the Component methods on the inner component field. This is obviously kinda annoying to do for each component. That’s why I implemented this procedural macro, which will automatically implement this logic on your component.

So basically instead of implementing Component for your components, you can just do as follows:

#[derive(Component)]
pub struct IpAddressInput {
  component: Input,
}

With the directive #[derive(Component)] we don’t have to implement the component trait.

❗ In order to work, the procedural macro requires you to name the “inner” component as component as I did in the example.

If we give a deeper look at the macro, we’ll see that what it does is:

impl Component for IpAddressInput {
    fn view(&mut self, frame: &mut Frame, area: Rect) {
        self.component.view(frame, area);
    }

    fn query<'a>(&'a self, attr: Attribute) -> Option<QueryResult<'a>> {
        self.component.query(attr)
    }

    fn attr(&mut self, query: Attribute, attr: AttrValue) {
        self.component.attr(query, attr)
    }

    fn state(&self) -> State {
        self.component.state()
    }

    fn perform(&mut self, cmd: Cmd) -> CmdResult {
        self.component.perform(cmd)
    }
}

§Get Started

In order to get started with tuirealm_derive all you need to do is to add tui-realm to your dependencies and enable the derive feature if needed.

If you’re using the default features:

[dependencies]
tuirealm = "^4"

If you’re not using the default features, be sure to enable the derive feature:

[dependencies]
tuirealm = { version = "^4", default-features = false, features = ["derive", "crossterm"] }

Then you need to include tuirealm in your project using the macro use directive:

src/lib.rs

#[macro_use]
extern crate tuirealm;

and finally derive Component on your components:


#[derive(Component)]
pub struct MyComponent {
  component: Radio,
}

❗ In order to work, the procedural macro requires you to name the “inner” component as component as I did in the example.

And ta-dah, you’re ready to go 🎉

§Custom field names

By default a field of name component will be used as can be seen in the earlier examples, but this can be customized.

First option is to use a container-level attribute:

#[derive(Component)]
#[component("radio")]
pub struct MyComponent1 {
  radio: Radio,
}

#[derive(Component)]
#[component = "radio"]
pub struct MyComponent2 {
  radio: Radio,
}

Or field-level attribute:

#[derive(Component)]
pub struct MyComponent {
  #[component]
  radio: Radio,
}

❗ Only one field can be the component and container- & field-level attributes cannot be used together.

Tuple Structs are also supported:

#[derive(Component)]
pub struct MyComponent1(Radio, SomeOtherType);

#[derive(Component)]
pub struct MyComponent2(SomeOtherType, #[component] Radio);

Derive Macros§

Component