codeberg_cli/render/ui/
mod.rs1use forgejo_api::structs::StateType;
2use miette::{Context, IntoDiagnostic};
3
4pub fn multi_fuzzy_select_with_key<T>(
13 items: &[T],
14 prompt: impl AsRef<str>,
15 is_selected: impl Fn(&T) -> bool,
16 f_display: impl Fn(&T) -> String,
17) -> miette::Result<Vec<&T>> {
18 let already_selected = items
20 .iter()
21 .enumerate()
22 .filter(|(_, elem)| is_selected(elem))
23 .map(|(idx, _)| idx)
24 .collect::<Vec<_>>();
25
26 let displayed_items = items.iter().map(f_display).collect::<Vec<_>>();
28
29 let selected_indices = inquire::MultiSelect::new(prompt.as_ref(), displayed_items)
31 .with_default(&already_selected)
32 .raw_prompt()
33 .into_diagnostic()
34 .context("There's nothing to select from")?;
35
36 let selected_items = selected_indices
38 .into_iter()
39 .map(|raw| raw.index)
40 .filter_map(|idx| items.get(idx))
41 .collect::<Vec<_>>();
42
43 Ok(selected_items)
44}
45
46pub fn fuzzy_select_with_key<T>(
48 items: &[T],
49 prompt: impl AsRef<str>,
50 f_display: impl Fn(&T) -> String,
51) -> miette::Result<&T> {
52 fuzzy_select_with_key_with_default(items, prompt, f_display, None)
53}
54
55pub fn fuzzy_select_with_key_with_default<T>(
63 items: &[T],
64 prompt: impl AsRef<str>,
65 f_display: impl Fn(&T) -> String,
66 default_index: Option<usize>,
67) -> miette::Result<&T> {
68 if items.is_empty() {
70 miette::bail!("Nothing to select from. Aborting.")
71 }
72
73 let displayed_items = items.iter().map(f_display).collect::<Vec<_>>();
74
75 let mut dialogue = inquire::Select::new(prompt.as_ref(), displayed_items);
77
78 if let Some(index) = default_index {
80 dialogue = dialogue.with_starting_cursor(index);
81 }
82
83 let selected_index = dialogue.raw_prompt().into_diagnostic()?.index;
85
86 Ok(&items[selected_index])
87}
88
89pub fn confirm_with_prompt(prompt: impl AsRef<str>) -> miette::Result<bool> {
94 inquire::Confirm::new(prompt.as_ref())
95 .with_help_message("(y/n)?")
96 .prompt()
97 .into_diagnostic()
98}
99
100pub fn select_state(current_state: Option<StateType>) -> miette::Result<String> {
103 fuzzy_select_with_key(
104 &[StateType::Open, StateType::Closed],
105 "Select the desired state",
106 |f| format!("{f:?}"),
107 )
108 .or(current_state
109 .as_ref()
110 .context("Not even current issue state available, aborting!"))
111 .and_then(|state| {
112 serde_json::to_string(&state)
113 .into_diagnostic()
114 .context("Couldn't convert given `state` properly for the API call!")
115 })
116 .map(|state| {
117 state
118 .trim_start_matches('"')
119 .trim_end_matches('"')
120 .to_string()
121 })
122}