use std::collections::BTreeMap;
use clap_complete::CompletionCandidate;
use crate::git;
use crate::repo::{Repo, MAIN_ALIAS};
pub fn worktrees() -> Vec<CompletionCandidate> {
candidates(false)
}
pub fn removable_worktrees() -> Vec<CompletionCandidate> {
candidates(true)
}
fn candidates(skip_main: bool) -> Vec<CompletionCandidate> {
let Ok(repo) = Repo::discover() else {
return Vec::new();
};
let Ok(worktrees) = repo.worktrees() else {
return Vec::new();
};
let Some(main) = worktrees.first() else {
return Vec::new();
};
worktrees
.iter()
.skip(usize::from(skip_main))
.map(|wt| {
let name = repo.display_name(wt, main);
let hint = if name == MAIN_ALIAS {
format!("main worktree — {}", wt.path.display())
} else {
wt.path.display().to_string()
};
CompletionCandidate::new(name).help(Some(hint.into()))
})
.collect()
}
pub fn addable_branches() -> Vec<CompletionCandidate> {
let Ok(repo) = Repo::discover() else {
return Vec::new();
};
let Ok(worktrees) = repo.worktrees() else {
return Vec::new();
};
let in_use: Vec<String> = worktrees.iter().filter_map(|w| w.branch.clone()).collect();
let locals = git::local_branches(&repo.cwd).unwrap_or_default();
let mut candidates: Vec<CompletionCandidate> = locals
.iter()
.filter(|b| !in_use.contains(b))
.map(|b| CompletionCandidate::new(b).help(Some("local branch".into())))
.collect();
let mut by_short: BTreeMap<String, Vec<String>> = BTreeMap::new();
for (full, short) in git::remote_branches(&repo.cwd).unwrap_or_default() {
if locals.contains(&short) || in_use.contains(&short) {
continue;
}
by_short.entry(short).or_default().push(full);
}
for (short, remotes) in by_short {
let help = if remotes.len() == 1 {
remotes[0].clone()
} else {
format!("{} — ambiguous, needs --from", remotes.join(", "))
};
candidates.push(CompletionCandidate::new(short).help(Some(help.into())));
}
candidates
}
pub fn start_points() -> Vec<CompletionCandidate> {
let Ok(repo) = Repo::discover() else {
return Vec::new();
};
git::start_points(&repo.cwd)
.unwrap_or_default()
.into_iter()
.map(CompletionCandidate::new)
.collect()
}