dirge-agent 0.4.1

Minimalistic coding agent written in Rust, optimized for memory footprint and performance
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_visible_bang() {
        assert_eq!(
            parse_shell_prefix("! ls"),
            Some(ShellPrefix::Visible("ls".into()))
        );
    }

    #[test]
    fn test_invisible_bang() {
        assert_eq!(
            parse_shell_prefix("!! ls"),
            Some(ShellPrefix::Invisible("ls".into()))
        );
    }

    #[test]
    fn test_no_bang() {
        assert_eq!(parse_shell_prefix("ls"), None);
    }

    #[test]
    fn test_bang_without_space() {
        assert_eq!(
            parse_shell_prefix("!ls"),
            Some(ShellPrefix::Visible("ls".into()))
        );
    }

    #[test]
    fn test_double_bang_without_space() {
        assert_eq!(
            parse_shell_prefix("!!ls"),
            Some(ShellPrefix::Invisible("ls".into()))
        );
    }

    #[test]
    fn test_block_cd() {
        assert_eq!(parse_shell_prefix("! cd /tmp"), None);
        assert_eq!(parse_shell_prefix("!! cd /tmp"), None);
        assert_eq!(parse_shell_prefix("!cd /tmp"), None);
    }
}

#[derive(Debug, PartialEq)]
pub enum ShellPrefix {
    Visible(String),
    Invisible(String),
}

pub fn parse_shell_prefix(text: &str) -> Option<ShellPrefix> {
    let trimmed = text.trim();
    if let Some(rest) = trimmed.strip_prefix("!!") {
        let cmd = rest.trim().to_string();
        if cmd.is_empty() || is_forbidden(&cmd) {
            return None;
        }
        return Some(ShellPrefix::Invisible(cmd));
    }
    if let Some(rest) = trimmed.strip_prefix('!') {
        let cmd = rest.trim().to_string();
        if cmd.is_empty() || is_forbidden(&cmd) {
            return None;
        }
        return Some(ShellPrefix::Visible(cmd));
    }
    None
}

fn is_forbidden(cmd: &str) -> bool {
    let first = cmd.split_whitespace().next().unwrap_or("");
    matches!(
        first.to_ascii_lowercase().as_str(),
        "cd" | "pushd" | "popd" | "exit" | "exec"
    )
}