use super::{
BasePrompt, DefaultPrompt, InteractionError, PasswordPrompt, PromptType, SelectionPrompt,
TextPrompt, ValidationPrompt,
};
use core::fmt::Debug;
use log::{error, info, warn};
pub struct PseudoInteractive<T: Clone + Debug> {
prompt_type: PromptType,
prompt: Option<String>,
default: Option<T>,
items: Vec<String>,
validator: Option<Box<dyn Fn(&T) -> Result<(), String>>>,
confirmation: Option<(String, String)>,
allow_empty: bool,
initial_value: Option<T>,
}
impl<T: Clone + Debug> PseudoInteractive<T> {
pub fn new(prompt_type: PromptType) -> Self {
Self {
prompt_type,
prompt: None,
default: None,
items: Vec::new(),
validator: None,
confirmation: None,
allow_empty: false,
initial_value: None,
}
}
}
impl<T: Clone + Debug> BasePrompt<T> for PseudoInteractive<T> {
fn set_prompt(&mut self, prompt: String) {
self.prompt = Some(prompt);
}
fn interact(&mut self) -> Result<T, InteractionError> {
let prompt = self
.prompt
.clone()
.unwrap_or_else(|| "[NO PROMPT SET]".to_owned());
let default = if let Some(initial_value) = &self.initial_value {
Some(initial_value.clone())
} else if let Some(default) = &self.default {
Some(default.clone())
} else {
None
};
if let Some(default) = default {
warn!(
"Non-interactive context. The {:?} prompt `{prompt}` will default to {default:#?} .",
self.prompt_type
);
if let Some(validator) = self.validator.as_mut() {
warn!(
"Non-interactive context. The {:?} prompt `{prompt}` will default to {default:#?} if valid.",
self.prompt_type
);
match validator(&default) {
Ok(_) => {
info!("Default value passed validation.");
Ok(default.to_owned())
}
Err(err) => {
error!("Default value failed validation: {err}");
Err(InteractionError::NotInteractive(self.prompt_type, prompt))
}
}
} else {
warn!(
"Non-interactive context. The {:?} prompt `{prompt}` will default to {default:#?}.",
self.prompt_type
);
Ok(default.to_owned())
}
} else {
error!("No default value found.");
Err(InteractionError::NotInteractive(self.prompt_type, prompt))
}
}
}
impl<T: Clone + Debug> DefaultPrompt<T> for PseudoInteractive<T> {
fn set_default(&mut self, value: T) {
self.default = Some(value);
}
}
impl<T: Clone + Debug> SelectionPrompt<T> for PseudoInteractive<T> {
fn add_items(&mut self, items: &[String]) {
self.items = Vec::from(items);
}
}
impl<T: Clone + Debug> ValidationPrompt<T> for PseudoInteractive<T> {
fn allow_empty(&mut self, empty: bool) {
self.allow_empty = empty;
}
fn set_validator(&mut self, validator: Box<dyn Fn(&T) -> Result<(), String>>) {
self.validator = Some(validator);
}
}
impl<T: Clone + Debug> PasswordPrompt<T> for PseudoInteractive<T> {
fn set_confirmation(&mut self, confirm_prompt: String, mismatch_err: String) {
self.confirmation = Some((confirm_prompt, mismatch_err));
}
}
impl TextPrompt<String> for PseudoInteractive<String> {
fn set_inital_text(&mut self, text: String) {
self.initial_value = Some(text);
}
}