A Real TUI with ratatui

Draw widgets, handle key events, and run a proper render loop.

Part 3 of 3Updated
cargo add ratatui crossterm

A ratatui app is a loop with three steps: draw the current state, wait for an event, update the state.

let mut terminal = ratatui::init();
loop {
    terminal.draw(|frame| {
        let block = Block::bordered().title("Guess (1-100)");
        frame.render_widget(Paragraph::new(input.as_str()).block(block), frame.area());
    })?;

    if let Event::Key(key) = event::read()? {
        match key.code {
            KeyCode::Char(c) if c.is_ascii_digit() => input.push(c),
            KeyCode::Backspace => { input.pop(); }
            KeyCode::Enter => submit(&mut game, &mut input),
            KeyCode::Esc => break,
            _ => {}
        }
    }
}
ratatui::restore();

The ratatui::restore() call matters β€” if you exit without it, the user’s terminal is left in raw mode. Wrap it in a guard type with a Drop impl if your app can panic.