ed

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

commit d5d23ab6a6497a337e79f55b3a1e4d80a454ff2b
parent 9508bae0bfd364cc1e60305b9c310dc836db18c9
Author: Byron Torres <b@torresjrjr.com>
Date:   Sat,  6 Jan 2024 12:43:52 +0000

add cmd_quit, Quit; for style

Diffstat:
Mbuffer.ha | 13+++++++++++--
Mcommand.ha | 61++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Minteraction.ha | 5++++-
Mmain.ha | 28++++++++++++++++------------
4 files changed, 89 insertions(+), 18 deletions(-)

diff --git a/buffer.ha b/buffer.ha @@ -10,6 +10,7 @@ type Buffer = struct{ trash: []*Line, cursor: size, modified: bool, + written: bool, }; type Line = struct{ @@ -29,6 +30,8 @@ fn buf_insert(buf: *Buffer, n: size, ls: *Line...) void = { // debug("buf_insert(): ls[{}].text='{}'", i, ls[i].text); // }; insert(buf.lines[n], ls...); + if (buf.written) + buf.modified = true; }; fn buf_deleteall(buf: *Buffer) void = { @@ -38,6 +41,8 @@ fn buf_deleteall(buf: *Buffer) void = { insert(buf.trash[0], buf.lines[1..]...); delete(buf.lines[1..]); }; + if (buf.written) + buf.modified = true; }; fn buf_delete(buf: *Buffer, a: size, b: size) void = { @@ -46,6 +51,8 @@ fn buf_delete(buf: *Buffer, a: size, b: size) void = { insert(buf.trash[0], buf.lines[a..b+1]...); delete(buf.lines[a..b+1]); + if (buf.written) + buf.modified = true; }; fn buf_read(buf: *Buffer, src: io::handle, a: size) ((size, size) | io::error | encoding::utf8::invalid) = { @@ -69,15 +76,17 @@ fn buf_read(buf: *Buffer, src: io::handle, a: size) ((size, size) | io::error | }; insert(buf.lines[a + 1], ls...); + if (buf.written) + buf.modified = true; const lenls = len(ls); return (sz, lenls); }; 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) { + for (let n = a; n <= b; n += 1) sz += fmt::fprintln(dest, buf.lines[n].text)?; - }; + buf.written = true; // TODO: move into cmd_write() ? return sz; }; diff --git a/command.ha b/command.ha @@ -105,6 +105,8 @@ fn lookupcmd(name: rune) CommandFn = { }; fn cmd_append(s: *Session, cmd: *Command) (void | Error) = { + s.warned = false; + const n = get_linenum(cmd.linenums, s.buf.cursor); for (let i = 0z; i < len(cmd.textinput); i += 1) { @@ -117,6 +119,8 @@ fn cmd_append(s: *Session, cmd: *Command) (void | Error) = { }; fn cmd_change(s: *Session, cmd: *Command) (void | Error) = { + s.warned = false; + const (a, b) = get_range( s, &cmd.linenums, @@ -150,6 +154,8 @@ fn cmd_change(s: *Session, cmd: *Command) (void | Error) = { }; fn cmd_delete(s: *Session, cmd: *Command) (void | Error) = { + s.warned = false; + const (a, b) = get_range( s, &cmd.linenums, @@ -172,7 +178,7 @@ fn cmd_edit(s: *Session, cmd: *Command) (void | Error) = { assert_noaddrs(s, cmd.linenums)?; if (s.buf.modified && !s.warned) { - s.warned = true; // TODO: reset this every Command somehow + s.warned = true; return BufferModified; }; @@ -205,6 +211,8 @@ fn cmd_edit(s: *Session, cmd: *Command) (void | Error) = { fn cmd_edit_forced(s: *Session, cmd: *Command) (void | Error) = void; fn cmd_filename(s: *Session, cmd: *Command) (void | Error) = { + s.warned = false; + assert_noaddrs(s, cmd.linenums)?; if (cmd.arg1 != "") { @@ -223,6 +231,8 @@ fn cmd_filename(s: *Session, cmd: *Command) (void | Error) = { }; fn cmd_global(s: *Session, cmd: *Command) (void | Error) = { + s.warned = false; + const (a, b) = get_range( s, &cmd.linenums, @@ -235,6 +245,8 @@ fn cmd_global(s: *Session, cmd: *Command) (void | Error) = { }; fn cmd_global_interative(s: *Session, cmd: *Command) (void | Error) = { + s.warned = false; + const (a, b) = get_range( s, &cmd.linenums, @@ -290,6 +302,8 @@ fn cmd_global_interative(s: *Session, cmd: *Command) (void | Error) = { }; fn cmd_help(s: *Session, cmd: *Command) (void | Error) = { + s.warned = false; + assert_noaddrs(s, cmd.linenums)?; if (s.lasterror is Error) { fmt::println(strerror(s.lasterror as Error))!; @@ -297,6 +311,8 @@ fn cmd_help(s: *Session, cmd: *Command) (void | Error) = { }; fn cmd_helpmode(s: *Session, cmd: *Command) (void | Error) = { + s.warned = false; + assert_noaddrs(s, cmd.linenums)?; s.helpmode = !s.helpmode; if (s.helpmode && s.lasterror is Error) { @@ -305,6 +321,8 @@ fn cmd_helpmode(s: *Session, cmd: *Command) (void | Error) = { }; fn cmd_insert(s: *Session, cmd: *Command) (void | Error) = { + s.warned = false; + const n = get_linenum(cmd.linenums, s.buf.cursor); const n = if (n == 0) 1z else n; @@ -322,6 +340,8 @@ fn cmd_insert(s: *Session, cmd: *Command) (void | Error) = { }; fn cmd_join(s: *Session, cmd: *Command) (void | Error) = { + s.warned = false; + const (a, b) = get_range( s, &cmd.linenums, @@ -356,6 +376,8 @@ fn cmd_join(s: *Session, cmd: *Command) (void | Error) = { }; fn cmd_mark(s: *Session, cmd: *Command) (void | Error) = { + s.warned = false; + const n = get_linenum(cmd.linenums, s.buf.cursor); assert_nonzero(s, n)?; @@ -393,6 +415,8 @@ fn cmd_mark(s: *Session, cmd: *Command) (void | Error) = { }; fn cmd_list(s: *Session, cmd: *Command) (void | Error) = { + s.warned = false; + const (a, b) = get_range( s, &cmd.linenums, @@ -407,6 +431,8 @@ fn cmd_list(s: *Session, cmd: *Command) (void | Error) = { }; fn cmd_move(s: *Session, cmd: *Command) (void | Error) = { + s.warned = false; + const (a, b) = get_range( s, &cmd.linenums, @@ -453,6 +479,8 @@ fn cmd_move(s: *Session, cmd: *Command) (void | Error) = { }; fn cmd_number(s: *Session, cmd: *Command) (void | Error) = { + s.warned = false; + const (a, b) = get_range( s, &cmd.linenums, @@ -467,6 +495,8 @@ fn cmd_number(s: *Session, cmd: *Command) (void | Error) = { }; fn cmd_print(s: *Session, cmd: *Command) (void | Error) = { + s.warned = false; + const (a, b) = get_range( s, &cmd.linenums, @@ -480,15 +510,28 @@ fn cmd_print(s: *Session, cmd: *Command) (void | Error) = { }; fn cmd_prompt(s: *Session, cmd: *Command) (void | Error) = { + s.warned = false; + assert_noaddrs(s, cmd.linenums)?; s.promptmode = !s.promptmode; }; -fn cmd_quit(s: *Session, cmd: *Command) (void | Error) = void; +fn cmd_quit(s: *Session, cmd: *Command) (void | Error) = { + if (s.buf.modified && !s.warned) { + s.warned = true; + return BufferModified; + }; -fn cmd_quit_forced(s: *Session, cmd: *Command) (void | Error) = void; + return Quit; +}; + +fn cmd_quit_forced(s: *Session, cmd: *Command) (void | Error) = { + return Quit; +}; fn cmd_read(s: *Session, cmd: *Command) (void | Error) = { + s.warned = false; + const n = get_linenum(cmd.linenums, s.buf.cursor); const fname = if (len(cmd.arg1) != 0) { s.buf.filename = cmd.arg1; @@ -512,6 +555,8 @@ fn cmd_read(s: *Session, cmd: *Command) (void | Error) = { }; fn cmd_substitute(s: *Session, cmd: *Command) (void | Error) = { + s.warned = false; + const (a, b) = get_range( s, &cmd.linenums, @@ -558,6 +603,8 @@ fn cmd_substitute(s: *Session, cmd: *Command) (void | Error) = { }; fn cmd_copy(s: *Session, cmd: *Command) (void | Error) = { + s.warned = false; + const (a, b) = get_range( s, &cmd.linenums, @@ -594,6 +641,8 @@ fn cmd_invglobal(s: *Session, cmd: *Command) (void | Error) = void; fn cmd_invglobal_interative(s: *Session, cmd: *Command) (void | Error) = void; fn cmd_write(s: *Session, cmd: *Command) (void | Error) = { + s.warned = false; + const (a, b) = get_range( s, &cmd.linenums, @@ -634,11 +683,15 @@ fn cmd_write(s: *Session, cmd: *Command) (void | Error) = { }; fn cmd_linenumber(s: *Session, cmd: *Command) (void | Error) = { + s.warned = false; + const n = get_linenum(cmd.linenums, addr_lastline(s.buf)); fmt::println(n)!; }; fn cmd_shellescape(s: *Session, cmd: *Command) (void | Error) = { + s.warned = false; + let iter = strings::iter(cmd.arg1); let new = memio::dynamic(); defer io::close(&new)!; let preview = false; @@ -703,6 +756,8 @@ fn cmd_shellescape(s: *Session, cmd: *Command) (void | Error) = { }; fn cmd_null(s: *Session, cmd: *Command) (void | Error) = { + s.warned = false; + const n = get_linenum( cmd.linenums, addr_nextline(s.buf, s.buf.cursor), diff --git a/interaction.ha b/interaction.ha @@ -6,11 +6,14 @@ use strings; use types; type InteractionError = !( - UnexpectedEOF + Quit + | UnexpectedEOF | utf8::invalid | io::error ); +type Quit = !void; + type UnexpectedEOF = !io::EOF; fn scanline(s: *Session) (str | InteractionError) = { diff --git a/main.ha b/main.ha @@ -96,16 +96,16 @@ export fn main() void = { errormsg(&s, strerror(err)); continue; }; + defer command_finish(&cmd); - // TODO: handle all ": void"s - execute(&s, &cmd): void; - - debug("main(): before command_finish()"); - command_finish(&cmd); - debug("main(): after command_finish()"); + match (execute(&s, &cmd)) { + case Quit => + debug("main() for match (exec) case Quit"); + break; + case => + void; + }; }; - - // dumpbuffer(&s.buf); }; fn exit_usage() never = { @@ -114,11 +114,13 @@ fn exit_usage() never = { }; fn errormsg(s: *Session, err: Error) void = { + if (err is Quit) + return; + fmt::errorln('?')!; - let errmsg = strerror(err); - if (s.helpmode) { - fmt::errorfln(errmsg)!; - }; + if (s.helpmode) + fmt::errorfln(strerror(err))!; + s.lasterror = err; }; @@ -127,6 +129,8 @@ fn strerror(err: Error) str = { // InteractionError case let e: InteractionError => match (e) { + case Quit => + return ""; case UnexpectedEOF => return "Unexpected end-of-file input"; case let e: encoding::utf8::invalid =>