undo 0.2.1

A undo/redo library based on the command pattern.
Documentation

Undo

A undo/redo library.

It uses the Command Pattern where the user implements the UndoCmd trait for each command and then the commands can be used with the UndoStack.

Build Status Crates.io Docs

[dependencies]
undo = "0.2.0"

Example

extern crate undo;

use std::rc::Rc;
use std::cell::RefCell;
use undo::{UndoCmd, UndoStack};

/// Pops an element from a vector.
#[derive(Clone)]
struct PopCmd {
    vec: Rc<RefCell<Vec<i32>>>,
    e: Option<i32>,
}

impl UndoCmd for PopCmd {
    fn redo(&mut self) {
        self.e = self.vec.borrow_mut().pop();
    }

    fn undo(&mut self) {
        self.vec.borrow_mut().push(self.e.unwrap());
        self.e = None;
    }
}

fn main() {
    // We need to use Rc<RefCell> since all commands are going to mutate the vec.
    let vec = Rc::new(RefCell::new(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));
    let mut undo_stack = UndoStack::new()
        .on_clean(|| println!("This is called when the stack changes from dirty to clean!"))
        .on_dirty(|| println!("This is called when the stack changes from clean to dirty!"));
    
    let cmd = PopCmd { vec: vec.clone(), e: None };
    undo_stack.push(cmd.clone());
    undo_stack.push(cmd.clone());
    undo_stack.push(cmd.clone());
    
    assert_eq!(vec.borrow().len(), 7);
    
    undo_stack.undo(); // on_dirty is going to be called here.
    undo_stack.undo();
    undo_stack.undo();
    
    assert_eq!(vec.borrow().len(), 10);
}

TODO

  • Add UndoCmd merging.
  • Add more examples.
  • ???