Skip to main content

rec/import/
bash_history.rs

1/// Parse a bash history file, extracting command lines.
2///
3/// Skips:
4/// - Lines starting with `#` (timestamps from HISTTIMEFORMAT)
5/// - Blank/whitespace-only lines
6///
7/// Each remaining line is trimmed and returned as one command.
8#[must_use]
9pub fn parse_bash_history(content: &str) -> Vec<String> {
10    content
11        .lines()
12        .map(str::trim)
13        .filter(|line| !line.is_empty() && !line.starts_with('#'))
14        .map(std::string::ToString::to_string)
15        .collect()
16}
17
18#[cfg(test)]
19mod tests {
20    use super::*;
21
22    #[test]
23    fn test_plain_history() {
24        let content = "ls -la\ngit status\ndocker compose up -d";
25        let result = parse_bash_history(content);
26        assert_eq!(result, vec!["ls -la", "git status", "docker compose up -d"]);
27    }
28
29    #[test]
30    fn test_history_with_timestamps() {
31        let content = "ls -la\n#1625000000\ngit status\n";
32        let result = parse_bash_history(content);
33        assert_eq!(result, vec!["ls -la", "git status"]);
34    }
35
36    #[test]
37    fn test_skips_blank_lines() {
38        let content = "echo hello\n\n\nls\n";
39        let result = parse_bash_history(content);
40        assert_eq!(result, vec!["echo hello", "ls"]);
41    }
42
43    #[test]
44    fn test_trims_whitespace() {
45        let content = "  echo hello  \n  ls -la  ";
46        let result = parse_bash_history(content);
47        assert_eq!(result, vec!["echo hello", "ls -la"]);
48    }
49
50    #[test]
51    fn test_empty_content() {
52        let result = parse_bash_history("");
53        assert!(result.is_empty());
54    }
55}