iforgor 0.3.3

The CLI tool for all those commands you forget about
Documentation
use serde::{Deserialize, Serialize};

use crate::command::CommandId;

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct History {
    pub history: Vec<CommandId>,
}

impl History {
    const MAX_ENTRIES: usize = 100;

    pub fn add_entry(&mut self, id: &CommandId) {
        self.history.retain(|hid| hid != id);
        self.history.push(id.clone());

        // Cap history size.
        if self.history.len() > Self::MAX_ENTRIES {
            let excess = self.history.len() - Self::MAX_ENTRIES;
            self.history.drain(..excess);
        }
    }
}

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

    #[test]
    fn add_entry_to_empty() {
        let mut h = History::default();
        h.add_entry(&"a".to_string());
        assert_eq!(h.history, vec!["a"]);
    }

    #[test]
    fn add_entry_deduplicates_and_moves_to_end() {
        let mut h = History {
            history: vec!["a".into(), "b".into(), "c".into()],
        };
        h.add_entry(&"a".to_string());
        assert_eq!(h.history, vec!["b", "c", "a"]);
    }

    #[test]
    fn add_entry_new_goes_to_end() {
        let mut h = History {
            history: vec!["a".into(), "b".into()],
        };
        h.add_entry(&"c".to_string());
        assert_eq!(h.history, vec!["a", "b", "c"]);
    }

}