use regex::Regex;
use crate::error::{Error, Result};
use crate::language::Language;
pub struct TextSplitter {
word_re: Regex,
sentence_re: Regex,
letter_re: Regex,
}
fn compile(body: &str) -> Result<Regex> {
Regex::new(body).map_err(|e| Error::InvalidPattern(format!("{body}: {e}")))
}
impl TextSplitter {
pub fn new(language: &Language) -> Result<Self> {
Ok(TextSplitter {
word_re: compile(&language.word_split_pattern)?,
sentence_re: compile(&language.sentence_boundary_pattern)?,
letter_re: compile(&language.letter_pattern)?,
})
}
pub fn split_words(&self, text: &str) -> Vec<String> {
let text = text.trim();
if text.is_empty() {
return Vec::new();
}
self.word_re
.split(text)
.filter(|w| !w.is_empty())
.map(String::from)
.collect()
}
pub fn split_sentences(&self, text: &str) -> Vec<String> {
let text = text.trim();
if text.is_empty() {
return Vec::new();
}
self.sentence_re
.split(text)
.filter(|p| !p.is_empty())
.map(|p| p.trim().to_string())
.collect()
}
pub fn count_letters(&self, text: &str) -> i64 {
let text = text.trim();
if text.is_empty() {
return 0;
}
self.letter_re.find_iter(text).count() as i64
}
pub fn count_words(&self, text: &str) -> i64 {
self.split_words(text).len() as i64
}
pub fn count_sentences(&self, text: &str) -> i64 {
let text = text.trim();
if text.is_empty() {
return 0;
}
let count = self.sentence_re.find_iter(text).count() as i64;
if count == 0 {
1
} else {
count
}
}
pub fn count_long_words(&self, text: &str, threshold: i64) -> i64 {
self.split_words(text)
.iter()
.filter(|w| self.count_letters(w) > threshold)
.count() as i64
}
}