Skip to content

Commit

Permalink
Adds 'starting_filter_input' to Select (#185)
Browse files Browse the repository at this point in the history
* initial

* fixed clippy 'replace the closure with the function itself'

* Added with_starting_filter_input to MultiSelect

* Updated Changelog

* Run scorer function on setup of select/multiselect prompts

---------

Co-authored-by: Cor Peters <C.Peters@Eekels.com>
Co-authored-by: Mikael Mello <git@mikaelmello.com>
  • Loading branch information
3 people authored Nov 1, 2023
1 parent 7b069c7 commit 1949b47
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 22 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
- 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)
- Keybindings Ctrl-p and Ctrl-n added for Up and Down actions
- Added 'with_starting_filter_input' to both Select and MultiSelect, which allows for setting an initial value to the filter section of the prompt.
- Keybindings Ctrl-j and Ctrl-g added for Enter and Cancel actions

### Fixes
Expand Down
11 changes: 11 additions & 0 deletions inquire/src/prompts/multiselect/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ static DEFAULT_MATCHER: Lazy<SkimMatcherV2> = Lazy::new(|| SkimMatcherV2::defaul
/// - **Options list**: Options displayed to the user. Must be **non-empty**.
/// - **Default selections**: Options that are selected by default when the prompt is first rendered. The user can unselect them. If any of the indices is out-of-range of the option list, the prompt will fail with an [`InquireError::InvalidConfiguration`] error.
/// - **Starting cursor**: Index of the cursor when the prompt is first rendered. Default is 0 (first option). If the index is out-of-range of the option list, the prompt will fail with an [`InquireError::InvalidConfiguration`] error.
/// - **Starting filter input**: Sets the initial value of the filter section of the prompt.
/// - **Help message**: Message displayed at the line below the prompt.
/// - **Formatter**: Custom formatter in case you need to pre-process the user input before showing it as the final answer.
/// - Prints the selected options string value, joined using a comma as the separator, by default.
Expand Down Expand Up @@ -83,6 +84,9 @@ pub struct MultiSelect<'a, T> {
/// Starting cursor index of the selection.
pub starting_cursor: usize,

/// Starting filter input
pub starting_filter_input: Option<&'a str>,

/// Reset cursor position to first option on filter input change.
/// Defaults to true.
pub reset_cursor: bool,
Expand Down Expand Up @@ -214,6 +218,7 @@ where
page_size: Self::DEFAULT_PAGE_SIZE,
vim_mode: Self::DEFAULT_VIM_MODE,
starting_cursor: Self::DEFAULT_STARTING_CURSOR,
starting_filter_input: None,
reset_cursor: Self::DEFAULT_RESET_CURSOR,
keep_filter: Self::DEFAULT_KEEP_FILTER,
scorer: Self::DEFAULT_SCORER,
Expand Down Expand Up @@ -302,6 +307,12 @@ where
self
}

/// Sets the starting filter input
pub fn with_starting_filter_input(mut self, starting_filter_input: &'a str) -> Self {
self.starting_filter_input = Some(starting_filter_input);
self
}

/// Sets the reset_cursor behaviour.
/// Will reset cursor to first option on filter input change.
/// Defaults to true.
Expand Down
33 changes: 22 additions & 11 deletions inquire/src/prompts/multiselect/prompt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,10 @@ where
scored_options,
help_message: mso.help_message,
cursor_index: mso.starting_cursor,
input: Input::new(),
input: mso
.starting_filter_input
.map(Input::new_with)
.unwrap_or_else(Input::new),
scorer: mso.scorer,
formatter: mso.formatter,
validator: mso.validator,
Expand Down Expand Up @@ -191,6 +194,18 @@ where

answer
}

fn run_scorer(&mut self) {
let mut options = self.score_options();
options.sort_unstable_by_key(|(_idx, score)| Reverse(*score));

self.scored_options = options.into_iter().map(|(idx, _)| idx).collect();
if self.config.reset_cursor {
let _ = self.update_cursor_position(0);
} else if self.scored_options.len() <= self.cursor_index {
let _ = self.update_cursor_position(self.scored_options.len().saturating_sub(1));
}
}
}

impl<'a, Backend, T> Prompt<Backend> for MultiSelectPrompt<'a, T>
Expand All @@ -215,6 +230,11 @@ where
(self.formatter)(&refs)
}

fn setup(&mut self) -> InquireResult<()> {
self.run_scorer();
Ok(())
}

fn submit(&mut self) -> InquireResult<Option<Vec<ListOption<T>>>> {
let answer = match self.validate_current_answer()? {
Validation::Valid => Some(self.get_final_answer()),
Expand Down Expand Up @@ -263,16 +283,7 @@ where
let result = self.input.handle(input_action);

if let InputActionResult::ContentChanged = result {
let mut options = self.score_options();
options.sort_unstable_by_key(|(_idx, score)| Reverse(*score));

self.scored_options = options.into_iter().map(|(idx, _)| idx).collect();
if self.config.reset_cursor {
let _ = self.update_cursor_position(0);
} else if self.scored_options.len() <= self.cursor_index {
let _ = self
.update_cursor_position(self.scored_options.len().saturating_sub(1));
}
self.run_scorer();
}

result.into()
Expand Down
11 changes: 11 additions & 0 deletions inquire/src/prompts/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ static DEFAULT_MATCHER: Lazy<SkimMatcherV2> = Lazy::new(|| SkimMatcherV2::defaul
/// - **Prompt message**: Required when creating the prompt.
/// - **Options list**: Options displayed to the user. Must be **non-empty**.
/// - **Starting cursor**: Index of the cursor when the prompt is first rendered. Default is 0 (first option). If the index is out-of-range of the option list, the prompt will fail with an [`InquireError::InvalidConfiguration`] error.
/// - **Starting filter input**: Sets the initial value of the filter section of the prompt.
/// - **Help message**: Message displayed at the line below the prompt.
/// - **Formatter**: Custom formatter in case you need to pre-process the user input before showing it as the final answer.
/// - Prints the selected option string value by default.
Expand Down Expand Up @@ -89,6 +90,9 @@ pub struct Select<'a, T> {
/// Starting cursor index of the selection.
pub starting_cursor: usize,

/// Starting filter input
pub starting_filter_input: Option<&'a str>,

/// Reset cursor position to first option on filter input change.
/// Defaults to true.
pub reset_cursor: bool,
Expand Down Expand Up @@ -199,6 +203,7 @@ where
scorer: Self::DEFAULT_SCORER,
formatter: Self::DEFAULT_FORMATTER,
render_config: get_configuration(),
starting_filter_input: None,
}
}

Expand Down Expand Up @@ -244,6 +249,12 @@ where
self
}

/// Sets the starting filter input
pub fn with_starting_filter_input(mut self, starting_filter_input: &'a str) -> Self {
self.starting_filter_input = Some(starting_filter_input);
self
}

/// Sets the reset_cursor behaviour.
/// Will reset cursor to first option on filter input change.
/// Defaults to true.
Expand Down
33 changes: 22 additions & 11 deletions inquire/src/prompts/select/prompt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ where
scored_options,
help_message: so.help_message,
cursor_index: so.starting_cursor,
input: Input::new(),
input: so
.starting_filter_input
.map(Input::new_with)
.unwrap_or_else(Input::new),
scorer: so.scorer,
formatter: so.formatter,
})
Expand Down Expand Up @@ -130,6 +133,18 @@ where

ListOption::new(index, value)
}

fn run_scorer(&mut self) {
let mut options = self.score_options();
options.sort_unstable_by_key(|(_idx, score)| Reverse(*score));

self.scored_options = options.into_iter().map(|(idx, _)| idx).collect();
if self.config.reset_cursor {
let _ = self.update_cursor_position(0);
} else if self.scored_options.len() <= self.cursor_index {
let _ = self.update_cursor_position(self.scored_options.len().saturating_sub(1));
}
}
}

impl<'a, Backend, T> Prompt<Backend> for SelectPrompt<'a, T>
Expand All @@ -153,6 +168,11 @@ where
(self.formatter)(answer.as_ref())
}

fn setup(&mut self) -> InquireResult<()> {
self.run_scorer();
Ok(())
}

fn submit(&mut self) -> InquireResult<Option<ListOption<T>>> {
let answer = match self.has_answer_highlighted() {
true => Some(self.get_final_answer()),
Expand All @@ -174,16 +194,7 @@ where
let result = self.input.handle(input_action);

if let InputActionResult::ContentChanged = result {
let mut options = self.score_options();
options.sort_unstable_by_key(|(_idx, score)| Reverse(*score));

self.scored_options = options.into_iter().map(|(idx, _)| idx).collect();
if self.config.reset_cursor {
let _ = self.update_cursor_position(0);
} else if self.scored_options.len() <= self.cursor_index {
let _ = self
.update_cursor_position(self.scored_options.len().saturating_sub(1));
}
self.run_scorer();
}

result.into()
Expand Down

0 comments on commit 1949b47

Please sign in to comment.