React pour le Terminal en Rust avec Flexbox et Hooks
Si vous avez déjà écrit une interface console en Rust, vous avez probablement utilisé Ratatui. C'est une bibliothèque solide qui alimente des dizaines d'excellents utilitaires. Mais dès qu'un projet dépasse quelques boutons, la corvée familière commence : vous devez diviser manuellement l'écran en rectangles avec Layout, calculer les pourcentages et les marges, et enchaîner les événements à travers des constructions massives match. Dans le développement web, nous sommes depuis longtemps habitués à l'approche par composants et au flexbox, mais dans le terminal, nous écrivons encore souvent comme si c'était 1998.
J'ai récemment découvert la crate iocraft, dont l'auteur a résolu ce problème de manière radicale. Il a apporté l'expérience de React, SwiftUI et Ink directement dans le monde de la programmation système en Rust.
Un modèle de composants familier
La bibliothèque est construite autour de la macro element!. Elle construit un arbre d'éléments en utilisant une syntaxe qui ressemble fortement à JSX ou à Swift déclaratif. Pas de calculs de coordonnées manuels. La mise en page est gérée par le moteur taffy, qui implémente fidèlement la spécification flexbox pour Rust.
Voici à quoi ressemble un classique Hello World :
use iocraft::prelude::*;
fn main() {
element! {
View(
border_style: BorderStyle::Round,
border_color: Color::Blue,
) {
Text(content: "Hello, world!")
}
}
.print();
}
Nous enveloppons simplement Text dans un conteneur View, appliquons une bordure bleue arrondie, et appelons .print(). Le résultat est envoyé vers la sortie standard sans avoir besoin de capturer le terminal en mode plein écran. C'est pratique si vous avez besoin d'une sortie de commande console ou de logs bien formatés plutôt qu'un tableau de bord interactif.
Hooks et état à l'intérieur du terminal
La ressemblance avec le développement frontend ne s'arrête pas à la mise en page statique. Pour les interfaces dynamiques, l'auteur a ajouté la macro #[component] et des hooks de cycle de vie familiers.
Dans le code ci-dessous, le composant Counter maintient son propre état local via use_state et démarre un timer async en arrière-plan 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();
}
Lorsque la valeur count change, iocraft déclenche un redessin de la partie affectée de l'écran. Le moteur optimise le passage des props : le contexte et les paramètres sont passés par référence, donc il n'y a pas d'allocations mémoire inutiles ni de clonage de structures lourdes ici.
Ce que la bibliothèque peut faire en pratique
Les primitives intégrées suffisent à construire des interfaces de n'importe quelle complexité. Les exemples du dépôt contiennent des recettes prêtes à l'emploi pour les tâches les plus courantes :
- Applications plein écran avec saisie de texte et gestion du focus
- Tableaux adaptatifs multi-colonnes
- Formulaires interactifs avec validation
- Calculatrices et superpositions avec fenêtres modales flottantes
Voyons à quoi ressemblent les mises en page d'éléments complexes en pratique :
Le style est multiplateforme. Les applications s'affichent aussi correctement dans les terminaux Linux/macOS standard que dans Windows PowerShell.
Faut-il passer de Ratatui ?
Si vous avez déjà un client terminal complexe écrit en Ratatui, il n'y a pas beaucoup d'intérêt à le réécrire de zéro. Ratatui est plus mature, avec une grande communauté autour et des dizaines de widgets tiers écrits pour lui.
Mais si vous démarrez un nouvel utilitaire CLI, que vous écrivez un outil interne pour votre équipe, ou que vous êtes simplement fatigué de compter manuellement les lignes et les colonnes du terminal, iocraft fait gagner beaucoup de temps. La syntaxe déclarative rend le code plus compact, et flexbox élimine les maux de tête liés au redimensionnement des fenêtres.
Le projet est distribué sous une double licence MIT / Apache-2.0. La documentation sur docs.rs est suffisamment détaillée, et le code source des exemples dans le dépôt montre clairement comment construire vos propres composants.
Projets similaires