| 5039 |      1 | (*  Title:      Pure/General/history.ML
 | 
|  |      2 |     ID:         $Id$
 | 
|  |      3 |     Author:     Markus Wenzel, TU Muenchen
 | 
|  |      4 | 
 | 
| 6680 |      5 | Histories of values, with undo and redo, and optional limit.
 | 
| 5039 |      6 | *)
 | 
|  |      7 | 
 | 
|  |      8 | signature HISTORY =
 | 
|  |      9 | sig
 | 
|  |     10 |   type 'a T
 | 
| 6680 |     11 |   val init: int option -> 'a -> 'a T
 | 
|  |     12 |   val is_initial: 'a T -> bool
 | 
| 5039 |     13 |   val current: 'a T -> 'a
 | 
| 16496 |     14 |   val previous: 'a T -> 'a option
 | 
| 7715 |     15 |   val clear: int -> 'a T -> 'a T
 | 
| 5039 |     16 |   val undo: 'a T -> 'a T
 | 
|  |     17 |   val redo: 'a T -> 'a T
 | 
| 6680 |     18 |   val apply_copy: ('a -> 'a) -> ('a -> 'a) -> 'a T -> 'a T
 | 
| 5039 |     19 |   val apply: ('a -> 'a) -> 'a T -> 'a T
 | 
| 6680 |     20 |   val map: ('a -> 'a) -> 'a T -> 'a T
 | 
| 5039 |     21 | end;
 | 
|  |     22 | 
 | 
|  |     23 | structure History: HISTORY =
 | 
|  |     24 | struct
 | 
|  |     25 | 
 | 
|  |     26 | 
 | 
|  |     27 | (* datatype history *)
 | 
|  |     28 | 
 | 
|  |     29 | datatype 'a T =
 | 
| 6680 |     30 |   History of 'a * (int option * int * 'a list * 'a list);
 | 
| 5039 |     31 | 
 | 
| 6680 |     32 | fun init lim x = History (x, (lim, 0, [], []));
 | 
|  |     33 | 
 | 
|  |     34 | fun is_initial (History (_, (_, len, _, _))) = len = 0;
 | 
| 5039 |     35 | 
 | 
| 6680 |     36 | fun current (History (x, _)) = x;
 | 
|  |     37 | 
 | 
| 16496 |     38 | fun previous (History (_, (_, _, x :: _, _))) = SOME x
 | 
|  |     39 |   | previous _ = NONE;
 | 
|  |     40 | 
 | 
| 7715 |     41 | fun clear n (History (x, (lim, len, undo_list, redo_list))) =
 | 
| 15570 |     42 |   History (x, (lim, Int.max (0, len - n), Library.drop (n, undo_list), redo_list));
 | 
| 5039 |     43 | 
 | 
| 6680 |     44 | fun undo (History (_, (_, _, [], _))) = error "No further undo information"
 | 
|  |     45 |   | undo (History (x, (lim, len, u :: undo_list, redo_list))) =
 | 
|  |     46 |       History (u, (lim, len - 1, undo_list, x :: redo_list));
 | 
| 5039 |     47 | 
 | 
| 6680 |     48 | fun redo (History (_, (_, _, _, []))) = error "No further redo information"
 | 
|  |     49 |   | redo (History (x, (lim, len, undo_list, r :: redo_list))) =
 | 
|  |     50 |       History (r, (lim, len + 1, x :: undo_list, redo_list));
 | 
|  |     51 | 
 | 
| 15531 |     52 | fun push NONE _ x xs = x :: xs
 | 
|  |     53 |   | push (SOME 0) _ _ _ = []
 | 
| 15570 |     54 |   | push (SOME n) len x xs = if len < n then x :: xs else Library.take (n, x :: xs);
 | 
| 5039 |     55 | 
 | 
| 6680 |     56 | fun apply_copy cp f (History (x, (lim, len, undo_list, _))) =
 | 
|  |     57 |   let val x' = cp x
 | 
|  |     58 |   in History (f x, (lim, len + 1, push lim len x' undo_list, [])) end;
 | 
| 5039 |     59 | 
 | 
| 6680 |     60 | fun apply f = apply_copy I f;
 | 
|  |     61 | 
 | 
|  |     62 | fun map f (History (x, hist)) = History (f x, hist);
 | 
| 5039 |     63 | 
 | 
|  |     64 | 
 | 
|  |     65 | end;
 |