use std::fs::{File, OpenOptions};
use std::io::{BufRead, BufReader, Write};
use std::path::Path;
pub struct CommandHistory {
history: Vec<String>,
position: usize,
history_file_path: String,
}
impl CommandHistory {
pub fn new(history_file_path: &str) -> CommandHistory {
let mut history = Vec::new();
if Path::new(history_file_path).exists() {
if let Ok(file) = File::open(history_file_path) {
let reader = BufReader::new(file);
for line in reader.lines() {
if let Ok(command) = line {
history.push(command);
}
}
}
}
let position = history.len();
CommandHistory {
history,
position,
history_file_path: history_file_path.to_string(),
}
}
pub fn add_command(&mut self, command: &str) {
if !command.is_empty() {
if self.history.is_empty() || self.history.last().unwrap() != command {
self.history.push(command.to_string());
self.position = self.history.len();
if let Ok(mut file) = OpenOptions::new()
.create(true)
.append(true)
.open(&self.history_file_path)
{
writeln!(file, "{}", command).unwrap();
}
}
}
}
pub fn move_up(&mut self) {
if self.position > 0 {
self.position -= 1;
}
}
pub fn move_down(&mut self) {
if self.position < self.history.len() {
self.position += 1;
}
}
pub fn get_current(&self) -> String {
if self.position < self.history.len() {
self.history[self.position].clone()
} else {
"".to_string()
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs;
#[test]
fn test_command_history() {
let test_history_path = "test_raftcli_history.txt";
let _ = fs::remove_file(test_history_path);
let mut command_history = CommandHistory::new(test_history_path);
command_history.add_command("first command");
command_history.add_command("second command");
command_history.add_command("third command");
command_history.move_up();
assert_eq!(command_history.get_current(), "third command");
command_history.move_up();
assert_eq!(command_history.get_current(), "second command");
command_history.move_up();
assert_eq!(command_history.get_current(), "first command");
command_history.move_up();
assert_eq!(command_history.get_current(), "first command");
command_history.move_down();
assert_eq!(command_history.get_current(), "second command");
command_history.move_down();
assert_eq!(command_history.get_current(), "third command");
command_history.move_down();
assert_eq!(command_history.get_current(), "third command");
command_history.move_down();
let _ = fs::remove_file(test_history_path);
}
}