history.ha (2788B)
1 // History of buffer changes; a chronological list of change sequences. 2 type History = []ChangeSeq; 3 4 // A record of a sequence of buffer changes; the effect of one command. 5 type ChangeSeq = []Change; 6 7 // A record of a single arbitrary buffer change. 8 type Change = (Addition | Deletion); 9 10 // The addition of a buffer chunk (start position, chunk size). 11 type Addition = (size, size); 12 13 // The deletion of a buffer chunk (start position, chunk size). 14 type Deletion = (size, size); 15 16 // The effect of the undo command. 17 type UndoMode = enum{ 18 POSIX, // undoes the last buffer change, including that of 'u' 19 FULL, // undoes the last buffer change, exlucding that of 'u' 20 }; 21 22 // There is no history to undo. 23 type NoHistory = !void; 24 25 fn hist_clear(buf: *Buffer) void = { 26 delete(buf.hist[..]); 27 }; 28 29 fn hist_newseq(buf: *Buffer) void = { 30 if (buf.redolastchange) 31 delete(buf.hist[ len(buf.hist) - 1 ]); 32 33 append(buf.hist, []: ChangeSeq); 34 }; 35 36 fn hist_discardseq(buf: *Buffer) void = { 37 debug("hist_discardseq()"); 38 delete(buf.hist[len(buf.hist) - 1]); 39 }; 40 41 fn hist_append(buf: *Buffer, change: Change) void = { 42 append(buf.hist[len(buf.hist) - 1], change); 43 }; 44 45 fn hist_tidy(s: *Session, buf: *Buffer, cmd_deletions: size) void = { 46 if (s.undomode == UndoMode::POSIX) { 47 buf_prunetrash(buf, cmd_deletions); 48 // TODO: prune history 49 }; 50 s.buf.redolastchange = false; 51 }; 52 53 fn hist_undo(buf: *Buffer) (void | NoHistory) = { 54 debug("hist_undo()"); 55 if (len(buf.hist) == 0) 56 return NoHistory; 57 58 let seq = buf.hist[ len(buf.hist) - 1 ]; 59 60 for (let j = len(seq) - 1; j < len(seq); j -= 1) 61 match (seq[j]) { 62 case let deln: Deletion => 63 let (n, m) = deln; 64 let lentrash = len(buf.trash); 65 let lines = buf.trash[(lentrash - m)..]; 66 insert(buf.lines[n], lines...); 67 delete(buf.trash[(lentrash - m)..]); 68 buf.cursor = (n + m) - 1; 69 case let addn: Addition => 70 let (n, m) = addn; 71 let lines = buf.lines[n..(n + m)]; 72 insert(buf.trash[0], lines...); 73 delete(buf.lines[n..(n + m)]); 74 let prev = addr_prevline(buf, n); 75 buf.cursor = prev; 76 }; 77 }; 78 79 fn hist_redo(buf: *Buffer) (void | NoHistory) = { 80 debug("hist_redo()"); 81 if (len(buf.hist) == 0) 82 return NoHistory; 83 84 let seq = buf.hist[ len(buf.hist) - 1 ]; 85 86 for (let i = 0z; i < len(seq); i += 1) 87 match (seq[i]) { 88 case let addn: Addition => 89 let (n, m) = addn; 90 //let lentrash = len(buf.trash); 91 //let lines = buf.trash[(lentrash - m)..]; 92 let lines = buf.trash[..m]; 93 insert(buf.lines[n], lines...); 94 //delete(buf.trash[(lentrash - m)..]); 95 delete(buf.trash[..m]); 96 buf.cursor = (n + m) - 1; 97 case let deln: Deletion => 98 let (n, m) = deln; 99 let lines = buf.lines[n..(n + m)]; 100 append(buf.trash, lines...); 101 delete(buf.lines[n..(n + m)]); 102 let prev = addr_prevline(buf, n); 103 buf.cursor = prev; 104 }; 105 };