polite_programming/
lib.rsextern crate regex;
use regex::Regex;
use std::process::{Command, Stdio};
use std::io::{BufRead, BufReader};
pub struct PleaseIgnore {
error_regex: Regex,
please_regex: Regex,
}
impl PleaseIgnore {
pub fn new() -> Self {
PleaseIgnore {
error_regex: Regex::new(r"error(\[E\d+\])?: ").unwrap(),
please_regex: Regex::new(r"\bplease\b").unwrap(),
}
}
pub fn analyze_compilation(&self, args: &[String]) -> std::io::Result<i32> {
let mut child = Command::new("cargo")
.arg("build")
.args(args)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()?;
let stderr = child.stderr.take().expect("Failed to capture stderr");
let stderr_reader = BufReader::new(stderr);
let mut in_error = false;
let mut current_error = String::new();
for line in stderr_reader.lines() {
let line = line?;
if self.error_regex.is_match(&line) {
if !current_error.is_empty() {
self.process_error(¤t_error);
}
in_error = true;
current_error.clear();
}
if in_error {
current_error.push_str(&line);
current_error.push('\n');
} else {
println!("{}", line);
}
if line.trim().is_empty() {
in_error = false;
if !current_error.is_empty() {
self.process_error(¤t_error);
}
current_error.clear();
}
}
if !current_error.is_empty() {
self.process_error(¤t_error);
}
let status = child.wait()?;
Ok(status.code().unwrap_or(1))
}
fn process_error(&self, error: &str) {
if self.please_regex.is_match(error) {
println!("Ignoring error due to 'please' usage:");
for line in error.lines() {
println!(" {}", line);
}
} else {
print!("{}", error);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_please_ignore() {
let pi = PleaseIgnore::new();
assert!(pi.please_regex.is_match("please"));
assert!(!pi.please_regex.is_match("no please here"));
}
}