use std::path::Path;
use libaipm::manifest::types::PluginType;
use super::wizard::{
package_prompt_steps, resolve_package_answers, styled_render_config, PromptAnswer, PromptKind,
PromptStep,
};
type WizardResult = (Option<String>, Option<PluginType>);
pub fn resolve(
interactive: bool,
dir: &Path,
flag_name: Option<String>,
flag_type: Option<PluginType>,
) -> Result<WizardResult, Box<dyn std::error::Error>> {
if interactive {
inquire::set_global_render_config(styled_render_config());
let steps = package_prompt_steps(dir, flag_name.as_deref(), flag_type);
let answers = execute_prompts(&steps)?;
Ok(resolve_package_answers(&answers, flag_name.as_deref(), flag_type))
} else {
Ok((flag_name, flag_type))
}
}
fn execute_prompts(steps: &[PromptStep]) -> Result<Vec<PromptAnswer>, Box<dyn std::error::Error>> {
let mut answers = Vec::with_capacity(steps.len());
for step in steps {
let answer = match &step.kind {
PromptKind::Text { placeholder, validate } => {
let mut prompt = inquire::Text::new(step.label).with_placeholder(placeholder);
if let Some(help) = step.help {
prompt = prompt.with_help_message(help);
}
if *validate {
prompt = prompt.with_validator(|input: &str| {
match libaipm::manifest::validate::check_name(
input,
libaipm::manifest::validate::ValidationMode::Interactive,
) {
Ok(()) => Ok(inquire::validator::Validation::Valid),
Err(msg) => Ok(inquire::validator::Validation::Invalid(msg.into())),
}
});
}
let result = prompt.prompt()?;
PromptAnswer::Text(result)
},
PromptKind::Confirm { default } => {
let mut prompt = inquire::Confirm::new(step.label).with_default(*default);
if let Some(help) = step.help {
prompt = prompt.with_help_message(help);
}
let result = prompt.prompt()?;
PromptAnswer::Bool(result)
},
PromptKind::Select { options, default_index } => {
let mut prompt = inquire::Select::new(step.label, options.clone())
.with_starting_cursor(*default_index);
if let Some(help) = step.help {
prompt = prompt.with_help_message(help);
}
let choice = prompt.prompt()?;
let index = options.iter().position(|o| *o == choice).ok_or_else(|| {
format!(
"internal error: selected choice `{choice}` not found in options for prompt `{}`",
step.label
)
})?;
PromptAnswer::Selected(index)
},
PromptKind::MultiSelect { options, defaults } => {
let mut prompt = inquire::MultiSelect::new(step.label, options.clone());
let default_indices: Vec<usize> = defaults
.iter()
.enumerate()
.filter_map(|(i, &d)| if d { Some(i) } else { None })
.collect();
prompt = prompt.with_default(&default_indices);
if let Some(help) = step.help {
prompt = prompt.with_help_message(help);
}
let selected = prompt.prompt()?;
let indices: Vec<usize> =
selected.iter().filter_map(|s| options.iter().position(|o| o == s)).collect();
PromptAnswer::MultiSelected(indices)
},
};
answers.push(answer);
}
Ok(answers)
}