React voor de Terminal in Rust met Flexbox en Hooks
Als je ooit een console-interface in Rust hebt geschreven, heb je waarschijnlijk Ratatui gebruikt. Het is een solide bibliotheek die tientallen geweldige utilities aandrijft. Maar zodra een project verder gaat dan een paar knoppen, begint de vertrouwde sleur: je moet het scherm handmatig in rechthoeken verdelen met Layout, percentages en margins berekenen, en events door enorme match-constructies threaden. In webontwikkeling zijn we allang gewend aan de componentbenadering en flexbox, maar in de terminal schrijven we nog steeds alsof het 1998 is.
Ik ontdekte onlangs de iocraft crate, waarvan de auteur dit probleem radicaal heeft opgelost. Ze hebben de ervaring van React, SwiftUI en Ink direct naar de wereld van systeemprogrammering in Rust gebracht.
Een Vertrouwd Componentmodel
De bibliotheek is gebouwd rond de element! macro. Het construeert een elementboom met syntax die sterk lijkt op JSX of declaratief Swift. Geen handmatige coördinaatberekeningen. De layout wordt afgehandeld door de taffy engine, die de flexbox-specificatie trouw implementeert voor Rust.
Zo ziet een klassieke Hello World eruit:
use iocraft::prelude::*;
fn main() {
element! {
View(
border_style: BorderStyle::Round,
border_color: Color::Blue,
) {
Text(content: "Hello, world!")
}
}
.print();
}
We verpakken simpelweg Text in een View container, passen een afgeronde blauwe rand toe, en roepen .print() aan. Het resultaat gaat naar standard output zonder de terminal in fullscreen-modus te hoeven capturen. Dit is handig als je netjes geformatteerde console command output of logs nodig hebt in plaats van een interactief dashboard.
Hooks en State Binnen de Terminal
De gelijkenis met frontend-ontwikkeling houdt niet op bij statische layout. Voor dynamische interfaces voegde de auteur de #[component] macro en vertrouwde lifecycle hooks toe.
In de onderstaande code houdt de Counter component zijn eigen lokale state bij via use_state en start een background async timer via use_future:
use iocraft::prelude::*;
use std::time::Duration;
#[component]
fn Counter(mut hooks: Hooks) -> impl Into<AnyElement<'static>> {
let mut count = hooks.use_state(|| 0);
hooks.use_future(async move {
loop {
smol::Timer::after(Duration::from_millis(100)).await;
count += 1;
}
});
element! {
Text(color: Color::Blue, content: format!("counter: {}", count))
}
}
fn main() {
smol::block_on(element!(Counter).render_loop()).unwrap();
}
Wanneer de count waarde verandert, triggert iocraft een hertekening van het getroffen deel van het scherm. De engine optimaliseert prop passing: context en parameters worden by reference doorgegeven, dus er zijn geen onnodige memory allocations of klonen van zware structuren hier.
Wat de Bibliotheek in de Praktijk Kan Doen
De ingebouwde primitives zijn genoeg om interfaces van elke complexiteit te bouwen. De repository voorbeelden bevatten kant-en-klare recepten voor de meest voorkomende taken:
- Fullscreen applicaties met tekstinvoer en focus handling
- Multi-column adaptieve tabellen
- Interactieve formulieren met validatie
- Calculators en overlays met drijvende modal windows
Laten we kijken hoe complexe element-layouts er in de praktijk uitzien:
Styling is cross-platform. Applicaties renderen even correct in standaard Linux/macOS terminals en in Windows PowerShell.
Is het de Moeite Waard om over te Schakelen van Ratatui
Als je al een complexe terminal client hebt geschreven in Ratatui, is er niet veel punt in deze van scratch herschrijven. Ratatui is volwassener, met een grote community eromheen en tientallen third-party widgets die ervoor geschreven zijn.
Maar als je een nieuwe CLI utility start, een intern tool voor je team schrijft, of gewoon moe bent van handmatig terminal rijen en kolommen tellen, bespaart iocraft veel tijd. Declaratieve syntax maakt de code compacter, en flexbox elimineert de hoofdpijn van het resizen van windows.
Het project wordt gedistribueerd onder dual MIT / Apache-2.0 licentiëring. De documentatie op docs.rs is gedetailleerd genoeg, en de voorbeeld source code in de repository laat duidelijk zien hoe je je eigen componenten bouwt.
Gerelateerde projecten