helen 0.1.0

Repository review gate.
Documentation
//! Small text formatting helpers for elenchus diagnostics.

use std::{fs, path::Path};

/// Returns a short hash prefix.
pub(super) fn short_hash(hash: &str) -> &str {
    hash.get(..16).unwrap_or(hash)
}

/// Shell-quotes text for a rerun suggestion.
pub(super) fn shell_quote(value: &str) -> String {
    if value
        .chars()
        .all(|character| character.is_ascii_alphanumeric() || matches!(character, '_' | '-' | '.'))
    {
        return value.to_owned();
    }
    format!("'{}'", value.replace('\'', "'\\''"))
}

/// Returns a formatted optional version line for an error.
pub(super) fn version_line_for_error(version: &str) -> String {
    if version.is_empty() {
        String::new()
    } else {
        format!("Version: {version}\n")
    }
}

/// Returns the first `count` lines from text.
pub(super) fn first_lines(text: &str, count: usize) -> String {
    let mut lines = String::new();
    for line in text.lines().take(count) {
        use std::fmt::Write as _;

        let _result = writeln!(&mut lines, "{line}");
    }
    lines
}

/// Returns the first `count` lines from a file, or an empty string if it is absent.
pub(super) fn first_lines_file(path: &Path, count: usize) -> String {
    fs::read_to_string(path)
        .map(|text| first_lines(&text, count))
        .unwrap_or_default()
}

/// Prefixes every line in text.
pub(super) fn prefix_lines(text: &str, prefix: &str) -> String {
    let mut lines = String::new();
    for line in text.lines() {
        use std::fmt::Write as _;

        let _result = writeln!(&mut lines, "{prefix}{line}");
    }
    lines
}

/// Returns the last non-empty line in text.
pub(super) fn last_non_empty_line(text: &str) -> String {
    text.lines()
        .map(str::trim)
        .rfind(|line| !line.is_empty())
        .unwrap_or_default()
        .to_owned()
}

#[cfg(test)]
mod tests {
    //! Tests for elenchus text helpers.

    use super::shell_quote;

    #[test]
    fn shell_quote_keeps_rerun_command_single_argument() {
        assert_eq!(shell_quote("abc-123"), "abc-123");
        assert_eq!(
            shell_quote("refactor(elenchus): Reuse approved review results"),
            "'refactor(elenchus): Reuse approved review results'"
        );
        assert_eq!(shell_quote("can't"), "'can'\\''t'");
    }
}