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

Limit visible options in fuzzy select #162

Merged
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 24 additions & 0 deletions examples/fuzzyselect.rs
Expand Up @@ -6,6 +6,30 @@ fn main() {
"Vanilla Cupcake",
"Chocolate Muffin",
"A Pile of sweet, sweet mustard",
"Carrots",
"Peas",
"Pistacio",
"Mustard",
"Cream",
"Banana",
"Chocolate",
"Flakes",
"Corn",
"Cake",
"Tarte",
"Cheddar",
"Vanilla",
"Hazelnut",
"Flour",
"Sugar",
"Salt",
"Potato",
"French Fries",
"Pizza",
"Mousse au chocolat",
"Brown sugar",
"Blueberry",
"Burger",
];

let selection = FuzzySelect::with_theme(&ColorfulTheme::default())
Expand Down
36 changes: 29 additions & 7 deletions src/prompts/fuzzy_select.rs
Expand Up @@ -146,12 +146,17 @@ impl FuzzySelect<'_> {
let mut size_vec = Vec::new();
for items in self.items.iter().as_slice() {
let size = &items.len();
size_vec.push(size.clone());
size_vec.push(*size);
}

// Fuzzy matcher
let matcher = fuzzy_matcher::skim::SkimMatcherV2::default();

// Subtract -2 because we need space to render the prompt.
let visible_term_rows = (term.size().0 as usize).max(3) - 2;
// Variable used to determine if we need to scroll through the list.
let mut starting_row = 0;

term.hide_cursor()?;

loop {
Expand All @@ -167,9 +172,14 @@ impl FuzzySelect<'_> {
.collect::<Vec<_>>();

// Renders all matching items, from best match to worst.
filtered_list.sort_unstable_by(|(_, s1), (_, s2)| s2.cmp(&s1));
filtered_list.sort_unstable_by(|(_, s1), (_, s2)| s2.cmp(s1));

for (idx, (item, _)) in filtered_list.iter().enumerate() {
for (idx, (item, _)) in filtered_list
.iter()
.enumerate()
.skip(starting_row)
.take(visible_term_rows)
{
render.select_prompt_item(item, idx == sel)?;
term.flush()?;
}
Expand All @@ -183,7 +193,13 @@ impl FuzzySelect<'_> {
term.show_cursor()?;
return Ok(None);
}
Key::ArrowUp | Key::BackTab if filtered_list.len() > 0 => {
Key::ArrowUp | Key::BackTab if !filtered_list.is_empty() => {
if sel == 0 {
starting_row =
filtered_list.len().max(visible_term_rows) - visible_term_rows;
} else if sel == starting_row {
starting_row -= 1;
}
if sel == !0 {
sel = filtered_list.len() - 1;
} else {
Expand All @@ -192,12 +208,17 @@ impl FuzzySelect<'_> {
}
term.flush()?;
}
Key::ArrowDown | Key::Tab if filtered_list.len() > 0 => {
Key::ArrowDown | Key::Tab if !filtered_list.is_empty() => {
if sel == !0 {
sel = 0;
} else {
sel = (sel as u64 + 1).rem(filtered_list.len() as u64) as usize;
}
if sel == visible_term_rows + starting_row {
starting_row += 1;
} else if sel == 0 {
starting_row = 0;
}
term.flush()?;
}
Key::ArrowLeft if position > 0 => {
Expand All @@ -208,14 +229,14 @@ impl FuzzySelect<'_> {
position += 1;
term.flush()?;
}
Key::Enter if filtered_list.len() > 0 => {
Key::Enter if !filtered_list.is_empty() => {
if self.clear {
render.clear()?;
}

if self.report {
render
.input_prompt_selection(self.prompt.as_str(), &filtered_list[sel].0)?;
.input_prompt_selection(self.prompt.as_str(), filtered_list[sel].0)?;
}

let sel_string = filtered_list[sel].0;
Expand All @@ -235,6 +256,7 @@ impl FuzzySelect<'_> {
position += 1;
term.flush()?;
sel = 0;
starting_row = 0;
}

_ => {}
Expand Down