React para o Terminal em Rust com Flexbox e Hooks
Se você já escreveu uma interface de console em Rust, provavelmente usou Ratatui. É uma biblioteca sólida que impulsiona dezenas de ótimos utilitários. Mas assim que um projeto vai além de alguns botões, a luta familiar começa: você tem que dividir manualmente a tela em retângulos usando Layout, calcular porcentagens e margens, e passar eventos por construções massivas de match. No desenvolvimento web, há muito nos acostumamos à abordagem de componentes e flexbox, mas no terminal ainda estamos frequentemente escrevendo como se fosse 1998.
Recentemente descobri a crate iocraft, cujo autor resolveu esse problema radicalmente. Eles trouxeram a experiência de React, SwiftUI e Ink diretamente para o mundo da programação de sistemas em Rust.
Um Modelo de Componentes Familiar
A biblioteca é construída em torno da macro element!. Ela constrói uma árvore de elementos usando uma sintaxe que se assemelha fortemente a JSX ou Swift declarativo. Sem cálculos manuais de coordenadas. O layout é tratado pelo motor taffy, que implementa fielmente a especificação flexbox para Rust.
Aqui está como fica um Hello World clássico:
use iocraft::prelude::*;
fn main() {
element! {
View(
border_style: BorderStyle::Round,
border_color: Color::Blue,
) {
Text(content: "Hello, world!")
}
}
.print();
}
Basta envolver Text em um container View, aplicar uma borda azul arredondada e chamar .print(). O resultado vai para a saída padrão sem precisar capturar o terminal em modo fullscreen. Isso é útil se você precisa de saída de comandos de console ou logs bem formatados em vez de um dashboard interativo.
Hooks e Estado Dentro do Terminal
A semelhança com o desenvolvimento frontend não termina com o layout estático. Para interfaces dinâmicas, o autor adicionou a macro #[component] e hooks familiares de ciclo de vida.
No código abaixo, o componente Counter mantém seu próprio estado local via use_state e inicia um timer assíncrono em segundo plano 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();
}
Quando o valor de count muda, iocraft aciona um redesenho da parte afetada da tela. O motor otimiza a passagem de props: contexto e parâmetros são passados por referência, então não há alocações de memória desnecessárias ou clonagem de estruturas pesadas aqui.
O Que a Biblioteca Pode Fazer na Prática
As primitivas integradas são suficientes para construir interfaces de qualquer complexidade. Os exemplos do repositório contêm receitas prontas para as tarefas mais comuns:
- Aplicações em tela cheia com entrada de texto e tratamento de foco
- Tabelas adaptativas multicoluna
- Formulários interativos com validação
- Calculadoras e sobreposições com janelas modais flutuantes
Vamos ver como ficam layouts de elementos complexos na prática:
O estilo é multiplataforma. Os aplicativos renderizam igualmente de forma correta em terminais padrão Linux/macOS e no Windows PowerShell.
Vale a Pena Trocar do Ratatui
Se você já tem um cliente de terminal complexo escrito em Ratatui, não faz muito sentido reescrevê-lo do zero. O Ratatui é mais maduro, com uma grande comunidade ao redor dele e dezenas de widgets de terceiros escritos para ele.
Mas se você está começando um novo utilitário CLI, escrevendo uma ferramenta interna para sua equipe, ou simplesmente cansado de contar manualmente linhas e colunas do terminal, iocraft economiza muito tempo. A sintaxe declarativa torna o código mais compacto, e o flexbox elimina a dor de cabeça de redimensionar janelas.
O projeto é distribuído sob licenciamento dual MIT / Apache-2.0. A documentação no docs.rs é detalhada o suficiente, e o código fonte dos exemplos no repositório mostra claramente como construir seus próprios componentes.
Projetos relacionados