16 releases
0.7.0-alpha.0 | Dec 13, 2022 |
---|---|
0.6.3 | Oct 10, 2023 |
0.6.2 | Sep 24, 2022 |
0.5.1 | Sep 12, 2022 |
0.1.0 | Sep 5, 2022 |
#956 in GUI
74KB
1.5K
SLoC
Intuitive
docs.rs Documentation
lib.rs
:
Intuitive
Intuitive is a component-based library for creating text-based user interfaces (TUIs) easily.
It is heavily inspired by React and SwiftUI, containing features that resemble functional components, hooks, and a declarative DSL.
Check out the Getting Started section below for a brief introduction to using Intuitive.
Design
The main focus of Intuitive is to simplify the implementation of full-terminal TUIs, such as lazygit. Intuitive attempts to make it easy to write reusable TUI components that are:
- readable (minimal-code)
- familiar (similar to existing web frameworks)
- fully-featured (conditional rendering, key/mouse-handling, responsive)
Getting Started
There are a few fundamental concepts within Intuitive:
- Writing components with
#[component(..)]
. - Using components with
render!
. - Using hooks.
A quick example of these three concepts in action looks like this:
use std::{thread, time::Duration};
use intuitive::{
component,
components::{Fixed, Padding, Section, Text},
element::Any as AnyElement,
error::Result,
render,
render::hooks::{UseEffect, UseState},
style::Color,
terminal::Terminal,
utils::layout::{Alignment, Amount},
};
#[component(Root)]
fn render() -> AnyElement {
let seconds = hooks.use_state(|| 0);
hooks.use_effect(|| {
thread::spawn({
let seconds = seconds.clone();
move || loop {
thread::sleep(Duration::from_secs(1));
seconds.update(|seconds| seconds + 1).unwrap();
}
});
});
render! {
Padding(amount: Amount::Percentage(10)) {
Fixed(height: Amount::Fixed(3)) {
Section(title: "Seconds", border: Color::Red) {
Text(
text: format!("This program has run for {} seconds", seconds.get()),
alignment: Alignment::Center
)
}
}
}
}
}
fn main() -> Result<()> {
Terminal::new()?.render(Root {})?;
Ok(())
}
Above, a Root
component is being defined using the #[component(..)]
attribute macro. It uses the
UseState
hook to create a State<i32>
, whose value is initially 0
. Then it uses the UseEffect
hook to
run a function when this component is first rendered. Specifically, it spawns a thread that increments seconds
once every second. This means that Root
will be re-rendered once a second, each time the seconds
is updated.
Then, Root::render
returns an element constructed using the Padding
, Fixed
, Section
, Text
components, and the render!
macro. Specifically, it constructs a section of text that will be centered on the
screen with a fixed height. The text displayed will show how many seconds have passed since the program started.
See the relevant documentation linked at the beginning of the Getting Started section for more details.
Dependencies
~4–12MB
~137K SLoC