hautils

[hare] Set of POSIX utilities
Log | Files | Refs | README | LICENSE

commit 746f261aaf63a48ce2a1a147feecbff594f39d2f
parent e6e0c2c14e2bbb1b7de015e009cdfd793e68dab7
Author: Byron Torres <b@torresjrjr.com>
Date:   Mon, 12 Jun 2023 01:52:43 +0000

main: add usage()

Signed-off-by: Byron Torres <b@torresjrjr.com>

Diffstat:
Mbasename.ha | 3+--
Mdirname.ha | 3+--
Mhead.ha | 9++++++---
Mmain/main.ha | 23+++++++++++++++++++++++
Mnl.ha | 39+++++++++++++++------------------------
Msleep.ha | 9++-------
Muname.ha | 3+--
Muniq.ha | 5+----
Mwc.ha | 4++--
9 files changed, 52 insertions(+), 46 deletions(-)

diff --git a/basename.ha b/basename.ha @@ -13,8 +13,7 @@ export fn utilmain() (main::error | void) = { const cmd = getopt::parse(os::args, help...); defer getopt::finish(&cmd); if (len(cmd.args) != 1 && len(cmd.args) != 2) { - getopt::printusage(os::stderr, os::args[0], help); - os::exit(1); + main::usage(help); }; let basename = path::basename(cmd.args[0]); if (len(cmd.args) == 2) { diff --git a/dirname.ha b/dirname.ha @@ -14,8 +14,7 @@ export fn utilmain() (main::error | void) = { const cmd = getopt::parse(os::args, help...); defer getopt::finish(&cmd); if (len(cmd.args) != 1) { - getopt::printusage(os::stderr, os::args[0], help); - os::exit(1); + main::usage(help); }; fmt::println(path::dirname(cmd.args[0]))?; return void; diff --git a/head.ha b/head.ha @@ -9,8 +9,11 @@ use os; use strconv; export fn utilmain() (void | main::error) = { - const cmd = getopt::parse(os::args, "print the first lines of files", - ('n', "lines", "set the number of lines to print")); + const help: []getopt::help = [ + "print the first lines of files", + ('n', "lines", "print maximum number of lines"), + ]; + const cmd = getopt::parse(os::args, help...); defer getopt::finish(&cmd); let n = 10u; @@ -19,7 +22,7 @@ export fn utilmain() (void | main::error) = { // Only opt is -n n = match (strconv::stou(opt.1)) { case (strconv::invalid | strconv::overflow) => - fmt::fatal("Invalid number given for -n"); + main::usage(help, 'n'); case let n: uint => yield n; }; diff --git a/main/main.ha b/main/main.ha @@ -1,6 +1,8 @@ use fmt; use fs; +use getopt; use io; +use os; use os::exec; export type error = !(io::error | fs::error | exec::error); @@ -19,3 +21,24 @@ export @symbol("main") fn main() void = { case void => void; }; }; + +// Prints to stderr a flag error message if specified, then the program usage. +// Exists the program with error code 1. +export @noreturn fn usage(help: []getopt::help, flags: rune...) void = { + const progname = os::args[0]; + + if (len(flags) == 1) { + fmt::errorfln("{}: invalid argument for option -{}", + progname, flags[0])!; + } else if (len(flags) > 1) { + fmt::errorf("{}: invalid combination of options", + progname)!; + for (let i = 0z; i < len(flags); i += 1) { + fmt::errorf(" -{}", flags[i])!; + }; + fmt::errorln()!; + }; + + getopt::printusage(os::stderr, progname, help)!; + os::exit(1); +}; diff --git a/nl.ha b/nl.ha @@ -59,7 +59,7 @@ export fn utilmain() (void | main::error) = { defer getopt::finish(&cmd); if (len(cmd.args) > 1) { - usage(help, void); + main::usage(help); }; static const delim_buf: [3 * 2 * 4]u8 = [0...]; // 3 pairs of runes @@ -98,7 +98,7 @@ export fn utilmain() (void | main::error) = { case let re: regex::regex => yield re; case let err: regex::error => - fmt::fatal("Error: -bp<string>: {}", err); + fmt::fatalf("Error: -bp<string>: {}", err); }; } else { yield switch (opt.1) { @@ -109,7 +109,7 @@ export fn utilmain() (void | main::error) = { case "n" => yield none; case => - usage(help, 'b'); + main::usage(help, 'b'); }; }; case 'd' => @@ -121,7 +121,7 @@ export fn utilmain() (void | main::error) = { case 2 => yield opt.1; case => - usage(help, 'd'); + main::usage(help, 'd'); }; case 'f' => foot_style = if (strings::hasprefix(opt.1, "p")) { @@ -130,7 +130,7 @@ export fn utilmain() (void | main::error) = { case let re: regex::regex => yield re; case let err: regex::error => - fmt::fatal("Error: -fp<string>: {}", err); + fmt::fatalf("Error: -fp<string>: {}", err); }; } else { yield switch (opt.1) { @@ -141,7 +141,7 @@ export fn utilmain() (void | main::error) = { case "n" => yield none; case => - usage(help, 'f'); + main::usage(help, 'f'); }; }; case 'h' => @@ -151,7 +151,7 @@ export fn utilmain() (void | main::error) = { case let re: regex::regex => yield re; case let err: regex::error => - fmt::fatal("Error: -hp<string>: {}", err); + fmt::fatalf("Error: -hp<string>: {}", err); }; } else { yield switch (opt.1) { @@ -162,25 +162,25 @@ export fn utilmain() (void | main::error) = { case "n" => yield none; case => - usage(help, 'h'); + main::usage(help, 'h'); }; }; case 'i' => ctx.incr = match (strconv::stoi(opt.1)) { case (strconv::invalid | strconv::overflow) => - usage(help, 'i'); + main::usage(help, 'i'); case let incr: int => yield incr; }; case 'l' => ctx.maxblanks = match (strconv::stou(opt.1)) { case (strconv::invalid | strconv::overflow) => - usage(help, 'l'); + main::usage(help, 'l'); case let maxblanks: uint => yield if (maxblanks > 0) maxblanks else - usage(help, 'l'); + main::usage(help, 'l'); }; case 'n' => ctx.mod.padding = switch (opt.1) { @@ -191,24 +191,24 @@ export fn utilmain() (void | main::error) = { case "rz" => yield fmt::padding::ZEROES; case => - usage(help, 'n'); + main::usage(help, 'n'); }; case 's' => ctx.sep = opt.1; case 'w' => ctx.mod.width = match (strconv::stou(opt.1)) { case (strconv::invalid | strconv::overflow) => - usage(help, 'w'); + main::usage(help, 'w'); case let width: uint => yield if (width > 0) width else - usage(help, 'w'); + main::usage(help, 'w'); }; case 'v' => startnum = match (strconv::stoi(opt.1)) { case (strconv::invalid | strconv::overflow) => - usage(help, 'v'); + main::usage(help, 'v'); case let startnum: int => yield startnum; }; @@ -356,12 +356,3 @@ fn isblank(line: str) bool = { }; return true; }; - -@noreturn fn usage(help: []getopt::help, flag: (rune | void)) void = { - if (flag is rune) { - fmt::errorfln("{}: invalid option parameter for -{}", - os::args[0], flag: rune)!; - }; - getopt::printusage(os::stderr, os::args[0], help); - os::exit(1); -}; diff --git a/sleep.ha b/sleep.ha @@ -13,20 +13,15 @@ export fn utilmain() (void | main::error) = { defer getopt::finish(&cmd); if (len(cmd.args) != 1) { - usage(help); + main::usage(help); }; const seconds = match (strconv::stou(cmd.args[0])) { case (strconv::invalid | strconv::overflow) => - usage(help); + main::usage(help); case let s: uint => yield s: int; }; time::sleep(seconds * time::SECOND); }; - -@noreturn fn usage(help: []getopt::help) void = { - getopt::printusage(os::stderr, os::args[0], help); - os::exit(1); -}; diff --git a/uname.ha b/uname.ha @@ -26,8 +26,7 @@ export fn utilmain() (void | main::error) = { defer getopt::finish(&cmd); if (len(cmd.args) != 0) { - getopt::printusage(os::stderr, os::args[0], help); - os::exit(1); + main::usage(help); }; let flags: flags = if (len(cmd.opts) == 0) flags::IMPLNAME else 0; diff --git a/uniq.ha b/uniq.ha @@ -124,8 +124,7 @@ export fn utilmain() (main::error | void) = { case 's' => cfg.skipchars = match (strconv::stou(opt.1)) { case (strconv::invalid | strconv::overflow) => - getopt::printusage(os::stderr, os::args[0], help); - fmt::fatal("Error: invalid argument for -s"); + main::usage(help, 's'); case let skipchars: uint => yield skipchars; }; @@ -140,7 +139,6 @@ export fn utilmain() (main::error | void) = { if (len(cmd.args) >= 1 && cmd.args[0] != "-") { match (os::open(cmd.args[0])) { case let err: fs::error => - getopt::printusage(os::stderr, os::args[0], help); fmt::fatalf("Error opening '{}': {}", cmd.args[0], fs::strerror(err)); case let file: io::file => @@ -154,7 +152,6 @@ export fn utilmain() (main::error | void) = { if (len(cmd.args) == 2) { match (os::create(cmd.args[1], 0o666, fs::flags::WRONLY)) { case let err: fs::error => - getopt::printusage(os::stderr, os::args[0], help); fmt::fatalf("Error opening '{}': {}", cmd.args[1], fs::strerror(err)); case let file: io::file => diff --git a/wc.ha b/wc.ha @@ -45,12 +45,12 @@ export fn utilmain() (main::error | void) = { switch (opt.0) { case 'c' => if (mode & items::CHARS != 0) { - fmt::fatal("Error: -c and -m are mutually exclusive"); + main::usage(help, 'c', 'm'); }; mode |= items::BYTES; case 'm' => if (mode & items::BYTES != 0) { - fmt::fatal("Error: -c and -m are mutually exclusive"); + main::usage(help, 'c', 'm'); }; mode |= items::CHARS; case 'l' =>