commit 3257635eedc132400da16934708d94f7bf966f32
parent 2cd2cb220b526a5b35743ff8e505fd5d06c309eb
Author: Byron Torres <b@torresjrjr.com>
Date: Wed, 17 Jan 2024 21:23:26 +0000
undo progress
Diffstat:
3 files changed, 29 insertions(+), 43 deletions(-)
diff --git a/buffer.ha b/buffer.ha
@@ -8,7 +8,7 @@ type Buffer = struct{
filename: str,
lines: []*Line,
trash: []*Line,
- hist: []ChangeSet,
+ hist: []ChangeSeq,
cursor: size,
modified: bool,
written: bool,
@@ -38,16 +38,10 @@ fn buf_insert(buf: *Buffer, n: size, ls: *Line...) void = {
hist_append(buf, (n, len(ls)): Addition);
- debug("buf_insert(): len('last changeset')={}", len(buf.hist[len(buf.hist) - 1]));
-
-// let change = Change{ kind = true, n = n, z = len(ls) };
-// let activeset = buf.hist[buf.activehist];
-// append(activeset, change);
+ debug("buf_insert(): len('last changeseq')={}", len(buf.hist[len(buf.hist) - 1]));
};
fn buf_deleteall(buf: *Buffer) void = {
- // buf_wipetrash(buf);
-
if (len(buf.lines) > 1) {
append(buf.trash, buf.lines[1..]...);
delete(buf.lines[1..]);
@@ -58,15 +52,6 @@ fn buf_deleteall(buf: *Buffer) void = {
fn buf_delete(buf: *Buffer, a: size, b: size) void = {
debug("buf_delete(a={}, b={})", a, b);
- // buf_wipetrash(buf);
-
- // The G command requires changed lines to be unmarked.
- // Command functions "change" lines using buf_delete() first.
- // If a line is trashed, it is effectively unmarked.
- // The G command function unmarks all lines first anyway.
- //for (let i = 0z; i < len(buf.lines); i += 1) {
- // buf.lines[i].globalmark = false;
- //};
append(buf.trash, buf.lines[a..b+1]...);
delete(buf.lines[a..b+1]);
@@ -76,13 +61,10 @@ fn buf_delete(buf: *Buffer, a: size, b: size) void = {
hist_append(buf, (a, (b + 1 - a)): Deletion);
- debug("buf_delete(): len('last changeset')={}", len(buf.hist[len(buf.hist) - 1]));
+ debug("buf_delete(): len('last changeseq')={}", len(buf.hist[len(buf.hist) - 1]));
};
fn buf_read(buf: *Buffer, src: io::handle, a: size) ((size, size) | io::error | encoding::utf8::invalid) = {
- // TODO: don't call this here, call it at a higher level
- // buf_wipetrash(buf);
-
let ls: []*Line = [];
let sz = 0z;
for (true) {
diff --git a/command.ha b/command.ha
@@ -121,7 +121,7 @@ fn cmd_append(s: *Session, cmd: *Command) (void | Error) = {
const n = get_linenum(cmd.linenums, s.buf.cursor);
- hist_newset(s.buf);
+ hist_newseq(s.buf); // TODO: special case, len(cmd.textinput) == 0
for (let i = 0z; i < len(cmd.textinput); i += 1) {
const line = alloc(Line{ text = cmd.textinput[i], ... });
buf_insert(s.buf, n + 1 + i, line);
@@ -147,6 +147,7 @@ fn cmd_change(s: *Session, cmd: *Command) (void | Error) = {
};
};
+ hist_newseq(s.buf);
buf_delete(s.buf, a, b);
for (let i = 0z; i < len(cmd.textinput); i += 1) {
@@ -176,7 +177,7 @@ fn cmd_delete(s: *Session, cmd: *Command) (void | Error) = {
)?;
assert_nonzero(s, a)?;
- hist_newset(s.buf);
+ hist_newseq(s.buf);
buf_delete(s.buf, a, b);
s.buf.cursor =
@@ -243,6 +244,7 @@ fn cmd_insert(s: *Session, cmd: *Command) (void | Error) = {
const n = get_linenum(cmd.linenums, s.buf.cursor);
const n = if (n == 0) 1z else n;
+ hist_newseq(s.buf); // TODO special case, zeros lines
for (let i = 0z; i < len(cmd.textinput); i += 1) {
const line = alloc(Line{ text = cmd.textinput[i], ... });
buf_insert(s.buf, n + i, line);
@@ -285,6 +287,7 @@ fn cmd_join(s: *Session, cmd: *Command) (void | Error) = {
...
});
+ hist_newseq(s.buf);
buf_delete(s.buf, a, b);
buf_insert(s.buf, a, newline);
@@ -375,6 +378,8 @@ fn cmd_move(s: *Session, cmd: *Command) (void | Error) = {
n;
const lines = alloc(s.buf.lines[a..b+1]...); defer free(lines); // TODO: mem?
+
+ hist_newseq(s.buf);
buf_delete(s.buf, a, b);
buf_insert(s.buf, dest, lines...);
@@ -457,6 +462,7 @@ fn cmd_read(s: *Session, cmd: *Command) (void | Error) = {
};
defer io::close(rd)!;
+ hist_newseq(s.buf); // TODO: special case, zero input
const (sz, _) = buf_read(s.buf, rd, n)?;
if (!s.suppressmode)
@@ -486,6 +492,7 @@ fn cmd_substitute(s: *Session, cmd: *Command) (void | Error) = {
let changes = 0z;
+ hist_newseq(s.buf); // TODO: special case, no match or changes
for (let n = a; n <= b; n += 1) {
const old = s.buf.lines[n].text;
const results = regex::findall(&re, old);
@@ -563,6 +570,8 @@ fn cmd_copy(s: *Session, cmd: *Command) (void | Error) = {
};
const lines = alloc(s.buf.lines[a..b+1]...); defer free(lines); // TODO: ?
+
+ hist_newseq(s.buf);
buf_insert(s.buf, dest, lines...);
s.buf.cursor = dest - 1 + len(lines);
@@ -574,7 +583,7 @@ fn cmd_undo(s: *Session, cmd: *Command) (void | Error) = {
assert_noaddrs(s, cmd.linenums)?;
- hist_undo(s.buf)?;
+ hist_undo(s.buf)?; // TODO: redo last undo too
};
fn cmd_vglobal(s: *Session, cmd: *Command) (void | Error) = {
diff --git a/history.ha b/history.ha
@@ -1,19 +1,23 @@
-type History = []ChangeSet;
+type History = []ChangeSeq;
-type ChangeSet = []Change;
+type ChangeSeq = []Change;
type Change = (Addition | Deletion);
+// chunk (position, size)
type Addition = (size, size);
+// chunk (position, size)
type Deletion = (size, size);
type NoHistory = !void;
-fn hist_newset(buf: *Buffer) void = {
-debug("hist_newset(): begin");
- append(buf.hist, []: ChangeSet);
-debug("hist_newset(): end");
+fn hist_newseq(buf: *Buffer) void = {
+ append(buf.hist, []: ChangeSeq);
+};
+
+fn hist_discardseq(buf: *Buffer) void = {
+ delete(buf.hist[len(buf.hist) - 1]);
};
fn hist_append(buf: *Buffer, change: Change) void = {
@@ -21,34 +25,25 @@ fn hist_append(buf: *Buffer, change: Change) void = {
};
fn hist_undo(buf: *Buffer) (void | NoHistory) = {
-debug("hist_undo(): len(buf.hist)={}", len(buf.hist));
if (len(buf.hist) == 0)
return NoHistory;
- let lastset = buf.hist[ len(buf.hist) - 1 ];
-debug("hist_undo(): len(lastset)={}", len(lastset));
+ let seq = buf.hist[ len(buf.hist) - 1 ];
- for (let i = len(lastset) - 1; i < len(lastset); i -= 1) {
- let change = lastset[i];
- match (change) {
+ for (let i = len(seq) - 1; i < len(seq); i -= 1)
+ match (seq[i]) {
case let deln: Deletion =>
let (n, m) = deln;
-debug("hist_undo(): deln=({}, {})", n, m);
let lentrash = len(buf.trash);
-debug("hist_undo(): lentrash={}", lentrash);
let lines = buf.trash[(lentrash - m)..];
-debug("hist_undo(): len(lines)={}", len(lines));
insert(buf.lines[n], lines...);
delete(buf.trash[(lentrash - m)..]);
case let addn: Addition =>
let (n, m) = addn;
-debug("hist_undo(): addn=({}, {})", n, m);
let lines = buf.lines[n..(n + m)];
-debug("hist_undo(): len(lines)={}", len(lines));
- append(buf.trash, lines...);
+ insert(buf.trash[0], lines...);
delete(buf.lines[n..(n + m)]);
};
- };
delete(buf.hist[ len(buf.hist) - 1 ]);
};