xbp_cli/cli/
interactive.rs1use dialoguer::theme::ColorfulTheme;
4use dialoguer::{FuzzySelect, MultiSelect};
5use std::fmt::Display;
6
7pub fn xbp_theme() -> ColorfulTheme {
9 ColorfulTheme::default()
10}
11
12pub fn searchable_select<T: Display>(
14 prompt: &str,
15 items: &[T],
16 default: usize,
17) -> Result<Option<usize>, String> {
18 if items.is_empty() {
19 return Ok(None);
20 }
21 let default = default.min(items.len().saturating_sub(1));
22 FuzzySelect::with_theme(&xbp_theme())
23 .with_prompt(format!("{prompt} (type to search)"))
24 .items(items)
25 .default(default)
26 .interact_opt()
27 .map_err(|error| format!("Prompt failed: {error}"))
28}
29
30pub fn searchable_multi_select<T: Display>(
32 prompt: &str,
33 items: &[T],
34 defaults: &[bool],
35) -> Result<Vec<usize>, String> {
36 if items.is_empty() {
37 return Ok(Vec::new());
38 }
39 let defaults = if defaults.len() == items.len() {
40 defaults.to_vec()
41 } else {
42 vec![false; items.len()]
43 };
44 MultiSelect::with_theme(&xbp_theme())
45 .with_prompt(format!("{prompt} (space to toggle, type to filter if supported)"))
46 .items(items)
47 .defaults(&defaults)
48 .interact()
49 .map_err(|error| format!("Prompt failed: {error}"))
50}