ed

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

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:
Mcommand.ha | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
Mmain.ha | 2++
Mparse.ha | 4++--
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;