//! `ripgrab grep` — one-shot scan without follow.
//!
//! Opens each path, walks every line once, applies the filter, writes the
//! matches to stdout. Useful in CI or pre-commit scripts.
use std::io;
use anyhow::Result;
use crate::cli::args::GrepArgs;
use crate::filter::{FilterSet, MatchOutcome};
use crate::render::mode::stream::StreamRenderer;
use crate::source::file::FileSource;
use crate::source::Source;
pub async fn run(args: GrepArgs) -> Result<()> {
let filter = FilterSet::compile(&args.includes, &[], None)?;
let compiled = args
.where_clause
.as_deref()
.map(crate::filter::dsl::parse_and_compile)
.transpose()?;
let stdout = io::stdout();
let mut renderer = StreamRenderer::new(stdout.lock(), true, true);
for path in &args.paths {
let mut src = FileSource::open(path).await?;
while let Some(item) = src.next_line().await? {
if let Some(c) = &compiled {
let mut ctx = crate::filter::dsl::EvalContext::new();
ctx.set("origin", &item.origin);
ctx.set("body", &item.line);
if !crate::filter::dsl::evaluate(c, &ctx) {
continue;
}
}
if let MatchOutcome::Plain = filter.apply(&item.line) {
renderer.render(&item.origin, &item.line)?;
}
}
}
renderer.flush()?;
Ok(())
}