use clap::Parser;
use dialoguer::theme::ColorfulTheme;
use std::{io::Result, iter::repeat};
#[derive(Debug, Parser)]
pub struct MultiSelect {
#[clap(short, long)]
message: String,
#[clap(short, long)]
cancel: bool,
#[clap(short = 'd', long = "default", requires = "cancel")]
return_default: bool,
#[clap(short, long)]
index: bool,
#[clap(long)]
no_inline: bool,
#[clap(short, long)]
selected: Vec<usize>,
items: Vec<String>,
}
impl MultiSelect {
pub fn run(&self) -> Result<()> {
let item_len = self.items.len();
if item_len == 0 {
return Ok(());
}
let theme = ColorfulTheme {
inline_selections: !self.no_inline,
..ColorfulTheme::default()
};
let mut input = dialoguer::MultiSelect::with_theme(&theme);
let mut defaults = vec![];
defaults.extend(repeat(false).take(item_len));
for i in &self.selected {
if *i > item_len {
continue;
}
defaults[i - 1] = true;
}
input
.with_prompt(&self.message)
.clear(true)
.items(&self.items)
.defaults(&defaults);
let ret = if self.cancel {
input.interact_opt()?
} else {
Some(input.interact()?)
};
let value = match ret {
Some(value) => value,
None if self.return_default => defaults
.into_iter()
.enumerate()
.filter_map(|(i, v)| if v { Some(i) } else { None })
.collect(),
None => std::process::exit(1),
};
if self.index {
for i in value {
println!("{}", i);
}
} else {
for i in value {
println!("{}", self.items[i]);
}
}
Ok(())
}
}