Intuitive: A crate for writing TUIs declaratively
I've written a few TUIs in Rust, and the amount of code needed for the UI components always felt excessive. For a while, I had been toying with the idea of being able to write components in a SwiftUI-like DSL and have state managed like React does with hooks. Intuitive is the result of that frustration and desire.
Resources
The documentation is on docs.rs and the source is on GitHub.
Example
A small example looks something like this:
use intuitive::{
component,
components::{stack::Flex::*, HStack, Section, Text, VStack},
error::Result,
on_key, render,
state::use_state,
terminal::Terminal,
};
#[component(Root)]
fn render() {
let text = use_state(|| String::new());
let on_key = on_key! { [text]
KeyEvent { code: Char(c), .. } => text.mutate(|text| text.push(c)),
KeyEvent { code: Backspace, .. } => text.mutate(|text| text.pop()),
KeyEvent { code: Esc, .. } => event::quit(),
};
render! {
VStack(flex: [Block(3), Grow(1)], on_key) {
Section(title: "Input") {
Text(text: text.get())
}
HStack(flex: [1, 2, 3]) {
Section(title: "Column 1")
Section(title: "Column 2")
Section(title: "Column 3")
}
}
}
}
fn main() -> Result<()> {
Terminal::new(Root::new())?.run()
}
Would produce a TUI like this. In fewer than 40 lines we have a complex layout with an input box. Also, as you can see this resembles SwiftUI in the rendering syntax, and React in the use_state hook-like state management.
There are more examples in the examples section of the repository and on the recipes section of the documentation.
Disclaimer
Intuitive already supports automatic resizing, key-handlers, and text styling. Mouse event support is almost ready (committed in the GitHub repo but has yet to be released). However, right now it's in between a proof-of-concept and an alpha version of the crate. I'm in the process of re-writing one of my larger TUI apps using Intuitive, and so far it has proven itself as a way to greatly reduce the amount of code necessary for a TUI.
Additionally, Intuitive's main focus is to make it as easy as possible to write (a readable) TUI implementation, even if this means a slight cost in performance.
Thanks!
I would be grateful for any feedback on the idea, design, and/or the implementation. I hope it's well-received, thanks!