use std::borrow::Cow;
use std::fmt::{Display, Error, Formatter};
use crate::engine::util::{map_byte_range_to_original, map_char_indices_to_original};
use crate::engine::util::{normalize_with_byte_mapping, normalize_with_char_mapping};
use crate::{CaseMatching, MatchEngine, MatchEngineFactory, MatchRange, MatchResult, SkimItem};
pub struct NormalizedEngine {
inner: Box<dyn MatchEngine>,
}
impl NormalizedEngine {
pub fn new(inner: Box<dyn MatchEngine>) -> Self {
Self { inner }
}
}
impl MatchEngine for NormalizedEngine {
fn match_item(&self, item: &dyn SkimItem) -> Option<MatchResult> {
let item_text = item.text();
let (normalized_text, char_mapping) = normalize_with_char_mapping(&item_text);
let (_, byte_mapping) = normalize_with_byte_mapping(&item_text);
let normalized_item: &dyn SkimItem = &NormalizedItem(normalized_text);
let mut result = self.inner.match_item(normalized_item)?;
result.matched_range = match result.matched_range {
MatchRange::Chars(indices) => MatchRange::Chars(map_char_indices_to_original(&indices, &char_mapping)),
MatchRange::ByteRange(start, end) => {
let (orig_start, orig_end) = map_byte_range_to_original(start, end, &byte_mapping, &item_text);
MatchRange::ByteRange(orig_start, orig_end)
}
};
Some(result)
}
}
impl Display for NormalizedEngine {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "(Normalized: {})", self.inner)
}
}
struct NormalizedItem(String);
impl SkimItem for NormalizedItem {
fn text(&self) -> Cow<'_, str> {
Cow::Borrowed(&self.0)
}
}
pub struct NormalizedEngineFactory {
inner: Box<dyn MatchEngineFactory>,
}
impl NormalizedEngineFactory {
pub fn new(inner: impl MatchEngineFactory + 'static) -> Self {
Self { inner: Box::new(inner) }
}
}
impl MatchEngineFactory for NormalizedEngineFactory {
fn create_engine_with_case(&self, query: &str, case: CaseMatching) -> Box<dyn MatchEngine> {
let (normalized_query, _) = normalize_with_char_mapping(query);
let inner_engine = self.inner.create_engine_with_case(&normalized_query, case);
Box::new(NormalizedEngine::new(inner_engine))
}
}