#![allow(clippy::cognitive_complexity)] use std::io; use crossterm::event::KeyEventKind; pub use crossterm::{ cursor, event::{self, Event, KeyCode, KeyEvent}, execute, queue, style, terminal::{self, ClearType}, Command, }; #[macro_use] mod macros; mod test; const MENU: &str = r#"Crossterm interactive test Controls: - 'q' - quit interactive test (or return to this menu) - any other key - continue with next step Available tests: 1. cursor 2. color (foreground, background) 3. attributes (bold, italic, ...) 4. input 5. synchronized output Select test to run ('1', '2', ...) or hit 'q' to quit. "#; fn run(w: &mut W) -> io::Result<()> where W: io::Write, { execute!(w, terminal::EnterAlternateScreen)?; terminal::enable_raw_mode()?; loop { queue!( w, style::ResetColor, terminal::Clear(ClearType::All), cursor::Hide, cursor::MoveTo(1, 1) )?; for line in MENU.split('\n') { queue!(w, style::Print(line), cursor::MoveToNextLine(1))?; } w.flush()?; match read_char()? { '1' => test::cursor::run(w)?, '2' => test::color::run(w)?, '3' => test::attribute::run(w)?, '4' => test::event::run(w)?, '5' => test::synchronized_output::run(w)?, 'q' => { execute!(w, cursor::SetCursorStyle::DefaultUserShape).unwrap(); break; } _ => {} }; } execute!( w, style::ResetColor, cursor::Show, terminal::LeaveAlternateScreen )?; terminal::disable_raw_mode() } pub fn read_char() -> std::io::Result { loop { if let Ok(Event::Key(KeyEvent { code: KeyCode::Char(c), kind: KeyEventKind::Press, modifiers: _, state: _, })) = event::read() { return Ok(c); } } } pub fn buffer_size() -> io::Result<(u16, u16)> { terminal::size() } fn main() -> std::io::Result<()> { let mut stdout = io::stdout(); run(&mut stdout) }