hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit 38e545ab95c3498c7d45288e14806daffd0e3435
parent 6297b8d4b472e662b9a650d2a77f56ed0d166d6f
Author: Autumn! <autumnull@posteo.net>
Date:   Sat, 27 May 2023 23:25:25 +0000

getopt: add subcommand context to errors

Signed-off-by: Autumn! <autumnull@posteo.net>

Diffstat:
Mgetopt/getopts.ha | 43++++++++++++++++++++++++-------------------
1 file changed, 24 insertions(+), 19 deletions(-)

diff --git a/getopt/getopts.ha b/getopt/getopts.ha @@ -58,34 +58,39 @@ export type subcmd_help = (str, []help); // -d <dflag>: d help text export type help = (cmd_help | flag_help | parameter_help | subcmd_help); -export type requires_arg = !rune; -export type unknown_option = !rune; -export type unknown_subcmd = !str; -export type error = !(requires_arg | unknown_option | unknown_subcmd); +export type requires_arg = rune; +export type unknown_option = rune; +export type unknown_subcmd = str; +export type error = !( + str, []help, + (requires_arg | unknown_option | unknown_subcmd), +); // A wrapper for [[tryparse]] in which if an error occurs, details are printed // to [[os::stderr]] and [[os::exit]] is called with a nonzero exit status. export fn parse(args: []str, help: help...) command = { - const cmd = args[0]; match (tryparse(args, help...)) { case let c: command => return c; - case let r: requires_arg => - fmt::errorfln("{}: option -{} requires an argument", cmd, r: rune)!; - case let r: unknown_option => - fmt::errorfln("{}: unrecognized option: -{}", cmd, r: rune)!; - case let s: unknown_subcmd => - fmt::errorfln("{}: unrecognized subcommand: {}", cmd, s: str)!; - printsubcmds(os::stderr, help)!; - fmt::errorln()!; + case let e: error => + match (e.2) { + case let r: requires_arg => + fmt::errorfln("{}: option -{} requires an argument", e.0, r: rune)!; + case let r: unknown_option => + fmt::errorfln("{}: unrecognized option: -{}", e.0, r: rune)!; + case let s: unknown_subcmd => + fmt::errorfln("{}: unrecognized subcommand: {}", e.0, s: str)!; + printsubcmds(os::stderr, e.1)!; + fmt::errorln()!; + }; + printusage(os::stderr, e.0, e.1)!; + os::exit(1); }; - printusage(os::stderr, args[0], help)!; - os::exit(1); }; // Parses command line arguments and returns a [[command]], or an [[error]] // if an error occurs. The argument list must include the command name as // the first item; [[os::args]] fulfills this criteria. -export fn tryparse(args: []str, help: help...) (command | ...error) = { +export fn tryparse(args: []str, help: help...) (command | error) = { let opts: [](rune, str) = []; let i = 1z; for (i < len(args); i += 1) :arg { @@ -118,7 +123,7 @@ export fn tryparse(args: []str, help: help...) (command | ...error) = { if (len(value) == 0) { if (i == len(args) - 1) { free(opts); - return r: requires_arg; + return (args[0], help, r: requires_arg): error; }; i += 1; append(opts, (r, args[i])); @@ -136,7 +141,7 @@ export fn tryparse(args: []str, help: help...) (command | ...error) = { os::exit(0); }; free(opts); - return r: unknown_option; + return (args[0], help, r: unknown_option): error; }; }; let subcmd: (void | (str, *command)) = void; @@ -156,7 +161,7 @@ export fn tryparse(args: []str, help: help...) (command | ...error) = { }; if (expects_subcmd && subcmd is void) { free(opts); - return args[i]: unknown_subcmd; + return (args[0], help, args[i]: unknown_subcmd): error; }; }; return command {