Expose lush global as a standard library (issue #26)

Register luaopen_lush() in stdlibs so the lush table is available as a
global. Users can now extend the shell by adding functions to
lush.builtins. The OP_LUSH VM access via integer keys is preserved.
This commit is contained in:
Cormac Shannon
2026-03-18 09:52:56 +00:00
parent 1766e40a68
commit 768de9fe8b
6 changed files with 161 additions and 24 deletions

111
testes/lush/lushlib.lua Normal file
View File

@@ -0,0 +1,111 @@
-- testes/lush/lushlib.lua
-- Tests for the lush standard library (issue #26).
print "testing lush library"
-- === lush global exists and is a table ===
do
assert(type(lush) == "table", "lush should be a table")
end
-- === named functions are accessible ===
do
assert(type(lush.command) == "function", "lush.command missing")
assert(type(lush.interactive) == "function", "lush.interactive missing")
assert(type(lush.getenv) == "function", "lush.getenv missing")
assert(type(lush.setenv) == "function", "lush.setenv missing")
assert(type(lush.subcmd) == "function", "lush.subcmd missing")
end
-- === lush.command works like backtick ===
do
local r = lush.command("echo hello")
assert(r.code == 0, "lush.command failed")
assert(r.stdout == "hello\n", "expected 'hello\\n', got: " .. r.stdout)
end
-- === lush.getenv / lush.setenv ===
do
lush.setenv("_LUSH_TEST_VAR", "42")
assert(lush.getenv("_LUSH_TEST_VAR") == "42")
lush.setenv("_LUSH_TEST_VAR", nil)
assert(lush.getenv("_LUSH_TEST_VAR") == nil)
end
-- === lush.builtins exists and has cd ===
do
assert(type(lush.builtins) == "table", "lush.builtins missing")
assert(type(lush.builtins.cd) == "function", "lush.builtins.cd missing")
assert(type(lush.builtins.exec) == "function", "lush.builtins.exec missing")
assert(type(lush.builtins.umask) == "function", "lush.builtins.umask missing")
end
-- === user-defined builtin via backtick ===
do
lush.builtins.greet = function(cmd, name)
-- builtins return {code, stdout, stderr}
local t = {}
t.code = 0
t.stdout = "hello " .. (name or "world") .. "\n"
t.stderr = ""
return t
end
local r = `greet lush`
assert(r.code == 0, "user builtin failed")
assert(r.stdout == "hello lush\n",
"expected 'hello lush\\n', got: " .. r.stdout)
-- clean up
lush.builtins.greet = nil
end
-- === user-defined builtin via lush.command ===
do
lush.builtins.myecho = function(cmd, ...)
local args = {...}
local t = {}
t.code = 0
t.stdout = table.concat(args, " ") .. "\n"
t.stderr = ""
return t
end
local r = lush.command("myecho foo bar")
assert(r.code == 0)
assert(r.stdout == "foo bar\n",
"expected 'foo bar\\n', got: " .. r.stdout)
lush.builtins.myecho = nil
end
-- === OP_LUSH still works (backtick, $VAR, !cmd syntax) ===
do
-- backtick
local r = `echo works`
assert(r.stdout == "works\n")
-- $VAR expansion
lush.setenv("_LUSH_LIB_TEST", "yes")
local val = $_LUSH_LIB_TEST
assert(val == "yes", "expected 'yes', got: " .. tostring(val))
lush.setenv("_LUSH_LIB_TEST", nil)
end
print "OK"