use colored::Colorize;
use inquire::Confirm;
use std::fs;
use std::process::Command;
use crate::cli::{print_ok, print_warning};
use crate::common::{CTP_GREEN, CTP_YELLOW, clear_line, show_cursor};
use crate::confirmation::style_message_markup;
use crate::error::LarpshellError;
use crate::shell_integration::remove_shell_integration;
pub fn uninstall_larpshell() -> Result<(), LarpshellError> {
eprintln!(
"{}",
style_message_markup("uninstalling larpshell...")
.custom_color(CTP_YELLOW)
.bold()
);
eprintln!();
handle_shell_integration();
uninstall_cargo_crate()?;
remove_config_optional()?;
remove_repo_optional()?;
eprintln!();
eprintln!(
"{}",
style_message_markup("larpshell successfully uninstalled.")
.custom_color(CTP_GREEN)
.bold()
);
eprintln!(
"{}",
style_message_markup(
"please restart your shell or run 'source ~/.bashrc' (or 'source ~/.config/fish/config.fish' for fish).",
)
.custom_color(CTP_YELLOW)
);
Ok(())
}
fn handle_shell_integration() {
match remove_shell_integration() {
Ok(true) => print_ok("removed shell integration"),
Ok(false) => eprintln!(
"{}",
style_message_markup(" no shell integration found").dimmed()
),
Err(e) => print_warning(&format!("failed to remove shell integration: {e}")),
}
}
fn uninstall_cargo_crate() -> Result<(), LarpshellError> {
let output = Command::new("cargo")
.args(["uninstall", "larpshell"])
.output()?;
if output.status.success() {
print_ok("uninstalled cargo crate");
} else {
let stderr = String::from_utf8_lossy(&output.stderr);
if stderr.contains("package 'larpshell' is not installed")
|| stderr.contains("not installed")
{
eprintln!(
"{}",
style_message_markup(" cargo crate not installed").dimmed()
);
} else {
let trimmed = stderr.trim();
print_warning(&format!("failed to uninstall: {trimmed}"));
}
}
Ok(())
}
fn remove_config_optional() -> Result<(), LarpshellError> {
eprintln!();
show_cursor();
let remove_config = Confirm::new("Remove configuration?")
.with_default(false)
.prompt()
.map_err(LarpshellError::InquireError)?;
clear_line();
if remove_config {
let config_dir = dirs::config_dir()
.ok_or_else(|| {
LarpshellError::ConfigError("failed to get config directory".to_string())
})?
.join("larpshell");
if config_dir.exists() {
fs::remove_dir_all(&config_dir)?;
print_ok("removed configuration");
} else {
eprintln!(
"{}",
style_message_markup(" no configuration found").dimmed()
);
}
}
Ok(())
}
fn remove_repo_optional() -> Result<(), LarpshellError> {
let current_dir = std::env::current_dir()?;
let cargo_toml = current_dir.join("Cargo.toml");
if cargo_toml.exists() {
let contents = fs::read_to_string(&cargo_toml)?;
if contents.contains("name = \"larpshell\"") {
eprintln!();
show_cursor();
let remove_repo = Confirm::new("Remove current directory (larpshell repository)?")
.with_default(false)
.prompt()
.map_err(LarpshellError::InquireError)?;
clear_line();
if remove_repo {
eprintln!(
"{}",
style_message_markup(" removing directory...").dimmed()
);
let parent = current_dir.parent().ok_or_else(|| {
LarpshellError::ConfigError("cannot remove root directory".to_string())
})?;
std::env::set_current_dir(parent)?;
fs::remove_dir_all(¤t_dir)?;
print_ok("removed larpshell repository");
}
}
}
Ok(())
}