En el mundo del desarrollo en Rust, las interfaces de usuario de texto (TUI) han ganado popularidad gracias a su eficiencia y portabilidad. En este artículo, exploramos cómo crear aplicaciones interactivas utilizando Ratatui, un crate poderoso para construir TUIs con control preciso de eventos. Aprenderemos a manejar inputs del usuario, actualizar estados y renderizar componentes dinámicos.
¿Por qué Ratatui para aplicaciones interactivas?
Configuración inicial: Dependencias en Cargo.toml
Agrega las siguientes dependencias a tu Cargo.toml:
[dependencies]
ratatui = "0.26"
crossterm = "0.27"
anyhow = "1.0"
Ejecuta cargo build para instalarlas.
Conceptos clave: Estado, Eventos y Renderizado
Una app TUI en Ratatui sigue este flujo:
Ejemplo práctico: Contador interactivo
Crearemos una TUI simple con un contador que sube/baja con las flechas y sale con 'q'.
Estructura del estado
#[derive(Default)]
struct App {
counter: u64,
}
Loop principal de eventos
loop {
// Manejar eventos
if let event::Event::Key(key) = event::read()? {
match key.code {
KeyCode::Up => app.counter += 1,
KeyCode::Down if app.counter > 0 => app.counter -= 1,
KeyCode::Char('q') => break,
_ => {},
}
}
// Renderizar
terminal.draw(|f| ui(f, &app))?;
}
Función de renderizado (ui)
fn ui(f: &mut Frame, app: &App) {
let size = f.size();
let block = Block::default().title("Contador Interactivo");
let text = vec![Line::from(format!("Contador: {}", app.counter))];
let paragraph = Paragraph::new(text).block(block);
f.render_widget(paragraph, size);
}
Código completo ejecutable
use anyhow::Result;
use crossterm::{
event::{self, KeyCode, Event},
execute,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
use ratatui::{
backend::CrosstermBackend,
layout::Rect,
style::{Style, Color},
text::{Line, Span},
widgets::{Block, Borders, Paragraph},
Frame,
};
use ratatui::prelude::*;
use std::io::{self, Stdout};
#[derive(Default)]
struct App {
counter: u64,
}
fn main() -> Result<()> {
// Configurar terminal
let mut stdout = io::stdout();
crossterm::execute!(stdout, EnterAlternateScreen)?;
enable_raw_mode()?;
let backend = CrosstermBackend::new(stdout);
let mut terminal = Terminal::new(backend)?;
let mut app = App::default();
loop {
terminal.draw(|f| ui(f, &app))?;
if let Event::Key(key) = event::read()? {
match key.code {
KeyCode::Up => app.counter += 1,
KeyCode::Down if app.counter > 0 => app.counter -= 1,
KeyCode::Char('q') | KeyCode::Esc => break,
_ => {},
}
}
}
disable_raw_mode()?;
execute!(terminal.backend_mut(), LeaveAlternateScreen)?;
terminal.show_cursor()?;
Ok(())
}
fn ui(f: &mut Frame, app: &App) {
let area = Rect::full(f.area());
let block = Block::default()
.title("Contador Interactivo (↑/↓ para cambiar, q para salir)")
.borders(Borders::ALL);
let text = vec![Line::from(format!("Contador: {} 👆", app.counter))];
let paragraph = Paragraph::new(text).block(block);
f.render_widget(paragraph, area);
}
Ejecuta con cargo run y prueba la interactividad. ¡Verás cómo el control de eventos hace magia!
Mejoras avanzadas
Explora la documentación de Ratatui para más. ¡Comparte tus creaciones en los comentarios!
¿Quieres comentar?
Inicia sesión con Telegram para participar en la conversación