rbam 0.1.1

A blazing-fast Rust Bash Alias Manager (create, list, and remove shell aliases).
use std::collections::HashMap;
use std::fs;

pub fn read_aliases() -> HashMap<String, String> {
    let mut aliases = HashMap::new();
    let mut path = dirs::home_dir().expect("No home dir");
    path.push(".bash_aliases");

    let contents = match fs::read_to_string(&path) {
        Ok(c) => c,
        Err(_) => {
            eprintln!("Cannot read .bash_aliases");
            return aliases;
        }
    };

    for line in contents.lines() {
        let trimmed = line.trim();
        if trimmed.starts_with("alias ")
            && let Some((name, cmd)) = parse_alias_line(trimmed)
        {
            aliases.insert(name, cmd);
        }
    }

    aliases
}

pub fn parse_alias_line(line: &str) -> Option<(String, String)> {
    let without_alias = line.strip_prefix("alias ")?;
    let parts: Vec<&str> = without_alias.splitn(2, '=').collect();

    if parts.len() != 2 {
        return None;
    }

    let name = parts[0].to_string();
    let cmd = parts[1].trim_matches('\'').trim_matches('"').to_string();

    Some((name, cmd))
}

pub fn get_aliases_path() -> std::path::PathBuf {
    let mut path = dirs::home_dir().expect("No home dir");
    path.push(".bash_aliases");
    path
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_parse_valid_alias_single_quotes() {
        let line = "alias cdn='ssh user@host'";
        let result = parse_alias_line(line);
        assert_eq!(
            result,
            Some(("cdn".to_string(), "ssh user@host".to_string()))
        );
    }

    #[test]
    fn test_parse_valid_alias_double_quotes() {
        let line = "alias prod=\"ssh deploy@prod.com\"";
        let result = parse_alias_line(line);
        assert_eq!(
            result,
            Some(("prod".to_string(), "ssh deploy@prod.com".to_string()))
        );
    }

    #[test]
    fn test_parse_alias_with_port() {
        let line = "alias staging='ssh -p 2222 user@host'";
        let result = parse_alias_line(line);
        assert_eq!(
            result,
            Some(("staging".to_string(), "ssh -p 2222 user@host".to_string()))
        );
    }

    #[test]
    fn test_parse_alias_with_equals_in_command() {
        let line = "alias test='echo KEY=VALUE'";
        let result = parse_alias_line(line);
        assert_eq!(
            result,
            Some(("test".to_string(), "echo KEY=VALUE".to_string()))
        );
    }

    #[test]
    fn test_parse_invalid_no_alias_prefix() {
        let line = "cdn='ssh user@host'";
        let result = parse_alias_line(line);
        assert_eq!(result, None);
    }

    #[test]
    fn test_parse_invalid_no_equals() {
        let line = "alias cdn";
        let result = parse_alias_line(line);
        assert_eq!(result, None);
    }

    #[test]
    fn test_parse_invalid_empty_name() {
        let line = "alias ='ssh user@host'";
        let result = parse_alias_line(line);
        assert!(result.is_some()); // Will parse but name is empty
        if let Some((name, _)) = result {
            assert_eq!(name, "");
        }
    }

    #[test]
    fn test_parse_alias_with_spaces() {
        let line = "alias my-server = 'ssh root@server.com'";
        let result = parse_alias_line(line);
        assert!(result.is_some());
    }
}