ytil_noxi/
inputlist.rs

1//! Utilities for user input selection from lists using Vimscript inputlist.
2
3use core::fmt::Display;
4
5use nvim_oxi::Array;
6
7/// Prompt the user to select an item from a numbered list.
8///
9/// Displays `prompt` followed by numbered `items` via the Vimscript
10/// `inputlist()` function and returns the chosen element (1-based user
11/// index translated to 0-based). Returns [`None`] if the user cancels.
12///
13/// # Errors
14/// - Invoking `inputlist()` fails.
15/// - The returned index cannot be converted to `usize` (negative or overflow).
16pub fn open<'a, I: Display>(prompt: &'a str, items: &'a [I]) -> color_eyre::Result<Option<&'a I>> {
17    let displayable_items: Vec<_> = items
18        .iter()
19        .enumerate()
20        .map(|(idx, item)| format!("{}. {item}", idx.saturating_add(1)))
21        .collect();
22
23    let prompt_and_items = std::iter::once(prompt.to_string())
24        .chain(displayable_items)
25        .collect::<Array>();
26
27    let idx = nvim_oxi::api::call_function::<_, i64>("inputlist", (prompt_and_items,))?;
28
29    Ok(usize::try_from(idx.saturating_sub(1))
30        .ok()
31        .and_then(|idx| items.get(idx)))
32}