ed

[hare] The standard editor
Log | Files | Refs | README | LICENSE

commit 745358a0b088a584d2ab0a20ba0e1a403b4997da
parent 3411c624b4fc926d0426ae41e65aca083faada01
Author: Byron Torres <b@torresjrjr.com>
Date:   Thu, 28 Dec 2023 07:31:50 +0000

add strerror; fix write; propagate buffer errors

Diffstat:
Mbuffer.ha | 13++++++-------
Mcommand.ha | 18+++++++++---------
Mmain.ha | 37+++++++++++++++++++++----------------
3 files changed, 36 insertions(+), 32 deletions(-)

diff --git a/buffer.ha b/buffer.ha @@ -1,4 +1,5 @@ use bufio; +use encoding::utf8; use fmt; use io; use strings; @@ -42,24 +43,22 @@ fn buf_delete(buf: *Buffer, a: size, b: size) void = { delete(buf.lines[a..b+1]); }; -fn buf_read(buf: *Buffer, src: io::handle, a: size) (size, size) = { +fn buf_read(buf: *Buffer, src: io::handle, a: size) ((size, size) | io::error | encoding::utf8::invalid) = { // TODO: don't call this here, call it at a higher level // buf_wipetrash(buf); let ls: []*Line = []; let sz = 0z; for (true) { - const bytes = match (bufio::read_line(src)) { + const bytes = match (bufio::read_line(src)?) { case let bs: []u8 => yield bs; case io::EOF => break; - case => - abort(); }; sz += len(bytes) + 1; // TODO: handle newlines better - const text = strings::fromutf8(bytes)!; + const text = strings::fromutf8(bytes)?; append(ls, alloc(Line { text = text, ... })); }; @@ -69,10 +68,10 @@ fn buf_read(buf: *Buffer, src: io::handle, a: size) (size, size) = { return (sz, lenls); }; -fn buf_write(buf: *Buffer, dest: io::handle, a: size, b: size) size = { +fn buf_write(buf: *Buffer, dest: io::handle, a: size, b: size) (size | io::error) = { let sz = 0z; for (let n = a; n <= b; n += 1) { - sz += fmt::fprintln(dest, buf.lines[n].text)!; + sz += fmt::fprintln(dest, buf.lines[n].text)?; }; return sz; }; diff --git a/command.ha b/command.ha @@ -177,7 +177,7 @@ fn cmd_edit(s: *Session, cmd: *Command) (void | Error) = { defer io::close(h)!; buf_deleteall(&s.buf); - const (sz, _) = buf_read(&s.buf, h, 0); + const (sz, _) = buf_read(&s.buf, h, 0)?; if (!s.suppressmode) { fmt::println(sz)!; }; @@ -203,16 +203,16 @@ fn cmd_global_manual(s: *Session, cmd: *Command) (void | Error) = void; fn cmd_help(s: *Session, cmd: *Command) (void | Error) = { assert_noaddrs(s, cmd.linenums)?; - if (s.lasterror != "") { - fmt::println(s.lasterror)!; + if (s.lasterror is Error) { + fmt::println(strerror(s.lasterror as Error))!; }; }; fn cmd_helpmode(s: *Session, cmd: *Command) (void | Error) = { assert_noaddrs(s, cmd.linenums)?; s.helpmode = !s.helpmode; - if (s.helpmode && s.lasterror != "") { - fmt::println(s.lasterror)!; + if (s.helpmode && s.lasterror is Error) { + fmt::println(strerror(s.lasterror as Error))!; }; }; @@ -416,7 +416,7 @@ fn cmd_read(s: *Session, cmd: *Command) (void | Error) = { const h = os::open(fname)?: io::handle; defer io::close(h)!; - const (sz, _) = buf_read(&s.buf, h, n); + const (sz, _) = buf_read(&s.buf, h, n)?; if (!s.suppressmode) { fmt::println(sz)!; }; @@ -509,7 +509,7 @@ fn cmd_write(s: *Session, cmd: *Command) (void | Error) = { const (a, b) = get_range( s, &cmd.linenums, - addr_linenum(&s.buf, 1)!, + addr_linenum(&s.buf, 1)?, addr_lastline(&s.buf), )?; assert_nonzero(s, a)?; @@ -525,7 +525,7 @@ fn cmd_write(s: *Session, cmd: *Command) (void | Error) = { }; }; - const h = match (os::open(fname)) { + const h = match (os::open(fname, fs::flag::WRONLY)) { case let err: fs::error => yield match (err) { case errors::noentry => @@ -538,7 +538,7 @@ fn cmd_write(s: *Session, cmd: *Command) (void | Error) = { }; defer io::close(h)!; - const sz = buf_write(&s.buf, h, a, b); + const sz = buf_write(&s.buf, h, a, b)?; if (!s.suppressmode) { fmt::println(sz)!; }; diff --git a/main.ha b/main.ha @@ -12,7 +12,7 @@ type Session = struct { buf: Buffer, mode: Mode, helpmode: bool, - lasterror: str, + lasterror: (void | Error), suppressmode: bool, promptmode: bool, prompt: str, @@ -43,6 +43,7 @@ export fn main() void = { }, prompt = "*", prev_shcmd = void, + lasterror = void, ... }; @@ -144,29 +145,33 @@ fn exit_usage(help: []getopt::help) never = { fn errormsg(s: *Session, err: Error) Error = { fmt::errorln('?')!; - const msg = match (err) { + let errmsg = strerror(err); + if (s.helpmode) { + fmt::errorfln(errmsg)!; + }; + s.lasterror = err; + return err; +}; + +fn strerror(err: Error) str = { + match (err) { case InvalidAddress => - yield "Invalid address"; + return "Invalid address"; case NoFilename => - yield "No filename"; + return "No filename"; case BufferModified => - yield "Buffer modified"; + return "Buffer modified"; case UnexpectedAddress => - yield "Unexpected address"; + return "Unexpected address"; case InvalidDestination => - yield "Invalid destination"; + return "Invalid destination"; case NoMatch => - yield "No match"; + return "No match"; case NoPrevShCmd => - yield "No previous shell command"; + return "No previous shell command"; case let e: regex::error => - yield regex::strerror(e); + return regex::strerror(e); case let e: fs::error => - yield fs::strerror(e); - }; - s.lasterror = msg; - if (s.helpmode) { - fmt::errorfln(msg)!; + return fs::strerror(e); }; - return err; };