zoi-rs 1.8.2

Universal Package Manager & Environment Setup Tool
Documentation
use crate::pkg::{config, db};
use anyhow::Result;
use colored::Colorize;
use comfy_table::{Attribute, Cell, ContentArrangement, Table, presets::UTF8_FULL};
use std::io::{self, Write};
use std::process::{Command, Stdio};

pub fn run(term: &str) -> Result<()> {
    println!(
        "{} Searching for packages providing '{}'...",
        "::".bold().blue(),
        term.cyan().bold()
    );

    let config = config::read_config()?;
    let mut registries = Vec::new();
    if let Some(default) = &config.default_registry {
        registries.push(default.handle.clone());
    }
    for reg in &config.added_registries {
        registries.push(reg.handle.clone());
    }

    let mut all_results = Vec::new();
    for handle in registries {
        if let Ok(res) = db::find_provides(&handle, term) {
            all_results.extend(res);
        }
    }

    if all_results.is_empty() {
        println!(
            "
{}",
            "No packages found providing this item.".yellow()
        );
        println!("Hint: Ensure you have run 'zoi sync --files' to index remote file lists.");
        return Ok(());
    }

    let mut table = Table::new();
    table
        .load_preset(UTF8_FULL)
        .set_content_arrangement(ContentArrangement::Dynamic)
        .set_header(vec![
            Cell::new("Package").add_attribute(Attribute::Bold),
            Cell::new("Version").add_attribute(Attribute::Bold),
            Cell::new("Matches").add_attribute(Attribute::Bold),
            Cell::new("Repo").add_attribute(Attribute::Bold),
        ]);

    for (pkg, matched_path) in all_results {
        let repo_display = &pkg.repo;
        table.add_row(vec![
            Cell::new(pkg.name).fg(comfy_table::Color::Cyan),
            Cell::new(pkg.version.unwrap_or_else(|| "N/A".to_string()))
                .fg(comfy_table::Color::Yellow),
            Cell::new(matched_path).fg(comfy_table::Color::Green),
            Cell::new(repo_display.clone()).fg(comfy_table::Color::DarkGrey),
        ]);
    }

    print_with_pager(&table.to_string())?;

    Ok(())
}

fn print_with_pager(content: &str) -> io::Result<()> {
    let pager = if crate::utils::command_exists("less") {
        "less"
    } else if crate::utils::command_exists("more") {
        "more"
    } else {
        print!("{}", content);
        return Ok(());
    };

    let mut command = Command::new(pager);
    if pager == "less" {
        command.arg("-R");
    }

    let mut child = command.stdin(Stdio::piped()).spawn()?;

    if let Some(mut stdin) = child.stdin.take() {
        let _ = stdin.write_all(content.as_bytes());
    }

    child.wait()?;
    Ok(())
}