aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile21
-rwxr-xr-xconfigure31
-rw-r--r--lettuce/README1
-rw-r--r--lettuce/expand/+test.ha5
-rw-r--r--lettuce/expand/README4
-rw-r--r--lettuce/expand/expand.ha67
-rw-r--r--readme.org13
8 files changed, 143 insertions, 0 deletions
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.