summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Thiel <sebastian.thiel@icloud.com>2023-12-26 22:10:45 +0100
committerSebastian Thiel <sebastian.thiel@icloud.com>2023-12-26 22:10:45 +0100
commitedbb446100405d16c19059d6ced096144f8bb54e (patch)
tree3a13a41d7864cb712524bffea5c6fedd89d6ed07
parent46fece5f295a8fb6f90ff969741f79d7c736c140 (diff)
parentb5b8aa26b648d8a034667bca8320ba7952a27780 (diff)
Merge branch 'tui-crates-upgrade'
-rw-r--r--Cargo.lock88
-rw-r--r--Cargo.toml7
-rw-r--r--Makefile1
-rw-r--r--src/interactive/app/eventloop.rs58
-rw-r--r--src/interactive/app/tests/journeys_readonly.rs44
-rw-r--r--src/interactive/app/tests/journeys_with_writes.rs12
-rw-r--r--src/interactive/app/tests/utils.rs15
-rw-r--r--src/interactive/widgets/glob.rs9
-rw-r--r--src/interactive/widgets/help.rs19
-rw-r--r--src/interactive/widgets/mark.rs31
-rw-r--r--src/main.rs4
-rw-r--r--src/options.rs2
12 files changed, 155 insertions, 135 deletions
diff --git a/Cargo.lock b/Cargo.lock
index a8c5572..681376e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -176,7 +176,7 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.42",
]
[[package]]
@@ -283,13 +283,12 @@ dependencies = [
[[package]]
name = "crosstermion"
-version = "0.12.1"
+version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4fb1963117df5f418acb1b1c9214992e587c9a576158a7177e38fbcf33bf9ea"
+checksum = "400415b86f4dc01b9e4e129e822dad900e546287319da7ab229654978d3e07e1"
dependencies = [
"crossterm",
"ratatui",
- "termion",
"tui-react",
]
@@ -314,7 +313,7 @@ dependencies = [
"gix-glob",
"gix-path",
"human_format",
- "itertools 0.12.0",
+ "itertools",
"jwalk",
"num_cpus",
"once_cell",
@@ -526,15 +525,6 @@ dependencies = [
[[package]]
name = "itertools"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
-dependencies = [
- "either",
-]
-
-[[package]]
-name = "itertools"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0"
@@ -559,17 +549,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
[[package]]
-name = "libredox"
-version = "0.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607"
-dependencies = [
- "bitflags 2.4.1",
- "libc",
- "redox_syscall",
-]
-
-[[package]]
name = "lock_api"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -641,12 +620,6 @@ dependencies = [
]
[[package]]
-name = "numtoa"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
-
-[[package]]
name = "objc"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -759,19 +732,19 @@ dependencies = [
[[package]]
name = "ratatui"
-version = "0.24.0"
+version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ebc917cfb527a566c37ecb94c7e3fd098353516fb4eb6bea17015ade0182425"
+checksum = "a5659e52e4ba6e07b2dad9f1158f578ef84a73762625ddb51536019f34d180eb"
dependencies = [
"bitflags 2.4.1",
"cassowary",
"crossterm",
"indoc",
- "itertools 0.11.0",
+ "itertools",
"lru",
"paste",
+ "stability",
"strum",
- "termion",
"unicode-segmentation",
"unicode-width",
]
@@ -806,12 +779,6 @@ dependencies = [
]
[[package]]
-name = "redox_termios"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20145670ba436b55d91fc92d25e71160fbfbdd57831631c8d7d36377a476f1cb"
-
-[[package]]
name = "regex-automata"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -846,7 +813,7 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.42",
]
[[package]]
@@ -886,6 +853,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
[[package]]
+name = "stability"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebd1b177894da2a2d9120208c3386066af06a488255caabc5de8ddca22dbc3ce"
+dependencies = [
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -910,14 +887,14 @@ dependencies = [
"proc-macro2",
"quote",
"rustversion",
- "syn",
+ "syn 2.0.42",
]
[[package]]
name = "syn"
-version = "2.0.42"
+version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b7d0a2c048d661a1a59fcd7355baa232f7ed34e0ee4df2eef3c1c1c0d3852d8"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
@@ -925,15 +902,14 @@ dependencies = [
]
[[package]]
-name = "termion"
-version = "2.0.3"
+name = "syn"
+version = "2.0.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4648c7def6f2043b2568617b9f9b75eae88ca185dbc1f1fda30e95a85d49d7d"
+checksum = "5b7d0a2c048d661a1a59fcd7355baa232f7ed34e0ee4df2eef3c1c1c0d3852d8"
dependencies = [
- "libc",
- "libredox",
- "numtoa",
- "redox_termios",
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
]
[[package]]
@@ -953,7 +929,7 @@ checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.42",
]
[[package]]
@@ -988,9 +964,9 @@ dependencies = [
[[package]]
name = "tui-react"
-version = "0.21.0"
+version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a93d64ce9d859e49cba06be4904ecda0fb94b1e22f51e027dc44c122bea9ed5b"
+checksum = "2ffacd73e2d4666c1aec4e85ab986354909e276f1dbff5c75f86bcebce566511"
dependencies = [
"log",
"ratatui",
@@ -1318,5 +1294,5 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.42",
]
diff --git a/Cargo.toml b/Cargo.toml
index a15e1c7..0c8e35a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -11,7 +11,6 @@ include = ["src/**/*", "Cargo.*", "LICENSE", "README.md", "CHANGELOG.md", "!**/t
[features]
default = ["tui-crossplatform", "trash-move"]
-tui-unix = ["crosstermion/tui-react-termion", "tui-shared"]
tui-crossplatform = ["crosstermion/tui-react-crossterm", "tui-shared"]
tui-shared = ["tui", "tui-react", "open", "unicode-segmentation", "unicode-width"]
@@ -33,9 +32,9 @@ chrono = { version = "0.4.31", default-features = false, features = ["std"] }
# 'tui' related
unicode-segmentation = { version = "1.3.0", optional = true }
unicode-width = { version = "0.1.5", optional = true }
-crosstermion = { version = "0.12.0", default-features = false, optional = true }
-tui = { package = "ratatui", version = "0.24.0", optional = true, default-features = false }
-tui-react = { version = "0.21.0", optional = true }
+crosstermion = { version = "0.13.0", default-features = false, optional = true }
+tui = { package = "ratatui", version = "0.25.0", optional = true, default-features = false }
+tui-react = { version = "0.22.0", optional = true }
open = { version = "5.0", optional = true }
wild = "2.0.4"
owo-colors = "4.0.0"
diff --git a/Makefile b/Makefile
index 5b633aa..d0cbce1 100644
--- a/Makefile
+++ b/Makefile
@@ -38,7 +38,6 @@ check:## run cargo-check with various features
cargo check --all
cargo check --all-features
cargo check --no-default-features
- cargo check --no-default-features --features tui-unix
cargo check --no-default-features --features tui-crossplatform
cargo check --no-default-features --features trash-move
diff --git a/src/interactive/app/eventloop.rs b/src/interactive/app/eventloop.rs
index 00b37e5..18e4bf7 100644
--- a/src/interactive/app/eventloop.rs
+++ b/src/interactive/app/eventloop.rs
@@ -6,7 +6,8 @@ use crate::interactive::{
SortMode,
};
use anyhow::Result;
-use crosstermion::input::{input_channel, Event, Key};
+use crosstermion::crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyModifiers};
+use crosstermion::input::{input_channel, Event};
use dua::{
traverse::{EntryData, Traversal},
WalkOptions, WalkResult,
@@ -104,7 +105,7 @@ impl AppState {
where
B: Backend,
{
- use crosstermion::input::Key::*;
+ use crosstermion::crossterm::event::KeyCode::*;
use FocussedPane::*;
{
@@ -114,8 +115,9 @@ impl AppState {
for event in events {
let key = match event {
- Event::Key(key) => key,
- Event::Resize(_, _) => Alt('\r'),
+ Event::Key(key) if key.kind != KeyEventKind::Release => key,
+ Event::Resize(_, _) => refresh_key(),
+ _ => continue,
};
self.reset_message();
@@ -123,20 +125,20 @@ impl AppState {
let glob_focussed = self.focussed == Glob;
let mut tree_view = self.tree_view(traversal);
let mut handled = true;
- match key {
+ match key.code {
Esc => {
if let Some(value) = self.handle_quit(&mut tree_view, window) {
return value;
}
}
- Char('\t') => {
+ Tab => {
self.cycle_focus(window);
}
Char('/') if !glob_focussed => {
self.toggle_glob_search(window);
}
Char('?') if !glob_focussed => self.toggle_help_pane(window),
- Ctrl('c') if !glob_focussed => {
+ Char('c') if key.modifiers.contains(KeyModifiers::CONTROL) && !glob_focussed => {
return Ok(ProcessingResult::ExitRequested(WalkResult {
num_errors: tree_view.traversal.io_errors,
}))
@@ -165,14 +167,12 @@ impl AppState {
}
Glob => {
let glob_pane = window.glob_pane.as_mut().expect("glob pane");
- match key {
- Char('\n') => {
- self.search_glob_pattern(&mut tree_view, &glob_pane.input)
- }
+ match key.code {
+ Enter => self.search_glob_pattern(&mut tree_view, &glob_pane.input),
_ => glob_pane.process_events(key),
}
}
- Main => match key {
+ Main => match key.code {
Char('O') => self.open_that(&tree_view),
Char(' ') => self.mark_entry(
CursorMode::KeepPosition,
@@ -180,12 +180,6 @@ impl AppState {
window,
&tree_view,
),
- Char('d') => self.mark_entry(
- CursorMode::Advance,
- MarkEntryMode::Toggle,
- window,
- &tree_view,
- ),
Char('x') => self.mark_entry(
CursorMode::Advance,
MarkEntryMode::MarkForDeletion,
@@ -195,24 +189,34 @@ impl AppState {
Char('a') => {
self.mark_all_entries(MarkEntryMode::Toggle, window, &tree_view)
}
- Char('u') | Char('h') | Backspace | Left => {
- self.exit_node_with_traversal(&tree_view)
- }
- Char('o') | Char('l') | Char('\n') | Right => {
+ Char('o') | Char('l') | Enter | Right => {
self.enter_node_with_traversal(&tree_view)
}
Char('H') | Home => self.change_entry_selection(CursorDirection::ToTop),
Char('G') | End => self.change_entry_selection(CursorDirection::ToBottom),
- Ctrl('u') | PageUp => self.change_entry_selection(CursorDirection::PageUp),
+ PageUp => self.change_entry_selection(CursorDirection::PageUp),
+ Char('u') if key.modifiers.contains(KeyModifiers::CONTROL) => {
+ 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 => {
+ PageDown => self.change_entry_selection(CursorDirection::PageDown),
+ Char('d') if key.modifiers.contains(KeyModifiers::CONTROL) => {
self.change_entry_selection(CursorDirection::PageDown)
}
Char('s') => self.cycle_sorting(&tree_view),
Char('m') => self.cycle_mtime_sorting(&tree_view),
Char('c') => self.cycle_count_sorting(&tree_view),
Char('g') => display.byte_vis.cycle(),
+ Char('d') => self.mark_entry(
+ CursorMode::Advance,
+ MarkEntryMode::Toggle,
+ window,
+ &tree_view,
+ ),
+ Char('u') | Char('h') | Backspace | Left => {
+ self.exit_node_with_traversal(&tree_view)
+ }
_ => {}
},
};
@@ -353,7 +357,7 @@ impl TerminalApp {
&mut self.traversal,
&mut self.display,
terminal,
- std::iter::once(Event::Key(Key::Alt('\r'))),
+ std::iter::once(Event::Key(refresh_key())),
)
.ok();
}
@@ -482,3 +486,7 @@ pub enum Interaction {
#[allow(dead_code)]
None,
}
+
+fn refresh_key() -> KeyEvent {
+ KeyEvent::new(KeyCode::Char('\r'), KeyModifiers::ALT)
+}
diff --git a/src/interactive/app/tests/journeys_readonly.rs b/src/interactive/app/tests/journeys_readonly.rs
index 9e06c3f..6781508 100644
--- a/src/interactive/app/tests/journeys_readonly.rs
+++ b/src/interactive/app/tests/journeys_readonly.rs
@@ -1,7 +1,9 @@
use anyhow::Result;
+use crosstermion::crossterm::event::KeyCode;
use pretty_assertions::assert_eq;
use std::ffi::OsString;
+use crate::interactive::app::tests::utils::into_codes;
use crate::interactive::{
app::tests::{
utils::{
@@ -65,28 +67,28 @@ fn simple_user_journey_read_only() -> Result<()> {
// SORTING
{
// when hitting the M key
- app.process_events(&mut terminal, into_keys(b"m".iter()))?;
+ app.process_events(&mut terminal, into_codes("m"))?;
assert_eq!(
app.state.sorting,
SortMode::MTimeDescending,
"it sets the sort mode to descending by mtime"
);
// when hitting the M key again
- app.process_events(&mut terminal, into_keys(b"m".iter()))?;
+ app.process_events(&mut terminal, into_codes("m"))?;
assert_eq!(
app.state.sorting,
SortMode::MTimeAscending,
"it sets the sort mode to ascending by mtime"
);
// when hitting the C key
- app.process_events(&mut terminal, into_keys(b"c".iter()))?;
+ app.process_events(&mut terminal, into_codes("c"))?;
assert_eq!(
app.state.sorting,
SortMode::CountDescending,
"it sets the sort mode to descending by count"
);
// when hitting the C key again
- app.process_events(&mut terminal, into_keys(b"c".iter()))?;
+ app.process_events(&mut terminal, into_codes("c"))?;
assert_eq!(
app.state.sorting,
SortMode::CountAscending,
@@ -98,7 +100,7 @@ fn simple_user_journey_read_only() -> Result<()> {
"it recomputes the cached entries"
);
// when hitting the S key
- app.process_events(&mut terminal, into_keys(b"s".iter()))?;
+ app.process_events(&mut terminal, into_codes("s"))?;
assert_eq!(
app.state.sorting,
SortMode::SizeDescending,
@@ -110,14 +112,14 @@ fn simple_user_journey_read_only() -> Result<()> {
"it recomputes the cached entries"
);
// when hitting the S key again
- app.process_events(&mut terminal, into_keys(b"s".iter()))?;
+ app.process_events(&mut terminal, into_codes("s"))?;
assert_eq!(
app.state.sorting,
SortMode::SizeAscending,
"it sets the sort mode to ascending by size"
);
// hit the S key again to get Descending - the rest depends on it
- app.process_events(&mut terminal, into_keys(b"s".iter()))?;
+ app.process_events(&mut terminal, into_codes("s"))?;
assert_eq!(app.state.sorting, SortMode::SizeDescending,);
assert_eq!(
@@ -130,35 +132,35 @@ fn simple_user_journey_read_only() -> Result<()> {
// Entry-Navigation
{
// when hitting the j key
- app.process_events(&mut terminal, into_keys(b"j".iter()))?;
+ app.process_events(&mut terminal, into_codes("j"))?;
assert_eq!(
node_by_name(&app, fixture_str(long_root)),
node_by_index(&app, *app.state.navigation().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, into_keys(b"j".iter()))?;
+ app.process_events(&mut terminal, into_codes("j"))?;
assert_eq!(
node_by_name(&app, fixture_str(long_root)),
node_by_index(&app, *app.state.navigation().selected.as_ref().unwrap()),
"it stays at the previous position"
);
// when hitting the k key
- app.process_events(&mut terminal, into_keys(b"k".iter()))?;
+ app.process_events(&mut terminal, into_codes("k"))?;
assert_eq!(
node_by_name(&app, fixture_str(short_root)),
node_by_index(&app, *app.state.navigation().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, into_keys(b"k".iter()))?;
+ app.process_events(&mut terminal, into_codes("k"))?;
assert_eq!(
node_by_name(&app, fixture_str(short_root)),
node_by_index(&app, *app.state.navigation().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, into_keys(b"o".iter()))?;
+ app.process_events(&mut terminal, into_codes("o"))?;
{
let new_root_idx = index_by_name(&app, fixture_str(short_root));
assert_eq!(
@@ -173,7 +175,7 @@ fn simple_user_journey_read_only() -> Result<()> {
);
// when hitting the u key while inside a sub-directory
- app.process_events(&mut terminal, into_keys(b"u".iter()))?;
+ app.process_events(&mut terminal, into_codes("u"))?;
{
assert_eq!(
app.traversal.root_index,
@@ -189,7 +191,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, into_keys(b"ju".iter()))?;
+ app.process_events(&mut terminal, into_codes("ju"))?;
{
assert_eq!(
app.traversal.root_index,
@@ -207,9 +209,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, into_keys(b"k".iter()))?;
+ app.process_events(&mut terminal, into_codes("k"))?;
let previously_selected_index = *app.state.navigation().selected.as_ref().unwrap();
- app.process_events(&mut terminal, into_keys(b"d".iter()))?;
+ app.process_events(&mut terminal, into_codes("d"))?;
{
assert_eq!(
Some(1),
@@ -231,7 +233,7 @@ fn simple_user_journey_read_only() -> Result<()> {
// when hitting the 'd' key again
{
- app.process_events(&mut terminal, into_keys(b"d".iter()))?;
+ app.process_events(&mut terminal, into_codes("d"))?;
assert_eq!(
Some(2),
@@ -248,7 +250,7 @@ fn simple_user_journey_read_only() -> Result<()> {
// when hitting the 'd' key once again
{
- app.process_events(&mut terminal, into_keys(b"d".iter()))?;
+ app.process_events(&mut terminal, into_codes("d"))?;
assert_eq!(
Some(1),
@@ -265,7 +267,7 @@ fn simple_user_journey_read_only() -> Result<()> {
}
// when hitting the spacebar (after moving up to the first entry)
{
- app.process_events(&mut terminal, into_keys(b"k ".iter()))?;
+ app.process_events(&mut terminal, into_codes("k "))?;
assert_eq!(
None,
@@ -284,7 +286,7 @@ fn simple_user_journey_read_only() -> Result<()> {
// Marking
{
// select something
- app.process_events(&mut terminal, into_keys(b" j ".iter()))?;
+ app.process_events(&mut terminal, into_codes(" j "))?;
assert_eq!(
Some(false),
app.window.mark_pane.as_ref().map(|p| p.has_focus()),
@@ -298,7 +300,7 @@ fn simple_user_journey_read_only() -> Result<()> {
);
// when advancing the selection to the marker pane
- app.process_events(&mut terminal, into_keys(b"\t".iter()))?;
+ app.process_events(&mut terminal, into_keys(Some(KeyCode::Tab)))?;
{
assert_eq!(
Some(true),
diff --git a/src/interactive/app/tests/journeys_with_writes.rs b/src/interactive/app/tests/journeys_with_writes.rs
index d14f8b4..9a941e6 100644
--- a/src/interactive/app/tests/journeys_with_writes.rs
+++ b/src/interactive/app/tests/journeys_with_writes.rs
@@ -1,9 +1,9 @@
use crate::interactive::app::tests::utils::{
- initialized_app_and_terminal_from_paths, into_keys, WritableFixture,
+ initialized_app_and_terminal_from_paths, into_codes, WritableFixture,
};
use anyhow::Result;
+use crosstermion::crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
use crosstermion::input::Event;
-use crosstermion::input::Key;
use pretty_assertions::assert_eq;
#[test]
@@ -13,7 +13,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, into_keys(b"doddd".iter()))?;
+ app.process_events(&mut terminal, into_codes("doddd"))?;
assert_eq!(
app.window.mark_pane.as_ref().map(|p| p.marked().len()),
@@ -26,7 +26,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![Event::Key(Key::Char('\t')), Event::Key(Key::Ctrl('r'))].into_iter(),
+ vec![
+ Event::Key(KeyCode::Tab.into()),
+ Event::Key(KeyEvent::new(KeyCode::Char('r'), KeyModifiers::CONTROL)),
+ ]
+ .into_iter(),
)?;
assert!(
app.window.mark_pane.is_none(),
diff --git a/src/interactive/app/tests/utils.rs b/src/interactive/app/tests/utils.rs
index 5c76f17..f6bc354 100644
--- a/src/interactive/app/tests/utils.rs
+++ b/src/interactive/app/tests/utils.rs
@@ -1,4 +1,5 @@
use anyhow::{Context, Error, Result};
+use crosstermion::crossterm::event::KeyCode;
use dua::{
traverse::{EntryData, Tree, TreeIndex},
ByteFormat, TraversalSorting, WalkOptions,
@@ -20,13 +21,15 @@ use tui_react::Terminal;
use crate::interactive::{app::tests::FIXTURE_PATH, Interaction, TerminalApp};
pub fn into_keys<'a>(
- bytes: impl Iterator<Item = &'a u8> + 'a,
+ codes: impl IntoIterator<Item = KeyCode> + 'a,
) -> impl Iterator<Item = crosstermion::input::Event> + 'a {
- bytes.map(|b| {
- crosstermion::input::Event::Key(crosstermion::input::Key::Char(
- std::char::from_u32(*b as u32).unwrap(),
- ))
- })
+ codes
+ .into_iter()
+ .map(|code| crosstermion::input::Event::Key(code.into()))
+}
+
+pub fn into_codes(input: &str) -> impl Iterator<Item = crosstermion::input::Event> + '_ {
+ into_keys(input.chars().map(KeyCode::Char))
}
pub fn node_by_index(app: &TerminalApp, id: TreeIndex) -> &EntryData {
diff --git a/src/interactive/widgets/glob.rs b/src/interactive/widgets/glob.rs
index 0ef95fd..bad9fd9 100644
--- a/src/interactive/widgets/glob.rs
+++ b/src/interactive/widgets/glob.rs
@@ -1,5 +1,6 @@
use anyhow::{anyhow, Context, Result};
use bstr::BString;
+use crosstermion::crossterm::event::KeyEventKind;
use crosstermion::input::Key;
use dua::traverse::{Tree, TreeIndex};
use petgraph::Direction;
@@ -36,9 +37,11 @@ pub struct GlobPane {
impl GlobPane {
pub fn process_events(&mut self, key: Key) {
- use crosstermion::input::Key::*;
-
- match key {
+ use crosstermion::crossterm::event::KeyCode::*;
+ if key.kind == KeyEventKind::Release {
+ return;
+ }
+ match key.code {
Char(to_insert) => {
self.enter_char(to_insert);
}
diff --git a/src/interactive/widgets/help.rs b/src/interactive/widgets/help.rs
index 0ec8b8c..092fb00 100644
--- a/src/interactive/widgets/help.rs
+++ b/src/interactive/widgets/help.rs
@@ -1,5 +1,7 @@
use crate::interactive::CursorDirection;
-use crosstermion::{input::Key, input::Key::*};
+pub use crosstermion::crossterm::event::KeyCode::*;
+use crosstermion::crossterm::event::{KeyEventKind, KeyModifiers};
+use crosstermion::input::Key;
use std::{borrow::Borrow, cell::RefCell};
use tui::{
buffer::Buffer,
@@ -34,13 +36,22 @@ fn margin(r: Rect, margin: u16) -> Rect {
impl HelpPane {
pub fn process_events(&mut self, key: Key) {
- match key {
+ if key.kind == KeyEventKind::Release {
+ return;
+ }
+ match key.code {
Char('H') => self.scroll_help(CursorDirection::ToTop),
Char('G') => self.scroll_help(CursorDirection::ToBottom),
- Ctrl('u') | PageUp => self.scroll_help(CursorDirection::PageUp),
+ Char('u') if key.modifiers.contains(KeyModifiers::CONTROL) => {
+ self.scroll_help(CursorDirection::PageUp)
+ }
+ Char('d') if key.modifiers.contains(KeyModifiers::CONTROL) => {
+ self.scroll_help(CursorDirection::PageDown)
+ }
+ PageUp => self.scroll_help(CursorDirection::PageUp),
+ PageDown => self.scroll_help(CursorDirection::PageDown),
Char('k') | Up => self.scroll_help(CursorDirection::Up),
Char('j') | Down => self.scroll_help(CursorDirection::Down),
- Ctrl('d') | PageDown => self.scroll_help(CursorDirection::PageDown),
_ => {}
};
}
diff --git a/src/interactive/widgets/mark.rs b/src/interactive/widgets/mark.rs
index 63ed54f..a774c73 100644
--- a/src/interactive/widgets/mark.rs
+++ b/src/interactive/widgets/mark.rs
@@ -3,7 +3,8 @@ use crate::interactive::{
app::tree_view::TreeView, fit_string_graphemes_with_ellipsis, widgets::entry_color,
CursorDirection,
};
-use crosstermion::{input::Key, input::Key::*};
+use crosstermion::crossterm::event::{KeyEventKind, KeyModifiers};
+use crosstermion::input::Key;
use dua::{traverse::TreeIndex, ByteFormat};
use itertools::Itertools;
use std::{
@@ -114,21 +115,35 @@ impl MarkPane {
self.marked.into_values().map(|v| v.path)
}
pub fn process_events(mut self, key: Key) -> Option<(Self, Option<MarkMode>)> {
+ use crosstermion::crossterm::event::KeyCode::*;
let action = None;
- match key {
- Ctrl('r') => return Some(self.prepare_deletion(MarkMode::Delete)),
+ if key.kind == KeyEventKind::Release {
+ return Some((self, action));
+ }
+ match key.code {
+ Char('r') if key.modifiers.contains(KeyModifiers::CONTROL) => {
+ return Some(self.prepare_deletion(MarkMode::Delete))
+ }
#[cfg(feature = "trash-move")]
- Ctrl('t') => return Some(self.prepare_deletion(MarkMode::Trash)),
- Char('x') | Char('d') | Char(' ') => {
- return self.remove_selected().map(|s| (s, action))
+ Char('t') if key.modifiers.contains(KeyModifiers::CONTROL) => {
+ return Some(self.prepare_deletion(MarkMode::Trash))
}
Char('a') => return None,
Char('H') => self.change_selection(CursorDirection::ToTop),
Char('G') => self.change_selection(CursorDirection::ToBottom),
- Ctrl('u') | PageUp => self.change_selection(CursorDirection::PageUp),
+ PageUp => self.change_selection(CursorDirection::PageUp),
+ Char('u') if key.modifiers.contains(KeyModifiers::CONTROL) => {
+ self.change_selection(CursorDirection::PageUp)
+ }
+ Char('d') if key.modifiers.contains(KeyModifiers::CONTROL) => {
+ self.change_selection(CursorDirection::PageDown)
+ }
+ PageDown => self.change_selection(CursorDirection::PageDown),
Char('k') | Up => self.change_selection(CursorDirection::Up),
Char('j') | Down => self.change_selection(CursorDirection::Down),
- Ctrl('d') | PageDown => self.change_selection(CursorDirection::PageDown),
+ Char('x') | Char('d') | Char(' ') => {
+ return self.remove_selected().map(|s| (s, action))
+ }
_ => {}
};
Some((self, action))
diff --git a/src/main.rs b/src/main.rs
index a610f6f..47be1f0 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -5,7 +5,7 @@ use dua::TraversalSorting;
use std::{fs, io, io::Write, path::PathBuf, process};
mod crossdev;
-#[cfg(any(feature = "tui-unix", feature = "tui-crossplatform"))]
+#[cfg(feature = "tui-crossplatform")]
mod interactive;
mod options;
@@ -31,7 +31,7 @@ fn main() -> Result<()> {
ignore_dirs: opt.ignore_dirs,
};
let res = match opt.command {
- #[cfg(any(feature = "tui-unix", feature = "tui-crossplatform"))]
+ #[cfg(feature = "tui-crossplatform")]
Some(Interactive { input }) => {
use crate::interactive::{Interaction, TerminalApp};
use anyhow::{anyhow, Context};
diff --git a/src/options.rs b/src/options.rs
index 6711795..13705b3 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -84,7 +84,7 @@ pub struct Args {
#[derive(Debug, clap::Subcommand)]
pub enum Command {
/// Launch the terminal user interface
- #[cfg(any(feature = "tui-unix", feature = "tui-crossplatform"))]
+ #[cfg(feature = "tui-crossplatform")]
#[clap(name = "interactive", visible_alias = "i")]
Interactive {
/// One or more input files or directories. If unset, we will use all entries in the current working directory.