run-kit 0.7.1

Universal multi-language runner and smart REPL
Documentation
use regex::Regex;

pub fn format_stderr(language: &str, stderr: &str, success: bool) -> String {
    if stderr.trim().is_empty() {
        return String::new();
    }

    let (scrubbed, _changed) = scrub_temp_paths(stderr);
    if success {
        return scrubbed;
    }

    format!("Error: {language} failed\n{scrubbed}")
}

fn scrub_temp_paths(stderr: &str) -> (String, bool) {
    let mut changed = false;
    let temp_dir = std::env::temp_dir();
    let temp = temp_dir.to_string_lossy();

    let mut output = stderr.to_string();
    if output.contains(temp.as_ref()) {
        output = output.replace(temp.as_ref(), "<temp>");
        changed = true;
    }

    if temp.as_ref().starts_with("/var/") {
        let private = format!("/private{temp}");
        if output.contains(&private) {
            output = output.replace(&private, "<temp>");
            changed = true;
        }
    }

    let re = Regex::new(r"<temp>/?(?:run-[^/]+|\.tmp[^/]+|run-[^/]+[^/]*)/").unwrap();
    if re.is_match(&output) {
        output = re.replace_all(&output, "<snippet>/").to_string();
        changed = true;
    }

    let re_noslash = Regex::new(r"<temp>\.tmp[^/]+/").unwrap();
    if re_noslash.is_match(&output) {
        output = re_noslash.replace_all(&output, "<snippet>/").to_string();
        changed = true;
    }

    (output, changed)
}