diff options
author | Sebastian Thiel <sebastian.thiel@icloud.com> | 2020-07-06 09:08:01 +0800 |
---|---|---|
committer | Sebastian Thiel <sebastian.thiel@icloud.com> | 2020-07-06 09:08:01 +0800 |
commit | 388a1347580df120cead11f98516ceb911373316 (patch) | |
tree | 0565cc1a6e6d4acfa08897c1d8d907fad6a5fda1 /src | |
parent | fddc8cbcadb50a6ad2bf06e883fe751f3bca55b3 (diff) |
convert input handling to crosstermion
Diffstat (limited to 'src')
-rw-r--r-- | src/interactive/app/eventloop.rs | 33 | ||||
-rw-r--r-- | src/interactive/app/handlers.rs | 2 | ||||
-rw-r--r-- | src/interactive/app_test/journeys_readonly.rs | 36 | ||||
-rw-r--r-- | src/interactive/app_test/journeys_with_writes.rs | 14 | ||||
-rw-r--r-- | src/interactive/app_test/utils.rs | 8 | ||||
-rw-r--r-- | src/interactive/widgets/help.rs | 2 | ||||
-rw-r--r-- | src/interactive/widgets/mark.rs | 2 |
7 files changed, 52 insertions, 45 deletions
diff --git a/src/interactive/app/eventloop.rs b/src/interactive/app/eventloop.rs index c815ed4..033f6e5 100644 --- a/src/interactive/app/eventloop.rs +++ b/src/interactive/app/eventloop.rs @@ -5,12 +5,12 @@ use crate::interactive::{ SortMode, }; use anyhow::Result; +use crosstermion::input::{key_input_channel, Key}; use dua::{ traverse::{Traversal, TreeIndex}, WalkOptions, WalkResult, }; -use std::{collections::BTreeMap, io, path::PathBuf}; -use termion::{event::Key, input::TermRead}; +use std::{collections::BTreeMap, path::PathBuf}; use tui::backend::Backend; use tui_react::Terminal; @@ -69,16 +69,16 @@ impl AppState { traversal: &mut Traversal, display: &mut DisplayOptions, terminal: &mut Terminal<B>, - keys: impl Iterator<Item = std::result::Result<Key, io::Error>>, + keys: impl Iterator<Item = Key>, ) -> Result<ProcessingResult> where B: Backend, { - use termion::event::Key::*; + use crosstermion::input::Key::*; use FocussedPane::*; self.draw(window, traversal, display.clone(), terminal)?; - for key in keys.filter_map(Result::ok) { + for key in keys { self.reset_message(); match key { Char('?') => self.toggle_help_pane(window), @@ -177,13 +177,13 @@ pub struct TerminalApp { pub window: MainWindow, } -type KeyboardInputAndApp = (flume::Receiver<io::Result<Key>>, TerminalApp); +type KeyboardInputAndApp = (flume::Receiver<Key>, TerminalApp); impl TerminalApp { pub fn process_events<B>( &mut self, terminal: &mut Terminal<B>, - keys: impl Iterator<Item = std::result::Result<Key, io::Error>>, + keys: impl Iterator<Item = Key>, ) -> Result<WalkResult> where B: Backend, @@ -213,18 +213,13 @@ impl TerminalApp { let mut display: DisplayOptions = options.clone().into(); display.byte_vis = ByteVisualization::PercentageAndBar; let mut window = MainWindow::default(); - let (keys_tx, keys_rx) = flume::unbounded(); - match mode { - Interaction::None => drop(keys_tx), - Interaction::Full => drop(std::thread::spawn(move || { - let keys = std::io::stdin().keys(); - for key in keys { - if keys_tx.send(key).is_err() { - break; - } - } - })), - } + let keys_rx = match mode { + Interaction::None => { + let (_, keys_rx) = flume::unbounded(); + keys_rx + } + Interaction::Full => key_input_channel(), + }; let fetch_buffered_key_events = || { let mut keys = Vec::new(); diff --git a/src/interactive/app/handlers.rs b/src/interactive/app/handlers.rs index 1758177..e940997 100644 --- a/src/interactive/app/handlers.rs +++ b/src/interactive/app/handlers.rs @@ -4,11 +4,11 @@ use crate::interactive::{ widgets::{HelpPane, MainWindow, MarkMode, MarkPane}, AppState, DisplayOptions, EntryDataBundle, }; +use crosstermion::input::Key; use dua::traverse::{Traversal, TreeIndex}; use itertools::Itertools; use petgraph::{visit::Bfs, Direction}; use std::{fs, io, path::PathBuf}; -use termion::event::Key; use tui::backend::Backend; use tui_react::Terminal; diff --git a/src/interactive/app_test/journeys_readonly.rs b/src/interactive/app_test/journeys_readonly.rs index 595491a..f5337ca 100644 --- a/src/interactive/app_test/journeys_readonly.rs +++ b/src/interactive/app_test/journeys_readonly.rs @@ -1,7 +1,7 @@ use crate::interactive::{ app_test::utils::{ - fixture_str, index_by_name, initialized_app_and_terminal_from_fixture, node_by_index, - node_by_name, + adapt, fixture_str, index_by_name, initialized_app_and_terminal_from_fixture, + node_by_index, node_by_name, }, app_test::FIXTURE_PATH, SortMode, @@ -54,7 +54,7 @@ fn simple_user_journey_read_only() -> Result<()> { // SORTING { // when hitting the S key - app.process_events(&mut terminal, b"s".keys())?; + app.process_events(&mut terminal, adapt(b"s".keys()))?; assert_eq!( app.state.sorting, SortMode::SizeAscending, @@ -66,7 +66,7 @@ fn simple_user_journey_read_only() -> Result<()> { "it recomputes the cached entries" ); // when hitting the S key again - app.process_events(&mut terminal, b"s".keys())?; + app.process_events(&mut terminal, adapt(b"s".keys()))?; assert_eq!( app.state.sorting, SortMode::SizeDescending, @@ -82,35 +82,35 @@ fn simple_user_journey_read_only() -> Result<()> { // Entry-Navigation { // when hitting the j key - app.process_events(&mut terminal, b"j".keys())?; + app.process_events(&mut terminal, adapt(b"j".keys()))?; assert_eq!( node_by_name(&app, fixture_str(long_root)), node_by_index(&app, *app.state.selected.as_ref().unwrap()), "it moves the cursor down and selects the next entry based on the current sort mode" ); // when hitting it while there is nowhere to go - app.process_events(&mut terminal, b"j".keys())?; + app.process_events(&mut terminal, adapt(b"j".keys()))?; assert_eq!( node_by_name(&app, fixture_str(long_root)), node_by_index(&app, *app.state.selected.as_ref().unwrap()), "it stays at the previous position" ); // when hitting the k key - app.process_events(&mut terminal, b"k".keys())?; + app.process_events(&mut terminal, adapt(b"k".keys()))?; assert_eq!( node_by_name(&app, fixture_str(short_root)), node_by_index(&app, *app.state.selected.as_ref().unwrap()), "it moves the cursor up and selects the next entry based on the current sort mode" ); // when hitting the k key again - app.process_events(&mut terminal, b"k".keys())?; + app.process_events(&mut terminal, adapt(b"k".keys()))?; assert_eq!( node_by_name(&app, fixture_str(short_root)), node_by_index(&app, *app.state.selected.as_ref().unwrap()), "it stays at the current cursor position as there is nowhere to go" ); // when hitting the o key with a directory selected - app.process_events(&mut terminal, b"o".keys())?; + app.process_events(&mut terminal, adapt(b"o".keys()))?; { let new_root_idx = index_by_name(&app, fixture_str(short_root)); assert_eq!( @@ -124,7 +124,7 @@ fn simple_user_journey_read_only() -> Result<()> { ); // when hitting the u key while inside a sub-directory - app.process_events(&mut terminal, b"u".keys())?; + app.process_events(&mut terminal, adapt(b"u".keys()))?; { assert_eq!( app.traversal.root_index, app.state.root, @@ -139,7 +139,7 @@ fn simple_user_journey_read_only() -> Result<()> { } // when hitting the u key while inside of the root directory // We are moving the cursor down just to have a non-default selection - app.process_events(&mut terminal, b"ju".keys())?; + app.process_events(&mut terminal, adapt(b"ju".keys()))?; { assert_eq!( app.traversal.root_index, app.state.root, @@ -156,9 +156,9 @@ fn simple_user_journey_read_only() -> Result<()> { // Deletion { // when hitting the 'd' key (also move cursor back to start) - app.process_events(&mut terminal, b"k".keys())?; + app.process_events(&mut terminal, adapt(b"k".keys()))?; let previously_selected_index = *app.state.selected.as_ref().unwrap(); - app.process_events(&mut terminal, b"d".keys())?; + app.process_events(&mut terminal, adapt(b"d".keys()))?; { assert_eq!( Some(1), @@ -180,7 +180,7 @@ fn simple_user_journey_read_only() -> Result<()> { // when hitting the 'd' key again { - app.process_events(&mut terminal, b"d".keys())?; + app.process_events(&mut terminal, adapt(b"d".keys()))?; assert_eq!( Some(2), @@ -197,7 +197,7 @@ fn simple_user_journey_read_only() -> Result<()> { // when hitting the 'd' key once again { - app.process_events(&mut terminal, b"d".keys())?; + app.process_events(&mut terminal, adapt(b"d".keys()))?; assert_eq!( Some(1), @@ -214,7 +214,7 @@ fn simple_user_journey_read_only() -> Result<()> { } // when hitting the spacebar (after moving up to the first entry) { - app.process_events(&mut terminal, b"k ".keys())?; + app.process_events(&mut terminal, adapt(b"k ".keys()))?; assert_eq!( None, @@ -233,7 +233,7 @@ fn simple_user_journey_read_only() -> Result<()> { // Marking { // select something - app.process_events(&mut terminal, b" j ".keys())?; + app.process_events(&mut terminal, adapt(b" j ".keys()))?; assert_eq!( Some(false), app.window.mark_pane.as_ref().map(|p| p.has_focus()), @@ -247,7 +247,7 @@ fn simple_user_journey_read_only() -> Result<()> { ); // when advancing the selection to the marker pane - app.process_events(&mut terminal, b"\t".keys())?; + app.process_events(&mut terminal, adapt(b"\t".keys()))?; { assert_eq!( Some(true), diff --git a/src/interactive/app_test/journeys_with_writes.rs b/src/interactive/app_test/journeys_with_writes.rs index 061fb4b..4efb331 100644 --- a/src/interactive/app_test/journeys_with_writes.rs +++ b/src/interactive/app_test/journeys_with_writes.rs @@ -1,10 +1,10 @@ use crate::interactive::app_test::utils::{ - initialized_app_and_terminal_from_paths, WritableFixture, + adapt, initialized_app_and_terminal_from_paths, WritableFixture, }; use anyhow::Result; use pretty_assertions::assert_eq; -use termion::event::Key; -use termion::input::TermRead; +use std::convert::TryInto; +use termion::{event::Key, input::TermRead}; #[test] fn basic_user_journey_with_deletion() -> Result<()> { @@ -12,7 +12,7 @@ fn basic_user_journey_with_deletion() -> Result<()> { let (mut terminal, mut app) = initialized_app_and_terminal_from_paths(&[fixture.root.clone()])?; // With a selection of items - app.process_events(&mut terminal, b"doddd".keys())?; + app.process_events(&mut terminal, adapt(b"doddd".keys()))?; assert_eq!( app.window.mark_pane.as_ref().map(|p| p.marked().len()), @@ -29,7 +29,11 @@ fn basic_user_journey_with_deletion() -> Result<()> { // When selecting the marker window and pressing the combination to delete entries app.process_events( &mut terminal, - vec![Ok(Key::Char('\t')), Ok(Key::Ctrl('r'))].into_iter(), + vec![ + Key::Char('\t').try_into().unwrap(), + Key::Ctrl('r').try_into().unwrap(), + ] + .into_iter(), )?; assert_eq!( app.window.mark_pane.is_none(), diff --git a/src/interactive/app_test/utils.rs b/src/interactive/app_test/utils.rs index 495ac01..c0f1c33 100644 --- a/src/interactive/app_test/utils.rs +++ b/src/interactive/app_test/utils.rs @@ -18,6 +18,14 @@ use std::{ use tui::backend::TestBackend; use tui_react::Terminal; +pub fn adapt( + keys: impl Iterator<Item = std::io::Result<termion::event::Key>>, +) -> impl Iterator<Item = crosstermion::input::Key> { + use std::convert::TryFrom; + keys.filter_map(Result::ok) + .filter_map(|k| crosstermion::input::Key::try_from(k).ok()) +} + pub fn node_by_index(app: &TerminalApp, id: TreeIndex) -> &EntryData { app.traversal.tree.node_weight(id).unwrap() } diff --git a/src/interactive/widgets/help.rs b/src/interactive/widgets/help.rs index d14d8a6..56cfaea 100644 --- a/src/interactive/widgets/help.rs +++ b/src/interactive/widgets/help.rs @@ -1,9 +1,9 @@ use crate::interactive::CursorDirection; +use crosstermion::{input::Key, input::Key::*}; use std::{ borrow::Borrow, cell::{Cell, RefCell}, }; -use termion::{event::Key, event::Key::*}; use tui::{ buffer::Buffer, layout::Rect, diff --git a/src/interactive/widgets/mark.rs b/src/interactive/widgets/mark.rs index 3c26a3a..7cc5e30 100644 --- a/src/interactive/widgets/mark.rs +++ b/src/interactive/widgets/mark.rs @@ -1,6 +1,7 @@ use crate::interactive::{ fit_string_graphemes_with_ellipsis, path_of, widgets::entry_color, CursorDirection, }; +use crosstermion::{input::Key, input::Key::*}; use dua::{ traverse::{Tree, TreeIndex}, ByteFormat, @@ -11,7 +12,6 @@ use std::{ collections::{btree_map::Entry, BTreeMap}, path::PathBuf, }; -use termion::{event::Key, event::Key::*}; use tui::{ buffer::Buffer, layout::{Constraint, Direction, Layout, Rect}, |