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

Implement fuzzy finder as default filter for Select/MultiSelect #176

Merged
merged 12 commits into from
Oct 1, 2023
Prev Previous commit
Next Next commit
Enable/Disable cursor resetting to first option
  • Loading branch information
Baarsgaard committed Sep 17, 2023
commit ef6349cefbc63d13ab644b2fdb9962ab63f86810
3 changes: 3 additions & 0 deletions inquire/src/prompts/multiselect/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ pub struct MultiSelectConfig {
pub page_size: usize,
/// Whether to keep the filter text when an option is selected.
pub keep_filter: bool,
/// Whether to reset the cursor to the first option on filter input change.
pub reset_cursor: bool,
}

impl<T> From<&MultiSelect<'_, T>> for MultiSelectConfig {
Expand All @@ -17,6 +19,7 @@ impl<T> From<&MultiSelect<'_, T>> for MultiSelectConfig {
vim_mode: value.vim_mode,
page_size: value.page_size,
keep_filter: value.keep_filter,
reset_cursor: value.reset_cursor,
}
}
}
17 changes: 17 additions & 0 deletions inquire/src/prompts/multiselect/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ pub struct MultiSelect<'a, T> {
/// Starting cursor index of the selection.
pub starting_cursor: usize,

/// Reset cursor position to first option on filter input change.
/// Defaults to true when 'fuzzy' is enabled.
pub reset_cursor: bool,

/// Function called with the current user input to score the provided
/// options.
/// The list of options is sorted in descending order (highest score first)
Expand Down Expand Up @@ -189,6 +193,10 @@ where
/// Default starting cursor index.
pub const DEFAULT_STARTING_CURSOR: usize = 0;

/// Default cursor behaviour on filter input change.
/// Defaults to true if 'fuzzy' is enabled.
pub const DEFAULT_RESET_CURSOR: bool = cfg!(feature = "fuzzy");
Baarsgaard marked this conversation as resolved.
Show resolved Hide resolved

/// Default behavior of keeping or cleaning the current filter value.
pub const DEFAULT_KEEP_FILTER: bool = true;

Expand All @@ -206,6 +214,7 @@ where
page_size: Self::DEFAULT_PAGE_SIZE,
vim_mode: Self::DEFAULT_VIM_MODE,
starting_cursor: Self::DEFAULT_STARTING_CURSOR,
reset_cursor: Self::DEFAULT_RESET_CURSOR,
keep_filter: Self::DEFAULT_KEEP_FILTER,
scorer: Self::DEFAULT_SCORER,
formatter: Self::DEFAULT_FORMATTER,
Expand Down Expand Up @@ -293,6 +302,14 @@ where
self
}

/// Sets the reset_cursor behaviour.
/// Will reset cursor to first option on filter input change.
/// Defaults to true if 'fuzzy' is enabled.
pub fn with_reset_cursor(mut self, reset_cursor: bool) -> Self {
self.reset_cursor = reset_cursor;
self
}

/// Sets the provided color theme to this prompt.
///
/// Note: The default render config considers if the NO_COLOR environment variable
Expand Down
4 changes: 3 additions & 1 deletion inquire/src/prompts/multiselect/prompt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,9 @@ where
options.sort_unstable_by_key(|(_idx, score)| Reverse(*score));

self.scored_options = options.into_iter().map(|(idx, _)| idx).collect();
if self.scored_options.len() <= self.cursor_index {
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));
}
Expand Down
3 changes: 3 additions & 0 deletions inquire/src/prompts/select/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@ pub struct SelectConfig {
pub vim_mode: bool,
/// Page size of the list of options.
pub page_size: usize,
/// Whether to reset the cursor to the first option on filter input change.
pub reset_cursor: bool,
}

impl<T> From<&Select<'_, T>> for SelectConfig {
fn from(value: &Select<'_, T>) -> Self {
Self {
vim_mode: value.vim_mode,
page_size: value.page_size,
reset_cursor: value.reset_cursor,
}
}
}
17 changes: 17 additions & 0 deletions inquire/src/prompts/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ pub struct Select<'a, T> {
/// Starting cursor index of the selection.
pub starting_cursor: usize,

/// Reset cursor position to first option on filter input change.
/// Defaults to true when 'fuzzy' is enabled.
pub reset_cursor: bool,

/// Function called with the current user input to score the provided
/// options.
pub scorer: Scorer<'a, T>,
Expand Down Expand Up @@ -174,6 +178,10 @@ where
/// Default starting cursor index.
pub const DEFAULT_STARTING_CURSOR: usize = 0;

/// Default cursor behaviour on filter input change.
/// Defaults to true if 'fuzzy' is enabled.
pub const DEFAULT_RESET_CURSOR: bool = cfg!(feature = "fuzzy");

/// Default help message.
pub const DEFAULT_HELP_MESSAGE: Option<&'a str> =
Some("↑↓ to move, enter to select, type to filter");
Expand All @@ -187,6 +195,7 @@ where
page_size: Self::DEFAULT_PAGE_SIZE,
vim_mode: Self::DEFAULT_VIM_MODE,
starting_cursor: Self::DEFAULT_STARTING_CURSOR,
reset_cursor: Self::DEFAULT_RESET_CURSOR,
scorer: Self::DEFAULT_SCORER,
formatter: Self::DEFAULT_FORMATTER,
render_config: get_configuration(),
Expand Down Expand Up @@ -235,6 +244,14 @@ where
self
}

/// Sets the reset_cursor behaviour.
/// Will reset cursor to first option on filter input change.
/// Defaults to true if 'fuzzy' is enabled.
pub fn with_reset_cursor(mut self, reset_cursor: bool) -> Self {
self.reset_cursor = reset_cursor;
self
}

/// Sets the provided color theme to this prompt.
///
/// Note: The default render config considers if the NO_COLOR environment variable
Expand Down
4 changes: 3 additions & 1 deletion inquire/src/prompts/select/prompt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,9 @@ where
options.sort_unstable_by_key(|(_idx, score)| Reverse(*score));

self.scored_options = options.into_iter().map(|(idx, _)| idx).collect();
if self.scored_options.len() <= self.cursor_index {
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));
}
Expand Down