use anyhow::{anyhow, Result};
use dialoguer::{theme::ColorfulTheme, Confirm, FuzzySelect, Select};
use crate::git::GitRepo;
use crate::state::StateManager;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum StashAction {
Stash,
Discard,
Abort,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum UnstashAction {
Apply,
Skip,
Abort,
}
pub fn select_branch() -> Result<String> {
let repo = GitRepo::open()?;
let state = StateManager::load(repo.git_dir())?;
let all_branches = repo.list_branches()?;
if all_branches.is_empty() {
return Err(anyhow!("No branches found"));
}
let current = repo.get_current_branch().ok();
let recent = state.recent_branches(20);
let recent_names: Vec<&str> = recent.iter().map(|(name, _)| *name).collect();
let mut branches: Vec<String> = Vec::new();
for name in &recent_names {
if all_branches.contains(&name.to_string()) {
branches.push(name.to_string());
}
}
for branch in &all_branches {
if !branches.contains(branch) {
branches.push(branch.clone());
}
}
let display_branches: Vec<String> = branches
.iter()
.map(|b| {
if Some(b.as_str()) == current.as_deref() {
format!("{} (current)", b)
} else {
b.clone()
}
})
.collect();
let selection = FuzzySelect::with_theme(&ColorfulTheme::default())
.with_prompt("Select branch")
.items(&display_branches)
.default(0)
.max_length(15)
.interact()?;
Ok(branches[selection].clone())
}
pub fn prompt_stash_conflict(changes_summary: &str) -> Result<StashAction> {
println!();
let items = vec![
"Stash changes (recommended)",
"Discard changes (lose all modifications)",
"Abort switch",
];
let selection = Select::with_theme(&ColorfulTheme::default())
.with_prompt(format!(
"You have uncommitted changes ({}).\nWhat would you like to do?",
changes_summary
))
.items(&items)
.default(0)
.interact()?;
Ok(match selection {
0 => StashAction::Stash,
1 => StashAction::Discard,
_ => StashAction::Abort,
})
}
pub fn prompt_unstash_conflict() -> Result<UnstashAction> {
println!();
let items = vec![
"Try to apply anyway (may have conflicts)",
"Skip restoring changes",
"Abort and stay on current branch",
];
let selection = Select::with_theme(&ColorfulTheme::default())
.with_prompt(
"There was an issue applying your stashed changes.\nWhat would you like to do?",
)
.items(&items)
.default(0)
.interact()?;
Ok(match selection {
0 => UnstashAction::Apply,
1 => UnstashAction::Skip,
_ => UnstashAction::Abort,
})
}
pub fn prompt_install(package_manager: &str) -> Result<bool> {
println!();
Confirm::with_theme(&ColorfulTheme::default())
.with_prompt(format!(
"Lock file has changed. Run `{} install`?",
package_manager
))
.default(true)
.interact()
.map_err(Into::into)
}
pub fn confirm_discard() -> Result<bool> {
Confirm::with_theme(&ColorfulTheme::default())
.with_prompt("Are you sure you want to discard all changes? This cannot be undone.")
.default(false)
.interact()
.map_err(Into::into)
}
pub fn confirm_delete(branch_name: &str) -> Result<bool> {
Confirm::with_theme(&ColorfulTheme::default())
.with_prompt(format!("Delete branch '{}'?", branch_name))
.default(false)
.interact()
.map_err(Into::into)
}