commit 7a91d68743d7c62f07e27af75e3883ea9a4ef959
parent 6143f14e22aa10e3bd446858b859c7f6eccf840a
Author: Byron Torres <b@torresjrjr.com>
Date: Tue, 13 Dec 2022 05:50:11 +0000
add cmd_copy(), invaliddestination; fix cmd_move()
Diffstat:
3 files changed, 64 insertions(+), 8 deletions(-)
diff --git a/command.ha b/command.ha
@@ -27,17 +27,20 @@ type suffix = enum {
type error = !(
invalidaddress
| unexpectedaddress
+ | invaliddestination
| nofilename
| buffermodified
| fs::error
);
+type unexpectedaddress = !void;
+
+type invaliddestination = !void;
+
type nofilename = !void;
type buffermodified = !void;
-type unexpectedaddress = !void;
-
// Executes the session's .cmd command.
fn execute(s: *session, cmd: *command) (void | error) = {
// TODO: move this into the cmd_* functions?
@@ -297,19 +300,39 @@ fn cmd_move(s: *session, cmd: *command) (void | error) = {
const iter = strings::iter(cmd.arg);
const n = match (scan_addr(&iter)) {
case let addr: address =>
- yield exec_addr(s, addr)? + 1;
+ yield 1 + (match (exec_addr(s, addr)) {
+ case let n: size =>
+ yield n;
+ case invalidaddress =>
+ return invaliddestination;
+ });
case void =>
return invalidaddress;
};
debug("cmd_move(): n={}", n);
- // TODO: write buf_get(&buf, a, b) ?
+ if (a < n && n <= b) {
+ return invaliddestination;
+ };
+
+ if (n == b + 1) {
+ return;
+ };
+
+ const dest = if (n > b) {
+ yield n - (1 + b - a);
+ } else {
+ yield n;
+ };
+
const ls = alloc(s.buf.lines[a..b+1]...); defer free(ls);
// for (let i = 0z; i < len(ls); i += 1) {
// debug("cmd_move(): ls[{}].text='{}'", i, ls[i].text);
// };
buf_delete(&s.buf, a, b);
- buf_insert(&s.buf, n, ls...);
+ buf_insert(&s.buf, dest, ls...);
+
+ s.buf.cursor = dest - 1 + len(ls);
};
fn cmd_number(s: *session, cmd: *command) (void | error) = {
@@ -377,7 +400,38 @@ fn cmd_read(s: *session, cmd: *command) (void | error) = {
fn cmd_substitute(s: *session, cmd: *command) (void | error) = void;
-fn cmd_copy(s: *session, cmd: *command) (void | error) = void;
+fn cmd_copy(s: *session, cmd: *command) (void | error) = {
+ const (a, b) = get_range(
+ s,
+ &cmd.linenums,
+ s.buf.cursor,
+ s.buf.cursor,
+ )?;
+ assert_nonzero(s, a)?;
+
+ // TODO: parse this properly in parse.ha?
+ const iter = strings::iter(cmd.arg);
+ const dest = match (scan_addr(&iter)) {
+ case let addr: address =>
+ yield 1 + (match (exec_addr(s, addr)) {
+ case let n: size =>
+ yield n;
+ case invalidaddress =>
+ return invaliddestination;
+ });
+ case void =>
+ return invalidaddress;
+ };
+ debug("cmd_copy(): dest={}", dest);
+
+ const ls = alloc(s.buf.lines[a..b+1]...); defer free(ls);
+// for (let i = 0z; i < len(ls); i += 1) {
+// debug("cmd_copy(): ls[{}].text='{}'", i, ls[i].text);
+// };
+ buf_insert(&s.buf, dest, ls...);
+
+ s.buf.cursor = dest - 1 + len(ls);
+};
fn cmd_undo(s: *session, cmd: *command) (void | error) = void;
diff --git a/main.ha b/main.ha
@@ -134,6 +134,8 @@ fn errormsg(s: *session, err: error) error = {
yield "Buffer modified";
case unexpectedaddress =>
yield "Unexpected address";
+ case invaliddestination =>
+ yield "Invalid destination";
case let e: fs::error =>
yield fs::strerror(e);
};
diff --git a/parse.ha b/parse.ha
@@ -226,9 +226,9 @@ fn scan_cmdfn(iter: *strings::iterator) commandfn = {
case 'n' => return &cmd_number;
case 'p' => return &cmd_print;
// case 'q' => return &cmd_quit;
-// case 'r' => return &cmd_read;
+ case 'r' => return &cmd_read;
// case 's' => return &cmd_substitute;
-// case 't' => return &cmd_copy;
+ case 't' => return &cmd_copy;
// case 'u' => return &cmd_undo;
// case 'v' => return &cmd_invglobal;
case 'w' => return &cmd_write;