ed

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit ef9ea186acb7f6e90a631d897c04095adb8fed2c
parent d5902aae514af4fa2197f0908888e8e4eb3e93cc
Author: Byron Torres <b@torresjrjr.com>
Date:   Sun, 12 Sep 2021 19:12:31 +0100

Rename command.ha > operation.ha; Add buf_delete()

Diffstat:
MMakefile | 2+-
Mbuffer.ha | 62++++++++++++++++++++++++++++++++++++++++++++------------------
Dcommand.ha | 64----------------------------------------------------------------
Med.ha | 12+++++++-----
Aoperation.ha | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mparse.ha | 5+++++
6 files changed, 135 insertions(+), 88 deletions(-)

diff --git a/Makefile b/Makefile @@ -4,7 +4,7 @@ HAREFLAGS= source=\ ed.ha \ buffer.ha \ - command.ha \ + operation.ha \ parse.ha \ util.ha diff --git a/buffer.ha b/buffer.ha @@ -3,6 +3,7 @@ use fmt; // Holds text and state. type buffer = struct { + fname: filename, cur: cursor, head: *linenode, tail: *linenode, @@ -103,28 +104,53 @@ fn buf_write(buf: *buffer, dest: *io::stream) size = { }; // Inserts the contents of b into buf where buf.cur points at. -fn buf_insert(buf: *buffer, b: *buffer) void = { - const localhead = buf.cur.node; - const localtail = localhead.next; +fn buf_insert(buf: *buffer, otherbuf: *buffer) void = { + const h = otherbuf.head.next; + const t = otherbuf.tail.prev; - let prevnode = localhead; - let ln = b.head; + const H = buf.cur.node; + const T = H.next; - for (true) { - match (ln.value) { - headnode => { - ln = ln.next; - }, - text: str => { - ln.prev = prevnode; + H.next = h; + h.prev = H; - prevnode.next = ln; - localtail.prev = ln; + T.prev = t; + t.next = T; - prevnode = ln; - ln = ln.next; - }, - tailnode => break + buf.cur.node = t; + // TODO: buf.cur.linenum = ??? +}; + +// Delete linenode h through t of buf. +fn buf_delete(buf: *buffer, h: *linenode, t: *linenode) void = { + if (!(h.value is str) || !(t.value is str)) { + abort("Internal: Invalid range"); // TODO: return error + }; + + const H = h.prev; + const T = t.next; + + H.next = T; + T.prev = H; + + t.next = h; // unnecessary but just in case + + let ln = h; + let nextnode = ln.next; + + for (true) { + if (ln == t) { + free(ln); + break; }; + + nextnode = ln.next; + free(ln); + ln = nextnode; + }; + + buf.cur.node = match (T.value) { + tailnode => T.prev, + str => T, }; }; diff --git a/command.ha b/command.ha @@ -1,64 +0,0 @@ -use os; -use fmt; -use fs; - -// 'e' command -fn cmd_edit(buf: *buffer, fname: filename) void = { - const n = match (fname) { - void => abort("TODO"), - fname: str => match (os::open(fname)) { - err: fs::error => fmt::fatal("Error {}", fs::strerror(err)), - f: io::file => buf_read(buf, &f), - }, - }; - - if (!surpress) { - fmt::println(n)?; - }; -}; - -// 'w' command -fn cmd_write(buf: *buffer, fname: filename) void = { - const mode = fs::mode::USER_RW | fs::mode::GROUP_R | fs::mode::OTHER_R; - const flags = [ - fs::flags::WRONLY, - fs::flags::TRUNC, - fs::flags::NOCTTY, - fs::flags::CLOEXEC, - ]; - const file = match (fname) { - void => abort("TODO"), - fname: str => match (os::open(fname, flags...)) { - fs::error => match (os::create(fname, mode)) { - err: fs::error => fmt::fatal("Error {}", fs::strerror(err)), - f: io::file => f, - }, - f: io::file => f, - }, - }; - - const n = buf_write(buf, &file); - if (!surpress) { - fmt::println(n)?; - }; - -}; - -// 'r' command -fn cmd_read(buf: *buffer, fname: filename) void = { - const scratch = new_buffer(); - const n = match (fname) { - void => abort("TODO"), - fname: str => match (os::open(fname)) { - err: fs::error => fmt::fatal("Error {}", fs::strerror(err)), - f: io::file => buf_read(scratch, &f), - }, - }; - - buf_insert(buf, scratch); - - if (!surpress) { - fmt::println(n)?; - }; -}; - diff --git a/ed.ha b/ed.ha @@ -42,9 +42,10 @@ export fn main() void = { }; const buf = new_buffer(); + buf.fname = fname; - if (fname is str) { - cmd_edit(buf, fname); + if (buf.fname is str) { + op_edit(buf); }; for (true) :repl { @@ -63,9 +64,10 @@ export fn main() void = { for (let i = 0z; i < len(ops); i += 1) :ops { const op = ops[i]; switch (op.cmd_alias) { - "e" => cmd_edit(buf, fname), - "r" => cmd_read(buf, fname), - "w" => cmd_write(buf, fname), + "e" => op_edit(buf), + "r" => op_read(buf), + "w" => op_write(buf), + "d" => op_delete(buf), " p" => print_buffer(buf), // DEBUG ONLY * => continue :repl // TODO: do user-error }; diff --git a/operation.ha b/operation.ha @@ -0,0 +1,78 @@ +use os; +use fmt; +use fs; + +// 'e' command +fn op_edit(buf: *buffer) void = { + const scratch = new_buffer(); + const n = match (buf.fname) { + void => abort("TODO"), + fname: str => match (os::open(fname)) { + err: fs::error => fmt::fatal("Error {}", fs::strerror(err)), + f: io::file => buf_read(scratch, &f), + }, + }; + + if (!(buf.head.next.value is tailnode)) { + buf_delete(buf, buf.head.next, buf.tail.prev); + }; + buf_insert(buf, scratch); + + if (!surpress) { + fmt::println(n)?; + }; +}; + +// 'w' command +fn op_write(buf: *buffer) void = { + const mode = fs::mode::USER_RW | fs::mode::GROUP_R | fs::mode::OTHER_R; + const flags = [ + fs::flags::WRONLY, + fs::flags::TRUNC, + fs::flags::NOCTTY, + fs::flags::CLOEXEC, + ]; + const file = match (buf.fname) { + void => abort("TODO"), + fname: str => match (os::open(fname, flags...)) { + fs::error => match (os::create(fname, mode)) { + err: fs::error => fmt::fatal("Error {}", fs::strerror(err)), + f: io::file => f, + }, + f: io::file => f, + }, + }; + + const n = buf_write(buf, &file); + if (!surpress) { + fmt::println(n)?; + }; + +}; + +// 'r' command +fn op_read(buf: *buffer) void = { + const scratch = new_buffer(); + const n = match (buf.fname) { + void => abort("TODO"), + fname: str => match (os::open(fname)) { + err: fs::error => fmt::fatal("Error {}", fs::strerror(err)), + f: io::file => buf_read(scratch, &f), + }, + }; + + buf_insert(buf, scratch); + + if (!surpress) { + fmt::println(n)?; + }; +}; + +// 'd' command +fn op_delete(buf: *buffer) void = { // TODO + const h = buf.cur.node; + const t = buf.cur.node; + + buf_delete(buf, h, t); +}; + diff --git a/parse.ha b/parse.ha @@ -51,6 +51,11 @@ fn parse_cmd(cmd: str) []operation = { cmd_alias = "w", param_fname = void, // TODO }), + "d" => append(ops, operation { + optype = optype::CMD, + cmd_alias = "d", + param_fname = void, // TODO + }), " p" => append(ops, operation { // DEBUG ONLY optype = optype::CMD, cmd_alias = " p",