codeberg_cli/render/ui/
mod.rs1use anyhow::Context;
2
3pub fn multi_fuzzy_select_with_key<T>(
12 items: &[T],
13 prompt: impl AsRef<str>,
14 is_selected: impl Fn(&T) -> bool,
15 f_display: impl Fn(&T) -> String,
16) -> anyhow::Result<Vec<&T>> {
17 let already_selected = items
19 .iter()
20 .enumerate()
21 .filter(|(_, elem)| is_selected(elem))
22 .map(|(idx, _)| idx)
23 .collect::<Vec<_>>();
24
25 let displayed_items = items.iter().map(f_display).collect::<Vec<_>>();
27
28 let selected_indices = inquire::MultiSelect::new(prompt.as_ref(), displayed_items)
30 .with_default(&already_selected)
31 .raw_prompt()
32 .context("There's nothing to select from")?;
33
34 let selected_items = selected_indices
36 .into_iter()
37 .map(|raw| raw.index)
38 .filter_map(|idx| items.get(idx))
39 .collect::<Vec<_>>();
40
41 Ok(selected_items)
42}
43
44pub fn fuzzy_select_with_key<T>(
46 items: &[T],
47 prompt: impl AsRef<str>,
48 f_display: impl Fn(&T) -> String,
49) -> anyhow::Result<&T> {
50 fuzzy_select_with_key_with_default(items, prompt, f_display, None)
51}
52
53pub fn fuzzy_select_with_key_with_default<T>(
61 items: &[T],
62 prompt: impl AsRef<str>,
63 f_display: impl Fn(&T) -> String,
64 default_index: Option<usize>,
65) -> anyhow::Result<&T> {
66 if items.is_empty() {
68 anyhow::bail!("Nothing to select from. Aborting.")
69 }
70
71 let displayed_items = items.iter().map(f_display).collect::<Vec<_>>();
72
73 let mut dialogue = inquire::Select::new(prompt.as_ref(), displayed_items);
75
76 if let Some(index) = default_index {
78 dialogue = dialogue.with_starting_cursor(index);
79 }
80
81 let selected_index = dialogue.raw_prompt().map_err(anyhow::Error::from)?.index;
83
84 Ok(&items[selected_index])
85}
86
87pub fn confirm_with_prompt(prompt: &str) -> anyhow::Result<bool> {
92 inquire::Confirm::new(prompt)
93 .with_help_message("(y/n)?")
94 .prompt()
95 .map_err(anyhow::Error::from)
96}