use std::{fmt::Display, str::FromStr};
use crate::{error::Context, Result};
pub fn input<T>(
prompt: &str,
initial: Option<T>,
skip: bool,
allow_empty: bool,
) -> Result<Option<T>>
where
T: Clone + FromStr + Display + ToString,
T::Err: Display + std::fmt::Debug,
T: PartialEq<str>,
{
if skip {
Ok(initial)
} else {
let theme = dialoguer::theme::ColorfulTheme::default();
let mut builder = dialoguer::Input::with_theme(&theme)
.with_prompt(prompt)
.allow_empty(allow_empty);
if let Some(v) = initial {
builder = builder.with_initial_text(v.to_string());
}
builder
.interact_text()
.map(|t: T| if t.ne("") { Some(t) } else { None })
.context("failed to prompt input")
}
}
pub fn confirm(prompt: &str, default: Option<bool>) -> Result<bool> {
let theme = dialoguer::theme::ColorfulTheme::default();
let mut builder = dialoguer::Confirm::with_theme(&theme).with_prompt(prompt);
if let Some(default) = default {
builder = builder.default(default);
}
builder.interact().context("failed to prompt confirm")
}
pub fn multiselect<T: ToString>(
prompt: &str,
items: &[T],
defaults: Option<&[bool]>,
) -> Result<Vec<usize>> {
let theme = dialoguer::theme::ColorfulTheme::default();
let mut builder = dialoguer::MultiSelect::with_theme(&theme)
.with_prompt(prompt)
.items(items);
if let Some(defaults) = defaults {
builder = builder.defaults(defaults);
}
builder.interact().context("failed to prompt multi-select")
}