A small PoC for deriving Ratatui Widget
trait from a struct. Inspired by:
https://users.rust-lang.org/t/writing-similar-code-for-each-field-in-struct-without-derive/108786.
Given the following type:
#[derive(Widget)]
pub struct Recipe {
pub name: String,
pub description: String,
}
and the following rendering code:
let recipe = Recipe {
name: "Pancakes".to_string(),
description: "Delicious pancakes".to_string(),
};
recipe.render(buf.area, buf);
This outputs:
name: Pancakes
description: Delicious pancakes
The macro expands to:
pub struct Recipe {
pub name: String,
pub description: String,
}
impl Widget for &Recipe {
fn render(self, area: Rect, buf: &mut Buffer) {
let mut y = area.y;
let row = Rect::new(area.x, y, area.width, area.height - y);
self.render_name(row, buf);
y += 1;
let row = Rect::new(area.x, y, area.width, area.height - y);
self.render_description(row, buf);
y += 1;
}
}
impl Recipe {
fn render_name(&self, area: Rect, buf: &mut Buffer) {
const LABEL_WIDTH: u16 = 13u16;
let label_area = Rect::new(area.x, area.y, LABEL_WIDTH, 1);
let value_area = Rect::new(
area.x + LABEL_WIDTH,
area.y,
area.width - LABEL_WIDTH,
1,
);
ratatui::text::Text::raw(" name: ").render(label_area, buf);
ratatui::text::Text::raw(self.name.to_string()).render(value_area, buf);
}
fn render_description(&self, area: Rect, buf: &mut Buffer) {
const LABEL_WIDTH: u16 = 13u16;
let label_area = Rect::new(area.x, area.y, LABEL_WIDTH, 1);
let value_area = Rect::new(
area.x + LABEL_WIDTH,
area.y,
area.width - LABEL_WIDTH,
1,
);
ratatui::text::Text::raw("description: ").render(label_area, buf);
ratatui::text::Text::raw(self.description.to_string()).render(value_area, buf);
}
}