/// A simple example demonstrating how to handle user input. This is /// a bit out of the scope of the library as it does not provide any /// input handling out of the box. However, it may helps some to get /// started. /// /// This is a very simple example: /// * A input box always focused. Every character you type is registered /// here /// * Pressing Backspace erases a character /// * Pressing Enter pushes the current input in the history of previous /// messages #[allow(dead_code)] mod util; use std::io::{self, Write}; use termion::cursor::Goto; use termion::event::Key; use termion::input::MouseTerminal; use termion::raw::IntoRawMode; use termion::screen::AlternateScreen; use tui::backend::TermionBackend; use tui::layout::{Constraint, Direction, Layout}; use tui::style::{Color, Style}; use tui::widgets::{Block, Borders, List, Paragraph, Text, Widget}; use tui::Terminal; use unicode_width::UnicodeWidthStr; use crate::util::event::{Event, Events}; /// App holds the state of the application struct App { /// Current value of the input box input: String, /// History of recorded messages messages: Vec, } impl Default for App { fn default() -> App { App { input: String::new(), messages: Vec::new(), } } } fn main() -> Result<(), failure::Error> { // Terminal initialization let stdout = io::stdout().into_raw_mode()?; let stdout = MouseTerminal::from(stdout); let stdout = AlternateScreen::from(stdout); let backend = TermionBackend::new(stdout); let mut terminal = Terminal::new(backend)?; // Setup event handlers let events = Events::new(); // Create default app state let mut app = App::default(); loop { // Draw UI terminal.draw(|mut f| { let chunks = Layout::default() .direction(Direction::Vertical) .margin(2) .constraints([Constraint::Length(3), Constraint::Min(1)].as_ref()) .split(f.size()); Paragraph::new([Text::raw(&app.input)].iter()) .style(Style::default().fg(Color::Yellow)) .block(Block::default().borders(Borders::ALL).title("Input")) .render(&mut f, chunks[0]); let messages = app .messages .iter() .enumerate() .map(|(i, m)| Text::raw(format!("{}: {}", i, m))); List::new(messages) .block(Block::default().borders(Borders::ALL).title("Messages")) .render(&mut f, chunks[1]); })?; // Put the cursor back inside the input box write!( terminal.backend_mut(), "{}", Goto(4 + app.input.width() as u16, 4) )?; // Handle input match events.next()? { Event::Input(input) => match input { Key::Char('q') => { break; } Key::Char('\n') => { app.messages.push(app.input.drain(..).collect()); } Key::Char(c) => { app.input.push(c); } Key::Backspace => { app.input.pop(); } _ => {} }, _ => {} } } Ok(()) }