Files
packie/cli/src/select.rs
T
2026-08-09 21:16:48 +08:00

70 lines
2.1 KiB
Rust

use crate::error;
use clap::Parser;
use console::style;
use dialoguer::Select;
use packie::PackieBuilder;
use rust_i18n::t;
use std::path::PathBuf;
#[derive(Debug, Parser)]
pub struct Cli {
file: PathBuf,
}
pub fn main(cli: Cli) -> Result<(), crate::Error> {
let mut packie = PackieBuilder::new().build()?;
let file = if cli.file.is_absolute() {
cli.file.clone()
} else {
std::env::current_dir()?.join(&cli.file)
};
let mut all_pkgs = Vec::with_capacity(1024);
let mut candidates = Vec::new();
packie.for_each_installation::<anyhow::Error>(|inst| {
all_pkgs.push(inst.pkg_manifest.pkg_ident());
Ok(())
})?;
for pkgident in all_pkgs {
let links = packie.links_of_pkg(&pkgident);
let Ok(links) = links.iter() else {
return Ok(());
};
if let Some(link) = links
.filter_map(|x| x.ok())
.find(|x| x.to == file.to_string_lossy())
{
candidates.push((pkgident, link));
}
}
if candidates.is_empty() {
return Err(crate::Error {
message: t!("select.empty_list").into(),
note: Some(t!("select.note_relative_path").into()),
});
}
let items = std::iter::once(t!("select.disabled").into())
.chain(candidates.iter().map(|x| x.0.to_string()))
.map(|x| style(x).green());
let choice = Select::new()
.with_prompt(t!("select.prompt_select_package"))
.items(items)
.interact()?;
if choice == 0 {
if let Err(err) = packie::link::remove(&file) {
if err.kind() == std::io::ErrorKind::InvalidData {
return Err(error!("select.not_a_link"));
}
if err.kind() == std::io::ErrorKind::NotFound {
return Ok(());
}
Err(err)?;
}
return Ok(());
}
let (pkgident, linkdes) = candidates.remove(choice - 1);
_ = packie::link::remove(&file);
_ = packie::link::deactivate_by_description(&mut packie, &pkgident, &linkdes);
packie::link::activate_by_description(&mut packie, &pkgident, &linkdes)?;
Ok(())
}