commit 9d66bb8b11c00654db0abfa08997f71525d941aa
parent 61d21ca3316cfb7902f0572de6aa93b083426b99
Author: Drew DeVault <sir@cmpwn.com>
Date: Thu, 8 Jul 2021 15:00:53 -0400
head: new command
Diffstat:
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);