use super::{HistoryKey, HistoryManager};
use crate::config::cli_config::CliConfig;
use dialoguer::BasicHistory;
use dialoguer::History;
use std::fs::{self, OpenOptions};
use std::io::{BufRead, BufReader, Write};
use std::path::PathBuf;
pub struct FileHistoryManager;
impl HistoryManager for FileHistoryManager {
fn load(&self, key: HistoryKey) -> BasicHistory {
let mut history = BasicHistory::new().max_entries(10).no_duplicates(true);
let Ok(file) = fs::File::open(get_history_path(key)) else {
return history;
};
BufReader::new(file)
.lines()
.map_while(Result::ok)
.filter(|line| !line.trim().is_empty())
.for_each(|line| {
history.write(&line);
});
history
}
fn save(&self, key: HistoryKey, history: &BasicHistory) {
let path = get_history_path(key);
if let Some(parent) = path.parent() {
let _ = fs::create_dir_all(parent);
}
let Ok(mut file) = OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(path)
else {
return;
};
for entry in collect_entries(history).iter().rev() {
let _ = writeln!(file, "{}", entry);
}
}
}
fn get_history_path(key: HistoryKey) -> PathBuf {
CliConfig::get_path()
.map(|p| p.parent().unwrap().to_path_buf())
.unwrap_or_else(|_| PathBuf::from("."))
.join(format!(".{}_history", key.as_str()))
}
fn collect_entries(history: &BasicHistory) -> Vec<String> {
(0..)
.map(|i| History::<String>::read(history, i))
.take_while(Option::is_some)
.flatten()
.collect()
}