use crate::{
config::Config,
package::{Package, Packages},
repo::Repo,
};
use anyhow::Result;
use colored::Colorize;
use console::Style;
use dialoguer::{theme::ColorfulTheme, MultiSelect};
use itertools::Itertools;
use std::{
fs::File,
io::{BufRead, BufReader},
path::Path,
};
pub fn history(path: &Path) -> Result<()> {
let hist_file = File::open(path)?;
let reader = BufReader::new(hist_file);
let catches: Vec<Package> = reader
.lines()
.filter_map(|x| x.ok())
.map(|x| x.split_whitespace().join(" "))
.sorted()
.dedup()
.map(|x| Packages::from_line(&x))
.map(|packages| packages.into_iter())
.flatten()
.collect();
if catches.is_empty() {
return Ok(());
};
let config = Config::from_default_file_or_new()?;
let repo = Repo::new(config, true)?;
let mut catches = Packages::from(catches);
catches.filter_saved_packages(&repo.read()?);
if catches.is_empty() {
return Ok(());
}
let colored_selection: Vec<String> = catches.iter().map(|x| x.color_full_name()).collect();
let mut select_style = ColorfulTheme::default();
select_style.active_item_style = Style::underlined(select_style.active_item_style);
let ms = MultiSelect::with_theme(&select_style)
.items(&colored_selection)
.with_prompt("Select packages to sync")
.paged(true)
.interact()?;
let mut checked = vec![];
ms.iter().for_each(|x| checked.push(catches[*x].clone()));
let len = checked.len();
if len == 0 {
println!("Nothing is checked");
return Ok(());
}
match len {
1 => println!("{}", "Mirror this command?".green().bold()),
n => println!("{}", format!("Mirror these {} commands?", n).green().bold()),
}
for catch in checked.iter() {
println!("- {}", catch.color_full_name());
}
if !dialoguer::Confirm::new().interact()? {
return Ok(());
}
repo.mirror(Packages::from(checked))
.expect("Could not mirror commands");
Ok(())
}