commit 81e485347e54ba192989617f85ae4603552b7ed1
parent 9b41df58c8b5cba57a25866ce763c30c3a47eafb
Author: Byron Torres <b@torresjrjr.com>
Date: Mon, 13 Sep 2021 00:58:59 +0100
Use ranges and *fn for operations
Diffstat:
M | buffer.ha | | | 15 | +++++++++++++-- |
M | ed.ha | | | 11 | +---------- |
M | operation.ha | | | 44 | ++++++++++++++++++++++++++++++++++++++++++++ |
M | parse.ha | | | 48 | ++++++++++++++---------------------------------- |
M | util.ha | | | 26 | ++++++++++++++++++++++---- |
5 files changed, 94 insertions(+), 50 deletions(-)
diff --git a/buffer.ha b/buffer.ha
@@ -4,9 +4,11 @@ use fmt;
// Holds text and state.
type buffer = struct {
fname: filename,
- cur: cursor,
head: *linenode,
tail: *linenode,
+ cur: cursor,
+ range_a: *linenode,
+ range_b: *linenode,
};
// Represents a cursor.
@@ -43,6 +45,8 @@ fn new_buffer() *buffer = {
cur = cur,
head = head,
tail = tail,
+ range_a = head,
+ range_b = head,
});
};
@@ -119,7 +123,12 @@ fn buf_insert(buf: *buffer, otherbuf: *buffer) void = {
t.next = T;
buf.cur.node = t;
- // TODO: buf.cur.linenum = ???
+ buf.range_a = t;
+ buf.range_b = t;
+ // TODO: How to free buffer?
+ // free(otherbuf.head);
+ // free(otherbuf.tail);
+ free(otherbuf);
};
// Delete linenode h through t of buf.
@@ -154,4 +163,6 @@ fn buf_delete(buf: *buffer, h: *linenode, t: *linenode) void = {
tailnode => T.prev,
str => T,
};
+ buf.range_a = buf.cur.node;
+ buf.range_b = buf.cur.node;
};
diff --git a/ed.ha b/ed.ha
@@ -63,16 +63,7 @@ export fn main() void = {
for (let i = 0z; i < len(ops); i += 1) :ops {
const op = ops[i];
- // TODO: refactor ops into function pointers,
- // and move alias to func mapping to parse_cmd().
- switch (op.cmd_alias) {
- "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
- };
+ op.func(buf);
};
};
};
diff --git a/operation.ha b/operation.ha
@@ -76,3 +76,47 @@ fn op_delete(buf: *buffer) void = { // TODO
buf_delete(buf, h, t);
};
+// 'n' command
+fn op_numbered(buf: *buffer) void = {
+ const a = buf.range_a;
+ const b = buf.range_b;
+ let ln = a;
+ let n = find_linenum(buf, buf.range_a);
+
+ for (true) {
+ match (ln.value) {
+ headnode => void,
+ txt: str => fmt::printfln("{}\t{}", n, txt)?,
+ tailnode => break
+ };
+
+ if (ln == b) {
+ break;
+ };
+
+ ln = ln.next;
+ n += 1;
+ };
+};
+
+// 'p' command
+fn op_print(buf: *buffer) void = {
+ const a = buf.range_a;
+ const b = buf.range_b;
+ let ln = a;
+
+ for (true) {
+ match (ln.value) {
+ headnode => void,
+ txt: str => fmt::printfln("{}", txt)?,
+ tailnode => break
+ };
+
+ if (ln == b) {
+ break;
+ };
+
+ ln = ln.next;
+ };
+};
+
diff --git a/parse.ha b/parse.ha
@@ -17,14 +17,12 @@
use fmt;
-// Represents an intended action by a user to the main buffer.
-type operation = struct {
- optype: optype,
- cmd_alias: str, // command function name alias
- param_fname: filename,
+// Represents an intended operation by a user to the main buffer.
+type op = struct {
+ func: *fn(buf: *buffer) void,
};
-// Represents what kind of action a user intends to perform.
+// Represents what kind of operation a user intends to perform.
type optype = enum {
CMD, // execute a command
CUR_LINENUM, // move cursor to a line number
@@ -32,35 +30,17 @@ type optype = enum {
CUR_MARK, // move cursor to a mark
};
-// Parses command line input into intended operations.
-fn parse_cmd(cmd: str) []operation = {
- let ops: []operation = [];
+// Parses command line input into intended ops.
+fn parse_cmd(cmd: str) []op = {
+ let ops: []op = [];
switch (cmd) {
- "e" => append(ops, operation {
- optype = optype::CMD,
- cmd_alias = "e",
- param_fname = void, // TODO
- }),
- "r" => append(ops, operation {
- optype = optype::CMD,
- cmd_alias = "r",
- param_fname = void, // TODO
- }),
- "w" => append(ops, operation {
- optype = optype::CMD,
- 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",
- param_fname = void,
- }),
+ "e" => append(ops, op { func = &op_edit, }),
+ "r" => append(ops, op { func = &op_read, }),
+ "w" => append(ops, op { func = &op_write, }),
+ "d" => append(ops, op { func = &op_delete, }),
+ "n" => append(ops, op { func = &op_numbered, }),
+ "p" => append(ops, op { func = &op_print, }),
+ " p" => append(ops, op { func = &print_buffer, }), // DEBUG ONLY
* => void, // TODO
};
diff --git a/util.ha b/util.ha
@@ -2,18 +2,36 @@ use fmt;
// Sequencially prints lines of a buffer.
fn print_buffer(buf: *buffer) void = {
- let linenode = buf.head;
+ let ln = buf.head;
for (true) {
- match (linenode.value) {
+ match (ln.value) {
headnode => {
- linenode = linenode.next;
+ ln = ln.next;
},
s: str => {
fmt::println(s)?;
- linenode = linenode.next;
+ ln = ln.next;
},
tailnode => break
};
};
};
+fn find_linenum(buf: *buffer, ln: *linenode) size = {
+ let x = buf.head;
+ let n = 0z;
+
+ for (true) {
+ match (x.value) {
+ tailnode => abort("Unreachable"), // TODO: refactor?
+ (str | headnode) => if (x == ln) {
+ break;
+ } else {
+ n += 1;
+ x = x.next;
+ },
+ };
+ };
+
+ return n;
+};