ed

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

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:
Mbuffer.ha | 15+++++++++++++--
Med.ha | 11+----------
Moperation.ha | 44++++++++++++++++++++++++++++++++++++++++++++
Mparse.ha | 48++++++++++++++----------------------------------
Mutil.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; +};