mirror of
https://github.com/NeoFlock/neonucleus.git
synced 2025-09-24 17:13:31 +02:00
130 lines
3.6 KiB
Lua
130 lines
3.6 KiB
Lua
local package = require("package")
|
|
local term = require("term")
|
|
|
|
local function optrequire(...)
|
|
local success, module = pcall(require, ...)
|
|
if success then
|
|
return module
|
|
end
|
|
end
|
|
|
|
local env -- forward declare for binding in metamethod
|
|
env = setmetatable({}, {
|
|
__index = function(_, k)
|
|
_ENV[k] = _ENV[k] or optrequire(k)
|
|
return _ENV[k]
|
|
end,
|
|
__pairs = function(t)
|
|
return function(_, key)
|
|
local k, v = next(t, key)
|
|
if not k and t == env then
|
|
t = _ENV
|
|
k, v = next(t)
|
|
end
|
|
if not k and t == _ENV then
|
|
t = package.loaded
|
|
k, v = next(t)
|
|
end
|
|
return k, v
|
|
end
|
|
end,
|
|
})
|
|
env._PROMPT = tostring(env._PROMPT or "\27[32mlua> \27[37m")
|
|
|
|
local function findTable(t, path)
|
|
if type(t) ~= "table" then return nil end
|
|
if not path or #path == 0 then return t end
|
|
local name = string.match(path, "[^.]+")
|
|
for k, v in pairs(t) do
|
|
if k == name then
|
|
return findTable(v, string.sub(path, #name + 2))
|
|
end
|
|
end
|
|
local mt = getmetatable(t)
|
|
if t == env then mt = {__index=_ENV} end
|
|
if mt then
|
|
return findTable(mt.__index, path)
|
|
end
|
|
return nil
|
|
end
|
|
|
|
local function findKeys(t, r, prefix, name)
|
|
if type(t) ~= "table" then return end
|
|
for k, v in pairs(t) do
|
|
if type(k) == "string" and string.match(k, "^"..name) then
|
|
local postfix = ""
|
|
if type(v) == "function" then postfix = "()"
|
|
elseif type(v) == "table" and getmetatable(v) and getmetatable(v).__call then postfix = "()"
|
|
elseif type(v) == "table" then postfix = "."
|
|
end
|
|
r[prefix..k..postfix] = true
|
|
end
|
|
end
|
|
local mt = getmetatable(t)
|
|
if t == env then mt = {__index=_ENV} end
|
|
if mt then
|
|
return findKeys(mt.__index, r, prefix, name)
|
|
end
|
|
end
|
|
|
|
local read_handler = {hint = function(line, index)
|
|
line = (line or "")
|
|
local tail = line:sub(index)
|
|
line = line:sub(1, index - 1)
|
|
local path = string.match(line, "[a-zA-Z_][a-zA-Z0-9_.]*$")
|
|
if not path then return nil end
|
|
local suffix = string.match(path, "[^.]+$") or ""
|
|
local prefix = string.sub(path, 1, #path - #suffix)
|
|
local tbl = findTable(env, prefix)
|
|
if not tbl then return nil end
|
|
local keys = {}
|
|
local hints = {}
|
|
findKeys(tbl, keys, string.sub(line, 1, #line - #suffix), suffix)
|
|
for key in pairs(keys) do
|
|
table.insert(hints, key .. tail)
|
|
end
|
|
return hints
|
|
end}
|
|
|
|
io.write("\27[37m".._VERSION .. " Copyright (C) 1994-2022 Lua.org, PUC-Rio\n")
|
|
io.write("\27[33mEnter a statement and hit enter to evaluate it.\n")
|
|
io.write("Prefix an expression with '=' to show its value.\n")
|
|
io.write("Press Ctrl+D to exit the interpreter.\n\27[37m")
|
|
|
|
while term.isAvailable() do
|
|
io.write(env._PROMPT)
|
|
local command = term.read(read_handler)
|
|
if not command then -- eof
|
|
return
|
|
end
|
|
local code, reason
|
|
if string.sub(command, 1, 1) == "=" then
|
|
code, reason = load("return " .. string.sub(command, 2), "=stdin", "t", env)
|
|
else
|
|
code, reason = load("return " .. command, "=stdin", "t", env)
|
|
if not code then
|
|
code, reason = load(command, "=stdin", "t", env)
|
|
end
|
|
end
|
|
if code then
|
|
local result = table.pack(xpcall(code, debug.traceback))
|
|
if not result[1] then
|
|
if type(result[2]) == "table" and result[2].reason == "terminated" then
|
|
os.exit(result[2].code)
|
|
end
|
|
io.stderr:write(tostring(result[2]) .. "\n")
|
|
else
|
|
local ok, why = pcall(function()
|
|
for i = 2, result.n do
|
|
io.write(require("serialization").serialize(result[i], true), i < result.n and "\t" or "\n")
|
|
end
|
|
end)
|
|
if not ok then
|
|
io.stderr:write("crashed serializing result: ", tostring(why))
|
|
end
|
|
end
|
|
else
|
|
io.stderr:write(tostring(reason) .. "\n")
|
|
end
|
|
end
|