use anyhow::{bail, Context, Result};
use colored::Colorize;
use crate::nix::{check_nix_available, run_nix_command};
use flk::flake::interfaces::profiles::Package;
use flk::flake::parsers::packages::extract_packages_from_output;
use flk::utils::visual::{display_list, display_table, with_spinner};
pub fn run_search(query: &str, limit: usize) -> Result<bool> {
println!(
"{} Searching nixpkgs for: {}",
"→".blue().bold(),
query.green()
);
let search_query = format!("*{}*", query);
if !check_nix_available() {
bail!("Nix command is not available, is it installed on the system?");
}
let (stdout, _, _) = with_spinner("Searching packages...", || {
run_nix_command(&[
"run",
"github:vic/nix-versions",
&search_query,
"--",
"--one",
])
.context("Failed to execute nix search. Is nix installed?")
})?;
let packages: Vec<Package> =
extract_packages_from_output(&stdout).context("Failed to parse nix search output")?;
if packages.is_empty() {
println!(
"{} No packages found for query '{}'",
"✗".red().bold(),
query
);
return Ok(false);
}
println!(
"\n{} Found {} package(s) (showing {}):\n",
"✓".green().bold(),
packages.len(),
packages.len()
);
println!("{}", display_list(&packages[..packages.len().min(limit)]));
Ok(true)
}
pub fn run_deep_search(package: &str) -> Result<()> {
println!(
"{} Getting details for: {}",
"→".blue().bold(),
package.green()
);
if !check_nix_available() {
bail!("Nix is not available!")
}
let (stdout, _, _) = with_spinner("Searching packages...", || {
run_nix_command(&["run", "github:vic/nix-versions", package, "--", "--all"])
.context("Failed to execute nix search. Is nix installed?")
})?;
let packages: Vec<Package> =
extract_packages_from_output(&stdout).context("Failed to parse nix search output")?;
if packages.is_empty() {
println!("{} No packages found for '{}'", "✗".red().bold(), package);
return Ok(());
}
println!("\n{}", "Search Results:".bold().underline());
println!("{}", display_table(&packages));
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use crate::nix::with_nix_runner;
const SAMPLE_OUTPUT: &str = "\
Name Version System Description
ripgrep 14.1.0 x86_64-linux Fast grep replacement
ripgrep-all 0.10.0 x86_64-linux Grep across many file formats
";
#[test]
fn run_search_returns_true_when_packages_found() {
with_nix_runner(
|args| {
assert_eq!(args[0], "run");
assert_eq!(args[1], "github:vic/nix-versions");
assert_eq!(args[2], "*ripgrep*");
Ok((SAMPLE_OUTPUT.into(), String::new(), true))
},
|| {
let found = run_search("ripgrep", 10).unwrap();
assert!(found);
},
);
}
#[test]
fn run_search_returns_false_when_no_packages() {
with_nix_runner(
|_| {
Ok((
"Name Version System Description\n".into(),
String::new(),
true,
))
},
|| {
let found = run_search("nope-nothing-here", 10).unwrap();
assert!(!found);
},
);
}
#[test]
fn run_search_propagates_nix_failure() {
with_nix_runner(
|_| Err(anyhow::anyhow!("nix exploded")),
|| {
let err = run_search("anything", 5).unwrap_err();
assert!(err.to_string().contains("nix search"));
},
);
}
#[test]
fn run_deep_search_handles_empty_results() {
with_nix_runner(
|args| {
assert_eq!(
args,
&["run", "github:vic/nix-versions", "ripgrep", "--", "--all"]
);
Ok((
"Name Version System Description\n".into(),
String::new(),
true,
))
},
|| run_deep_search("ripgrep").unwrap(),
);
}
}