summaryrefslogtreecommitdiffstats
path: root/src/interactive
diff options
context:
space:
mode:
authorSebastian Thiel <sebastian.thiel@icloud.com>2020-07-06 09:08:01 +0800
committerSebastian Thiel <sebastian.thiel@icloud.com>2020-07-06 09:08:01 +0800
commit388a1347580df120cead11f98516ceb911373316 (patch)
tree0565cc1a6e6d4acfa08897c1d8d907fad6a5fda1 /src/interactive
parentfddc8cbcadb50a6ad2bf06e883fe751f3bca55b3 (diff)
convert input handling to crosstermion
Diffstat (limited to 'src/interactive')
-rw-r--r--src/interactive/app/eventloop.rs33
-rw-r--r--src/interactive/app/handlers.rs2
-rw-r--r--src/interactive/app_test/journeys_readonly.rs36
-rw-r--r--src/interactive/app_test/journeys_with_writes.rs14
-rw-r--r--src/interactive/app_test/utils.rs8
-rw-r--r--src/interactive/widgets/help.rs2
-rw-r--r--src/interactive/widgets/mark.rs2
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},