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:
M | Makefile | | | 2 | +- |
M | buffer.ha | | | 62 | ++++++++++++++++++++++++++++++++++++++++++++------------------ |
D | command.ha | | | 64 | ---------------------------------------------------------------- |
M | ed.ha | | | 12 | +++++++----- |
A | operation.ha | | | 78 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | parse.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",