blob: 653fd7e633a5f2cbc6fa9896ea336b01516697fb [file] [log] [blame] [raw]
local component = require("component")
local package = require("package")
local term = require("term")
local serialization = require("serialization")
local shell = require("shell")
local args, options = shell.parse(...)
local env = setmetatable({}, {__index = _ENV})
if #args > 0 then
local script, reason = loadfile(args[1], nil, env)
if not script then
io.stderr:write(tostring(reason) .. "\n")
os.exit(false)
end
local result, reason = pcall(script, table.unpack(args, 2))
if not result then
io.stderr:write(reason)
os.exit(false)
end
end
if #args == 0 or options.i then
local function optrequire(...)
local success, module = pcall(require, ...)
if success then
return module
end
end
setmetatable(env, {
__index = function(t, k)
_ENV[k] = _ENV[k] or optrequire(k)
return _ENV[k]
end,
__pairs = function(self)
local t = self
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
})
local history = {}
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 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 function hint(line, index)
line = (line or ""):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 t = findTable(env, prefix)
if not t then return nil end
local r1, r2 = {}, {}
findKeys(t, r1, string.sub(line, 1, #line - #suffix), suffix)
for k in pairs(r1) do
table.insert(r2, k)
end
table.sort(r2)
return r2
end
component.gpu.setForeground(0xFFFFFF)
term.write("Lua 5.2.4 Copyright (C) 1994-2015 Lua.org, PUC-Rio\n")
component.gpu.setForeground(0xFFFF00)
term.write("Enter a statement and hit enter to evaluate it.\n")
term.write("Prefix an expression with '=' to show its value.\n")
term.write("Press Ctrl+C to exit the interpreter.\n")
component.gpu.setForeground(0xFFFFFF)
while term.isAvailable() do
local foreground = component.gpu.setForeground(0x00FF00)
term.write(tostring(env._PROMPT or "lua> "))
component.gpu.setForeground(foreground)
local command = term.read(history, nil, hint)
if command == nil then -- eof
return
end
while #history > 10 do
table.remove(history, 1)
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(command, "=stdin", "t", env)
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
for i = 2, result.n do
term.write(serialization.serialize(result[i], true) .. "\t", true)
end
if term.getCursor() > 1 then
term.write("\n")
end
end
else
io.stderr:write(tostring(reason) .. "\n")
end
end
end