diff --git a/examples/fuzzyselect.rs b/examples/fuzzyselect.rs index 93b9b623..a00fb6b1 100644 --- a/examples/fuzzyselect.rs +++ b/examples/fuzzyselect.rs @@ -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()) diff --git a/src/prompts/fuzzy_select.rs b/src/prompts/fuzzy_select.rs index 4d423e49..e17b4908 100644 --- a/src/prompts/fuzzy_select.rs +++ b/src/prompts/fuzzy_select.rs @@ -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 { @@ -167,9 +172,14 @@ impl FuzzySelect<'_> { .collect::>(); // 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()?; } @@ -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 { @@ -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 => { @@ -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; @@ -235,6 +256,7 @@ impl FuzzySelect<'_> { position += 1; term.flush()?; sel = 0; + starting_row = 0; } _ => {}