codeberg_cli/render/ui/
mod.rs

1use anyhow::Context;
2
3pub fn multi_fuzzy_select_with_key<T>(
4    items: &[T],
5    prompt: impl AsRef<str>,
6    is_selected: impl Fn(&T) -> bool,
7    f_display: impl Fn(&T) -> String,
8) -> anyhow::Result<Vec<&T>> {
9    let already_selected = items
10        .iter()
11        .enumerate()
12        .filter(|(_, elem)| is_selected(elem))
13        .map(|(idx, _)| idx)
14        .collect::<Vec<_>>();
15
16    let displayed_items = items.iter().map(f_display).collect::<Vec<_>>();
17
18    let selected_indices = inquire::MultiSelect::new(prompt.as_ref(), displayed_items)
19        .with_default(&already_selected)
20        .raw_prompt()
21        .context("There's nothing to select from")?;
22
23    let selected_items = selected_indices
24        .into_iter()
25        .map(|raw| raw.index)
26        .filter_map(|idx| items.get(idx))
27        .collect::<Vec<_>>();
28
29    Ok(selected_items)
30}
31
32pub fn fuzzy_select_with_key<T>(
33    items: &[T],
34    prompt: impl AsRef<str>,
35    f_display: impl Fn(&T) -> String,
36) -> anyhow::Result<&T> {
37    fuzzy_select_with_key_with_default(items, prompt, f_display, None)
38}
39
40pub fn fuzzy_select_with_key_with_default<T>(
41    items: &[T],
42    prompt: impl AsRef<str>,
43    f_display: impl Fn(&T) -> String,
44    default_index: Option<usize>,
45) -> anyhow::Result<&T> {
46    // return `None` if we have nothing to select from
47    if items.is_empty() {
48        anyhow::bail!("Nothing to select from. Aborting.")
49    }
50
51    let displayed_items = items.iter().map(f_display).collect::<Vec<_>>();
52
53    // build standard dialogue
54    let mut dialogue = inquire::Select::new(prompt.as_ref(), displayed_items);
55
56    // optionally add default selection
57    if let Some(index) = default_index {
58        dialogue = dialogue.with_starting_cursor(index);
59    }
60
61    // select an item by key
62    let selected_index = dialogue.raw_prompt().map_err(anyhow::Error::from)?.index;
63
64    Ok(&items[selected_index])
65}
66
67pub fn confirm_with_prompt(prompt: &str) -> anyhow::Result<bool> {
68    inquire::Confirm::new(prompt)
69        .with_help_message("(y/n)?")
70        .prompt()
71        .map_err(anyhow::Error::from)
72}