diff --git a/Cargo.lock b/Cargo.lock index 0ce69b24..631a5295 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -186,6 +186,7 @@ version = "2.3.9" dependencies = [ "atty", "byte-unit", + "crossbeam-channel", "failure", "failure-tools", "filesize", diff --git a/Cargo.toml b/Cargo.toml index 4bfa1c45..11ab704e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ tui-react = { path = "./tui-react", version = "0.2" } num_cpus = "1.10.0" unicode-segmentation = "1.3.0" filesize = "0.2.0" +crossbeam-channel = "0.4.2" [[bin]] name="dua" diff --git a/src/interactive/app/eventloop.rs b/src/interactive/app/eventloop.rs index 88f2c11d..db6014ee 100644 --- a/src/interactive/app/eventloop.rs +++ b/src/interactive/app/eventloop.rs @@ -45,6 +45,11 @@ pub struct TerminalApp { pub window: MainWindow, } +/// A set of events that multiple kinds of input sources +enum Event { + Key(Key), +} + impl TerminalApp { pub fn draw_window( window: &mut MainWindow, @@ -73,7 +78,7 @@ impl TerminalApp { pub fn process_events( &mut self, mut terminal: Terminal, - keys: impl Iterator>, + keys: impl Iterator> + Send + 'static, ) -> Result where B: Backend, @@ -81,53 +86,70 @@ impl TerminalApp { use termion::event::Key::*; use FocussedPane::*; + let (keys_tx, keys_rx) = crossbeam_channel::bounded(1); + std::thread::spawn(move || { + for key in keys.filter_map(Result::ok) { + if keys_tx.send(Event::Key(key)).is_err() { + break; + } + } + }); + self.draw(&mut terminal)?; - for key in keys.filter_map(Result::ok) { + for event in keys_rx { self.update_message(); - match key { - Char('?') => self.toggle_help_pane(), - Char('\t') => { - self.cycle_focus(); - } - Ctrl('c') => break, - Char('q') | Esc => match self.state.focussed { - Main => { - drop(terminal); - io::stdout().flush().ok(); - // Exit 'quickly' to avoid having to wait for all memory to be freed by us. - // Let the OS do it - we have nothing to lose, literally. - std::process::exit(0); - } - Mark => self.state.focussed = Main, - Help => { - self.state.focussed = Main; - self.window.help_pane = None + match event { + Event::Key(key) => { + match key { + Char('?') => self.toggle_help_pane(), + Char('\t') => { + self.cycle_focus(); + } + Ctrl('c') => break, + Char('q') | Esc => match self.state.focussed { + Main => { + drop(terminal); + io::stdout().flush().ok(); + // Exit 'quickly' to avoid having to wait for all memory to be freed by us. + // Let the OS do it - we have nothing to lose, literally. + std::process::exit(0); + } + Mark => self.state.focussed = Main, + Help => { + self.state.focussed = Main; + self.window.help_pane = None + } + }, + _ => {} } - }, - _ => {} - } - match self.state.focussed { - FocussedPane::Mark => self.dispatch_to_mark_pane(key, &mut terminal), - FocussedPane::Help => { - self.window.help_pane.as_mut().expect("help pane").key(key); + match self.state.focussed { + FocussedPane::Mark => self.dispatch_to_mark_pane(key, &mut terminal), + FocussedPane::Help => { + self.window.help_pane.as_mut().expect("help pane").key(key); + } + FocussedPane::Main => match key { + Char('O') => self.open_that(), + Char(' ') => self.mark_entry(false), + Char('d') => self.mark_entry(true), + Char('u') | Char('h') | Backspace | Left => self.exit_node(), + Char('o') | Char('l') | Char('\n') | Right => self.enter_node(), + Ctrl('u') | PageUp => { + self.change_entry_selection(CursorDirection::PageUp) + } + Char('k') | Up => self.change_entry_selection(CursorDirection::Up), + Char('j') | Down => self.change_entry_selection(CursorDirection::Down), + Ctrl('d') | PageDown => { + self.change_entry_selection(CursorDirection::PageDown) + } + Char('s') => self.cycle_sorting(), + Char('g') => self.display.byte_vis.cycle(), + _ => {} + }, + }; + self.draw(&mut terminal)?; } - FocussedPane::Main => match key { - Char('O') => self.open_that(), - Char(' ') => self.mark_entry(false), - Char('d') => self.mark_entry(true), - Char('u') | Char('h') | Backspace | Left => self.exit_node(), - Char('o') | Char('l') | Char('\n') | Right => self.enter_node(), - Ctrl('u') | PageUp => self.change_entry_selection(CursorDirection::PageUp), - Char('k') | Up => self.change_entry_selection(CursorDirection::Up), - Char('j') | Down => self.change_entry_selection(CursorDirection::Down), - Ctrl('d') | PageDown => self.change_entry_selection(CursorDirection::PageDown), - Char('s') => self.cycle_sorting(), - Char('g') => self.display.byte_vis.cycle(), - _ => {} - }, - }; - self.draw(&mut terminal)?; + } } Ok(WalkResult { num_errors: self.traversal.io_errors,