use colored::Colorize;
use dialoguer::Select;
use crate::git;
pub fn run_save(message: &str) {
let files = git::parse_status();
if files.is_empty() {
println!();
println!(" {} Nothing to stash — working directory is clean.", "✔".green());
println!();
return;
}
println!();
let result = git::run(&["stash", "push", "-m", message]);
if result.success {
println!(" {} Stashed: \"{}\"", "✔".green().bold(), message.bold());
println!();
println!(" {} file(s) tucked away.", files.len());
println!(" Restore later with {}", "g stash pop".cyan());
} else {
println!(" {} Failed: {}", "✖".red(), result.stderr);
}
println!();
}
pub fn run_pop() {
let stashes = list_stashes();
if stashes.is_empty() {
println!();
println!(" {} No stashes found.", "⚠".yellow());
println!();
return;
}
println!();
println!(" {}:", "Your stashes".bold());
println!();
let display: Vec<String> = stashes
.iter()
.map(|(idx, msg)| {
format!("{} {}", format!("stash@{{{}}}", idx).dimmed(), msg)
})
.collect();
let refs: Vec<&str> = display.iter().map(|s| s.as_str()).collect();
let selection = Select::new()
.with_prompt(" Which stash to restore?")
.items(&refs)
.default(0)
.interact();
let selection = match selection {
Ok(s) => s,
Err(_) => {
println!(" Cancelled.");
println!();
return;
}
};
let (stash_idx, stash_msg) = &stashes[selection];
let stash_ref = format!("stash@{{{}}}", stash_idx);
println!();
let result = git::run(&["stash", "pop", &stash_ref]);
if result.success {
println!(
" {} Restored: \"{}\"",
"✔".green().bold(),
stash_msg.bold()
);
println!(" Changes are back in your working directory.");
} else {
if result.stderr.contains("CONFLICT") || result.stdout.contains("CONFLICT") {
println!(
" {} Restored with conflicts!",
"⚠".yellow().bold()
);
println!(" Some files have merge conflicts. Resolve them, then:");
println!(" {} {}", "→".dimmed(), "g save \"resolved stash conflicts\"".cyan());
} else {
println!(" {} Failed: {}", "✖".red(), result.stderr);
}
}
println!();
}
pub fn run_list() {
let stashes = list_stashes();
if stashes.is_empty() {
println!();
println!(" {} No stashes found.", "⚠".yellow());
println!();
return;
}
println!();
println!(" {}:", "Your stashes".bold());
println!();
for (idx, msg) in &stashes {
println!(
" {} {}",
format!("{})", idx).dimmed(),
msg
);
}
println!();
println!(" Restore with {}", "g stash pop".cyan());
println!();
}
fn list_stashes() -> Vec<(usize, String)> {
let result = git::run(&["stash", "list", "--pretty=format:%gd|%s"]);
if !result.success || result.stdout.is_empty() {
return vec![];
}
result
.stdout
.lines()
.enumerate()
.filter_map(|(i, line)| {
let parts: Vec<&str> = line.splitn(2, '|').collect();
if parts.len() < 2 {
return None;
}
let raw_msg = parts[1].trim();
let msg = if let Some(pos) = raw_msg.find(": ") {
raw_msg[pos + 2..].to_string()
} else {
raw_msg.to_string()
};
Some((i, msg))
})
.collect()
}