diff --git a/CHANGELOG.md b/CHANGELOG.md index 085a8d92..a1ef8b68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,13 +19,13 @@ - Implement fuzzy search as default on Select and MultiSelect prompts. [#176](https://github.com/mikaelmello/inquire/pull/176) - Add new option on Select/MultiSelect prompts allowing to reset selection to the first item on filter-input changes. [#176](https://github.com/mikaelmello/inquire/pull/176) - Emacs-like keybindings added where applicable: -- Ctrl-p/Ctrl-n for up/down -- Ctrl-b/Ctrl-f for left/right -- Ctrl-j/Ctrl-g for enter/cancel + - Ctrl-p/Ctrl-n for up/down + - Ctrl-b/Ctrl-f for left/right + - Ctrl-j/Ctrl-g for enter/cancel - Added 'with_starting_filter_input' to both Select and MultiSelect, which allows for setting an initial value to the filter section of the prompt. - Added 'without_filtering' to both Select and MultiSelect, useful when you want to simplify the UX if the filter does not add any value, such as when the list is already short. - Added 'with_answered_prompt_prefix' to RenderConfig to allow customization of answered prompt prefix. -- Added vim-like keybindings for monthly/yearly shifts on DateSelect. +- Revamped keybindings for DateSelect. ### Fixes diff --git a/inquire/src/prompts/dateselect/action.rs b/inquire/src/prompts/dateselect/action.rs index 058f29c4..e53ff80e 100644 --- a/inquire/src/prompts/dateselect/action.rs +++ b/inquire/src/prompts/dateselect/action.rs @@ -30,42 +30,53 @@ pub enum DateSelectPromptAction { impl InnerAction for DateSelectPromptAction { type Config = DateSelectConfig; - fn from_key(key: Key, config: &DateSelectConfig) -> Option { - if config.vim_mode { - let action = match key { - Key::Char('h', KeyModifiers::NONE) => Some(Self::GoToPrevDay), - Key::Char('l', KeyModifiers::NONE) => Some(Self::GoToNextDay), - Key::Char('k', KeyModifiers::NONE) => Some(Self::GoToPrevWeek), - Key::Char('j', KeyModifiers::NONE) => Some(Self::GoToNextWeek), - Key::Char('h', KeyModifiers::CONTROL) => Some(Self::GoToPrevMonth), - Key::Char('l', KeyModifiers::CONTROL) => Some(Self::GoToNextMonth), - Key::Char('k', KeyModifiers::CONTROL) => Some(Self::GoToPrevYear), - Key::Char('j', KeyModifiers::CONTROL) => Some(Self::GoToNextYear), - _ => None, - }; + fn from_key(key: Key, _: &DateSelectConfig) -> Option { + let action = match key { + Key::Left(KeyModifiers::NONE) // standard + | Key::Char('b', KeyModifiers::CONTROL) // emacs + | Key::Char('h', KeyModifiers::NONE) // vim + => Self::GoToPrevDay, + + Key::Right(KeyModifiers::NONE) // standard + | Key::Char('f', KeyModifiers::CONTROL) // emacs + | Key::Char('l', KeyModifiers::NONE) // vim + => Self::GoToNextDay, - if action.is_some() { - return action; - } - } + Key::Up(KeyModifiers::NONE) // standard + | Key::Char('p', KeyModifiers::CONTROL) // emacs + | Key::Char('k', KeyModifiers::NONE) // vim + => Self::GoToPrevWeek, + + Key::Down(KeyModifiers::NONE) // standard + | Key::Char('n', KeyModifiers::CONTROL) // emacs + | Key::Char('j', KeyModifiers::NONE) // vim + | Key::Tab // not sure? keeping it for compatibility reasons now + => Self::GoToNextWeek, + + Key::PageUp(KeyModifiers::NONE) // standard + | Key::Char('[', KeyModifiers::NONE) // alternative when page up is not available + | Key::Left(_) // alternative 2, when the left above with no modifiers is not matched + | Key::Char('v' | 'V', KeyModifiers::ALT | KeyModifiers::META) // emacs + | Key::Char('b' | 'B', _) // vim, ideally ctrl-b should be used, but it's not available due to emacs + => Self::GoToPrevMonth, + + Key::PageDown(KeyModifiers::NONE) // standard + | Key::Char(']', KeyModifiers::NONE) // alternative when page down is not available + | Key::Right(_) // alternative 2, when the right above with no modifiers is not matched + | Key::Char('v' | 'V', KeyModifiers::CONTROL) // emacs + | Key::Char('f' | 'F', _) // vim, ideally ctrl-f should be used, but it's not available due to emacs + => Self::GoToNextMonth, + + Key::PageUp(_) // standard, when the above with no modifiers is not matched + | Key::Char('{' | '[', _) // alternative when page up is not available + | Key::Up(_) // alternative 2, when the up above with no modifiers is not matched + => Self::GoToPrevYear, + + Key::PageDown(_) // standard, when the above with no modifiers is not matched + | Key::Char('}' | ']', _) // alternative when page down is not available + | Key::Down(_) // alternative 2, when the down above with no modifiers is not matched + => Self::GoToNextYear, - let action = match key { - Key::Left(KeyModifiers::NONE) | Key::Char('b', KeyModifiers::CONTROL) => { - Self::GoToPrevDay - } - Key::Right(KeyModifiers::NONE) | Key::Char('f', KeyModifiers::CONTROL) => { - Self::GoToNextDay - } - Key::Up(KeyModifiers::NONE) | Key::Char('p', KeyModifiers::CONTROL) => { - Self::GoToPrevWeek - } - Key::Down(KeyModifiers::NONE) | Key::Char('n', KeyModifiers::CONTROL) | Key::Tab => { - Self::GoToNextWeek - } - Key::Left(KeyModifiers::CONTROL) => Self::GoToPrevMonth, - Key::Right(KeyModifiers::CONTROL) => Self::GoToNextMonth, - Key::Up(KeyModifiers::CONTROL) => Self::GoToPrevYear, - Key::Down(KeyModifiers::CONTROL) => Self::GoToNextYear, _ => return None, }; diff --git a/inquire/src/prompts/dateselect/config.rs b/inquire/src/prompts/dateselect/config.rs index f92867d0..61c26b54 100644 --- a/inquire/src/prompts/dateselect/config.rs +++ b/inquire/src/prompts/dateselect/config.rs @@ -5,7 +5,7 @@ use crate::DateSelect; /// Configuration settings used in the execution of a DateSelectPrompt. #[derive(Copy, Clone, Debug)] pub struct DateSelectConfig { - /// Whether to use vim-style keybindings. + /// Whether to support vim-style keybindings. pub vim_mode: bool, /// Min date allowed to be selected. diff --git a/inquire/src/prompts/dateselect/mod.rs b/inquire/src/prompts/dateselect/mod.rs index 6b890cd2..1a9e5002 100644 --- a/inquire/src/prompts/dateselect/mod.rs +++ b/inquire/src/prompts/dateselect/mod.rs @@ -119,7 +119,7 @@ impl<'a> DateSelect<'a> { /// Default help message. pub const DEFAULT_HELP_MESSAGE: Option<&'a str> = - Some("arrows to move, with ctrl to move months and years, enter to select"); + Some("arrows to move, []{} move months and years, enter to select"); /// Default validators added to the [DateSelect] prompt, none. pub const DEFAULT_VALIDATORS: Vec> = vec![]; diff --git a/inquire/src/prompts/dateselect/prompt.rs b/inquire/src/prompts/dateselect/prompt.rs index 75a1eb77..cf968710 100644 --- a/inquire/src/prompts/dateselect/prompt.rs +++ b/inquire/src/prompts/dateselect/prompt.rs @@ -1,9 +1,9 @@ use std::{ - cmp::{max, min}, + cmp::{max, min, Ordering}, ops::Add, }; -use chrono::{Datelike, Duration, NaiveDate}; +use chrono::{Datelike, Duration, Months, NaiveDate}; use crate::{ date_utils::{get_current_date, get_month}, @@ -60,27 +60,22 @@ impl<'a> DateSelectPrompt<'a> { } fn shift_months(&mut self, qty: i32) -> ActionResult { - let date = self.current_date; - - let years = qty / 12; - let months = qty % 12; - - let new_year = date.year() + years; - let cur_month = date.month0() as i32; - let mut new_month = (cur_month + months) % 12; - if new_month < 0 { - new_month += 12; - } - - let new_date = date - .with_month0(new_month as u32) - .and_then(|d| d.with_year(new_year)); + let new_date = match qty.cmp(&0) { + Ordering::Greater | Ordering::Equal => { + let qty_as_months = Months::new(qty as u32); + self.current_date + .checked_add_months(qty_as_months) + .unwrap_or(NaiveDate::MAX) + } + Ordering::Less => { + let qty_as_months = Months::new((-qty) as u32); + self.current_date + .checked_sub_months(qty_as_months) + .unwrap_or(NaiveDate::MIN) + } + }; - if let Some(new_date) = new_date { - self.update_date(new_date) - } else { - ActionResult::Clean - } + self.update_date(new_date) } fn update_date(&mut self, new_date: NaiveDate) -> ActionResult { diff --git a/inquire/src/prompts/dateselect/test.rs b/inquire/src/prompts/dateselect/test.rs index 76d1d15c..1f0b7aaa 100644 --- a/inquire/src/prompts/dateselect/test.rs +++ b/inquire/src/prompts/dateselect/test.rs @@ -60,3 +60,268 @@ fn closure_validator() { assert_eq!(today_date.pred_opt().unwrap(), ans); } + +#[test] +/// Tests the behaviour of several keybindings in an admittedly naive way. +fn daily_navigation_checks() { + let input = vec![ + Key::Left(KeyModifiers::NONE), + Key::Left(KeyModifiers::NONE), + Key::Left(KeyModifiers::NONE), + Key::Right(KeyModifiers::NONE), + Key::Right(KeyModifiers::NONE), + Key::Right(KeyModifiers::NONE), + Key::Right(KeyModifiers::NONE), + Key::Right(KeyModifiers::NONE), + Key::Right(KeyModifiers::NONE), + Key::Right(KeyModifiers::NONE), + Key::Right(KeyModifiers::NONE), + Key::Enter, + ]; + let mut backend = fake_backend(input); + + let starting_date = NaiveDate::from_ymd_opt(2023, 1, 15).unwrap(); + + let ans = DateSelect::new("Question") + .with_starting_date(starting_date) + .prompt_with_backend(&mut backend) + .unwrap(); + + assert_eq!(NaiveDate::from_ymd_opt(2023, 1, 20).unwrap(), ans); +} + +#[test] +/// Tests the behaviour of several keybindings in an admittedly naive way. +fn weekly_navigation_checks() { + let input = vec![ + Key::Up(KeyModifiers::NONE), + Key::Up(KeyModifiers::NONE), + Key::Up(KeyModifiers::NONE), + Key::Down(KeyModifiers::NONE), + Key::Down(KeyModifiers::NONE), + Key::Down(KeyModifiers::NONE), + Key::Down(KeyModifiers::NONE), + Key::Down(KeyModifiers::NONE), + Key::Down(KeyModifiers::NONE), + Key::Down(KeyModifiers::NONE), + Key::Down(KeyModifiers::NONE), + Key::Enter, + ]; + let mut backend = fake_backend(input); + + let starting_date = NaiveDate::from_ymd_opt(2023, 1, 15).unwrap(); + + let ans = DateSelect::new("Question") + .with_starting_date(starting_date) + .prompt_with_backend(&mut backend) + .unwrap(); + + assert_eq!(NaiveDate::from_ymd_opt(2023, 2, 19).unwrap(), ans); +} + +#[test] +/// Tests the behaviour of several keybindings in an admittedly naive way. +fn monthly_navigation_checks() { + let input = vec![ + Key::Char('[', KeyModifiers::NONE), + Key::Char(']', KeyModifiers::NONE), + Key::Char('[', KeyModifiers::NONE), + Key::Char(']', KeyModifiers::NONE), + Key::Char('[', KeyModifiers::NONE), + Key::Char('[', KeyModifiers::NONE), + Key::Enter, + ]; + let mut backend = fake_backend(input); + + let starting_date = NaiveDate::from_ymd_opt(2023, 1, 15).unwrap(); + + let ans = DateSelect::new("Question") + .with_starting_date(starting_date) + .prompt_with_backend(&mut backend) + .unwrap(); + + assert_eq!(NaiveDate::from_ymd_opt(2022, 11, 15).unwrap(), ans); +} + +#[test] +/// Tests the behaviour of several keybindings in an admittedly naive way. +fn yearly_navigation_checks() { + let input = vec![ + Key::Char('}', KeyModifiers::NONE), + Key::Char('{', KeyModifiers::NONE), + Key::Char('}', KeyModifiers::NONE), + Key::Char('{', KeyModifiers::NONE), + Key::Char('}', KeyModifiers::NONE), + Key::Char('}', KeyModifiers::NONE), + Key::Enter, + ]; + let mut backend = fake_backend(input); + + let starting_date = NaiveDate::from_ymd_opt(2023, 1, 15).unwrap(); + + let ans = DateSelect::new("Question") + .with_starting_date(starting_date) + .prompt_with_backend(&mut backend) + .unwrap(); + + assert_eq!(NaiveDate::from_ymd_opt(2025, 1, 15).unwrap(), ans); +} + +#[test] +/// Tests the behaviour of several keybindings in an admittedly naive way. +fn naive_navigation_combination() { + let input = vec![ + // start: 2023-01-15 + Key::Up(KeyModifiers::NONE), + Key::Char('[', KeyModifiers::NONE), + Key::Up(KeyModifiers::NONE), + Key::Left(KeyModifiers::NONE), + Key::Char(']', KeyModifiers::NONE), + Key::Char('[', KeyModifiers::NONE), + Key::Down(KeyModifiers::NONE), + Key::Left(KeyModifiers::NONE), + Key::Down(KeyModifiers::NONE), + Key::Char('[', KeyModifiers::NONE), + Key::Left(KeyModifiers::NONE), + Key::Char('}', KeyModifiers::NONE), + Key::Down(KeyModifiers::NONE), + Key::Char('[', KeyModifiers::NONE), + Key::Right(KeyModifiers::NONE), + Key::Down(KeyModifiers::NONE), + Key::Down(KeyModifiers::NONE), + Key::Right(KeyModifiers::NONE), + Key::Down(KeyModifiers::NONE), + Key::Right(KeyModifiers::NONE), + Key::Char(']', KeyModifiers::NONE), + Key::Char('}', KeyModifiers::NONE), + Key::Right(KeyModifiers::NONE), + Key::Down(KeyModifiers::NONE), + Key::Right(KeyModifiers::NONE), + Key::Char('{', KeyModifiers::NONE), + Key::Down(KeyModifiers::NONE), + Key::Right(KeyModifiers::NONE), + Key::Char('{', KeyModifiers::NONE), + Key::Right(KeyModifiers::NONE), + Key::Char('}', KeyModifiers::NONE), + Key::Right(KeyModifiers::NONE), + Key::Char('}', KeyModifiers::NONE), + Key::Up(KeyModifiers::NONE), + Key::Enter, + ]; + let mut backend = fake_backend(input); + + let starting_date = NaiveDate::from_ymd_opt(2023, 1, 15).unwrap(); + + let ans = DateSelect::new("Question") + .with_starting_date(starting_date) + .prompt_with_backend(&mut backend) + .unwrap(); + + assert_eq!(NaiveDate::from_ymd_opt(2024, 12, 24).unwrap(), ans); +} + +#[test] +/// Tests the behaviour of several keybindings in an admittedly naive way. +fn emacs_naive_navigation_combination() { + let input = vec![ + // start: 2023-01-15 + Key::Char('p', KeyModifiers::CONTROL), + Key::Char('v', KeyModifiers::ALT), + Key::Char('p', KeyModifiers::CONTROL), + Key::Char('b', KeyModifiers::CONTROL), + Key::Char('v', KeyModifiers::CONTROL), + Key::Char('v', KeyModifiers::ALT), + Key::Char('n', KeyModifiers::CONTROL), + Key::Char('b', KeyModifiers::CONTROL), + Key::Char('n', KeyModifiers::CONTROL), + Key::Char('v', KeyModifiers::ALT), + Key::Char('b', KeyModifiers::CONTROL), + Key::Char('}', KeyModifiers::NONE), + Key::Char('n', KeyModifiers::CONTROL), + Key::Char('v', KeyModifiers::ALT), + Key::Char('f', KeyModifiers::CONTROL), + Key::Char('n', KeyModifiers::CONTROL), + Key::Char('n', KeyModifiers::CONTROL), + Key::Char('f', KeyModifiers::CONTROL), + Key::Char('n', KeyModifiers::CONTROL), + Key::Char('f', KeyModifiers::CONTROL), + Key::Char('v', KeyModifiers::CONTROL), + Key::Char('}', KeyModifiers::NONE), + Key::Char('f', KeyModifiers::CONTROL), + Key::Char('n', KeyModifiers::CONTROL), + Key::Char('f', KeyModifiers::CONTROL), + Key::Char('{', KeyModifiers::NONE), + Key::Char('n', KeyModifiers::CONTROL), + Key::Char('f', KeyModifiers::CONTROL), + Key::Char('{', KeyModifiers::NONE), + Key::Char('f', KeyModifiers::CONTROL), + Key::Char('}', KeyModifiers::NONE), + Key::Char('f', KeyModifiers::CONTROL), + Key::Char('}', KeyModifiers::NONE), + Key::Char('p', KeyModifiers::CONTROL), + Key::Enter, + ]; + let mut backend = fake_backend(input); + + let starting_date = NaiveDate::from_ymd_opt(2023, 1, 15).unwrap(); + + let ans = DateSelect::new("Question") + .with_starting_date(starting_date) + .prompt_with_backend(&mut backend) + .unwrap(); + + assert_eq!(NaiveDate::from_ymd_opt(2024, 12, 24).unwrap(), ans); +} + +#[test] +/// Tests the behaviour of several keybindings in an admittedly naive way. +fn vim_naive_navigation_combination() { + let input = vec![ + // start: 2023-01-15 + Key::Char('k', KeyModifiers::NONE), + Key::Char('b', KeyModifiers::ALT), + Key::Char('k', KeyModifiers::NONE), + Key::Char('h', KeyModifiers::NONE), + Key::Char('f', KeyModifiers::ALT), + Key::Char('b', KeyModifiers::ALT), + Key::Char('j', KeyModifiers::NONE), + Key::Char('h', KeyModifiers::NONE), + Key::Char('j', KeyModifiers::NONE), + Key::Char('b', KeyModifiers::ALT), + Key::Char('h', KeyModifiers::NONE), + Key::Char('}', KeyModifiers::NONE), + Key::Char('j', KeyModifiers::NONE), + Key::Char('b', KeyModifiers::ALT), + Key::Char('l', KeyModifiers::NONE), + Key::Char('j', KeyModifiers::NONE), + Key::Char('j', KeyModifiers::NONE), + Key::Char('l', KeyModifiers::NONE), + Key::Char('j', KeyModifiers::NONE), + Key::Char('l', KeyModifiers::NONE), + Key::Char('f', KeyModifiers::ALT), + Key::Char('}', KeyModifiers::NONE), + Key::Char('l', KeyModifiers::NONE), + Key::Char('j', KeyModifiers::NONE), + Key::Char('l', KeyModifiers::NONE), + Key::Char('{', KeyModifiers::NONE), + Key::Char('j', KeyModifiers::NONE), + Key::Char('l', KeyModifiers::NONE), + Key::Char('{', KeyModifiers::NONE), + Key::Char('l', KeyModifiers::NONE), + Key::Char('}', KeyModifiers::NONE), + Key::Char('l', KeyModifiers::NONE), + Key::Char('}', KeyModifiers::NONE), + Key::Char('k', KeyModifiers::NONE), + Key::Enter, + ]; + let mut backend = fake_backend(input); + + let starting_date = NaiveDate::from_ymd_opt(2023, 1, 15).unwrap(); + + let ans = DateSelect::new("Question") + .with_starting_date(starting_date) + .prompt_with_backend(&mut backend) + .unwrap(); + + assert_eq!(NaiveDate::from_ymd_opt(2024, 12, 24).unwrap(), ans); +} diff --git a/inquire/src/prompts/multiselect/action.rs b/inquire/src/prompts/multiselect/action.rs index c02b76ff..e61a3fbf 100644 --- a/inquire/src/prompts/multiselect/action.rs +++ b/inquire/src/prompts/multiselect/action.rs @@ -48,11 +48,11 @@ impl InnerAction for MultiSelectPromptAction { let action = match key { Key::Up(KeyModifiers::NONE) | Key::Char('p', KeyModifiers::CONTROL) => Self::MoveUp, - Key::PageUp => Self::PageUp, + Key::PageUp(_) => Self::PageUp, Key::Home => Self::MoveToStart, Key::Down(KeyModifiers::NONE) | Key::Char('n', KeyModifiers::CONTROL) => Self::MoveDown, - Key::PageDown => Self::PageDown, + Key::PageDown(_) => Self::PageDown, Key::End => Self::MoveToEnd, Key::Char(' ', KeyModifiers::NONE) => Self::ToggleCurrentOption, diff --git a/inquire/src/prompts/select/action.rs b/inquire/src/prompts/select/action.rs index 9acc1022..c372c57c 100644 --- a/inquire/src/prompts/select/action.rs +++ b/inquire/src/prompts/select/action.rs @@ -42,11 +42,11 @@ impl InnerAction for SelectPromptAction { let action = match key { Key::Up(KeyModifiers::NONE) | Key::Char('p', KeyModifiers::CONTROL) => Self::MoveUp, - Key::PageUp => Self::PageUp, + Key::PageUp(_) => Self::PageUp, Key::Home => Self::MoveToStart, Key::Down(KeyModifiers::NONE) | Key::Char('n', KeyModifiers::CONTROL) => Self::MoveDown, - Key::PageDown => Self::PageDown, + Key::PageDown(_) => Self::PageDown, Key::End => Self::MoveToEnd, key => match InputAction::from_key(key, &()) { diff --git a/inquire/src/prompts/text/action.rs b/inquire/src/prompts/text/action.rs index ee18654a..b98f7b30 100644 --- a/inquire/src/prompts/text/action.rs +++ b/inquire/src/prompts/text/action.rs @@ -31,12 +31,12 @@ impl InnerAction for TextPromptAction { Key::Up(KeyModifiers::NONE) | Key::Char('p', KeyModifiers::CONTROL) => { Self::MoveToSuggestionAbove } - Key::PageUp => Self::MoveToSuggestionPageUp, + Key::PageUp(_) => Self::MoveToSuggestionPageUp, Key::Down(KeyModifiers::NONE) | Key::Char('n', KeyModifiers::CONTROL) => { Self::MoveToSuggestionBelow } - Key::PageDown => Self::MoveToSuggestionPageDown, + Key::PageDown(_) => Self::MoveToSuggestionPageDown, Key::Tab => Self::UseCurrentSuggestion, diff --git a/inquire/src/terminal/console.rs b/inquire/src/terminal/console.rs index d355d3a8..3ba56ce6 100644 --- a/inquire/src/terminal/console.rs +++ b/inquire/src/terminal/console.rs @@ -154,8 +154,8 @@ impl From for crate::ui::Key { Key::Del => Self::Delete(KeyModifiers::empty()), Key::Home => Self::Home, Key::End => Self::End, - Key::PageUp => Self::PageUp, - Key::PageDown => Self::PageDown, + Key::PageUp => Self::PageUp(KeyModifiers::empty()), + Key::PageDown => Self::PageDown(KeyModifiers::empty()), Key::ArrowUp => Self::Up(KeyModifiers::empty()), Key::ArrowDown => Self::Down(KeyModifiers::empty()), Key::ArrowLeft => Self::Left(KeyModifiers::empty()), diff --git a/inquire/src/terminal/crossterm.rs b/inquire/src/terminal/crossterm.rs index 555c7102..f49b8c7a 100644 --- a/inquire/src/terminal/crossterm.rs +++ b/inquire/src/terminal/crossterm.rs @@ -234,6 +234,15 @@ impl From for crate::ui::KeyModifiers { if m.contains(KeyModifiers::SHIFT) { modifiers |= crate::ui::KeyModifiers::SHIFT; } + if m.contains(KeyModifiers::SUPER) { + modifiers |= crate::ui::KeyModifiers::SUPER; + } + if m.contains(KeyModifiers::HYPER) { + modifiers |= crate::ui::KeyModifiers::HYPER; + } + if m.contains(KeyModifiers::META) { + modifiers |= crate::ui::KeyModifiers::META; + } modifiers } @@ -271,12 +280,14 @@ impl From for Key { } => Self::End, KeyEvent { code: KeyCode::PageUp, + modifiers: m, .. - } => Self::PageUp, + } => Self::PageUp(m.into()), KeyEvent { code: KeyCode::PageDown, + modifiers: m, .. - } => Self::PageDown, + } => Self::PageDown(m.into()), KeyEvent { code: KeyCode::Up, modifiers: m, @@ -347,8 +358,8 @@ mod test { Key::Delete(m) => KeyEvent::new(KeyCode::Delete, m.try_into()?), Key::Home => KeyEvent::new(KeyCode::Home, KeyModifiers::NONE), Key::End => KeyEvent::new(KeyCode::End, KeyModifiers::NONE), - Key::PageUp => KeyEvent::new(KeyCode::PageUp, KeyModifiers::NONE), - Key::PageDown => KeyEvent::new(KeyCode::PageDown, KeyModifiers::NONE), + Key::PageUp(m) => KeyEvent::new(KeyCode::PageUp, m.try_into()?), + Key::PageDown(m) => KeyEvent::new(KeyCode::PageDown, m.try_into()?), Key::Up(m) => KeyEvent::new(KeyCode::Up, m.try_into()?), Key::Down(m) => KeyEvent::new(KeyCode::Down, m.try_into()?), Key::Left(m) => KeyEvent::new(KeyCode::Left, m.try_into()?), diff --git a/inquire/src/terminal/termion.rs b/inquire/src/terminal/termion.rs index b8434501..9ad222ae 100644 --- a/inquire/src/terminal/termion.rs +++ b/inquire/src/terminal/termion.rs @@ -250,8 +250,8 @@ impl From for crate::ui::Key { Key::Delete => Self::Delete(KeyModifiers::empty()), Key::Home => Self::Home, Key::End => Self::End, - Key::PageUp => Self::PageUp, - Key::PageDown => Self::PageDown, + Key::PageUp => Self::PageUp(KeyModifiers::empty()), + Key::PageDown => Self::PageDown(KeyModifiers::empty()), Key::Up => Self::Up(KeyModifiers::empty()), Key::Down => Self::Down(KeyModifiers::empty()), Key::Left => Self::Left(KeyModifiers::empty()), diff --git a/inquire/src/ui/key.rs b/inquire/src/ui/key.rs index bf606247..fad99dde 100644 --- a/inquire/src/ui/key.rs +++ b/inquire/src/ui/key.rs @@ -8,6 +8,9 @@ bitflags! { const SHIFT = 0b0000_0001; const CONTROL = 0b0000_0010; const ALT = 0b0000_0100; + const SUPER = 0b0000_1000; + const HYPER = 0b0001_0000; + const META = 0b0010_0000; const NONE = 0b0000_0000; } } @@ -21,8 +24,8 @@ pub enum Key { Delete(KeyModifiers), Home, End, - PageUp, - PageDown, + PageUp(KeyModifiers), + PageDown(KeyModifiers), Up(KeyModifiers), Down(KeyModifiers), Left(KeyModifiers),