console-rs / dialoguer

Rust utility library for nice command line prompts and similar things
MIT License
1.33k stars 143 forks source link

FuzzySelect returns wrong index if items has duplicate entries #286

Open mike-lloyd03 opened 1 year ago

mike-lloyd03 commented 1 year ago

If a slice with duplicate values is passed to the items() method on a new FuzzySelect, the index of the first item is returned if the user selects the second item.

use dialoguer::{console::Term, FuzzySelect};

fn main() {
    let items = ["item0", "item1", "item1", "item3", "item4"];

    let selection = FuzzySelect::new()
        .items(&items)
        .interact_on_opt(&Term::stderr())
        .unwrap();

    if let Some(index) = selection {
        println!("Selection: {index}");
    }
}

Selecting the first item returns the correct index.

|
  item0
> item1
  item1
  item3
  item4

Selection: 1

Selecting the second item returns the incorrect index.

|
  item0
  item1
> item1
  item3
  item4

Selection: 1
mike-lloyd03 commented 1 year ago

I think the issue originates here where the selected index is determined from the string of the item that was chosen.

https://github.com/console-rs/dialoguer/blob/d952d17d1c09b6dcbfdb94850818fdce8c02bfeb/src/prompts/fuzzy_select.rs#L334-L336

I'm not seeing an easy way to determine the index that is selected instead of the string itself.

zopadan commented 7 months ago

Perhaps, as an added benefit to the user, duplicate items in the list can be determined and renamed as such? E.g. | item0 item1 item1 (Duplicate 1) item3 item4

Can have any N number of duplicates. This would generate unique names for each item in the list.

zopadan commented 7 months ago

Perhaps, as an added benefit to the user, duplicate items in the list can be determined and renamed as such? E.g. | item0 item1 item1 (Duplicate 1) item3 item4

Can have any N number of duplicates. This would generate unique names for each item in the list.

This is of course assuming that any of the select menus can and should support duplicate entries. I can't really think of a reason that would be needed (how could the 2 similar selections actually result in different outcomes?), so the simple solution would be to always return a set of only unique entries in the items list.