use crate::cli::ensure_daemon_running;
use crate::config::{find_vyctor_root, load_config};
use crate::search::SearchEngine;
use anyhow::Result;
use colored::Colorize;
pub async fn run(
query: &str,
folder: Option<&str>,
count: usize,
full: bool,
verbose: bool,
) -> Result<()> {
let root = find_vyctor_root()?;
let config = load_config()?;
ensure_daemon_running(&root, &config)?;
let engine = SearchEngine::new(&root, &config, verbose)?;
println!("{} Searching for: {}", "→".cyan(), query.italic());
if let Some(folder) = folder {
println!(" In folder: {}", folder.cyan());
}
if verbose {
if let Some(model) = engine.reranker_model() {
println!(" Reranker: {}", model.cyan());
}
}
println!();
let (results, timing) = engine.search(query, count, folder).await?;
if results.is_empty() {
println!("{} No results found.", "!".yellow());
return Ok(());
}
if verbose {
let timing_str = if let Some(rerank_time) = timing.rerank_time {
format!(
"embed: {}, search: {}, rerank: {}",
format!("{:?}", timing.embed_time).dimmed(),
format!("{:?}", timing.search_time).dimmed(),
format!("{:?}", rerank_time).dimmed()
)
} else {
format!(
"embed: {}, search: {}",
format!("{:?}", timing.embed_time).dimmed(),
format!("{:?}", timing.search_time).dimmed()
)
};
println!(
"Found {} result{} in {} ({}):",
results.len().to_string().green(),
if results.len() == 1 { "" } else { "s" },
format!("{:?}", timing.total_time).dimmed(),
timing_str
);
} else {
println!(
"Found {} result{} in {}:",
results.len().to_string().green(),
if results.len() == 1 { "" } else { "s" },
format!("{:?}", timing.total_time).dimmed(),
);
}
println!();
for (i, result) in results.iter().enumerate() {
let score_pct = (result.score * 100.0) as i32;
let score_str = format!("{}%", score_pct);
let colored_score = if score_pct >= 80 {
score_str.green()
} else if score_pct >= 60 {
score_str.yellow()
} else {
score_str.red()
};
println!(
"{} {} [{}]",
format!("{}.", i + 1).bold(),
result.file_path.cyan(),
colored_score
);
println!(" Lines {}-{}", result.start_line, result.end_line);
if full {
println!();
for line in result.chunk_content.lines() {
println!(" {}", line.dimmed());
}
} else {
let preview_lines: Vec<&str> = result.chunk_content.lines().take(3).collect();
println!();
for line in preview_lines {
let truncated = if line.len() > 80 {
format!("{}...", &line[..77])
} else {
line.to_string()
};
println!(" {}", truncated.dimmed());
}
let total_lines = result.chunk_content.lines().count();
if total_lines > 3 {
println!(
" {} more lines...",
format!("(+{})", total_lines - 3).dimmed()
);
}
}
println!();
}
Ok(())
}