Closed orhun closed 3 weeks ago
I think this would seem like an improper use of macros that would cause more confusion than benefits.
This pattern seems like it's akin to tokio's main macro. Tokio requires this because it's translating an async function into a sync one by rewriting the async part to be an async closure that runs on the runtime. But we're not really doing anything like that in this. A strong downside is that it seems to make using color_eyre or anyhow more difficult
Instead of this, I'd suggest making the following method that accepts a Fn / FnMut / FnOnce like:
fn with_terminal<F, T, E>(f: F) -> Result<T, E>
where F: Fn(Terminal) -> Result<T, E> {
let terminal = ratatui::init();
let result = f(terminal);
ratatui::restore();
result
}
Then:
fn main() -> Result<()> {
color_eyre::install()?;
ratatui::with_terminal(|terminal| {
loop {
terminal
.draw(|frame: &mut Frame| frame.render_widget(Text::raw("Hello World!"), frame.area()))
.expect("failed to draw frame");
if matches!(event::read().expect("failed to read event"), Event::Key(_)) {
break;
}
}
});
}
But given that we've just introduced ratatui::init, I'd suggest letting it breathe a little before introducing more complexity.
A question I'd use for when to use a macro or not is "is this a case where the macro code has a significant benefit over plain rust code?". I think the answer is probably "no" here.
Yeah, I agree. Adding a macro before we have more complexity seems unnecessary. It was a cool experiment nevertheless :)
We can come back to this again in the future if needed.
Would love to get @kdheepak's input on this as well.
I like the with_terminal
approach but agree about exploring writing code withratatui::init
for a bit.
Let's give it some time then :)
Makes it possible to write this code:
This was an idea brought up in my FrOSCon talk, I liked it and decided to give it a try.