use super::grammar;
use super::model::{RawHit, SearchKind};
use rootle_provider::Provider;
const PREVIEW_CAP: usize = 8;
const BACKEND_CAP: usize = 500;
#[derive(Debug, Clone, Default)]
pub struct SearchOutcome {
pub clipped: bool,
pub index_as_of: Option<String>,
pub client_filtered: usize,
pub unfiltered: Vec<String>,
}
fn code_query(kind: SearchKind, query: &str, scope_label: &str, extension: &str) -> String {
let mut q = match kind {
SearchKind::Grep => query.to_string(),
SearchKind::FileFind => format!("path:{query}"),
};
if scope_label != "global" {
q.push(' ');
q.push_str(scope_label); }
let ext = extension.trim_start_matches('.');
if !ext.is_empty() {
q.push_str(&format!(" extension:{ext}"));
}
q
}
pub fn run_view_search(
provider: &dyn Provider,
kind: SearchKind,
query: &str,
scope_label: &str,
extension: &str,
on_hits: &(dyn Fn(Vec<RawHit>) + Send + Sync),
) -> rootle_provider::ProviderResult<SearchOutcome> {
if kind == SearchKind::FileFind && scope_label.starts_with("repo:") {
return tree_file_find(
provider,
query,
&scope_label["repo:".len()..],
extension,
on_hits,
);
}
let capabilities = provider.capabilities();
let supported = match kind {
SearchKind::FileFind => capabilities.file_search,
SearchKind::Grep => capabilities.code_search,
};
if !supported {
return Err(rootle_provider::ProviderError::new(
rootle_provider::ErrorKind::Provider,
format!("{} unsupported by {}", kind.slug(), provider.name()),
));
}
code_search(provider, kind, query, scope_label, extension, on_hits)
}
mod file_find;
mod grep;
mod previews;
pub(crate) use file_find::file_find_score;
use file_find::tree_file_find;
use grep::code_search;
use previews::add_blob_heads;
pub(crate) use previews::{locate_in_blob, locate_matches};
#[cfg(test)]
mod tests;