Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds 'starting_filter_input' to Select #185

Merged
merged 6 commits into from
Nov 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading