Initial commit
This commit is contained in:
247
apps/Lua.lua
Normal file
247
apps/Lua.lua
Normal file
@@ -0,0 +1,247 @@
|
||||
require = requireInjector(getfenv(1))
|
||||
local Util = require('util')
|
||||
local UI = require('ui')
|
||||
local Event = require('event')
|
||||
local History = require('history')
|
||||
|
||||
local sandboxEnv = Util.shallowCopy(getfenv(1))
|
||||
sandboxEnv.exit = function() Event.exitPullEvents() end
|
||||
sandboxEnv.require = requireInjector(sandboxEnv)
|
||||
setmetatable(sandboxEnv, { __index = _G })
|
||||
|
||||
multishell.setTitle(multishell.getCurrent(), 'Lua')
|
||||
UI:configure('Lua', ...)
|
||||
|
||||
local command = ''
|
||||
local history = History.load('.lua_history', 25)
|
||||
|
||||
local resultsPage = UI.Page({
|
||||
menuBar = UI.MenuBar({
|
||||
buttons = {
|
||||
{ text = 'Local', event = 'local' },
|
||||
{ text = 'Global', event = 'global' },
|
||||
{ text = 'Device', event = 'device' },
|
||||
},
|
||||
}),
|
||||
prompt = UI.TextEntry({
|
||||
y = 2,
|
||||
shadowText = 'enter command',
|
||||
backgroundFocusColor = colors.black,
|
||||
limit = 256,
|
||||
accelerators = {
|
||||
enter = 'command_enter',
|
||||
up = 'history_back',
|
||||
down = 'history_forward',
|
||||
mouse_rightclick = 'clear_prompt',
|
||||
},
|
||||
}),
|
||||
grid = UI.ScrollingGrid({
|
||||
y = 3,
|
||||
columns = {
|
||||
{ heading = 'Key', key = 'name' },
|
||||
{ heading = 'Value', key = 'value' },
|
||||
},
|
||||
sortColumn = 'name',
|
||||
autospace = true,
|
||||
}),
|
||||
notification = UI.Notification(),
|
||||
})
|
||||
|
||||
function resultsPage:setPrompt(value, focus)
|
||||
self.prompt:setValue(value)
|
||||
self.prompt.scroll = 0
|
||||
self.prompt:setPosition(#value)
|
||||
self.prompt:updateScroll()
|
||||
|
||||
if value:sub(-1) == ')' then
|
||||
self.prompt:setPosition(#value - 1)
|
||||
end
|
||||
|
||||
self.prompt:draw()
|
||||
if focus then
|
||||
resultsPage:setFocus(self.prompt)
|
||||
end
|
||||
end
|
||||
|
||||
function resultsPage:enable()
|
||||
self:setFocus(self.prompt)
|
||||
UI.Page.enable(self)
|
||||
end
|
||||
|
||||
function resultsPage:eventHandler(event)
|
||||
|
||||
if event.type == 'global' then
|
||||
resultsPage:setPrompt('', true)
|
||||
self:executeStatement('getfenv(0)')
|
||||
command = nil
|
||||
|
||||
elseif event.type == 'local' then
|
||||
resultsPage:setPrompt('', true)
|
||||
self:executeStatement('getfenv(1)')
|
||||
command = nil
|
||||
|
||||
elseif event.type == 'device' then
|
||||
resultsPage:setPrompt('device', true)
|
||||
self:executeStatement('device')
|
||||
|
||||
elseif event.type == 'history_back' then
|
||||
local value = history.back()
|
||||
if value then
|
||||
self:setPrompt(value)
|
||||
end
|
||||
|
||||
elseif event.type == 'history_forward' then
|
||||
self:setPrompt(history.forward() or '')
|
||||
|
||||
elseif event.type == 'clear_prompt' then
|
||||
self:setPrompt('')
|
||||
history.setPosition(#history.entries + 1)
|
||||
|
||||
elseif event.type == 'command_enter' then
|
||||
local s = tostring(self.prompt.value)
|
||||
|
||||
if #s > 0 then
|
||||
history.add(s)
|
||||
self:executeStatement(s)
|
||||
else
|
||||
local t = { }
|
||||
for k = #history.entries, 1, -1 do
|
||||
table.insert(t, {
|
||||
name = #t + 1,
|
||||
value = history.entries[k],
|
||||
isHistory = true,
|
||||
pos = k,
|
||||
})
|
||||
end
|
||||
history.setPosition(#history.entries + 1)
|
||||
command = nil
|
||||
self.grid:setValues(t)
|
||||
self.grid:setIndex(1)
|
||||
self.grid:adjustWidth()
|
||||
self:draw()
|
||||
end
|
||||
return true
|
||||
|
||||
else
|
||||
return UI.Page.eventHandler(self, event)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function resultsPage:setResult(result)
|
||||
local t = { }
|
||||
|
||||
local function safeValue(v)
|
||||
local t = type(v)
|
||||
if t == 'string' or t == 'number' then
|
||||
return v
|
||||
end
|
||||
return tostring(v)
|
||||
end
|
||||
|
||||
if type(result) == 'table' then
|
||||
for k,v in pairs(result) do
|
||||
local entry = {
|
||||
name = safeValue(k),
|
||||
rawName = k,
|
||||
value = safeValue(v),
|
||||
rawValue = v,
|
||||
}
|
||||
if type(v) == 'table' then
|
||||
if Util.size(v) == 0 then
|
||||
entry.value = 'table: (empty)'
|
||||
else
|
||||
entry.value = 'table'
|
||||
end
|
||||
end
|
||||
table.insert(t, entry)
|
||||
end
|
||||
else
|
||||
table.insert(t, {
|
||||
name = type(result),
|
||||
value = tostring(result),
|
||||
rawValue = result,
|
||||
})
|
||||
end
|
||||
self.grid:setValues(t)
|
||||
self.grid:setIndex(1)
|
||||
self.grid:adjustWidth()
|
||||
self:draw()
|
||||
end
|
||||
|
||||
function resultsPage.grid:eventHandler(event)
|
||||
|
||||
local entry = self:getSelected()
|
||||
|
||||
local function commandAppend()
|
||||
if entry.isHistory then
|
||||
history.setPosition(entry.pos)
|
||||
return entry.value
|
||||
end
|
||||
if type(entry.rawValue) == 'function' then
|
||||
if command then
|
||||
return command .. '.' .. entry.name .. '()'
|
||||
end
|
||||
return entry.name .. '()'
|
||||
end
|
||||
if command then
|
||||
if type(entry.rawName) == 'number' then
|
||||
return command .. '[' .. entry.name .. ']'
|
||||
end
|
||||
if entry.name:match("%W") or
|
||||
entry.name:sub(1, 1):match("%d") then
|
||||
return command .. "['" .. tostring(entry.name) .. "']"
|
||||
end
|
||||
return command .. '.' .. entry.name
|
||||
end
|
||||
return entry.name
|
||||
end
|
||||
|
||||
if event.type == 'grid_focus_row' then
|
||||
if self.focused then
|
||||
resultsPage:setPrompt(commandAppend())
|
||||
end
|
||||
elseif event.type == 'grid_select' then
|
||||
resultsPage:setPrompt(commandAppend(), true)
|
||||
resultsPage:executeStatement(commandAppend())
|
||||
else
|
||||
return UI.Grid.eventHandler(self, event)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function resultsPage:rawExecute(s)
|
||||
|
||||
local fn, m = loadstring("return (" .. s .. ')', 'lua')
|
||||
if not fn then
|
||||
fn, m = loadstring(s, 'lua')
|
||||
end
|
||||
|
||||
if fn then
|
||||
setfenv(fn, sandboxEnv)
|
||||
fn, m = pcall(fn)
|
||||
end
|
||||
|
||||
return fn, m
|
||||
end
|
||||
|
||||
function resultsPage:executeStatement(statement)
|
||||
|
||||
command = statement
|
||||
|
||||
local s, m = self:rawExecute(command)
|
||||
|
||||
if s and m then
|
||||
self:setResult(m)
|
||||
else
|
||||
self.grid:setValues({ })
|
||||
self.grid:draw()
|
||||
if m then
|
||||
self.notification:error(m, 5)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
UI:setPage(resultsPage)
|
||||
Event.pullEvents()
|
||||
UI.term:reset()
|
||||
Reference in New Issue
Block a user