sys

A set of unix utils in hare!
Log | Files | Refs | README

commit cd47ebf8e8ced89b6310c1463a6a178dae8e8e66
parent 06340e832c686eefef414710cdb5bc2fa405e1c9
Author: thing1 <thing1@seacrossedlovers.xyz>
Date:   Tue, 24 Feb 2026 12:09:52 +0000

added wc

Diffstat:
MMakefile | 11++++++++---
MTODO.md | 3+--
Acmd/rcsh/spec | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Acmd/split.ha | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Acmd/wc.ha | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mnewcmd.sh | 1+
6 files changed, 166 insertions(+), 5 deletions(-)

diff --git a/Makefile b/Makefile @@ -7,7 +7,7 @@ DESTDIR= PREFIX=/usr/local BINDIR=$(PREFIX)/bin -all: bin/ls bin/rainbow bin/cat bin/uniq +all: bin/ls bin/rainbow bin/cat bin/uniq bin/split bin/wc clean: rm -rf bin/* @@ -23,7 +23,12 @@ bin/rainbow: cmd/rainbow.ha bin/cat: cmd/cat.ha $(HARE) build $(HAREFLAGS) -o $@ cmd/cat.ha - - bin/uniq: cmd/uniq.ha $(HARE) build $(HAREFLAGS) -o $@ cmd/uniq.ha + +bin/split: cmd/split.ha + $(HARE) build $(HAREFLAGS) -o $@ cmd/split.ha + +bin/wc: cmd/wc.ha + $(HARE) build $(HAREFLAGS) -o $@ cmd/wc.ha + diff --git a/TODO.md b/TODO.md @@ -1,6 +1,5 @@ -- split +- yes - fmt -- wc - build system - shell - redo ls's colors in a more idiomatic way diff --git a/cmd/rcsh/spec b/cmd/rcsh/spec @@ -0,0 +1,50 @@ +rcsh - the "really cool shell" + +BNF: + +prog : imports fns exprs + +imports : import imports + | import + +import : "import" NAME + +fns : fn fns + | fn + +fn : "func" NAME(args) '{' exprs '}' + +args : arg ',' args + | arg + +arg : NAME + +exprs : expr exprs + | expr + +expr : fcall + | try '{' exprs '}' catch '{' exprs '}' + | "throw" except + | value '>' '{' exprs '}' // makes exprs stdin NAME + | value '<' '{' exprs '}' // makes exprs stdout NAME + | value '<' '<' '{' exprs '}' // makes exprs stdout NAME (append) + | value '<>' '{' exprs '}' // makes exprs stdin and stdout NAME + | expr | value + | expr > value + | expr < value + | expr >> value + | NAME '=' value + | cd value + + +value : '$' NAME + | STRING + | $(expr) // makes stdout the value + | fcall + +fcall : NAME '(' values ')' + +values : value, values + | value + +except : EPERM | ENOENT | ESRCH | EINTR | EIO | ENXIO | E2BIG | ENOEXEC | EBADF | ECHILD | EAGAIN | ENOMEM | EACCES | EFAULT | ENOTBLK | EBUSY | EEXIST | EXDEV | ENODEV | ENOTDIR | EISDIR | EINVAL | ENFILE | EMFILE | ENOTTY | ETXTBSY | EFBIG | ENOSPC | ESPIPE | EROFS | EMLINK | EPIPE | EDOM | ERANGE | EDEADLK | ENAMETOOLONG | ENOLCK | ENOSYS | ENOTEMPTY | ELOOP | ENOMSG | EIDRM | ECHRNG | EL2NSYNC | EL3HLT | EL3RST | ELNRNG | EUNATCH | ENOCSI | EL2HLT | EBADE | EBADR | EXFULL | ENOANO | EBADRQC | EBADSLT | EBFONT | ENOSTR | ENODATA | ETIME | ENOSR | ENONET | ENOPKG | EREMOTE | ENOLINK | EADV | ESRMNT | ECOMM | EPROTO | EMULTIHOP | EDOTDOT | EBADMSG | EOVERFLOW | ENOTUNIQ | EBADFD | EREMCHG | ELIBACC | ELIBBAD | ELIBSCN | ELIBMAX | ELIBEXEC | EILSEQ | ERESTART | ESTRPIPE | EUSERS | ENOTSOCK | EDESTADDRREQ | EMSGSIZE | EPROTOTYPE | ENOPROTOOPT | EPROTONOSUPPORT | ESOCKTNOSUPPORT | EOPNOTSUPP diff --git a/cmd/split.ha b/cmd/split.ha @@ -0,0 +1,49 @@ +use fmt; +use io; +use os; +use strings; +use bufio; +use encoding::utf8; +use getopt; + +use util; + +let delim = " "; + +fn run() void = { + let sc = bufio::newscanner(os::stdin); + defer bufio::finish(&sc); + + for (true) { + match (bufio::scan_string(&sc, delim)) { + case let s: str => fmt::println(s)!; + case io::EOF => break; + case let e: io::error => util::die(io::strerror(e)); + }; + }; + + match (bufio::scan_line(&sc)) { + case let s: str => fmt::println(s)!; + case io::EOF => return; + case let e: io::error => util::die(io::strerror(e)); + case let e: utf8::invalid => util::die(utf8::strerror(e)); + }; +}; + +export fn main() void = { + let cmd = getopt::parse(os::args, + "split", + ('d', "delim", "set a deliminer between tokens"), + ); + defer getopt::finish(&cmd); + + for (let opt .. cmd.opts) { + switch (opt.0) { + case 'd' => + delim = util::escape(opt.1); + case => abort(); + }; + }; + + run(); +}; diff --git a/cmd/wc.ha b/cmd/wc.ha @@ -0,0 +1,57 @@ +use fmt; +use io; +use os; +use strings; +use bufio; +use encoding::utf8; +use getopt; + +use util; + +let delim = " "; + +fn run() size = { + let sc = bufio::newscanner(os::stdin); + defer bufio::finish(&sc); + + let count = 0z; + + for (true) { + match (bufio::scan_string(&sc, delim)) { + case let s: str => + let ss = strings::split(s, "\n")!; + count += len(ss); + free(ss); + case io::EOF => return count + 1; + case let e: io::error => util::die(io::strerror(e)); + }; + }; +}; + +export fn main() void = { + let cmd = getopt::parse(os::args, + "word count", + ('l', "count lines"), + ('w', "count words (default)"), + ('c', "count charaters"), + ); + defer getopt::finish(&cmd); + + for (let opt .. cmd.opts) { + switch (opt.0) { + case 'l' => delim = "\n"; + case 'w' => delim = " "; + case 'c' => delim = ""; + case => abort(); + }; + }; + + if (len(delim) == 0) { + free(match (io::drain(os::stdin)) { + case let buf: []u8 => + fmt::println(len(buf))!; + yield buf; + case let e: io::error => util::die(io::strerror(e)); + }); + } else fmt::println(run())!; +}; diff --git a/newcmd.sh b/newcmd.sh @@ -2,3 +2,4 @@ echo "bin/$1: cmd/$1.ha" echo " \$(HARE) build \$(HAREFLAGS) -o \$@ cmd/$1.ha" +echo