use crate::{EdError, Result};
use std::fmt::Debug;
pub trait Snapshot{
fn create_snapshot(&self) -> Self;
}
#[derive(Clone, Debug)]
pub struct History<T> where
T: Default + Debug + Snapshot + PartialEq,
{
snapshots: Vec<(String, T)>,
viewed_i: usize,
saved_i: Option<usize>,
pub dont_snapshot: bool,
}
impl<T> Default for History<T> where
T: Default + Debug + Snapshot + PartialEq,
{
fn default() -> Self { Self::new() }
}
impl <T> History<T> where
T: Default + Debug + Snapshot + PartialEq,
{
pub fn new() -> Self {
Self{
snapshots: vec![("Before reading in a file (empty)".to_owned(), T::default())],
viewed_i: 0,
saved_i: Some(0),
dont_snapshot: false,
}
}
pub fn saved(&self) -> bool {
self.saved_i == Some(self.viewed_i)
}
pub fn set_saved(&mut self) {
if !self.dont_snapshot {
self.saved_i = Some(self.viewed_i);
} else {
self.saved_i = None;
}
}
pub fn set_unsaved(&mut self) {
self.saved_i = None;
}
pub fn current(&self) -> &T {
&self.snapshots[self.viewed_i].1
}
pub fn current_mut(&mut self,
modification_cause: String,
) -> &mut T {
self.snapshot(modification_cause);
&mut self.snapshots[self.viewed_i].1
}
fn internal_create_snapshot(&mut self, label: String) {
self.snapshots.push((label, self.snapshots[self.viewed_i].1.create_snapshot()));
self.viewed_i = self.snapshots.len() - 1;
}
pub fn snapshot(&mut self,
modification_cause: String,
) {
if self.viewed_i < self.snapshots.len() - 1 {
self.internal_create_snapshot(format!(
"u{}",
self.snapshots.len().saturating_sub(self.viewed_i + 1),
));
}
if !self.dont_snapshot {
self.internal_create_snapshot(modification_cause);
}
}
pub fn dedup_present(&mut self) {
let mut last_2_iter = self.snapshots.iter().rev().take(2);
if last_2_iter.next().map(|x| &x.1) == last_2_iter.next().map(|x| &x.1) {
self.snapshots.pop();
self.viewed_i = self.snapshots.len() - 1;
}
}
pub fn snapshots(&self) -> &Vec<(String, T)> {
&self.snapshots
}
pub fn len(&self) -> usize {
self.snapshots.len()
}
pub fn saved_i(&self) -> Option<usize> {
self.saved_i
}
pub fn viewed_i(&self) -> usize {
self.viewed_i
}
pub fn set_viewed_i(&mut self, new_i: usize) -> Result<&str> {
if new_i < self.len() {
self.viewed_i = new_i;
Ok(&self.snapshots[self.viewed_i].0)
}
else {
Err(EdError::UndoIndexTooBig{
index: new_i,
history_len: self.len(),
relative_redo_limit: self.len() - self.viewed_i - 1,
})
}
}
}