hautils

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 9d66bb8b11c00654db0abfa08997f71525d941aa
parent 61d21ca3316cfb7902f0572de6aa93b083426b99
Author: Drew DeVault <sir@cmpwn.com>
Date:   Thu,  8 Jul 2021 15:00:53 -0400

head: new command

Diffstat:
M.gitignore | 1+
MMakefile | 2++
Ahead.ha | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mmain/main.ha | 2+-
4 files changed, 61 insertions(+), 1 deletion(-)

diff --git a/.gitignore b/.gitignore @@ -3,3 +3,4 @@ false true tee uname +head diff --git a/Makefile b/Makefile @@ -5,6 +5,7 @@ HARE=hare utils=\ cat \ false \ + head \ tee \ true \ uname @@ -22,6 +23,7 @@ clean: cat: cat.ha main/main.ha false: false.ha +head: head.ha tee: tee.ha true: true.ha uname: uname.ha diff --git a/head.ha b/head.ha @@ -0,0 +1,57 @@ +use bufio; +use errors; +use fmt; +use fs; +use getopt; +use io; +use main; +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")); + defer getopt::finish(&cmd); + + let n = 10u; + for (let i = 0z; i < len(cmd.opts); i += 1) { + const opt = cmd.opts[i]; + // Only opt is -n + n = match (strconv::stou(opt.1)) { + (strconv::invalid | strconv::overflow) => + fmt::fatal("Invalid number given for -n"), + n: uint => n, + }; + }; + + if (len(cmd.args) == 0) { + head(os::stdin, n)?; + }; + + for (let i = 0z; i < len(cmd.args); i += 1) { + const file = match (os::open(cmd.args[i])) { + err: fs::error => fmt::fatal("Error opening '{}': {}", + cmd.args[i], fs::strerror(err)), + file: *io::stream => file, + }; + defer io::close(file); + head(file, n)?; + }; +}; + +fn head(in: *io::stream, n: uint) (void | main::error) = { + static let buf: [os::BUFSIZ]u8 = [0...]; + const in = bufio::buffered(in, buf, []); + defer io::close(in); + + for (n > 0; n -= 1) { + let line = match (bufio::scanline(in)) { + err: io::error => return err, + io::EOF => break, + line: []u8 => line, + }; + defer free(line); + io::write(os::stdout, line)?; + fmt::println()?; + }; +}; diff --git a/main/main.ha b/main/main.ha @@ -2,7 +2,7 @@ use fmt; use fs; use io; -export type error = (io::error | fs::error); +export type error = !(io::error | fs::error); @symbol("utilmain") fn utilmain() (main::error | void);