ed

[hare] The standard editor
Log | Files | Refs | README | LICENSE

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 };