use crate::elision::{self, Elided};
use super::{MATCH_CAP, Predicate};
pub(super) const LINE_CAP: usize = 512;
#[derive(Clone, Copy)]
pub(super) enum Limit {
Hits,
Bytes,
}
impl Limit {
pub(super) fn said(self) -> String {
let narrow = "narrow `path` to one directory or file, or search for a longer `text`";
match self {
Limit::Hits => {
format!("stopped at {MATCH_CAP} matches, the most one search returns; {narrow}")
}
Limit::Bytes => format!(
"stopped at {} bytes of match text, the most one search returns; {narrow}, or ask for less `context`",
kernel::consts_policy::INTERVAL_CAP_BYTES
),
}
}
}
pub(super) fn context_block(lines: &[&str], at: usize, looking: &Predicate) -> String {
let first = at.saturating_sub(looking.context);
let last = at
.saturating_add(looking.context)
.min(lines.len().saturating_sub(1));
(first..=last)
.filter_map(|index| {
let line = lines.get(index)?;
let centre = if index == at {
line.find(&looking.needle).unwrap_or(0)
} else {
0
};
Some(windowed(line, centre))
})
.collect::<Vec<String>>()
.join(
"
",
)
}
fn windowed(line: &str, centre: usize) -> String {
if line.len() <= LINE_CAP {
return line.to_owned();
}
let start = centre
.saturating_sub(LINE_CAP / 2)
.min(line.len().saturating_sub(LINE_CAP));
let end = start.saturating_add(LINE_CAP);
let tail_cut = elision::splice(line, end, line.len(), Elided::Tail).text;
if start == 0 {
return tail_cut;
}
elision::splice(&tail_cut, 0, start, Elided::Head).text
}