# Rundo
Rundo is a redo / undo library for rust which can auto generate undo op. Below is an example to use Rundo.
```rust
extern crate rundo; use rundo::prelude::*;
struct Point { x: f32, y: f32, }
fn main(){
let mut space = Workspace::new(Point! {x: 2.0, y: 2.0,}); *space.get_mut().x = 3.0;
// x was changed to 3.0 assert_eq!(*space.data.x, 3.0);
// x will undo to 2.0 space.undo(); assert_eq!(*space.data.x, 2.0);
// x will redo to 3.0
space.redo();
assert_eq!(*space.data.x, 3.0);
}
``
Note the macro
Point!at the first line of main function, why not use
Point {...}` ? That because Rundo redefined origin Point type with the same shape, but support undo redo. You can use it as same as before, but to literal construct must use a same name macro replace.
You can access data or modify with Workspace.data
directly, like:
```rust
extern crate rundo; use rundo::prelude::*;
struct Point { x: f32, y: f32, }
fn main(){ let mut space = Workspace::new(Point! {x: 2.0, y: 2.0,}); { let point = &mut space.data; // modify also allowed *point.x = 3.0; }
// but undo not work, x not rollback to 2.0 space.undo(); assert_eq!(*space.data.x, 3.0); }
```
The change wasn't captured automatic. Generally, change only between in begin_op
and end_op
will be captured. Like this example:
```rust
extern crate rundo; use rundo::prelude::*;
struct Point { x: f32, y: f32, }
fn main(){
let mut space = Workspace::new(Point! {x: 2.0, y: 2.0,}); space.beginop(); { let point = &mut space.data; *point.x = 5.0; *point.y = 5.0; } // change will be captured, and change op will be generated. space.endop();
// undo work correctly space.undo(); assert_eq!(*space.data.x, 2.0); } ```
Use get_mut
to access data, Rundo will auto help you capture the the changes.
```rust
extern crate rundo; use rundo::prelude::*;
struct Point { x: f32, y: f32, }
fn main(){
let mut space = Workspace::new(Point! {x: 2.0, y: 2.0,});
{
let point = &mut space.get_mut(); // <+--
*point.x = 4.0; // +
*point.y = 4.0; // +
// + change in this scope
} // <+- generate a single op.
// undo also work. space.undo(); assert_eq!(*space.data.x, 2.0); } ``` After point lifetime over, all change will be captured and generate an undo operator.
begin_op
and end_op
support nested use. This will work:
```compilefail space.beginop(); // do some change here space.beginop(); // do some change here space.beginop(); // do some change here space.endop(); space.endop(); space.end_op();
``
All change will be collected by the outer most pair
beginop/endop` capture.