diff --git a/Cargo.toml b/Cargo.toml index 150e3a8..3fe7148 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,9 +20,7 @@ version = "0.18" default-features = false [dev-dependencies] -termion = "1" +crossterm = "0.23" [dev-dependencies.tui] version = "0.18" -default-features = false -features = ["termion"] diff --git a/examples/example.rs b/examples/example.rs index 46cb2bc..1e45fbf 100644 --- a/examples/example.rs +++ b/examples/example.rs @@ -1,13 +1,14 @@ mod util; -use crate::util::{ - event::{Event, Events}, - StatefulTree, +use crate::util::StatefulTree; +use crossterm::{ + event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode}, + execute, + terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, }; use std::{error::Error, io}; -use termion::{event::Key, input::MouseTerminal, raw::IntoRawMode, screen::AlternateScreen}; use tui::{ - backend::TermionBackend, + backend::{Backend, CrosstermBackend}, style::{Color, Modifier, Style}, widgets::{Block, Borders}, Terminal, @@ -40,17 +41,33 @@ impl<'a> App<'a> { fn main() -> Result<(), Box> { // Terminal initialization - let stdout = io::stdout().into_raw_mode()?; - let stdout = MouseTerminal::from(stdout); - let stdout = AlternateScreen::from(stdout); - let backend = TermionBackend::new(stdout); + enable_raw_mode()?; + let mut stdout = io::stdout(); + execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?; + let backend = CrosstermBackend::new(stdout); let mut terminal = Terminal::new(backend)?; - let events = Events::new(); - // App - let mut app = App::new(); + let app = App::new(); + let res = run_app(&mut terminal, app); + // restore terminal + disable_raw_mode()?; + execute!( + terminal.backend_mut(), + LeaveAlternateScreen, + DisableMouseCapture + )?; + terminal.show_cursor()?; + + if let Err(err) = res { + println!("{:?}", err); + } + + Ok(()) +} + +fn run_app(terminal: &mut Terminal, mut app: App) -> io::Result<()> { loop { terminal.draw(|f| { let area = f.size(); @@ -71,31 +88,16 @@ fn main() -> Result<(), Box> { f.render_stateful_widget(items, area, &mut app.tree.state); })?; - match events.next()? { - Event::Input(input) => match input { - Key::Char('q') => { - break; - } - Key::Left => { - app.tree.close(); - } - Key::Right => { - app.tree.open(); - } - Key::Char('\n') => { - app.tree.toggle(); - } - Key::Down => { - app.tree.next(); - } - Key::Up => { - app.tree.previous(); - } + if let Event::Key(key) = event::read()? { + match key.code { + KeyCode::Char('q') => return Ok(()), + KeyCode::Left => app.tree.close(), + KeyCode::Right => app.tree.open(), + KeyCode::Char('\n') => app.tree.toggle(), + KeyCode::Down => app.tree.next(), + KeyCode::Up => app.tree.previous(), _ => {} - }, - Event::Tick => {} + } } } - - Ok(()) } diff --git a/examples/util/event.rs b/examples/util/event.rs deleted file mode 100644 index 26d1a81..0000000 --- a/examples/util/event.rs +++ /dev/null @@ -1,73 +0,0 @@ -use std::io; -use std::sync::mpsc; -use std::thread; -use std::time::Duration; - -use termion::event::Key; -use termion::input::TermRead; - -pub enum Event { - Input(I), - Tick, -} - -/// A small event handler that wrap termion input and tick events. Each event -/// type is handled in its own thread and returned to a common `Receiver` -#[allow(dead_code)] -pub struct Events { - rx: mpsc::Receiver>, -} - -#[derive(Debug, Clone, Copy)] -pub struct Config { - pub exit_key: Key, - pub tick_rate: Duration, -} - -impl Default for Config { - fn default() -> Self { - Self { - exit_key: Key::Char('q'), - tick_rate: Duration::from_millis(250), - } - } -} - -impl Events { - pub fn new() -> Self { - Self::with_config(Config::default()) - } - - pub fn with_config(config: Config) -> Self { - let (tx, rx) = mpsc::channel(); - { - let tx = tx.clone(); - thread::spawn(move || { - let stdin = io::stdin(); - #[allow(clippy::manual_flatten)] - for evt in stdin.keys() { - if let Ok(key) = evt { - if let Err(err) = tx.send(Event::Input(key)) { - eprintln!("{}", err); - return; - } - if key == config.exit_key { - return; - } - } - } - }) - }; - thread::spawn(move || loop { - if tx.send(Event::Tick).is_err() { - break; - } - thread::sleep(config.tick_rate); - }); - Self { rx } - } - - pub fn next(&self) -> Result, mpsc::RecvError> { - self.rx.recv() - } -} diff --git a/examples/util/mod.rs b/examples/util/mod.rs index fe3a6b8..91e1169 100644 --- a/examples/util/mod.rs +++ b/examples/util/mod.rs @@ -1,5 +1,3 @@ -pub mod event; - use tui_tree_widget::{flatten, get_identifier_without_leaf, TreeItem, TreeState}; pub struct StatefulTree<'a> {