From c91a1ec08d60676216a875c1b5ddb78d31187026 Mon Sep 17 00:00:00 2001 From: rezural <69941255+rezural@users.noreply.github.com> Date: Fri, 5 Mar 2021 08:32:16 +1100 Subject: [PATCH] Table paging release (#3128) * use the InputHandler functionality from minus * respond to Q and ESC character to quit * use arijit79/minus main branch until new release is pushed * rename NushellMinusInputHandler to MinusInputHandler --- crates/nu-command/Cargo.toml | 5 +- .../nu-command/src/commands/table/command.rs | 117 ++++++++++++++++++ 2 files changed, 120 insertions(+), 2 deletions(-) diff --git a/crates/nu-command/Cargo.toml b/crates/nu-command/Cargo.toml index 12ec1695fe..1c39b24cf0 100644 --- a/crates/nu-command/Cargo.toml +++ b/crates/nu-command/Cargo.toml @@ -38,6 +38,7 @@ chrono = { version = "0.4.19", features = ["serde"] } chrono-tz = "0.5.3" clap = "2.33.3" codespan-reporting = "0.11.0" +crossterm = { version = "0.19.0", optional = true } csv = "1.1.3" ctrlc = { version = "3.1.7", optional = true } derive-new = "0.5.8" @@ -62,7 +63,7 @@ itertools = "0.10.0" lazy_static = "1.*" log = "0.4.14" meval = "0.2.0" -minus = { optional = true, features = ["async_std_lib", "search"], git = "https://github.com/rezural/minus", branch = "nushell" } +minus = { optional = true, features = ["async_std_lib", "search"], git = "https://github.com/arijit79/minus", branch = "main" } num-bigint = { version = "0.3.1", features = ["serde"] } num-format = { version = "0.4.0", features = ["with-num-bigint"] } num-traits = "0.2.14" @@ -131,5 +132,5 @@ stable = [] trash-support = ["trash"] directories = ["directories-next"] dirs = ["dirs-next"] -table-pager = ["minus"] +table-pager = ["minus", "crossterm"] diff --git a/crates/nu-command/src/commands/table/command.rs b/crates/nu-command/src/commands/table/command.rs index 35657b9c02..0e80759794 100644 --- a/crates/nu-command/src/commands/table/command.rs +++ b/crates/nu-command/src/commands/table/command.rs @@ -198,6 +198,7 @@ async fn table( .set_exit_strategy(ExitStrategy::PagerQuit) .set_searchable(true) .set_page_if_havent_overflowed(false) + .set_input_handler(Box::new(input_handling::MinusInputHandler {})) .finish(); let stream_data = async { @@ -309,6 +310,122 @@ async fn table( Ok(OutputStream::empty()) } +#[cfg(feature = "table-pager")] +mod input_handling { + use crossterm::event::{Event, KeyCode, KeyEvent, KeyModifiers, MouseEvent, MouseEventKind}; + use minus::{InputEvent, InputHandler, LineNumbers, SearchMode}; + pub struct MinusInputHandler; + + impl InputHandler for MinusInputHandler { + fn handle_input( + &self, + ev: Event, + upper_mark: usize, + search_mode: SearchMode, + ln: LineNumbers, + rows: usize, + ) -> Option { + match ev { + // Scroll up by one. + Event::Key(KeyEvent { + code: KeyCode::Up, + modifiers: KeyModifiers::NONE, + }) => Some(InputEvent::UpdateUpperMark(upper_mark.saturating_sub(1))), + + // Scroll down by one. + Event::Key(KeyEvent { + code: KeyCode::Down, + modifiers: KeyModifiers::NONE, + }) => Some(InputEvent::UpdateUpperMark(upper_mark.saturating_add(1))), + + // Mouse scroll up/down + Event::Mouse(MouseEvent { + kind: MouseEventKind::ScrollUp, + .. + }) => Some(InputEvent::UpdateUpperMark(upper_mark.saturating_sub(5))), + Event::Mouse(MouseEvent { + kind: MouseEventKind::ScrollDown, + .. + }) => Some(InputEvent::UpdateUpperMark(upper_mark.saturating_add(5))), + // Go to top. + Event::Key(KeyEvent { + code: KeyCode::Home, + modifiers: KeyModifiers::NONE, + }) => Some(InputEvent::UpdateUpperMark(0)), + // Go to bottom. + Event::Key(KeyEvent { + code: KeyCode::End, + modifiers: KeyModifiers::NONE, + }) => Some(InputEvent::UpdateUpperMark(usize::MAX)), + + // Page Up/Down + Event::Key(KeyEvent { + code: KeyCode::PageUp, + modifiers: KeyModifiers::NONE, + }) => Some(InputEvent::UpdateUpperMark( + upper_mark.saturating_sub(rows - 1), + )), + Event::Key(KeyEvent { + code: KeyCode::PageDown, + modifiers: KeyModifiers::NONE, + }) => Some(InputEvent::UpdateUpperMark( + upper_mark.saturating_add(rows - 1), + )), + + // Resize event from the terminal. + Event::Resize(_, height) => Some(InputEvent::UpdateRows(height as usize)), + // Switch line number display. + Event::Key(KeyEvent { + code: KeyCode::Char('l'), + modifiers: KeyModifiers::CONTROL, + }) => Some(InputEvent::UpdateLineNumber(!ln)), + // Quit. + Event::Key(KeyEvent { + code: KeyCode::Char('q'), + modifiers: KeyModifiers::NONE, + }) + | Event::Key(KeyEvent { + code: KeyCode::Char('Q'), + modifiers: KeyModifiers::SHIFT, + }) + | Event::Key(KeyEvent { + code: KeyCode::Esc, + modifiers: KeyModifiers::NONE, + }) + | Event::Key(KeyEvent { + code: KeyCode::Char('c'), + modifiers: KeyModifiers::CONTROL, + }) => Some(InputEvent::Exit), + Event::Key(KeyEvent { + code: KeyCode::Char('/'), + modifiers: KeyModifiers::NONE, + }) => Some(InputEvent::Search(SearchMode::Unknown)), + Event::Key(KeyEvent { + code: KeyCode::Down, + modifiers: KeyModifiers::CONTROL, + }) => { + if search_mode == SearchMode::Unknown { + Some(InputEvent::NextMatch) + } else { + None + } + } + Event::Key(KeyEvent { + code: KeyCode::Up, + modifiers: KeyModifiers::CONTROL, + }) => { + if search_mode == SearchMode::Unknown { + Some(InputEvent::PrevMatch) + } else { + None + } + } + _ => None, + } + } + } +} + #[cfg(test)] mod tests { use super::Command;