Skip to content

Commit

Permalink
Don't try to shutdown keyinput thread to not lose input events
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron committed Mar 29, 2020
1 parent e811eff commit 80979a1
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 99 deletions.
16 changes: 16 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
flume = {version = "0.7.1", default-features = false}

[[bin]]
name="dua"
Expand Down
173 changes: 77 additions & 96 deletions src/interactive/app/eventloop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,96 +62,75 @@ impl AppState {
draw_window(window, props, terminal)
}

pub fn process_event<B>(
pub fn process_events<B>(
&mut self,
window: &mut MainWindow,
traversal: &mut Traversal,
display: &mut DisplayOptions,
terminal: &mut Terminal<B>,
key: Key,
keys: impl Iterator<Item = Result<Key, io::Error>>,
) -> Result<ProcessingResult, Error>
where
B: Backend,
{
use termion::event::Key::*;
use FocussedPane::*;

self.reset_message();
match key {
Char('?') => self.toggle_help_pane(window),
Char('\t') => {
self.cycle_focus(window);
}
Ctrl('c') => {
return Ok(ProcessingResult::ExitRequested(WalkResult {
num_errors: traversal.io_errors,
}))
}
Char('q') | Esc => match self.focussed {
Main => {
self.draw(window, traversal, display.clone(), terminal)?;
for key in keys.filter_map(Result::ok) {
self.reset_message();
match key {
Char('?') => self.toggle_help_pane(window),
Char('\t') => {
self.cycle_focus(window);
}
Ctrl('c') => {
return Ok(ProcessingResult::ExitRequested(WalkResult {
num_errors: traversal.io_errors,
}))
}
Mark => self.focussed = Main,
Help => {
self.focussed = Main;
window.help_pane = None
}
},
_ => {}
}

match self.focussed {
FocussedPane::Mark => {
self.dispatch_to_mark_pane(key, window, traversal, display.clone(), terminal)
}
FocussedPane::Help => {
window.help_pane.as_mut().expect("help pane").key(key);
Char('q') | Esc => match self.focussed {
Main => {
return Ok(ProcessingResult::ExitRequested(WalkResult {
num_errors: traversal.io_errors,
}))
}
Mark => self.focussed = Main,
Help => {
self.focussed = Main;
window.help_pane = None
}
},
_ => {}
}
FocussedPane::Main => match key {
Char('O') => self.open_that(traversal),
Char(' ') => self.mark_entry(false, window, traversal),
Char('d') => self.mark_entry(true, window, traversal),
Char('u') | Char('h') | Backspace | Left => {
self.exit_node_with_traversal(traversal)

match self.focussed {
FocussedPane::Mark => {
self.dispatch_to_mark_pane(key, window, traversal, display.clone(), terminal)
}
Char('o') | Char('l') | Char('\n') | Right => {
self.enter_node_with_traversal(traversal)
FocussedPane::Help => {
window.help_pane.as_mut().expect("help pane").key(key);
}
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(traversal),
Char('g') => display.byte_vis.cycle(),
_ => {}
},
};
self.draw(window, traversal, display.clone(), terminal)?;
Ok(ProcessingResult::Finished(WalkResult {
num_errors: traversal.io_errors,
}))
}
pub fn process_events<B>(
&mut self,
window: &mut MainWindow,
traversal: &mut Traversal,
display: &mut DisplayOptions,
terminal: &mut Terminal<B>,
keys: impl Iterator<Item = Result<Key, io::Error>>,
) -> Result<ProcessingResult, Error>
where
B: Backend,
{
self.reset_message();
self.draw(window, traversal, display.clone(), terminal)?;
for key in keys.filter_map(Result::ok) {
if let r @ ProcessingResult::ExitRequested(_) =
self.process_event(window, traversal, display, terminal, key)?
{
return Ok(r);
}
FocussedPane::Main => match key {
Char('O') => self.open_that(traversal),
Char(' ') => self.mark_entry(false, window, traversal),
Char('d') => self.mark_entry(true, window, traversal),
Char('u') | Char('h') | Backspace | Left => {
self.exit_node_with_traversal(traversal)
}
Char('o') | Char('l') | Char('\n') | Right => {
self.enter_node_with_traversal(traversal)
}
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(traversal),
Char('g') => display.byte_vis.cycle(),
_ => {}
},
};
self.draw(window, traversal, display.clone(), terminal)?;
}
Ok(ProcessingResult::Finished(WalkResult {
num_errors: traversal.io_errors,
Expand Down Expand Up @@ -206,7 +185,7 @@ impl TerminalApp {
options: WalkOptions,
input: Vec<PathBuf>,
mode: Interaction,
) -> Result<Option<TerminalApp>, Error>
) -> Result<Option<(flume::Receiver<io::Result<Key>>, TerminalApp)>, Error>
where
B: Backend,
{
Expand All @@ -215,7 +194,7 @@ impl TerminalApp {
let mut display: DisplayOptions = options.clone().into();
display.byte_vis = ByteVisualization::PercentageAndBar;
let mut window = MainWindow::default();
let (keys_tx, keys_rx) = std::sync::mpsc::channel(); // unbounded
let (keys_tx, keys_rx) = flume::unbounded();
match mode {
Interaction::None => drop(keys_tx),
Interaction::Full => drop(std::thread::spawn(move || {
Expand All @@ -228,7 +207,7 @@ impl TerminalApp {
})),
}

let fetch_buffered_key_events = move || {
let fetch_buffered_key_events = || {
let mut keys = Vec::new();
while let Ok(key) = keys_rx.try_recv() {
keys.push(key);
Expand Down Expand Up @@ -273,30 +252,32 @@ impl TerminalApp {
Some(t) => t,
None => return Ok(None),
};
drop(fetch_buffered_key_events); // shutdown input event handler early for good measure

Ok(Some(TerminalApp {
state: {
let mut s = state.unwrap_or_else(|| {
let sorting = Default::default();
let root = traversal.root_index;
let entries = sorted_entries(&traversal.tree, root, sorting);
AppState {
root,
sorting,
entries,
..Default::default()
}
});
s.is_scanning = false;
s.entries = sorted_entries(&traversal.tree, s.root, s.sorting);
s.selected = s.selected.or_else(|| s.entries.get(0).map(|b| b.index));
s
Ok(Some((
keys_rx,
TerminalApp {
state: {
let mut s = state.unwrap_or_else(|| {
let sorting = Default::default();
let root = traversal.root_index;
let entries = sorted_entries(&traversal.tree, root, sorting);
AppState {
root,
sorting,
entries,
..Default::default()
}
});
s.is_scanning = false;
s.entries = sorted_entries(&traversal.tree, s.root, s.sorting);
s.selected = s.selected.or_else(|| s.entries.get(0).map(|b| b.index));
s
},
display,
traversal,
window,
},
display,
traversal,
window,
}))
)))
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/interactive/app_test/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,8 @@ pub fn initialized_app_and_terminal_with_closure<P: AsRef<Path>>(
},
input,
Interaction::None,
)?;
)?
.map(|(_, app)| app);
Ok((
terminal,
app.expect("app that didn't try to abort iteration"),
Expand Down
4 changes: 2 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use failure::{Error, ResultExt};
use failure_tools::ok_or_exit;
use std::{fs, io, io::Write, path::PathBuf, process};
use structopt::StructOpt;
use termion::{input::TermRead, raw::IntoRawMode, screen::AlternateScreen};
use termion::{raw::IntoRawMode, screen::AlternateScreen};
use tui::backend::TermionBackend;
use tui_react::Terminal;

Expand Down Expand Up @@ -49,7 +49,7 @@ fn run() -> Result<(), Error> {
paths_from(input)?,
Interaction::Full,
)?
.map(|mut app| app.process_events(&mut terminal, io::stdin().keys()));
.map(|(keys_rx, mut app)| app.process_events(&mut terminal, keys_rx.into_iter()));

drop(terminal);
io::stdout().flush().ok();
Expand Down

0 comments on commit 80979a1

Please sign in to comment.