use crate::App;
use crate::shell::setup::{
InteractiveSetup, SetupContext, apply_user_choices, execute_setup, handle_interactive_error,
is_recoverable_interactive_error, post_setup_actions, pre_setup_checks,
};
use color_eyre::eyre::Context as _;
use yansi::Paint;
pub async fn setup_shell(
app: &mut App,
using_env_var: bool,
dry_run: bool,
no_interactive: bool,
) -> crate::Result<()> {
if app.source_set {
println!(
"{}",
Paint::white("✓ Shell environment PATH already includes path to zv")
);
let context = SetupContext::new_with_interactive(
app.shell.clone().unwrap_or_default(),
app.clone(),
using_env_var,
dry_run,
no_interactive,
);
post_setup_actions(&context).await?;
return Ok(());
}
let shell = app.shell.clone().unwrap_or_default();
let context = SetupContext::new_with_interactive(
shell,
app.clone(),
using_env_var,
dry_run,
no_interactive,
);
if dry_run {
println!(
"{} zv setup for {} shell...",
Paint::yellow("Previewing"),
Paint::cyan(&context.shell.to_string())
);
} else {
println!(
"Setting up zv for {} shell...",
Paint::cyan(&context.shell.to_string())
);
}
let requirements = pre_setup_checks(&context)
.await
.with_context(|| "Pre-setup checks failed")?;
let final_requirements = if should_use_interactive(&context) {
let interactive_setup = InteractiveSetup::new(context.clone(), requirements.clone());
match interactive_setup.run_interactive_flow().await {
Ok(user_choices) => {
apply_user_choices(requirements, user_choices)?
}
Err(e) => {
if let Some(zv_error) = e.downcast_ref::<crate::ZvError>() {
if is_recoverable_interactive_error(zv_error) {
if let Some(message) = handle_interactive_error(zv_error) {
crate::tools::warn(message);
crate::tools::warn("Falling back to non-interactive mode");
}
requirements
} else {
if let Some(suggestion) = handle_interactive_error(zv_error) {
crate::tools::error(suggestion);
}
return Err(e);
}
} else {
return Err(e);
}
}
}
} else {
requirements
};
execute_setup(&context, &final_requirements)
.await
.with_context(|| "Setup execution failed")?;
if dry_run {
println!("{}", Paint::cyan("→ Dry Run Complete"));
println!("Run {} to apply these changes", Paint::green("zv setup"));
} else {
println!("{}", Paint::green("→ Setup Complete"));
println!(
"Restart your shell or run the appropriate source command to apply changes immediately"
);
}
Ok(())
}
fn should_use_interactive(context: &SetupContext) -> bool {
if context.no_interactive {
return false;
}
if std::env::var("CI").is_ok() {
return false;
}
if let Ok(term) = std::env::var("TERM")
&& term == "dumb"
{
return false;
}
crate::tools::supports_interactive_prompts()
}