1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//! Wrapper types to provide undo-redo functionality.
//!
//! # Sample code
//! ```
//! use gur::prelude::*;
//! use gur::cur::{Cur, CurBuilder};
//!
//! // Appication state
//! #[derive(Clone)]
//! struct MyState {
//! data: String
//! }
//!
//! fn main() {
//! // Initialize
//! let mut state: Cur<MyState> = CurBuilder::new().build(MyState{ data: "My".to_string() });
//! assert_eq!("My", state.data);
//!
//! // Change state
//! state.edit(|mut state: MyState| { state.data += "State"; state });
//! assert_eq!("MyState", state.data);
//!
//! // Undo
//! state.undo();
//! assert_eq!("My", state.data);
//!
//! // Redo
//! state.redo();
//! assert_eq!("MyState", state.data);
//! }
//! ```
//! Where [Cur\<T\>](crate::cur::Cur) is a type providing undo-redo functionality.
//! The `MyState` is a type of user's application state.
//! `MyState` implements the [Clone] trait required by [Cur\<T\>](crate::cur::Cur).
//! Then the variable `state` as type `Cur<MyState>` is created to get the ability to undo-redo.
//!
//! The [edit](crate::interface::IEdit::edit) takes a closure to change the variable.
//! The closure is a function that consumes a current state as internal type `MyState` and returns a new state.
//! [undo](crate::interface::IUndoRedo::undo) can restore the previous state.
//! The [redo](crate::interface::IUndoRedo::redo) is reverse operation of the [undo](crate::interface::IUndoRedo::undo).
//!
//! The [Cur\<T\>](crate::cur::Cur) implements [Deref](std::ops::Deref).
//! So the variable can be used as like smart pointers.
//!
//! # `Ur` family
//! [Ur](crate::ur::Ur) is a most basic type in this crate.
//! Some variants are provided in this crate.
//! The variants and their features are listed below.
//!
//! | Type | Requirements | Thread safety | Description |
//! | :----------------------------- | :----------------------------------------- | :-----------: | :---------------------------------------------------------------------------- |
//! | [Ur\<T\>](crate::ur::Ur) | `T`: [Snapshot](crate::snapshot::Snapshot) | No | A basic wrapper for types implementing [Snapshot](crate::snapshot::Snapshot). |
//! | [Cur\<T\>](crate::cur::Cur) | `T`: [Clone] | No | Another simple wrapper for types implementing [Clone]. |
//! | [Aur\<T\>](crate::aur::Aur) | `T`: [Snapshot](crate::snapshot::Snapshot) | Yes | [Ur\<T\>](crate::ur::Ur) + [Send] + [Sync] |
//! | [Acur\<T\>](crate::acur::Acur) | `T`: [Clone] | Yes | [Cur\<T\>](crate::cur::Cur) + [Send] + [Sync] |
//!
//! ## Requirements
//! For example, [Ur\<T\>](crate::ur::Ur) requires `T` implementing [Snapshot](crate::snapshot::Snapshot).
//! On the other hand, [Cur\<T\>](crate::cur::Cur) requires [Clone] instead of [Snapshot](crate::snapshot::Snapshot) for simplicity.
//!
//! ## Thread safety
//! Some types of them can be [Send] and [Sync] and some not.
//! See [interface](crate::interface) for more details about thread safety.
//!
//! # Generative approach
//! This section describes a basic concept of this crate.
//! The concept is that "Undoing is regenerating (recomputing) the old state."
//!
//! For explanation, a sample history of changes is shown as follows,
//! ```txt
//! t: state
//! c: command
//! s: snapshot
//!
//! old <----------------------> new
//! c1 c2 c3
//! t0 -----> t1 -----> t2 -----> t3
//! | +--------------> |
//! | | |
//! s0 +--------------------------+
//! undo t3 -> t2
//! ```
//! Where `tx` is an application state at time point `x`,
//! `cx` is a command to change a state `tx-1` to next `tx`,
//! and `sx` is a snapshot of a state `tx`.
//!
//! The application state have changed in order of `t0`, `t1`, `t2`, and `t3`.
//! Now, the current state is `t3`.
//!
//! Let us consider undoing the current state `t3` to its previous state `t2`.
//! First, the system restores an old state from its snapshot at any point in the history.
//! In this case, We would have to restore the state `t0` from `s0` because there is only one snapshot `s0`.
//! Then the system reruns the commands (`c1` and `c2`) in order.
//! Finally, the target state `t2` will be obtained.
//!
//! # Data structure
//! A history is managed as chain of commands and snapshots to perform the
//! process described above.
//! No intermediate states are stored.
//! ```txt
//! c: command
//! s: snapshot
//!
//! old <----------------------------------------------> new
//! /--\ +--+ +--+ +--+ /----\ +----+ +----+
//! |s0|--|c1|--|c2|--...--|cn|--|sn+1|--|cn+2|--|cn+3|--...
//! \--/ +--+ +--+ +--+ \----/ +----+ +----+
//! ```
//! The frequency of snapshots can be customized by "trigger functions."
//! See [crate::triggers] for more details.
//!
//! # Pros and Cons
//! ## Pros
//! The advantages of this approach are usability and robustness.
//! There are no backward opeartions in the undoing process.
//! So users almost never have to write additional codes for the process.
//! If there are tests for the application state object, the correctness of undo-redo process is
//! also guaranteed.
//!
//! ## Cons
//! Users should pay attention to side effects of commands.
//!
//! See also ["`edit` with side effects"](crate::interface#edit-with-side-effects) for more details.