mirror of
https://github.com/kepler155c/opus
synced 2025-10-24 20:27:39 +00:00
ui improvements
This commit is contained in:
55
sys/apis/ansi.lua
Normal file
55
sys/apis/ansi.lua
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
local Ansi = setmetatable({ }, {
|
||||||
|
__call = function(self, ...)
|
||||||
|
local str = '\027['
|
||||||
|
for k,v in ipairs({ ...}) do
|
||||||
|
if k == 1 then
|
||||||
|
str = str .. v
|
||||||
|
else
|
||||||
|
str = str .. ';' .. v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return str .. 'm'
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
Ansi.codes = {
|
||||||
|
reset = 0,
|
||||||
|
white = 1,
|
||||||
|
orange = 2,
|
||||||
|
magenta = 3,
|
||||||
|
lightBlue = 4,
|
||||||
|
yellow = 5,
|
||||||
|
lime = 6,
|
||||||
|
pink = 7,
|
||||||
|
gray = 8,
|
||||||
|
lightGray = 9,
|
||||||
|
cyan = 10,
|
||||||
|
purple = 11,
|
||||||
|
blue = 12,
|
||||||
|
brown = 13,
|
||||||
|
green = 14,
|
||||||
|
red = 15,
|
||||||
|
black = 16,
|
||||||
|
onwhite = 21,
|
||||||
|
onorange = 22,
|
||||||
|
onmagenta = 23,
|
||||||
|
onlightBlue = 24,
|
||||||
|
onyellow = 25,
|
||||||
|
onlime = 26,
|
||||||
|
onpink = 27,
|
||||||
|
ongray = 28,
|
||||||
|
onlightGray = 29,
|
||||||
|
oncyan = 30,
|
||||||
|
onpurple = 31,
|
||||||
|
onblue = 32,
|
||||||
|
onbrown = 33,
|
||||||
|
ongreen = 34,
|
||||||
|
onred = 35,
|
||||||
|
onblack = 36,
|
||||||
|
}
|
||||||
|
|
||||||
|
for k,v in pairs(Ansi.codes) do
|
||||||
|
Ansi[k] = Ansi(v)
|
||||||
|
end
|
||||||
|
|
||||||
|
return Ansi
|
||||||
@@ -1,47 +1,50 @@
|
|||||||
local Util = require('util')
|
local Util = require('util')
|
||||||
|
|
||||||
local History = { }
|
local History = { }
|
||||||
|
local History_mt = { __index = History }
|
||||||
|
|
||||||
function History.load(filename, limit)
|
function History.load(filename, limit)
|
||||||
|
|
||||||
local entries = Util.readLines(filename) or { }
|
local self = setmetatable({
|
||||||
local pos = #entries + 1
|
limit = limit,
|
||||||
|
filename = filename,
|
||||||
|
}, History_mt)
|
||||||
|
|
||||||
return {
|
self.entries = Util.readLines(filename) or { }
|
||||||
entries = entries,
|
self.pos = #self.entries + 1
|
||||||
|
|
||||||
add = function(line)
|
return self
|
||||||
local last = entries[pos] or entries[pos - 1]
|
end
|
||||||
if not last or line ~= last then
|
|
||||||
table.insert(entries, line)
|
function History:add(line)
|
||||||
if limit then
|
if line ~= self.entries[#self.entries] then
|
||||||
while #entries > limit do
|
table.insert(self.entries, line)
|
||||||
table.remove(entries, 1)
|
if self.limit then
|
||||||
end
|
while #self.entries > self.limit do
|
||||||
end
|
table.remove(self.entries, 1)
|
||||||
Util.writeLines(filename, entries)
|
|
||||||
pos = #entries + 1
|
|
||||||
end
|
end
|
||||||
end,
|
end
|
||||||
|
Util.writeLines(self.filename, self.entries)
|
||||||
|
self.pos = #self.entries + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
setPosition = function(p)
|
function History:reset()
|
||||||
pos = p
|
self.pos = #self.entries + 1
|
||||||
end,
|
end
|
||||||
|
|
||||||
back = function()
|
function History:back()
|
||||||
if pos > 1 then
|
if self.pos > 1 then
|
||||||
pos = pos - 1
|
self.pos = self.pos - 1
|
||||||
return entries[pos]
|
return self.entries[self.pos]
|
||||||
end
|
end
|
||||||
end,
|
end
|
||||||
|
|
||||||
forward = function()
|
function History:forward()
|
||||||
if pos <= #entries then
|
if self.pos <= #self.entries then
|
||||||
pos = pos + 1
|
self.pos = self.pos + 1
|
||||||
return entries[pos]
|
return self.entries[self.pos]
|
||||||
end
|
end
|
||||||
end,
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return History
|
return History
|
||||||
|
|||||||
308
sys/apis/ui.lua
308
sys/apis/ui.lua
@@ -1,8 +1,9 @@
|
|||||||
local Util = require('util')
|
local Ansi = require('ansi')
|
||||||
local class = require('class')
|
local class = require('class')
|
||||||
local Event = require('event')
|
local Event = require('event')
|
||||||
local Tween = require('ui.tween')
|
|
||||||
local Region = require('ui.region')
|
local Region = require('ui.region')
|
||||||
|
local Tween = require('ui.tween')
|
||||||
|
local Util = require('util')
|
||||||
|
|
||||||
local mapColorToGray = {
|
local mapColorToGray = {
|
||||||
[ colors.white ] = colors.white,
|
[ colors.white ] = colors.white,
|
||||||
@@ -725,15 +726,6 @@ function UI.Window:centeredWrite(y, text, bg, fg)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- deprecated - use print instead
|
|
||||||
function UI.Window:wrappedWrite(x, y, text, len, bg, fg)
|
|
||||||
for _,v in pairs(Util.wordWrap(text, len)) do
|
|
||||||
self:write(x, y, v, bg, fg)
|
|
||||||
y = y + 1
|
|
||||||
end
|
|
||||||
return y
|
|
||||||
end
|
|
||||||
|
|
||||||
function UI.Window:print(text, bg, fg, indent)
|
function UI.Window:print(text, bg, fg, indent)
|
||||||
indent = indent or 1
|
indent = indent or 1
|
||||||
|
|
||||||
@@ -752,40 +744,73 @@ function UI.Window:print(text, bg, fg, indent)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
local function pieces(f, bg, fg)
|
||||||
TODO
|
local pos = 1
|
||||||
local test = "\027[0;1;33mYou tell foo, \"// Test string.\"\027[0;37mbar"
|
local t = { }
|
||||||
for sequence, text in string.gmatch (test, "\027%[([0-9;]+)m([^\027]+)") do
|
while true do
|
||||||
for ansi in string.gmatch (sequence, "%d+") do
|
local s = f:find('\027', pos)
|
||||||
print ("ANSI code: ", ansi)
|
if not s then
|
||||||
end -- for
|
break
|
||||||
print ("Text: ", text)
|
end
|
||||||
|
if pos < s then
|
||||||
|
table.insert(t, f:sub(pos, s - 1))
|
||||||
|
end
|
||||||
|
local seq = f:sub(s)
|
||||||
|
seq = seq:match("\027%[([%d;]+)m")
|
||||||
|
local e = { }
|
||||||
|
for color in string.gmatch(seq, "%d+") do
|
||||||
|
color = tonumber(color)
|
||||||
|
if color == 0 then
|
||||||
|
e.fg = fg
|
||||||
|
e.bg = bg
|
||||||
|
elseif color > 20 then
|
||||||
|
e.bg = 2 ^ (color - 21)
|
||||||
|
else
|
||||||
|
e.fg = 2 ^ (color - 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.insert(t, e)
|
||||||
|
pos = s + #seq + 3
|
||||||
|
end
|
||||||
|
if pos < #f then
|
||||||
|
table.insert(t, f:sub(pos))
|
||||||
|
end
|
||||||
|
return t
|
||||||
end
|
end
|
||||||
--]]
|
|
||||||
|
|
||||||
local lines = Util.split(text)
|
local lines = Util.split(text)
|
||||||
for k,line in pairs(lines) do
|
for k,line in pairs(lines) do
|
||||||
local lx = 1
|
local fragments = pieces(line, bg, fg)
|
||||||
while true do
|
for l, fragment in ipairs(fragments) do
|
||||||
local word = nextWord(line, lx)
|
local lx = 1
|
||||||
if not word then
|
if type(fragment) == 'table' then -- ansi sequence
|
||||||
if lines[k + 1] then
|
fg = fragment.fg
|
||||||
self.cursorX = indent
|
bg = fragment.bg
|
||||||
self.cursorY = self.cursorY + 1
|
else
|
||||||
|
while true do
|
||||||
|
local word = nextWord(fragment, lx)
|
||||||
|
if not word then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
local w = word
|
||||||
|
if self.cursorX + #word > self.width then
|
||||||
|
self.cursorX = indent
|
||||||
|
self.cursorY = self.cursorY + 1
|
||||||
|
w = word:gsub(' ', '')
|
||||||
|
end
|
||||||
|
self:write(self.cursorX, self.cursorY, w, bg, fg)
|
||||||
|
self.cursorX = self.cursorX + #word
|
||||||
|
lx = lx + #word
|
||||||
end
|
end
|
||||||
break
|
|
||||||
end
|
end
|
||||||
local w = word
|
end
|
||||||
if self.cursorX + #word > self.width then
|
if lines[k + 1] then
|
||||||
self.cursorX = indent
|
self.cursorX = indent
|
||||||
self.cursorY = self.cursorY + 1
|
self.cursorY = self.cursorY + 1
|
||||||
w = word:gsub(' ', '')
|
|
||||||
end
|
|
||||||
self:write(self.cursorX, self.cursorY, w, bg, fg)
|
|
||||||
self.cursorX = self.cursorX + #word
|
|
||||||
lx = lx + #word
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return self.cursorX, self.cursorY
|
||||||
end
|
end
|
||||||
|
|
||||||
function UI.Window:setFocus(focus)
|
function UI.Window:setFocus(focus)
|
||||||
@@ -852,22 +877,24 @@ function UI.Window:scrollIntoView()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function UI.Window:addTransition(effect, x, y, width, height)
|
function UI.Window:addTransition(effect, args)
|
||||||
if self.parent then
|
if self.parent then
|
||||||
x = x or 1
|
args = args or { }
|
||||||
y = y or 1
|
if not args.x then -- not good
|
||||||
width = width or self.width
|
args.x, args.y = getPosition(self)
|
||||||
height = height or self.height
|
args.width = self.width
|
||||||
self.parent:addTransition(effect, x + self.x - 1, y + self.y - 1, width, height)
|
args.height = self.height
|
||||||
|
end
|
||||||
|
|
||||||
|
args.canvas = args.canvas or self.canvas
|
||||||
|
self.parent:addTransition(effect, args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function UI.Window:emit(event)
|
function UI.Window:emit(event)
|
||||||
local parent = self
|
local parent = self
|
||||||
--debug(self.UIElement .. ' emitting ' .. event.type)
|
|
||||||
while parent do
|
while parent do
|
||||||
if parent.eventHandler then
|
if parent.eventHandler then
|
||||||
--debug('calling ' .. parent.UIElement)
|
|
||||||
if parent:eventHandler(event) then
|
if parent:eventHandler(event) then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@@ -1089,13 +1116,16 @@ function Canvas:blit(device, src, tgt)
|
|||||||
|
|
||||||
for i = 0, src.ey - src.y do
|
for i = 0, src.ey - src.y do
|
||||||
local line = self.lines[src.y + i]
|
local line = self.lines[src.y + i]
|
||||||
if line.dirty then
|
if line and line.dirty then
|
||||||
local t, fg, bg = line.text, line.fg, line.bg
|
local t, fg, bg = line.text, line.fg, line.bg
|
||||||
if src.x > 1 or src.ex < self.ex then
|
if src.x > 1 or src.ex < self.ex then
|
||||||
t = t:sub(src.x, src.ex)
|
t = t:sub(src.x, src.ex)
|
||||||
fg = fg:sub(src.x, src.ex)
|
fg = fg:sub(src.x, src.ex)
|
||||||
bg = bg:sub(src.x, src.ex)
|
bg = bg:sub(src.x, src.ex)
|
||||||
end
|
end
|
||||||
|
--if tgt.y + i > self.ey then -- wrong place to do clipping ??
|
||||||
|
-- break
|
||||||
|
--end
|
||||||
device.setCursorPos(tgt.x, tgt.y + i)
|
device.setCursorPos(tgt.x, tgt.y + i)
|
||||||
device.blit(t, fg, bg)
|
device.blit(t, fg, bg)
|
||||||
end
|
end
|
||||||
@@ -1106,7 +1136,7 @@ end
|
|||||||
UI.TransitionSlideLeft = class()
|
UI.TransitionSlideLeft = class()
|
||||||
UI.TransitionSlideLeft.defaults = {
|
UI.TransitionSlideLeft.defaults = {
|
||||||
UIElement = 'TransitionSlideLeft',
|
UIElement = 'TransitionSlideLeft',
|
||||||
ticks = 4,
|
ticks = 6,
|
||||||
easing = 'outQuint',
|
easing = 'outQuint',
|
||||||
}
|
}
|
||||||
function UI.TransitionSlideLeft:init(args)
|
function UI.TransitionSlideLeft:init(args)
|
||||||
@@ -1146,7 +1176,7 @@ end
|
|||||||
UI.TransitionSlideRight = class()
|
UI.TransitionSlideRight = class()
|
||||||
UI.TransitionSlideRight.defaults = {
|
UI.TransitionSlideRight.defaults = {
|
||||||
UIElement = 'TransitionSlideRight',
|
UIElement = 'TransitionSlideRight',
|
||||||
ticks = 4,
|
ticks = 6,
|
||||||
easing = 'outQuint',
|
easing = 'outQuint',
|
||||||
}
|
}
|
||||||
function UI.TransitionSlideRight:init(args)
|
function UI.TransitionSlideRight:init(args)
|
||||||
@@ -1201,6 +1231,31 @@ function UI.TransitionExpandUp:update(device)
|
|||||||
return self.pos.y ~= self.y
|
return self.pos.y ~= self.y
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--[[-- TransitionGrow --]]--
|
||||||
|
UI.TransitionGrow = class()
|
||||||
|
UI.TransitionGrow.defaults = {
|
||||||
|
UIElement = 'TransitionGrow',
|
||||||
|
ticks = 3,
|
||||||
|
easing = 'linear',
|
||||||
|
}
|
||||||
|
function UI.TransitionGrow:init(args)
|
||||||
|
local defaults = UI:getDefaults(UI.TransitionGrow, args)
|
||||||
|
UI.setProperties(self, defaults)
|
||||||
|
self.tween = Tween.new(self.ticks,
|
||||||
|
{ x = self.width / 2 - 1, y = self.height / 2 - 1, w = 1, h = 1 },
|
||||||
|
{ x = 1, y = 1, w = self.width, h = self.height }, self.easing)
|
||||||
|
end
|
||||||
|
|
||||||
|
function UI.TransitionGrow:update(device)
|
||||||
|
local finished = self.tween:update(1)
|
||||||
|
local subj = self.tween.subject
|
||||||
|
local rect = { x = math.floor(subj.x), y = math.floor(subj.y) }
|
||||||
|
rect.ex = math.floor(rect.x + subj.w - 1)
|
||||||
|
rect.ey = math.floor(rect.y + subj.h - 1)
|
||||||
|
self.canvas:blit(device, rect, { x = self.x + rect.x - 1, y = self.y + rect.y - 1})
|
||||||
|
return not finished
|
||||||
|
end
|
||||||
|
|
||||||
--[[-- Terminal for computer / advanced computer / monitor --]]--
|
--[[-- Terminal for computer / advanced computer / monitor --]]--
|
||||||
UI.Device = class(UI.Window)
|
UI.Device = class(UI.Window)
|
||||||
UI.Device.defaults = {
|
UI.Device.defaults = {
|
||||||
@@ -1271,26 +1326,33 @@ function UI.Device:reset()
|
|||||||
self.device.setCursorPos(1, 1)
|
self.device.setCursorPos(1, 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
function UI.Device:addTransition(effect, x, y, width, height)
|
-- refactor into canvas...
|
||||||
|
function UI.Device:addTransition(effect, args)
|
||||||
if not self.transitions then
|
if not self.transitions then
|
||||||
self.transitions = { }
|
self.transitions = { }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
args = args or { }
|
||||||
|
args.ex = args.x + args.width - 1
|
||||||
|
args.ey = args.y + args.height - 1
|
||||||
|
args.canvas = args.canvas or self.canvas
|
||||||
|
|
||||||
if type(effect) == 'string' then
|
if type(effect) == 'string' then
|
||||||
local c
|
local transitions = {
|
||||||
if effect == 'slideLeft' then
|
slideLeft = UI.TransitionSlideLeft,
|
||||||
c = UI.TransitionSlideLeft
|
slideRight = UI.TransitionSlideRight,
|
||||||
else
|
expandUp = UI.TransitionExpandUp,
|
||||||
c = UI.TransitionSlideRight
|
grow = UI.TransitionGrow,
|
||||||
end
|
|
||||||
effect = c {
|
|
||||||
x = x,
|
|
||||||
y = y,
|
|
||||||
ex = x + width - 1,
|
|
||||||
ey = y + height - 1,
|
|
||||||
canvas = self.canvas,
|
|
||||||
}
|
}
|
||||||
|
local c = transitions[effect]
|
||||||
|
if not c then
|
||||||
|
error('Invalid transition: ' .. effect)
|
||||||
|
end
|
||||||
|
effect = c(args)
|
||||||
|
else
|
||||||
|
Util.merge(effect, args)
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(self.transitions, effect)
|
table.insert(self.transitions, effect)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1335,8 +1397,8 @@ function UI.Device:sync()
|
|||||||
end
|
end
|
||||||
|
|
||||||
if self:getCursorBlink() then
|
if self:getCursorBlink() then
|
||||||
self.device.setCursorBlink(true)
|
|
||||||
self.device.setCursorPos(self.cursorX, self.cursorY)
|
self.device.setCursorPos(self.cursorX, self.cursorY)
|
||||||
|
self.device.setCursorBlink(true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1954,10 +2016,10 @@ UI.ScrollingGrid.defaults = {
|
|||||||
sliderChar = '#',
|
sliderChar = '#',
|
||||||
upArrowChar = '^',
|
upArrowChar = '^',
|
||||||
downArrowChar = 'v',
|
downArrowChar = 'v',
|
||||||
|
scrollbarColor = colors.lightGray,
|
||||||
}
|
}
|
||||||
function UI.ScrollingGrid:init(args)
|
function UI.ScrollingGrid:init(args)
|
||||||
local defaults = UI:getDefaults(UI.ScrollingGrid, args)
|
UI.Grid.init(self, UI:getDefaults(UI.ScrollingGrid, args))
|
||||||
UI.Grid.init(self, defaults)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function UI.ScrollingGrid:drawRows()
|
function UI.ScrollingGrid:drawRows()
|
||||||
@@ -1968,44 +2030,36 @@ end
|
|||||||
function UI.ScrollingGrid:drawScrollbar()
|
function UI.ScrollingGrid:drawScrollbar()
|
||||||
local ts = Util.size(self.values)
|
local ts = Util.size(self.values)
|
||||||
if ts > self.pageSize then
|
if ts > self.pageSize then
|
||||||
local sbSize = self.pageSize - 2
|
local maxScroll = ts - self.pageSize
|
||||||
local sa = ts
|
local percent = (self.scrollOffset - 1) / maxScroll
|
||||||
sa = self.pageSize / sa
|
local sliderSize = self.pageSize / ts * (self.pageSize - 2)
|
||||||
sa = math.floor(sbSize * sa)
|
local row = 2
|
||||||
if sa < 1 then
|
|
||||||
sa = 1
|
if self.disableHeader then
|
||||||
|
row = 1
|
||||||
end
|
end
|
||||||
if sa > sbSize then
|
|
||||||
sa = sbSize
|
|
||||||
end
|
|
||||||
local sp = ts-self.pageSize
|
|
||||||
sp = self.scrollOffset / sp
|
|
||||||
sp = math.floor(sp * (sbSize-sa + 0.5))
|
|
||||||
|
|
||||||
local x = self.width
|
local x = self.width
|
||||||
|
for i = 1, self.pageSize - 2 do
|
||||||
|
self:write(x, row + i, self.lineChar, nil, self.scrollbarColor)
|
||||||
|
end
|
||||||
|
|
||||||
|
local y = Util.round((self.pageSize - 2 - sliderSize) * percent)
|
||||||
|
for i = 1, Util.round(sliderSize) do
|
||||||
|
self:write(x, row + y + i, self.sliderChar, nil, self.scrollbarColor)
|
||||||
|
end
|
||||||
|
|
||||||
|
local color = self.scrollbarColor
|
||||||
if self.scrollOffset > 1 then
|
if self.scrollOffset > 1 then
|
||||||
self:write(x, 2, self.upArrowChar)
|
color = colors.white
|
||||||
else
|
|
||||||
self:write(x, 2, ' ')
|
|
||||||
end
|
|
||||||
local row = 0
|
|
||||||
for i = 1, sp - 1 do
|
|
||||||
self:write(x, row+3, self.lineChar)
|
|
||||||
row = row + 1
|
|
||||||
end
|
|
||||||
for i = 1, sa do
|
|
||||||
self:write(x, row+3, self.sliderChar)
|
|
||||||
row = row + 1
|
|
||||||
end
|
|
||||||
for i = row, sbSize do
|
|
||||||
self:write(x, row+3, self.lineChar)
|
|
||||||
row = row + 1
|
|
||||||
end
|
end
|
||||||
|
self:write(x, 2, self.upArrowChar, nil, color)
|
||||||
|
|
||||||
|
color = self.scrollbarColor
|
||||||
if self.scrollOffset + self.pageSize - 1 < Util.size(self.values) then
|
if self.scrollOffset + self.pageSize - 1 < Util.size(self.values) then
|
||||||
self:write(x, self.pageSize + 1, self.downArrowChar)
|
color = colors.white
|
||||||
else
|
|
||||||
self:write(x, self.pageSize + 1, ' ')
|
|
||||||
end
|
end
|
||||||
|
self:write(x, self.pageSize + 1, self.downArrowChar, nil, color)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -2035,6 +2089,31 @@ function UI.ScrollingGrid:setIndex(index)
|
|||||||
UI.Grid.setIndex(self, index)
|
UI.Grid.setIndex(self, index)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function UI.ScrollingGrid:eventHandler(event)
|
||||||
|
|
||||||
|
if event.type == 'mouse_click' or event.type == 'mouse_doubleclick' then
|
||||||
|
if event.x == self.width then
|
||||||
|
local ts = Util.size(self.values)
|
||||||
|
if ts > self.pageSize then
|
||||||
|
local row = 2
|
||||||
|
if self.disableHeader then
|
||||||
|
row = 1
|
||||||
|
end
|
||||||
|
if event.y == row then
|
||||||
|
self:setIndex(self.scrollOffset - 1)
|
||||||
|
elseif event.y == self.height then
|
||||||
|
self:setIndex(self.scrollOffset + self.pageSize)
|
||||||
|
else
|
||||||
|
-- ... percentage ...
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return UI.Grid.eventHandler(self, event)
|
||||||
|
end
|
||||||
|
|
||||||
--[[-- Menu --]]--
|
--[[-- Menu --]]--
|
||||||
UI.Menu = class(UI.Grid)
|
UI.Menu = class(UI.Grid)
|
||||||
UI.Menu.defaults = {
|
UI.Menu.defaults = {
|
||||||
@@ -2591,14 +2670,7 @@ function UI.Notification:display(value, timeout)
|
|||||||
|
|
||||||
-- need to get the current canvas - not ui.term.canvas
|
-- need to get the current canvas - not ui.term.canvas
|
||||||
self.canvas = UI.term.canvas:addLayer(self, self.backgroundColor, self.textColor or colors.white)
|
self.canvas = UI.term.canvas:addLayer(self, self.backgroundColor, self.textColor or colors.white)
|
||||||
self:addTransition(UI.TransitionExpandUp {
|
self:addTransition('expandUp', { ticks = self.height })
|
||||||
x = self.x,
|
|
||||||
y = self.y,
|
|
||||||
ex = self.x + self.width - 1,
|
|
||||||
ey = self.y + self.height - 1,
|
|
||||||
canvas = self.canvas,
|
|
||||||
ticks = self.height,
|
|
||||||
})
|
|
||||||
self.canvas:setVisible(true)
|
self.canvas:setVisible(true)
|
||||||
self:clear()
|
self:clear()
|
||||||
for k,v in pairs(lines) do
|
for k,v in pairs(lines) do
|
||||||
@@ -3209,6 +3281,29 @@ function UI.Text:draw()
|
|||||||
self:write(1, 1, Util.widthify(value, self.width), self.backgroundColor)
|
self:write(1, 1, Util.widthify(value, self.width), self.backgroundColor)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--[[-- Text --]]--
|
||||||
|
UI.TextArea = class(UI.Window)
|
||||||
|
UI.TextArea.defaults = {
|
||||||
|
UIElement = 'TextArea',
|
||||||
|
value = '',
|
||||||
|
}
|
||||||
|
function UI.TextArea:init(args)
|
||||||
|
local defaults = UI:getDefaults(UI.TextArea, args)
|
||||||
|
UI.Window.init(self, defaults)
|
||||||
|
end
|
||||||
|
|
||||||
|
function UI.TextArea:setText(text)
|
||||||
|
self.value = text
|
||||||
|
self:draw()
|
||||||
|
end
|
||||||
|
|
||||||
|
function UI.TextArea:draw()
|
||||||
|
local value = self.value or ''
|
||||||
|
self:clear()
|
||||||
|
self:setCursorPos(1, 1)
|
||||||
|
self:print(self.value)
|
||||||
|
end
|
||||||
|
|
||||||
--[[-- Form --]]--
|
--[[-- Form --]]--
|
||||||
UI.Form = class(UI.Window)
|
UI.Form = class(UI.Window)
|
||||||
UI.Form.defaults = {
|
UI.Form.defaults = {
|
||||||
@@ -3347,8 +3442,6 @@ function UI.Dialog:init(args)
|
|||||||
defaults.width = UI.term.width-11
|
defaults.width = UI.term.width-11
|
||||||
end
|
end
|
||||||
defaults.titleBar = UI.TitleBar({ previousPage = true, title = defaults.title })
|
defaults.titleBar = UI.TitleBar({ previousPage = true, title = defaults.title })
|
||||||
|
|
||||||
--UI.setProperties(defaults, args)
|
|
||||||
UI.Page.init(self, defaults)
|
UI.Page.init(self, defaults)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -3358,6 +3451,11 @@ function UI.Dialog:setParent()
|
|||||||
self.y = math.floor((self.parent.height - self.height) / 2) + 1
|
self.y = math.floor((self.parent.height - self.height) / 2) + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function UI.Dialog:enable(...)
|
||||||
|
self:addTransition('grow')
|
||||||
|
UI.Page.enable(self, ...)
|
||||||
|
end
|
||||||
|
|
||||||
function UI.Dialog:eventHandler(event)
|
function UI.Dialog:eventHandler(event)
|
||||||
if event.type == 'cancel' then
|
if event.type == 'cancel' then
|
||||||
UI:setPreviousPage()
|
UI:setPreviousPage()
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ return function(args)
|
|||||||
function selectFile:enable(path, fn)
|
function selectFile:enable(path, fn)
|
||||||
self:setPath(path)
|
self:setPath(path)
|
||||||
self.fn = fn
|
self.fn = fn
|
||||||
UI.Page.enable(self)
|
UI.Dialog.enable(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function selectFile:setPath(path)
|
function selectFile:setPath(path)
|
||||||
@@ -133,7 +133,7 @@ return function(args)
|
|||||||
UI:setPreviousPage()
|
UI:setPreviousPage()
|
||||||
self.fn()
|
self.fn()
|
||||||
else
|
else
|
||||||
return UI.Page.eventHandler(self, event)
|
return UI.Dialog.eventHandler(self, event)
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -473,27 +473,25 @@ end
|
|||||||
-- word wrapping based on:
|
-- word wrapping based on:
|
||||||
-- https://www.rosettacode.org/wiki/Word_wrap#Lua and
|
-- https://www.rosettacode.org/wiki/Word_wrap#Lua and
|
||||||
-- http://lua-users.org/wiki/StringRecipes
|
-- http://lua-users.org/wiki/StringRecipes
|
||||||
local function splittokens(s)
|
|
||||||
local res = {}
|
|
||||||
for w in s:gmatch("%S+") do
|
|
||||||
res[#res+1] = w
|
|
||||||
end
|
|
||||||
return res
|
|
||||||
end
|
|
||||||
|
|
||||||
local function paragraphwrap(text, linewidth, res)
|
local function paragraphwrap(text, linewidth, res)
|
||||||
linewidth = linewidth or 75
|
linewidth = linewidth or 75
|
||||||
local spaceleft = linewidth
|
local spaceleft = linewidth
|
||||||
local line = {}
|
local line = { }
|
||||||
|
|
||||||
for _, word in ipairs(splittokens(text)) do
|
for word in text:gmatch("%S+") do
|
||||||
if #word + 1 > spaceleft then
|
local len = #word + 1
|
||||||
|
|
||||||
|
--if colorMode then
|
||||||
|
-- word:gsub('()@([@%d])', function(pos, c) len = len - 2 end)
|
||||||
|
--end
|
||||||
|
|
||||||
|
if len > spaceleft then
|
||||||
table.insert(res, table.concat(line, ' '))
|
table.insert(res, table.concat(line, ' '))
|
||||||
line = { word }
|
line = { word }
|
||||||
spaceleft = linewidth - #word
|
spaceleft = linewidth - len - 1
|
||||||
else
|
else
|
||||||
table.insert(line, word)
|
table.insert(line, word)
|
||||||
spaceleft = spaceleft - (#word + 1)
|
spaceleft = spaceleft - len
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ function Browser.grid:eventHandler(event)
|
|||||||
if event.type == 'copy' then -- let copy be handled by parent
|
if event.type == 'copy' then -- let copy be handled by parent
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
return UI.Grid.eventHandler(self, event)
|
return UI.ScrollingGrid.eventHandler(self, event)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Browser.statusBar:draw()
|
function Browser.statusBar:draw()
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ local Util = require('util')
|
|||||||
|
|
||||||
local sandboxEnv = setmetatable(Util.shallowCopy(getfenv(1)), { __index = _G })
|
local sandboxEnv = setmetatable(Util.shallowCopy(getfenv(1)), { __index = _G })
|
||||||
sandboxEnv.exit = function() Event.exitPullEvents() end
|
sandboxEnv.exit = function() Event.exitPullEvents() end
|
||||||
|
sandboxEnv._echo = function( ... ) return ... end
|
||||||
requireInjector(sandboxEnv)
|
requireInjector(sandboxEnv)
|
||||||
|
|
||||||
multishell.setTitle(multishell.getCurrent(), 'Lua')
|
multishell.setTitle(multishell.getCurrent(), 'Lua')
|
||||||
@@ -16,15 +17,15 @@ UI:configure('Lua', ...)
|
|||||||
local command = ''
|
local command = ''
|
||||||
local history = History.load('usr/.lua_history', 25)
|
local history = History.load('usr/.lua_history', 25)
|
||||||
|
|
||||||
local page = UI.Page({
|
local page = UI.Page {
|
||||||
menuBar = UI.MenuBar({
|
menuBar = UI.MenuBar {
|
||||||
buttons = {
|
buttons = {
|
||||||
{ text = 'Local', event = 'local' },
|
{ text = 'Local', event = 'local' },
|
||||||
{ text = 'Global', event = 'global' },
|
{ text = 'Global', event = 'global' },
|
||||||
{ text = 'Device', event = 'device', name = 'Device' },
|
{ text = 'Device', event = 'device', name = 'Device' },
|
||||||
},
|
},
|
||||||
}),
|
},
|
||||||
prompt = UI.TextEntry({
|
prompt = UI.TextEntry {
|
||||||
y = 2,
|
y = 2,
|
||||||
shadowText = 'enter command',
|
shadowText = 'enter command',
|
||||||
limit = 256,
|
limit = 256,
|
||||||
@@ -35,8 +36,8 @@ local page = UI.Page({
|
|||||||
mouse_rightclick = 'clear_prompt',
|
mouse_rightclick = 'clear_prompt',
|
||||||
-- [ 'control-space' ] = 'autocomplete',
|
-- [ 'control-space' ] = 'autocomplete',
|
||||||
},
|
},
|
||||||
}),
|
},
|
||||||
grid = UI.ScrollingGrid({
|
grid = UI.ScrollingGrid {
|
||||||
y = 3,
|
y = 3,
|
||||||
columns = {
|
columns = {
|
||||||
{ heading = 'Key', key = 'name' },
|
{ heading = 'Key', key = 'name' },
|
||||||
@@ -44,9 +45,9 @@ local page = UI.Page({
|
|||||||
},
|
},
|
||||||
sortColumn = 'name',
|
sortColumn = 'name',
|
||||||
autospace = true,
|
autospace = true,
|
||||||
}),
|
},
|
||||||
notification = UI.Notification(),
|
notification = UI.Notification(),
|
||||||
})
|
}
|
||||||
|
|
||||||
function page:setPrompt(value, focus)
|
function page:setPrompt(value, focus)
|
||||||
self.prompt:setValue(value)
|
self.prompt:setValue(value)
|
||||||
@@ -138,23 +139,24 @@ function page:eventHandler(event)
|
|||||||
self:executeStatement('device')
|
self:executeStatement('device')
|
||||||
|
|
||||||
elseif event.type == 'history_back' then
|
elseif event.type == 'history_back' then
|
||||||
local value = history.back()
|
local value = history:back()
|
||||||
if value then
|
if value then
|
||||||
self:setPrompt(value)
|
self:setPrompt(value)
|
||||||
end
|
end
|
||||||
|
|
||||||
elseif event.type == 'history_forward' then
|
elseif event.type == 'history_forward' then
|
||||||
self:setPrompt(history.forward() or '')
|
self:setPrompt(history:forward() or '')
|
||||||
|
|
||||||
elseif event.type == 'clear_prompt' then
|
elseif event.type == 'clear_prompt' then
|
||||||
self:setPrompt('')
|
self:setPrompt('')
|
||||||
history.setPosition(#history.entries + 1)
|
history:reset()
|
||||||
|
|
||||||
elseif event.type == 'command_enter' then
|
elseif event.type == 'command_enter' then
|
||||||
local s = tostring(self.prompt.value)
|
local s = tostring(self.prompt.value)
|
||||||
|
|
||||||
if #s > 0 then
|
if #s > 0 then
|
||||||
history.add(s)
|
history:add(s)
|
||||||
|
history:back()
|
||||||
self:executeStatement(s)
|
self:executeStatement(s)
|
||||||
else
|
else
|
||||||
local t = { }
|
local t = { }
|
||||||
@@ -166,7 +168,7 @@ function page:eventHandler(event)
|
|||||||
pos = k,
|
pos = k,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
history.setPosition(#history.entries + 1)
|
history:reset()
|
||||||
command = nil
|
command = nil
|
||||||
self.grid:setValues(t)
|
self.grid:setValues(t)
|
||||||
self.grid:setIndex(1)
|
self.grid:setIndex(1)
|
||||||
@@ -228,7 +230,7 @@ function page.grid:eventHandler(event)
|
|||||||
|
|
||||||
local function commandAppend()
|
local function commandAppend()
|
||||||
if entry.isHistory then
|
if entry.isHistory then
|
||||||
history.setPosition(entry.pos)
|
--history.setPosition(entry.pos)
|
||||||
return entry.value
|
return entry.value
|
||||||
end
|
end
|
||||||
if type(entry.rawValue) == 'function' then
|
if type(entry.rawValue) == 'function' then
|
||||||
@@ -262,15 +264,14 @@ function page.grid:eventHandler(event)
|
|||||||
clipboard.setData(entry.rawValue)
|
clipboard.setData(entry.rawValue)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
return UI.Grid.eventHandler(self, event)
|
return UI.ScrollingGrid.eventHandler(self, event)
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function page:rawExecute(s)
|
function page:rawExecute(s)
|
||||||
local fn, m = loadstring('return (' .. s .. ')', 'lua')
|
local fn, m = load('return _echo(' ..s.. ');', 'lua', nil, sandboxEnv)
|
||||||
if fn then
|
if fn then
|
||||||
setfenv(fn, sandboxEnv)
|
|
||||||
m = { pcall(fn) }
|
m = { pcall(fn) }
|
||||||
fn = table.remove(m, 1)
|
fn = table.remove(m, 1)
|
||||||
if #m == 1 then
|
if #m == 1 then
|
||||||
@@ -279,9 +280,8 @@ function page:rawExecute(s)
|
|||||||
return fn, m
|
return fn, m
|
||||||
end
|
end
|
||||||
|
|
||||||
fn, m = loadstring(s, 'lua')
|
fn, m = load(s, 'lua', nil, sandboxEnv)
|
||||||
if fn then
|
if fn then
|
||||||
setfenv(fn, sandboxEnv)
|
|
||||||
fn, m = pcall(fn)
|
fn, m = pcall(fn)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -270,11 +270,23 @@ function page.container:setCategory(categoryName)
|
|||||||
local col, row = gutter, 2
|
local col, row = gutter, 2
|
||||||
local count = #self.children
|
local count = #self.children
|
||||||
|
|
||||||
|
local r = math.random(1, 4)
|
||||||
-- reposition all children
|
-- reposition all children
|
||||||
for k,child in ipairs(self.children) do
|
for k,child in ipairs(self.children) do
|
||||||
child.x = self.width
|
if r == 1 then
|
||||||
child.y = math.floor(self.height)
|
child.x = math.random(1, self.width)
|
||||||
child.tween = Tween.new(6, child, { x = col, y = row }, 'outSine')
|
child.y = math.random(1, self.height)
|
||||||
|
elseif r == 2 then
|
||||||
|
child.x = self.width
|
||||||
|
child.y = self.height
|
||||||
|
elseif r == 3 then
|
||||||
|
child.x = math.floor(self.width / 2)
|
||||||
|
child.y = math.floor(self.height / 2)
|
||||||
|
elseif r == 4 then
|
||||||
|
child.x = self.width - col
|
||||||
|
child.y = row
|
||||||
|
end
|
||||||
|
child.tween = Tween.new(6, child, { x = col, y = row }, 'linear')
|
||||||
|
|
||||||
if k < count then
|
if k < count then
|
||||||
col = col + child.width
|
col = col + child.width
|
||||||
@@ -286,25 +298,25 @@ function page.container:setCategory(categoryName)
|
|||||||
end
|
end
|
||||||
|
|
||||||
self:initChildren()
|
self:initChildren()
|
||||||
self.animate = true
|
|
||||||
|
local transition = { i = 1, parent = self, children = self.children }
|
||||||
|
function transition:update(device)
|
||||||
|
self.parent:clear()
|
||||||
|
for _,child in ipairs(self.children) do
|
||||||
|
child.tween:update(1)
|
||||||
|
child.x = math.floor(child.x)
|
||||||
|
child.y = math.floor(child.y)
|
||||||
|
child:draw()
|
||||||
|
end
|
||||||
|
self.canvas:blit(device, self, self)
|
||||||
|
self.i = self.i + 1
|
||||||
|
return self.i < 7
|
||||||
|
end
|
||||||
|
self:addTransition(transition)
|
||||||
end
|
end
|
||||||
|
|
||||||
function page.container:draw()
|
function page.container:draw()
|
||||||
if self.animate then
|
UI.ViewportWindow.draw(self)
|
||||||
self.animate = false
|
|
||||||
for i = 1, 6 do
|
|
||||||
for _,child in ipairs(self.children) do
|
|
||||||
child.tween:update(1)
|
|
||||||
child.x = math.floor(child.x)
|
|
||||||
child.y = math.floor(child.y)
|
|
||||||
end
|
|
||||||
UI.ViewportWindow.draw(self)
|
|
||||||
self:sync()
|
|
||||||
os.sleep()
|
|
||||||
end
|
|
||||||
else
|
|
||||||
UI.ViewportWindow.draw(self)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function page:refresh()
|
function page:refresh()
|
||||||
@@ -442,10 +454,7 @@ local editor = UI.Dialog {
|
|||||||
text = 'Icon', event = 'loadIcon', help = 'Select icon'
|
text = 'Icon', event = 'loadIcon', help = 'Select icon'
|
||||||
},
|
},
|
||||||
image = UI.NftImage {
|
image = UI.NftImage {
|
||||||
y = 6,
|
y = 6, x = 2, height = 3, width = 8,
|
||||||
x = 2,
|
|
||||||
height = 3,
|
|
||||||
width = 8,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
statusBar = UI.StatusBar(),
|
statusBar = UI.StatusBar(),
|
||||||
@@ -462,7 +471,7 @@ function editor:enable(app)
|
|||||||
end
|
end
|
||||||
self.form.image:setImage(icon)
|
self.form.image:setImage(icon)
|
||||||
end
|
end
|
||||||
UI.Page.enable(self)
|
UI.Dialog.enable(self)
|
||||||
self:focusFirst()
|
self:focusFirst()
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -531,7 +540,7 @@ function editor:eventHandler(event)
|
|||||||
page:refresh()
|
page:refresh()
|
||||||
page:draw()
|
page:draw()
|
||||||
else
|
else
|
||||||
return UI.Page.eventHandler(self, event)
|
return UI.Dialog.eventHandler(self, event)
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -489,17 +489,18 @@ local function autocomplete(line, suggestions)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function shellRead(_tHistory )
|
local function shellRead(history)
|
||||||
term.setCursorBlink( true )
|
term.setCursorBlink( true )
|
||||||
|
|
||||||
local sLine = ""
|
local sLine = ""
|
||||||
local nHistoryPos
|
|
||||||
local nPos = 0
|
local nPos = 0
|
||||||
local lastPattern
|
local lastPattern
|
||||||
|
|
||||||
local w = term.getSize()
|
local w = term.getSize()
|
||||||
local sx = term.getCursorPos()
|
local sx = term.getCursorPos()
|
||||||
|
|
||||||
|
history:reset()
|
||||||
|
|
||||||
local function redraw( sReplace )
|
local function redraw( sReplace )
|
||||||
local nScroll = 0
|
local nScroll = 0
|
||||||
if sx + nPos >= w then
|
if sx + nPos >= w then
|
||||||
@@ -563,32 +564,19 @@ local function shellRead(_tHistory )
|
|||||||
redraw()
|
redraw()
|
||||||
end
|
end
|
||||||
elseif param == keys.up or param == keys.down then
|
elseif param == keys.up or param == keys.down then
|
||||||
if _tHistory then
|
redraw(" ")
|
||||||
redraw(" ")
|
if param == keys.up then
|
||||||
if param == keys.up then
|
sLine = history:back()
|
||||||
if nHistoryPos == nil then
|
else
|
||||||
if #_tHistory > 0 then
|
sLine = history:forward()
|
||||||
nHistoryPos = #_tHistory
|
|
||||||
end
|
|
||||||
elseif nHistoryPos > 1 then
|
|
||||||
nHistoryPos = nHistoryPos - 1
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if nHistoryPos == #_tHistory then
|
|
||||||
nHistoryPos = nil
|
|
||||||
elseif nHistoryPos ~= nil then
|
|
||||||
nHistoryPos = nHistoryPos + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if nHistoryPos then
|
|
||||||
sLine = _tHistory[nHistoryPos]
|
|
||||||
nPos = string.len( sLine )
|
|
||||||
else
|
|
||||||
sLine = ""
|
|
||||||
nPos = 0
|
|
||||||
end
|
|
||||||
redraw()
|
|
||||||
end
|
end
|
||||||
|
if sLine then
|
||||||
|
nPos = string.len(sLine)
|
||||||
|
else
|
||||||
|
sLine = ""
|
||||||
|
nPos = 0
|
||||||
|
end
|
||||||
|
redraw()
|
||||||
elseif param == keys.backspace then
|
elseif param == keys.backspace then
|
||||||
if nPos > 0 then
|
if nPos > 0 then
|
||||||
redraw(" ")
|
redraw(" ")
|
||||||
@@ -637,13 +625,13 @@ while not bExit do
|
|||||||
write("$ " )
|
write("$ " )
|
||||||
term.setTextColour(_colors.commandTextColor)
|
term.setTextColour(_colors.commandTextColor)
|
||||||
term.setBackgroundColor(colors.black)
|
term.setBackgroundColor(colors.black)
|
||||||
local sLine = shellRead(history.entries)
|
local sLine = shellRead(history)
|
||||||
if bExit then -- terminated
|
if bExit then -- terminated
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
sLine = Util.trim(sLine)
|
sLine = Util.trim(sLine)
|
||||||
if #sLine > 0 and sLine ~= 'exit' then
|
if #sLine > 0 and sLine ~= 'exit' then
|
||||||
history.add(sLine)
|
history:add(sLine)
|
||||||
end
|
end
|
||||||
term.setTextColour(_colors.textColor)
|
term.setTextColour(_colors.textColor)
|
||||||
if #sLine > 0 then
|
if #sLine > 0 then
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ local function snmpConnection(socket)
|
|||||||
socket:write('pong')
|
socket:write('pong')
|
||||||
|
|
||||||
elseif msg.type == 'script' then
|
elseif msg.type == 'script' then
|
||||||
|
|
||||||
local fn, msg = loadstring(msg.args, 'script')
|
local fn, msg = loadstring(msg.args, 'script')
|
||||||
if fn then
|
if fn then
|
||||||
multishell.openTab({
|
multishell.openTab({
|
||||||
@@ -38,6 +37,21 @@ local function snmpConnection(socket)
|
|||||||
printError(msg)
|
printError(msg)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
elseif msg.type == 'scriptEx' then
|
||||||
|
local s, m = pcall(function()
|
||||||
|
local env = setmetatable(Util.shallowCopy(getfenv(1)), { __index = _G })
|
||||||
|
local fn, m = load(msg.args, 'script', nil, env)
|
||||||
|
if not fn then
|
||||||
|
error(m)
|
||||||
|
end
|
||||||
|
return { fn() }
|
||||||
|
end)
|
||||||
|
if s then
|
||||||
|
socket:write(m)
|
||||||
|
else
|
||||||
|
socket:write({ s, m })
|
||||||
|
end
|
||||||
|
|
||||||
elseif msg.type == 'gps' then
|
elseif msg.type == 'gps' then
|
||||||
if gpsRequested then
|
if gpsRequested then
|
||||||
repeat
|
repeat
|
||||||
|
|||||||
Reference in New Issue
Block a user