commit e741b8bd1d5c4129c3ece8a86789d551479a6f20
parent 905650984a0a7221922e40d5dd2702ad8aab4a5e
Author: Byron Torres <b@torresjrjr.com>
Date: Tue, 22 Nov 2022 20:46:50 +0000
add command.ha, util.ha, cmd_edit()
Diffstat:
5 files changed, 121 insertions(+), 10 deletions(-)
diff --git a/Makefile b/Makefile
@@ -4,6 +4,8 @@ HAREFLAGS=
source=\
main.ha \
buffer.ha \
+ command.ha \
+ util.ha \
all: ed
diff --git a/buffer.ha b/buffer.ha
@@ -1,7 +1,12 @@
+use bufio;
+use fmt;
+use io;
+use strings;
+
type buffer = struct {
filename: (void | str),
- lines: []line,
- trash: []line,
+ lines: []*line,
+ trash: []*line,
cursor: size,
};
@@ -10,3 +15,50 @@ type line = struct {
mark: rune,
globalmark: bool,
};
+
+fn buf_deleteall(buf: *buffer) void = {
+ buf_wipetrash(buf);
+
+ for (len(buf.lines) > 1) {
+ insert(buf.trash[0], buf.lines[1]);
+ delete(buf.lines[1]);
+ };
+};
+
+fn buf_read(buf: *buffer, src: io::handle, a: size) size = {
+ buf_wipetrash(buf);
+
+ let newlines: []*line = [];
+ let sz = 0z;
+ for (true) {
+ const bytes = match (bufio::scanline(src)) {
+ case let bs: []u8 =>
+ yield bs;
+ case io::EOF =>
+ break;
+ case =>
+ abort();
+ };
+
+ sz += len(bytes);
+ const text = strings::fromutf8(bytes)!;
+
+ append(newlines, alloc(line { text = text, ... }));
+ };
+
+ insert(buf.lines[a + 1], newlines...);
+ return sz;
+};
+
+fn buf_write(buf: *buffer, dest: io::handle, a: size, b: size) void = {
+ for (let n = a; n <= b; n += 1) {
+ fmt::fprintln(dest, buf.lines[n].text)!;
+ };
+};
+
+fn buf_wipetrash(buf: *buffer) void = {
+ for (len(buf.trash) > 0) {
+ free(buf.trash[0].text);
+ delete(buf.trash[0]);
+ };
+};
diff --git a/command.ha b/command.ha
@@ -0,0 +1,29 @@
+use fmt;
+use fs;
+use io;
+use os;
+
+fn cmd_edit(s: *session, file: (void | str)) void = {
+ if (file is void) {
+ if (s.buffer.filename is void) {
+ return errormsg(s, "No current filename");
+ };
+ } else {
+ s.buffer.filename = file;
+ };
+ const file = s.buffer.filename as str;
+
+ const h = match (os::open(file)) {
+ case let err: fs::error =>
+ return errormsg(s, fs::strerror(err));
+ case let h: io::file =>
+ yield h: io::handle;
+ };
+ defer io::close(h)!;
+
+ buf_deleteall(&s.buffer);
+ const sz = buf_read(&s.buffer, h, 0);
+ if (!s.suppressmode) {
+ fmt::println(sz)!;
+ };
+};
diff --git a/main.ha b/main.ha
@@ -22,16 +22,24 @@ export fn main() void = {
const cmd = getopt::parse(os::args, help...);
defer getopt::finish(&cmd);
- const sesh = session{ ... };
+ const s = session{
+ buffer = buffer{
+ filename = void,
+ lines = [ alloc(line{ ... }) ],
+ trash = [],
+ ...
+ },
+ ...
+ };
for (let i = 0z; i < len(cmd.opts); i += 1) {
const opt = cmd.opts[i];
switch (opt.0) {
case 'p' =>
- sesh.prompt = opt.1;
- sesh.promptmode = true;
+ s.prompt = opt.1;
+ s.promptmode = true;
case 's' =>
- sesh.suppressmode = true;
+ s.suppressmode = true;
};
};
@@ -39,24 +47,29 @@ export fn main() void = {
exit_usage(help);
};
- sesh.buffer.filename = if (len(cmd.args) == 1) {
- yield switch (cmd.args[0]) {
+ if (len(cmd.args) == 1) {
+ switch (cmd.args[0]) {
case "-" =>
fmt::fatal("Invalid filename '-'");
case "" =>
fmt::fatal("Invalid filename ''");
case =>
- yield cmd.args[0];
+ s.buffer.filename = cmd.args[0];
};
};
+ if (s.buffer.filename is str) {
+ cmd_edit(&s, s.buffer.filename as str);
+ };
+
for (true) :repl {
- fmt::error(sesh.prompt)!;
+ fmt::error(s.prompt)!;
const rawline = match (bufio::scanline(os::stdin)) {
case let rawline: []u8 =>
yield rawline;
case io::EOF =>
+ fmt::println()!;
break;
case =>
abort();
@@ -65,6 +78,8 @@ export fn main() void = {
const input = fmt::bsprint(rawline);
};
+
+ dumpbuffer(&s.buffer);
};
@noreturn fn exit_usage(help: []getopt::help) void = {
@@ -72,3 +87,9 @@ export fn main() void = {
os::exit(1);
};
+fn errormsg(s: *session, msgfmt: str, args: fmt::field...) void = {
+ fmt::errorln('?')!;
+ if (s.helpmode) {
+ fmt::errorfln(msgfmt)!;
+ };
+};
diff --git a/util.ha b/util.ha
@@ -0,0 +1,7 @@
+use fmt;
+
+fn dumpbuffer(buf: *buffer) void = {
+ for (let n = 1z; n < len(buf.lines); n += 1) {
+ fmt::printfln("{}\t{}", n, buf.lines[n].text)!;
+ };
+};