ui improvements

This commit is contained in:
kepler155c@gmail.com 2017-10-03 00:50:54 -04:00
parent c0baa00668
commit 8e381d3ebf
10 changed files with 393 additions and 228 deletions

55
sys/apis/ansi.lua Normal file
View 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

View File

@ -1,47 +1,50 @@
local Util = require('util')
local History = { }
local History = { }
local History_mt = { __index = History }
function History.load(filename, limit)
local entries = Util.readLines(filename) or { }
local pos = #entries + 1
local self = setmetatable({
limit = limit,
filename = filename,
}, History_mt)
return {
entries = entries,
self.entries = Util.readLines(filename) or { }
self.pos = #self.entries + 1
add = function(line)
local last = entries[pos] or entries[pos - 1]
if not last or line ~= last then
table.insert(entries, line)
if limit then
while #entries > limit do
table.remove(entries, 1)
end
end
Util.writeLines(filename, entries)
pos = #entries + 1
return self
end
function History:add(line)
if line ~= self.entries[#self.entries] then
table.insert(self.entries, line)
if self.limit then
while #self.entries > self.limit do
table.remove(self.entries, 1)
end
end,
end
Util.writeLines(self.filename, self.entries)
self.pos = #self.entries + 1
end
end
setPosition = function(p)
pos = p
end,
function History:reset()
self.pos = #self.entries + 1
end
back = function()
if pos > 1 then
pos = pos - 1
return entries[pos]
end
end,
function History:back()
if self.pos > 1 then
self.pos = self.pos - 1
return self.entries[self.pos]
end
end
forward = function()
if pos <= #entries then
pos = pos + 1
return entries[pos]
end
end,
}
function History:forward()
if self.pos <= #self.entries then
self.pos = self.pos + 1
return self.entries[self.pos]
end
end
return History

View File

@ -1,8 +1,9 @@
local Util = require('util')
local Ansi = require('ansi')
local class = require('class')
local Event = require('event')
local Tween = require('ui.tween')
local Region = require('ui.region')
local Tween = require('ui.tween')
local Util = require('util')
local mapColorToGray = {
[ colors.white ] = colors.white,
@ -725,15 +726,6 @@ function UI.Window:centeredWrite(y, text, bg, fg)
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)
indent = indent or 1
@ -752,40 +744,73 @@ function UI.Window:print(text, bg, fg, indent)
end
end
--[[
TODO
local test = "\027[0;1;33mYou tell foo, \"// Test string.\"\027[0;37mbar"
for sequence, text in string.gmatch (test, "\027%[([0-9;]+)m([^\027]+)") do
for ansi in string.gmatch (sequence, "%d+") do
print ("ANSI code: ", ansi)
end -- for
print ("Text: ", text)
local function pieces(f, bg, fg)
local pos = 1
local t = { }
while true do
local s = f:find('\027', pos)
if not s then
break
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
--]]
local lines = Util.split(text)
for k,line in pairs(lines) do
local lx = 1
while true do
local word = nextWord(line, lx)
if not word then
if lines[k + 1] then
self.cursorX = indent
self.cursorY = self.cursorY + 1
local fragments = pieces(line, bg, fg)
for l, fragment in ipairs(fragments) do
local lx = 1
if type(fragment) == 'table' then -- ansi sequence
fg = fragment.fg
bg = fragment.bg
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
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
if lines[k + 1] then
self.cursorX = indent
self.cursorY = self.cursorY + 1
end
end
return self.cursorX, self.cursorY
end
function UI.Window:setFocus(focus)
@ -852,22 +877,24 @@ function UI.Window:scrollIntoView()
end
end
function UI.Window:addTransition(effect, x, y, width, height)
function UI.Window:addTransition(effect, args)
if self.parent then
x = x or 1
y = y or 1
width = width or self.width
height = height or self.height
self.parent:addTransition(effect, x + self.x - 1, y + self.y - 1, width, height)
args = args or { }
if not args.x then -- not good
args.x, args.y = getPosition(self)
args.width = self.width
args.height = self.height
end
args.canvas = args.canvas or self.canvas
self.parent:addTransition(effect, args)
end
end
function UI.Window:emit(event)
local parent = self
--debug(self.UIElement .. ' emitting ' .. event.type)
while parent do
if parent.eventHandler then
--debug('calling ' .. parent.UIElement)
if parent:eventHandler(event) then
return true
end
@ -1089,13 +1116,16 @@ function Canvas:blit(device, src, tgt)
for i = 0, src.ey - src.y do
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
if src.x > 1 or src.ex < self.ex then
t = t:sub(src.x, src.ex)
fg = fg:sub(src.x, src.ex)
bg = bg:sub(src.x, src.ex)
end
--if tgt.y + i > self.ey then -- wrong place to do clipping ??
-- break
--end
device.setCursorPos(tgt.x, tgt.y + i)
device.blit(t, fg, bg)
end
@ -1106,7 +1136,7 @@ end
UI.TransitionSlideLeft = class()
UI.TransitionSlideLeft.defaults = {
UIElement = 'TransitionSlideLeft',
ticks = 4,
ticks = 6,
easing = 'outQuint',
}
function UI.TransitionSlideLeft:init(args)
@ -1146,7 +1176,7 @@ end
UI.TransitionSlideRight = class()
UI.TransitionSlideRight.defaults = {
UIElement = 'TransitionSlideRight',
ticks = 4,
ticks = 6,
easing = 'outQuint',
}
function UI.TransitionSlideRight:init(args)
@ -1201,6 +1231,31 @@ function UI.TransitionExpandUp:update(device)
return self.pos.y ~= self.y
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 --]]--
UI.Device = class(UI.Window)
UI.Device.defaults = {
@ -1271,26 +1326,33 @@ function UI.Device:reset()
self.device.setCursorPos(1, 1)
end
function UI.Device:addTransition(effect, x, y, width, height)
-- refactor into canvas...
function UI.Device:addTransition(effect, args)
if not self.transitions then
self.transitions = { }
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
local c
if effect == 'slideLeft' then
c = UI.TransitionSlideLeft
else
c = UI.TransitionSlideRight
end
effect = c {
x = x,
y = y,
ex = x + width - 1,
ey = y + height - 1,
canvas = self.canvas,
local transitions = {
slideLeft = UI.TransitionSlideLeft,
slideRight = UI.TransitionSlideRight,
expandUp = UI.TransitionExpandUp,
grow = UI.TransitionGrow,
}
local c = transitions[effect]
if not c then
error('Invalid transition: ' .. effect)
end
effect = c(args)
else
Util.merge(effect, args)
end
table.insert(self.transitions, effect)
end
@ -1335,8 +1397,8 @@ function UI.Device:sync()
end
if self:getCursorBlink() then
self.device.setCursorBlink(true)
self.device.setCursorPos(self.cursorX, self.cursorY)
self.device.setCursorBlink(true)
end
end
@ -1954,10 +2016,10 @@ UI.ScrollingGrid.defaults = {
sliderChar = '#',
upArrowChar = '^',
downArrowChar = 'v',
scrollbarColor = colors.lightGray,
}
function UI.ScrollingGrid:init(args)
local defaults = UI:getDefaults(UI.ScrollingGrid, args)
UI.Grid.init(self, defaults)
UI.Grid.init(self, UI:getDefaults(UI.ScrollingGrid, args))
end
function UI.ScrollingGrid:drawRows()
@ -1968,44 +2030,36 @@ end
function UI.ScrollingGrid:drawScrollbar()
local ts = Util.size(self.values)
if ts > self.pageSize then
local sbSize = self.pageSize - 2
local sa = ts
sa = self.pageSize / sa
sa = math.floor(sbSize * sa)
if sa < 1 then
sa = 1
local maxScroll = ts - self.pageSize
local percent = (self.scrollOffset - 1) / maxScroll
local sliderSize = self.pageSize / ts * (self.pageSize - 2)
local row = 2
if self.disableHeader then
row = 1
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
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
self:write(x, 2, self.upArrowChar)
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
color = colors.white
end
self:write(x, 2, self.upArrowChar, nil, color)
color = self.scrollbarColor
if self.scrollOffset + self.pageSize - 1 < Util.size(self.values) then
self:write(x, self.pageSize + 1, self.downArrowChar)
else
self:write(x, self.pageSize + 1, ' ')
color = colors.white
end
self:write(x, self.pageSize + 1, self.downArrowChar, nil, color)
end
end
@ -2035,6 +2089,31 @@ function UI.ScrollingGrid:setIndex(index)
UI.Grid.setIndex(self, index)
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 --]]--
UI.Menu = class(UI.Grid)
UI.Menu.defaults = {
@ -2591,14 +2670,7 @@ function UI.Notification:display(value, timeout)
-- 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:addTransition(UI.TransitionExpandUp {
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:addTransition('expandUp', { ticks = self.height })
self.canvas:setVisible(true)
self:clear()
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)
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 --]]--
UI.Form = class(UI.Window)
UI.Form.defaults = {
@ -3347,8 +3442,6 @@ function UI.Dialog:init(args)
defaults.width = UI.term.width-11
end
defaults.titleBar = UI.TitleBar({ previousPage = true, title = defaults.title })
--UI.setProperties(defaults, args)
UI.Page.init(self, defaults)
end
@ -3358,6 +3451,11 @@ function UI.Dialog:setParent()
self.y = math.floor((self.parent.height - self.height) / 2) + 1
end
function UI.Dialog:enable(...)
self:addTransition('grow')
UI.Page.enable(self, ...)
end
function UI.Dialog:eventHandler(event)
if event.type == 'cancel' then
UI:setPreviousPage()

View File

@ -53,7 +53,7 @@ return function(args)
function selectFile:enable(path, fn)
self:setPath(path)
self.fn = fn
UI.Page.enable(self)
UI.Dialog.enable(self)
end
function selectFile:setPath(path)
@ -133,7 +133,7 @@ return function(args)
UI:setPreviousPage()
self.fn()
else
return UI.Page.eventHandler(self, event)
return UI.Dialog.eventHandler(self, event)
end
return true
end

View File

@ -473,27 +473,25 @@ end
-- word wrapping based on:
-- https://www.rosettacode.org/wiki/Word_wrap#Lua and
-- 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)
linewidth = linewidth or 75
local spaceleft = linewidth
local line = {}
local line = { }
for _, word in ipairs(splittokens(text)) do
if #word + 1 > spaceleft then
for word in text:gmatch("%S+") do
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, ' '))
line = { word }
spaceleft = linewidth - #word
spaceleft = linewidth - len - 1
else
table.insert(line, word)
spaceleft = spaceleft - (#word + 1)
spaceleft = spaceleft - len
end
end

View File

@ -143,7 +143,7 @@ function Browser.grid:eventHandler(event)
if event.type == 'copy' then -- let copy be handled by parent
return false
end
return UI.Grid.eventHandler(self, event)
return UI.ScrollingGrid.eventHandler(self, event)
end
function Browser.statusBar:draw()

View File

@ -8,6 +8,7 @@ local Util = require('util')
local sandboxEnv = setmetatable(Util.shallowCopy(getfenv(1)), { __index = _G })
sandboxEnv.exit = function() Event.exitPullEvents() end
sandboxEnv._echo = function( ... ) return ... end
requireInjector(sandboxEnv)
multishell.setTitle(multishell.getCurrent(), 'Lua')
@ -16,15 +17,15 @@ UI:configure('Lua', ...)
local command = ''
local history = History.load('usr/.lua_history', 25)
local page = UI.Page({
menuBar = UI.MenuBar({
local page = UI.Page {
menuBar = UI.MenuBar {
buttons = {
{ text = 'Local', event = 'local' },
{ text = 'Global', event = 'global' },
{ text = 'Device', event = 'device', name = 'Device' },
},
}),
prompt = UI.TextEntry({
},
prompt = UI.TextEntry {
y = 2,
shadowText = 'enter command',
limit = 256,
@ -35,8 +36,8 @@ local page = UI.Page({
mouse_rightclick = 'clear_prompt',
-- [ 'control-space' ] = 'autocomplete',
},
}),
grid = UI.ScrollingGrid({
},
grid = UI.ScrollingGrid {
y = 3,
columns = {
{ heading = 'Key', key = 'name' },
@ -44,9 +45,9 @@ local page = UI.Page({
},
sortColumn = 'name',
autospace = true,
}),
},
notification = UI.Notification(),
})
}
function page:setPrompt(value, focus)
self.prompt:setValue(value)
@ -138,23 +139,24 @@ function page:eventHandler(event)
self:executeStatement('device')
elseif event.type == 'history_back' then
local value = history.back()
local value = history:back()
if value then
self:setPrompt(value)
end
elseif event.type == 'history_forward' then
self:setPrompt(history.forward() or '')
self:setPrompt(history:forward() or '')
elseif event.type == 'clear_prompt' then
self:setPrompt('')
history.setPosition(#history.entries + 1)
history:reset()
elseif event.type == 'command_enter' then
local s = tostring(self.prompt.value)
if #s > 0 then
history.add(s)
history:add(s)
history:back()
self:executeStatement(s)
else
local t = { }
@ -166,7 +168,7 @@ function page:eventHandler(event)
pos = k,
})
end
history.setPosition(#history.entries + 1)
history:reset()
command = nil
self.grid:setValues(t)
self.grid:setIndex(1)
@ -228,7 +230,7 @@ function page.grid:eventHandler(event)
local function commandAppend()
if entry.isHistory then
history.setPosition(entry.pos)
--history.setPosition(entry.pos)
return entry.value
end
if type(entry.rawValue) == 'function' then
@ -262,15 +264,14 @@ function page.grid:eventHandler(event)
clipboard.setData(entry.rawValue)
end
else
return UI.Grid.eventHandler(self, event)
return UI.ScrollingGrid.eventHandler(self, event)
end
return true
end
function page:rawExecute(s)
local fn, m = loadstring('return (' .. s .. ')', 'lua')
local fn, m = load('return _echo(' ..s.. ');', 'lua', nil, sandboxEnv)
if fn then
setfenv(fn, sandboxEnv)
m = { pcall(fn) }
fn = table.remove(m, 1)
if #m == 1 then
@ -279,9 +280,8 @@ function page:rawExecute(s)
return fn, m
end
fn, m = loadstring(s, 'lua')
fn, m = load(s, 'lua', nil, sandboxEnv)
if fn then
setfenv(fn, sandboxEnv)
fn, m = pcall(fn)
end

View File

@ -270,11 +270,23 @@ function page.container:setCategory(categoryName)
local col, row = gutter, 2
local count = #self.children
local r = math.random(1, 4)
-- reposition all children
for k,child in ipairs(self.children) do
child.x = self.width
child.y = math.floor(self.height)
child.tween = Tween.new(6, child, { x = col, y = row }, 'outSine')
if r == 1 then
child.x = math.random(1, self.width)
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
col = col + child.width
@ -286,25 +298,25 @@ function page.container:setCategory(categoryName)
end
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
function page.container:draw()
if self.animate then
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
UI.ViewportWindow.draw(self)
end
function page:refresh()
@ -442,10 +454,7 @@ local editor = UI.Dialog {
text = 'Icon', event = 'loadIcon', help = 'Select icon'
},
image = UI.NftImage {
y = 6,
x = 2,
height = 3,
width = 8,
y = 6, x = 2, height = 3, width = 8,
},
},
statusBar = UI.StatusBar(),
@ -462,7 +471,7 @@ function editor:enable(app)
end
self.form.image:setImage(icon)
end
UI.Page.enable(self)
UI.Dialog.enable(self)
self:focusFirst()
end
@ -531,7 +540,7 @@ function editor:eventHandler(event)
page:refresh()
page:draw()
else
return UI.Page.eventHandler(self, event)
return UI.Dialog.eventHandler(self, event)
end
return true
end

View File

@ -489,17 +489,18 @@ local function autocomplete(line, suggestions)
end
end
local function shellRead(_tHistory )
local function shellRead(history)
term.setCursorBlink( true )
local sLine = ""
local nHistoryPos
local nPos = 0
local lastPattern
local w = term.getSize()
local sx = term.getCursorPos()
history:reset()
local function redraw( sReplace )
local nScroll = 0
if sx + nPos >= w then
@ -563,32 +564,19 @@ local function shellRead(_tHistory )
redraw()
end
elseif param == keys.up or param == keys.down then
if _tHistory then
redraw(" ")
if param == keys.up then
if nHistoryPos == nil then
if #_tHistory > 0 then
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()
redraw(" ")
if param == keys.up then
sLine = history:back()
else
sLine = history:forward()
end
if sLine then
nPos = string.len(sLine)
else
sLine = ""
nPos = 0
end
redraw()
elseif param == keys.backspace then
if nPos > 0 then
redraw(" ")
@ -637,13 +625,13 @@ while not bExit do
write("$ " )
term.setTextColour(_colors.commandTextColor)
term.setBackgroundColor(colors.black)
local sLine = shellRead(history.entries)
local sLine = shellRead(history)
if bExit then -- terminated
break
end
sLine = Util.trim(sLine)
if #sLine > 0 and sLine ~= 'exit' then
history.add(sLine)
history:add(sLine)
end
term.setTextColour(_colors.textColor)
if #sLine > 0 then

View File

@ -26,7 +26,6 @@ local function snmpConnection(socket)
socket:write('pong')
elseif msg.type == 'script' then
local fn, msg = loadstring(msg.args, 'script')
if fn then
multishell.openTab({
@ -38,6 +37,21 @@ local function snmpConnection(socket)
printError(msg)
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
if gpsRequested then
repeat