Ratatui - a more structured way to handle state
- In this example we a struct, arbitrarily named App to repreent the state of the program. It will hold the text to be displayed and a flag indicating if we need to exit the program.
- We also separated the draw and the handle_key_event methods and moved the run method into the struct.
- We also implemented the Widget. Later we'll use a lot more widgets to improve the look of the application.
examples/ratatui/handle-the-keyboard-state/Cargo.toml
[package] name = "hello-world" version = "0.1.0" edition = "2021" [dependencies] crossterm = "0.28.1" ratatui = "0.29.0"
examples/ratatui/handle-the-keyboard-state/src/main.rs
use std::io; use crossterm::event::KeyModifiers; use ratatui::{ buffer::Buffer, crossterm::event::{self, KeyCode, KeyEventKind}, layout::Rect, style::Stylize, widgets::{Paragraph, Widget}, DefaultTerminal, Frame, }; #[derive(Debug, Default)] struct App { text: String, exit: bool, } impl App { fn run(&mut self, terminal: &mut DefaultTerminal) -> io::Result<()> { while !self.exit { terminal.draw(|frame| self.draw(frame))?; if let event::Event::Key(key) = event::read()? { self.handle_key_event(key); } } Ok(()) } fn draw(&self, frame: &mut Frame<'_>) { frame.render_widget(self, frame.area()); } fn handle_key_event(&mut self, key: event::KeyEvent) { if key.kind == KeyEventKind::Press { match key.code { KeyCode::Esc => self.exit = true, KeyCode::Char('c') if key.modifiers == KeyModifiers::CONTROL => self.exit = true, _ => self.text = format!("{} - {}", key.modifiers, key.code), } } } } impl Widget for &App { fn render(self, area: Rect, buf: &mut Buffer) { Paragraph::new(self.text.clone()) .white() .on_blue() .render(area, buf); } } fn main() -> io::Result<()> { let mut terminal = ratatui::init(); terminal.clear()?; let app_result = App::default().run(&mut terminal); ratatui::restore(); app_result }