ed

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

commit 9c424f72cc0e2c42ae646ed84f3dff3c22d50f7d
parent bf56170ec27ec0f4877c419a921fcdea61951750
Author: Byron Torres <b@torresjrjr.com>
Date:   Sat,  6 Jan 2024 21:08:54 +0000

add error for invalid global subcmd

Diffstat:
Mbuffer.ha | 4++++
Mcommand.ha | 35++++++++++++++++++++++-------------
Mmain.ha | 12++++++++----
3 files changed, 34 insertions(+), 17 deletions(-)

diff --git a/buffer.ha b/buffer.ha @@ -49,6 +49,10 @@ fn buf_delete(buf: *Buffer, a: size, b: size) void = { debug("buf_delete(a={}, b={})", a, b); // buf_wipetrash(buf); + // The G command requires changed lines to be unmarked. + // Command functions "change" lines using buf_delete() first. + // If a line is trashed, it is effectively unmarked. + // The G command function unmarks all lines first anyway. //for (let i = 0z; i < len(buf.lines); i += 1) { // buf.lines[i].globalmark = false; //}; diff --git a/command.ha b/command.ha @@ -38,6 +38,8 @@ type CmdError = !( | BufferModified | NoMatch | NoPrevShCmd + | NoPrevGlobalSubCmd + | InvalidGlobalSubCmd | regex::error | fs::error ); @@ -52,6 +54,10 @@ type BufferModified = !void; type NoPrevShCmd = !void; +type NoPrevGlobalSubCmd = !void; + +type InvalidGlobalSubCmd = !rune; + fn command_finish(cmd: *Command) void = { //debug("command_finish(): delete(cmd.linenums[..])"); delete(cmd.linenums[..]); @@ -280,7 +286,7 @@ fn cmd_global_interative(s: *Session, cmd: *Command) (void | Error) = { }; }; - let prevsubcmd: (void | Command) = void; + let prevsubcmd: (void | Command) = void; // TODO: handle mem for :marks (true) { // find next global-marked line @@ -298,19 +304,26 @@ fn cmd_global_interative(s: *Session, cmd: *Command) (void | Error) = { fmt::println(line.text)!; - let subcmd = parse(s.input)!; + // TODO: handle termination by SIGINT signal + + // TODO: handle mem + // TODO: just use 'parse()?' when compiler allows + //let subcmd = parse(s.input)?; + let subcmd = match (parse(s.input)) { + case let c: Command => + yield c; + case let e: ParseError => + return e; + case let e: InteractionError => + return e; + }; // write new parse_global_interactive() function instead // as to avoid reading multiple lines in the case of // 'a', 'c', 'i' ? switch (subcmd.cmdname) { case 'a', 'c', 'i', 'g', 'G', 'v', 'V' => - // TODO: how to handle? - // return !InvalidGlobalInteractiveSubcmd; ? - fmt::printfln( - "Error: Invalid interactive global subcommand '{}'", - subcmd.cmdname, - )!; + errormsg(s, subcmd.cmdname: InvalidGlobalSubCmd); continue; case NUL => line.globalmark = false; @@ -318,8 +331,7 @@ fn cmd_global_interative(s: *Session, cmd: *Command) (void | Error) = { case '&' => match (prevsubcmd) { case void => - // TODO: return NoPrevGlobalSubCmd; - abort("global interactive: &: no previous command"); + return NoPrevGlobalSubCmd; case let prevsubcmd: Command => subcmd = prevsubcmd; }; @@ -332,9 +344,6 @@ fn cmd_global_interative(s: *Session, cmd: *Command) (void | Error) = { execute(s, &subcmd)?; - // TODO: test if line was modified. - // TODO: make cmd_ functions save to session whether line was - // modified, instead of here? line.globalmark = false; }; }; diff --git a/main.ha b/main.ha @@ -22,7 +22,7 @@ type Session = struct{ prev_shcmd: (str | void), }; -type Error = !(...InteractionError | ParseError | CmdError); +type Error = !(...InteractionError | ...ParseError | ...CmdError); def help: [_]getopt::help = [ "standard line editor", @@ -99,7 +99,7 @@ export fn main() void = { defer command_finish(&cmd); if (cmd.cmdname == '&') { - errormsg(&s, strerror('&': UnknownCommand)); + errormsg(&s, '&': UnknownCommand); continue; }; @@ -158,14 +158,18 @@ fn strerror(err: Error) str = { return "No match"; case NoPrevShCmd => return "No previous shell command"; + case NoPrevGlobalSubCmd => + return "No previous global subcommand"; + case let e: InvalidGlobalSubCmd => + return "Invalid interactive global subcommand"; // TODO: append 'e'? case let e: regex::error => return regex::strerror(e); case let e: fs::error => debug("foo"); return fs::strerror(e); // ParseError - case UnknownCommand => - return "Unknown command"; + case let e: UnknownCommand => + return "Unknown command"; // TODO: append 'e'? case UnexpectedSuffix => return "Unexpected suffix"; case TrailingCharacters =>