use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
pub fn find() -> Option<PathBuf> {
let ok = Command::new("tesseract")
.arg("--version")
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()
.is_ok_and(|s| s.success());
ok.then(|| PathBuf::from("tesseract"))
}
pub fn read(tesseract: &Path, image: &Path) -> String {
let Ok(out) = Command::new(tesseract)
.arg(image)
.args(["stdout", "--psm", "11"])
.stderr(Stdio::null())
.output()
else {
return String::new();
};
clean(&String::from_utf8_lossy(&out.stdout))
}
pub fn clean(raw: &str) -> String {
raw.lines()
.map(str::trim)
.filter(|l| {
let chars = l.chars().filter(|c| !c.is_whitespace()).count();
let alnum = l.chars().filter(|c| c.is_alphanumeric()).count();
chars > 0
&& alnum * 10 >= chars * 7
&& l.split_whitespace()
.any(|w| w.chars().filter(|c| c.is_alphabetic()).count() >= 3)
})
.collect::<Vec<_>>()
.join(" / ")
}
#[cfg(test)]
mod tests {
#[test]
fn drops_noise() {
assert_eq!(
super::clean(" | ~ .\nDAY 3 in Kyoto\n\n,.;\nee\nbest ramen!\n"),
"DAY 3 in Kyoto / best ramen!"
);
}
}