From 3bf3455924006c8ea81d5f269d5307f97490c267 Mon Sep 17 00:00:00 2001 From: winter Sparkles Date: Mon, 24 Aug 2026 00:44:14 +0100 Subject: initial commit we have 'expand::home' --- .gitignore | 1 + Makefile | 21 +++++++++++++++ configure | 31 ++++++++++++++++++++++ lettuce/README | 1 + lettuce/expand/+test.ha | 5 ++++ lettuce/expand/README | 4 +++ lettuce/expand/expand.ha | 67 ++++++++++++++++++++++++++++++++++++++++++++++++ readme.org | 13 ++++++++++ 8 files changed, 143 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100755 configure create mode 100644 lettuce/README create mode 100644 lettuce/expand/+test.ha create mode 100644 lettuce/expand/README create mode 100644 lettuce/expand/expand.ha create mode 100644 readme.org diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aee2e4c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +config.mk diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..fe5c30f --- /dev/null +++ b/Makefile @@ -0,0 +1,21 @@ +include config.mk + +ifdef USE_ASAN +LDFLAGS += -fsanitize=address +export LDFLAGS +HAREFLAGS += -lc +endif + +all: + +check: + $(HARE) test $(HAREFLAGS) + +install: + mkdir -p $(DESTDIR)$(THIRDPARTYDIR)/lettuce/ + cp -R lettuce/* $(DESTDIR)$(THIRDPARTYDIR)/lettuce/ + +uninstall: + rm -rf $(DESTDIR)$(THIRDPARTYDIR)/lettuce/ + +.PHONY: check install uninstall diff --git a/configure b/configure new file mode 100755 index 0000000..dd20e46 --- /dev/null +++ b/configure @@ -0,0 +1,31 @@ +#!/bin/sh +# behold my awful terrible fake configure script + +cd "$(dirname "$0")" || exit 1 + +# put in variables as given by long options +# e.g. --my-option=/usr becomes MY_OPTION=/usr +for arg in "$@"; do + without_dashes="${arg#--}" + name="${without_dashes%%=*}" + name="${name//-/_}" + value="${without_dashes#*=}" + echo "${name^^}:=${value}" +done > config.mk + +# and here are some defaults in case nobody bothered to pass options +cat >>config.mk <<'EOF' +HARE ?= hare +DESTDIR ?= +PREFIX ?= /usr/local +SRCDIR ?= $(PREFIX)/src +HARESRCDIR ?= $(SRCDIR)/hare +THIRDPARTYDIR ?= $(HARESRCDIR)/third-party +EOF + +# TODO: parse --host/--target/--build into appropriate hare architecture ? + +# i feel like i need to say something on completion, because this script is so +# much faster and quieter than real autoconf configure, you might think it +# didn't do anything otherwise +echo 'configure: done' 1>&2 diff --git a/lettuce/README b/lettuce/README new file mode 100644 index 0000000..939e792 --- /dev/null +++ b/lettuce/README @@ -0,0 +1 @@ +lettuce: miscellaneous useful routines diff --git a/lettuce/expand/+test.ha b/lettuce/expand/+test.ha new file mode 100644 index 0000000..5a9a806 --- /dev/null +++ b/lettuce/expand/+test.ha @@ -0,0 +1,5 @@ +use os; + +@init fn setup_testenv() void = { + os::setenv("HOME", "/home/test")!; +}; diff --git a/lettuce/expand/README b/lettuce/expand/README new file mode 100644 index 0000000..a43ca99 --- /dev/null +++ b/lettuce/expand/README @@ -0,0 +1,4 @@ +expand: shell-style path/variable expansion + +Kind of like using [[wordexp::]], except it doesn't spawn a shell and doesn't +mess up all your whitespace. diff --git a/lettuce/expand/expand.ha b/lettuce/expand/expand.ha new file mode 100644 index 0000000..8661858 --- /dev/null +++ b/lettuce/expand/expand.ha @@ -0,0 +1,67 @@ +use os; +use strings; +use unix::passwd; + +use fmt; + +// Replace prefixes of a string with user's home directory à la posix. +// The caller must free the return value. +// +// - ~ (at the start) becomes the value of HOME environment variable +// - ~user (at the start) becomes the homedir of said user (via a passwd lookup) +export fn home(in: str) (str | nomem) = { + let prefix = ""; + let suffix = in; + let freeprefix = false; + + if (in == "~" || strings::hasprefix(in, "~/")) { + // simple $HOME expansion + suffix = strings::trimprefix(in, "~"); + prefix = match (os::getenv("HOME")) { + case void => yield "."; // TODO: use passwd lookup in this case + case let path: str => yield path; + }; + } else if (strings::hasprefix(in, "~")) { + // passwd lookup + const substr = strings::trimprefix(in, "~"); + const user = strings::cut(substr, "/").0; + prefix = match (passwd::getuser(user)?) { + case void => yield "."; // TODO: ??? + case let pw: passwd::pwent => + defer passwd::pwent_finish(&pw); + freeprefix = true; + yield strings::dup(pw.homedir)?; + }; + suffix = strings::bytesub(substr, len(user), strings::end)!; + }; + + const result = strings::concat(prefix, suffix); + if (freeprefix) free(prefix); + return result; +}; + +@test fn justhome() void = { + const cooked = home("~")!; + defer free(cooked); + assert(cooked == "/home/test"); +}; + +@test fn simplehome() void = { + const cooked = home("~/foo/bar.xyz")!; + defer free(cooked); + assert(cooked == "/home/test/foo/bar.xyz"); + + const cooked = home("meow/~/woof")!; + defer free(cooked); + assert(cooked == "meow/~/woof"); +}; + +@test fn roothome() void = { + const cooked = home("~root/meow")!; + defer free(cooked); + assert(cooked == "/root/meow"); + + const cooked = home("~root")!; + defer free(cooked); + assert(cooked == "/root"); +}; diff --git a/readme.org b/readme.org new file mode 100644 index 0000000..bff74da --- /dev/null +++ b/readme.org @@ -0,0 +1,13 @@ +#+title: lettuce +#+author: winter Sparkles + +"lettuce" is a collection of generally useful routines for hare programmes. or, +you can think of it as extra stuff i would put in the standard library if i was +in charge of the standard library. + +as with any hare module, consult haredoc for documentation (or just read the +comments next to each function in the source code). + +* installation +the usual incantation: =./configure=, =doas make install=. =make check= runs +tests. -- cgit v1.3