Lots of shit
This commit is contained in:
250
lib/basalt/libraries/basaltDraw.lua
Normal file
250
lib/basalt/libraries/basaltDraw.lua
Normal file
@@ -0,0 +1,250 @@
|
||||
local tHex = require("tHex")
|
||||
local utils = require("utils")
|
||||
local split = utils.splitString
|
||||
local sub,rep = string.sub,string.rep
|
||||
|
||||
return function(drawTerm)
|
||||
local terminal = drawTerm or term.current()
|
||||
local mirrorTerm
|
||||
local width, height = terminal.getSize()
|
||||
local cacheT = {}
|
||||
local cacheBG = {}
|
||||
local cacheFG = {}
|
||||
|
||||
local emptySpaceLine
|
||||
local emptyColorLines = {}
|
||||
|
||||
local function createEmptyLines()
|
||||
emptySpaceLine = rep(" ", width)
|
||||
for n = 0, 15 do
|
||||
local nColor = 2 ^ n
|
||||
local sHex = tHex[nColor]
|
||||
emptyColorLines[nColor] = rep(sHex, width)
|
||||
end
|
||||
end
|
||||
----
|
||||
createEmptyLines()
|
||||
|
||||
local function recreateWindowArray()
|
||||
createEmptyLines()
|
||||
local emptyText = emptySpaceLine
|
||||
local emptyFG = emptyColorLines[colors.white]
|
||||
local emptyBG = emptyColorLines[colors.black]
|
||||
for currentY = 1, height do
|
||||
cacheT[currentY] = sub(cacheT[currentY] == nil and emptyText or cacheT[currentY] .. emptyText:sub(1, width - cacheT[currentY]:len()), 1, width)
|
||||
cacheFG[currentY] = sub(cacheFG[currentY] == nil and emptyFG or cacheFG[currentY] .. emptyFG:sub(1, width - cacheFG[currentY]:len()), 1, width)
|
||||
cacheBG[currentY] = sub(cacheBG[currentY] == nil and emptyBG or cacheBG[currentY] .. emptyBG:sub(1, width - cacheBG[currentY]:len()), 1, width)
|
||||
end
|
||||
end
|
||||
recreateWindowArray()
|
||||
|
||||
local function blit(x, y, t, fg, bg)
|
||||
if #t == #fg and #t == #bg then
|
||||
if y >= 1 and y <= height then
|
||||
if x + #t > 0 and x <= width then
|
||||
local newCacheT, newCacheFG, newCacheBG
|
||||
local oldCacheT, oldCacheFG, oldCacheBG = cacheT[y], cacheFG[y], cacheBG[y]
|
||||
local startN, endN = 1, #t
|
||||
|
||||
if x < 1 then
|
||||
startN = 1 - x + 1
|
||||
endN = width - x + 1
|
||||
elseif x + #t > width then
|
||||
endN = width - x + 1
|
||||
end
|
||||
|
||||
newCacheT = sub(oldCacheT, 1, x - 1) .. sub(t, startN, endN)
|
||||
newCacheFG = sub(oldCacheFG, 1, x - 1) .. sub(fg, startN, endN)
|
||||
newCacheBG = sub(oldCacheBG, 1, x - 1) .. sub(bg, startN, endN)
|
||||
|
||||
if x + #t <= width then
|
||||
newCacheT = newCacheT .. sub(oldCacheT, x + #t, width)
|
||||
newCacheFG = newCacheFG .. sub(oldCacheFG, x + #t, width)
|
||||
newCacheBG = newCacheBG .. sub(oldCacheBG, x + #t, width)
|
||||
end
|
||||
|
||||
cacheT[y], cacheFG[y], cacheBG[y] = newCacheT,newCacheFG,newCacheBG
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function setText(x, y, t)
|
||||
if y >= 1 and y <= height then
|
||||
if x + #t > 0 and x <= width then
|
||||
local newCacheT
|
||||
local oldCacheT = cacheT[y]
|
||||
local startN, endN = 1, #t
|
||||
|
||||
if x < 1 then
|
||||
startN = 1 - x + 1
|
||||
endN = width - x + 1
|
||||
elseif x + #t > width then
|
||||
endN = width - x + 1
|
||||
end
|
||||
|
||||
newCacheT = sub(oldCacheT, 1, x - 1) .. sub(t, startN, endN)
|
||||
|
||||
if x + #t <= width then
|
||||
newCacheT = newCacheT .. sub(oldCacheT, x + #t, width)
|
||||
end
|
||||
|
||||
cacheT[y] = newCacheT
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function setBG(x, y, bg)
|
||||
if y >= 1 and y <= height then
|
||||
if x + #bg > 0 and x <= width then
|
||||
local newCacheBG
|
||||
local oldCacheBG = cacheBG[y]
|
||||
local startN, endN = 1, #bg
|
||||
|
||||
if x < 1 then
|
||||
startN = 1 - x + 1
|
||||
endN = width - x + 1
|
||||
elseif x + #bg > width then
|
||||
endN = width - x + 1
|
||||
end
|
||||
|
||||
newCacheBG = sub(oldCacheBG, 1, x - 1) .. sub(bg, startN, endN)
|
||||
|
||||
if x + #bg <= width then
|
||||
newCacheBG = newCacheBG .. sub(oldCacheBG, x + #bg, width)
|
||||
end
|
||||
|
||||
cacheBG[y] = newCacheBG
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function setFG(x, y, fg)
|
||||
if y >= 1 and y <= height then
|
||||
if x + #fg > 0 and x <= width then
|
||||
local newCacheFG
|
||||
local oldCacheFG = cacheFG[y]
|
||||
local startN, endN = 1, #fg
|
||||
|
||||
if x < 1 then
|
||||
startN = 1 - x + 1
|
||||
endN = width - x + 1
|
||||
elseif x + #fg > width then
|
||||
endN = width - x + 1
|
||||
end
|
||||
|
||||
newCacheFG = sub(oldCacheFG, 1, x - 1) .. sub(fg, startN, endN)
|
||||
|
||||
if x + #fg <= width then
|
||||
newCacheFG = newCacheFG .. sub(oldCacheFG, x + #fg, width)
|
||||
end
|
||||
|
||||
cacheFG[y] = newCacheFG
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
local function setText(x, y, text)
|
||||
if (y >= 1) and (y <= height) then
|
||||
local emptyLine = rep(" ", #text)
|
||||
blit(x, y, text, emptyLine, emptyLine)
|
||||
end
|
||||
end
|
||||
|
||||
local function setFG(x, y, colorStr)
|
||||
if (y >= 1) and (y <= height) then
|
||||
local w = #colorStr
|
||||
local emptyLine = rep(" ", w)
|
||||
local text = sub(cacheT[y], x, w)
|
||||
blit(x, y, text, colorStr, emptyLine)
|
||||
end
|
||||
end
|
||||
|
||||
local function setBG(x, y, colorStr)
|
||||
if (y >= 1) and (y <= height) then
|
||||
local w = #colorStr
|
||||
local emptyLine = rep(" ", w)
|
||||
local text = sub(cacheT[y], x, w)
|
||||
blit(x, y, text, emptyLine, colorStr)
|
||||
end
|
||||
end]]
|
||||
|
||||
local drawHelper = {
|
||||
setSize = function(w, h)
|
||||
width, height = w, h
|
||||
recreateWindowArray()
|
||||
end,
|
||||
|
||||
setMirror = function(mirror)
|
||||
mirrorTerm = mirror
|
||||
end,
|
||||
|
||||
setBG = function(x, y, colorStr)
|
||||
setBG(x, y, colorStr)
|
||||
end,
|
||||
|
||||
setText = function(x, y, text)
|
||||
setText(x, y, text)
|
||||
end,
|
||||
|
||||
setFG = function(x, y, colorStr)
|
||||
setFG(x, y, colorStr)
|
||||
end;
|
||||
|
||||
blit = function(x, y, t, fg, bg)
|
||||
blit(x, y, t, fg, bg)
|
||||
end,
|
||||
|
||||
drawBackgroundBox = function(x, y, width, height, bgCol)
|
||||
local colorStr = rep(tHex[bgCol], width)
|
||||
for n = 1, height do
|
||||
setBG(x, y + (n - 1), colorStr)
|
||||
end
|
||||
end,
|
||||
drawForegroundBox = function(x, y, width, height, fgCol)
|
||||
local colorStr = rep(tHex[fgCol], width)
|
||||
for n = 1, height do
|
||||
setFG(x, y + (n - 1), colorStr)
|
||||
end
|
||||
end,
|
||||
drawTextBox = function(x, y, width, height, symbol)
|
||||
local textStr = rep(symbol, width)
|
||||
for n = 1, height do
|
||||
setText(x, y + (n - 1), textStr)
|
||||
end
|
||||
end,
|
||||
|
||||
update = function()
|
||||
local xC, yC = terminal.getCursorPos()
|
||||
local isBlinking = false
|
||||
if (terminal.getCursorBlink ~= nil) then
|
||||
isBlinking = terminal.getCursorBlink()
|
||||
end
|
||||
terminal.setCursorBlink(false)
|
||||
if(mirrorTerm~=nil)then mirrorTerm.setCursorBlink(false) end
|
||||
for n = 1, height do
|
||||
terminal.setCursorPos(1, n)
|
||||
terminal.blit(cacheT[n], cacheFG[n], cacheBG[n])
|
||||
if(mirrorTerm~=nil)then
|
||||
mirrorTerm.setCursorPos(1, n)
|
||||
mirrorTerm.blit(cacheT[n], cacheFG[n], cacheBG[n])
|
||||
end
|
||||
end
|
||||
terminal.setBackgroundColor(colors.black)
|
||||
terminal.setCursorBlink(isBlinking)
|
||||
terminal.setCursorPos(xC, yC)
|
||||
if(mirrorTerm~=nil)then
|
||||
mirrorTerm.setBackgroundColor(colors.black)
|
||||
mirrorTerm.setCursorBlink(isBlinking)
|
||||
mirrorTerm.setCursorPos(xC, yC)
|
||||
end
|
||||
|
||||
end,
|
||||
|
||||
setTerm = function(newTerm)
|
||||
terminal = newTerm
|
||||
end,
|
||||
}
|
||||
return drawHelper
|
||||
end
|
||||
55
lib/basalt/libraries/basaltEvent.lua
Normal file
55
lib/basalt/libraries/basaltEvent.lua
Normal file
@@ -0,0 +1,55 @@
|
||||
return function()
|
||||
local events = {}
|
||||
|
||||
local event = {
|
||||
registerEvent = function(self, _event, func)
|
||||
if (events[_event] == nil) then
|
||||
events[_event] = {}
|
||||
end
|
||||
table.insert(events[_event], func)
|
||||
end,
|
||||
|
||||
removeEvent = function(self, _event, index)
|
||||
events[_event][index[_event]] = nil
|
||||
end,
|
||||
|
||||
hasEvent = function(self, _event)
|
||||
return events[_event]~=nil
|
||||
end,
|
||||
|
||||
getEventCount = function(self, _event)
|
||||
return events[_event]~=nil and #events[_event] or 0
|
||||
end,
|
||||
|
||||
getEvents = function(self)
|
||||
local t = {}
|
||||
for k,v in pairs(events)do
|
||||
table.insert(t, k)
|
||||
end
|
||||
return t
|
||||
end,
|
||||
|
||||
clearEvent = function(self, _event)
|
||||
events[_event] = nil
|
||||
end,
|
||||
|
||||
clear = function(self, _event)
|
||||
events = {}
|
||||
end,
|
||||
|
||||
sendEvent = function(self, _event, ...)
|
||||
local returnValue
|
||||
if (events[_event] ~= nil) then
|
||||
for _, value in pairs(events[_event]) do
|
||||
local val = value(...)
|
||||
if(val==false)then
|
||||
returnValue = val
|
||||
end
|
||||
end
|
||||
end
|
||||
return returnValue
|
||||
end,
|
||||
}
|
||||
event.__index = event
|
||||
return event
|
||||
end
|
||||
20
lib/basalt/libraries/basaltLogs.lua
Normal file
20
lib/basalt/libraries/basaltLogs.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
local logDir = ""
|
||||
local logFileName = "basaltLog.txt"
|
||||
|
||||
local defaultLogType = "Debug"
|
||||
|
||||
fs.delete(logDir~="" and logDir.."/"..logFileName or logFileName)
|
||||
|
||||
local mt = {
|
||||
__call = function(_,text, typ)
|
||||
if(text==nil)then return end
|
||||
local dirStr = logDir~="" and logDir.."/"..logFileName or logFileName
|
||||
local handle = fs.open(dirStr, fs.exists(dirStr) and "a" or "w")
|
||||
handle.writeLine("[Basalt]["..os.date("%Y-%m-%d %H:%M:%S").."]["..(typ and typ or defaultLogType).."]: "..tostring(text))
|
||||
handle.close()
|
||||
end,
|
||||
}
|
||||
|
||||
return setmetatable({}, mt)
|
||||
|
||||
--Work in progress
|
||||
199
lib/basalt/libraries/basaltMon.lua
Normal file
199
lib/basalt/libraries/basaltMon.lua
Normal file
@@ -0,0 +1,199 @@
|
||||
-- Right now this doesn't support scroll(n)
|
||||
-- Because this lbirary is mainly made for basalt - it doesn't need scroll support, maybe i will add it in the future
|
||||
|
||||
local tHex = {
|
||||
[colors.white] = "0",
|
||||
[colors.orange] = "1",
|
||||
[colors.magenta] = "2",
|
||||
[colors.lightBlue] = "3",
|
||||
[colors.yellow] = "4",
|
||||
[colors.lime] = "5",
|
||||
[colors.pink] = "6",
|
||||
[colors.gray] = "7",
|
||||
[colors.lightGray] = "8",
|
||||
[colors.cyan] = "9",
|
||||
[colors.purple] = "a",
|
||||
[colors.blue] = "b",
|
||||
[colors.brown] = "c",
|
||||
[colors.green] = "d",
|
||||
[colors.red] = "e",
|
||||
[colors.black] = "f",
|
||||
}
|
||||
|
||||
local type,len,rep,sub = type,string.len,string.rep,string.sub
|
||||
|
||||
|
||||
return function (monitorNames)
|
||||
local monitors = {}
|
||||
for k,v in pairs(monitorNames)do
|
||||
monitors[k] = {}
|
||||
for a,b in pairs(v)do
|
||||
local mon = peripheral.wrap(b)
|
||||
if(mon==nil)then
|
||||
error("Unable to find monitor "..b)
|
||||
end
|
||||
monitors[k][a] = mon
|
||||
monitors[k][a].name = b
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local x,y,monX,monY,monW,monH,w,h = 1,1,1,1,0,0,0,0
|
||||
local blink,scale = false,1
|
||||
local fg,bg = colors.white,colors.black
|
||||
|
||||
|
||||
local function calcSize()
|
||||
local maxW,maxH = 0,0
|
||||
for k,v in pairs(monitors)do
|
||||
local _maxW,_maxH = 0,0
|
||||
for a,b in pairs(v)do
|
||||
local nw,nh = b.getSize()
|
||||
_maxW = _maxW + nw
|
||||
_maxH = nh > _maxH and nh or _maxH
|
||||
end
|
||||
maxW = maxW > _maxW and maxW or _maxW
|
||||
maxH = maxH + _maxH
|
||||
end
|
||||
w,h = maxW,maxH
|
||||
end
|
||||
calcSize()
|
||||
|
||||
local function calcPosition()
|
||||
local relY = 0
|
||||
local mX,mY = 0,0
|
||||
for k,v in pairs(monitors)do
|
||||
local relX = 0
|
||||
local _mh = 0
|
||||
for a,b in pairs(v)do
|
||||
local mw,mh = b.getSize()
|
||||
if(x-relX>=1)and(x-relX<=mw)then
|
||||
mX = a
|
||||
end
|
||||
b.setCursorPos(x-relX, y-relY)
|
||||
relX = relX + mw
|
||||
if(_mh<mh)then _mh = mh end
|
||||
end
|
||||
if(y-relY>=1)and(y-relY<=_mh)then
|
||||
mY = k
|
||||
end
|
||||
relY = relY + _mh
|
||||
end
|
||||
monX,monY = mX,mY
|
||||
end
|
||||
calcPosition()
|
||||
|
||||
local function call(f, ...)
|
||||
local t = {...}
|
||||
return function()
|
||||
for k,v in pairs(monitors)do
|
||||
for a,b in pairs(v)do
|
||||
b[f](table.unpack(t))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function cursorBlink()
|
||||
call("setCursorBlink", false)()
|
||||
if not(blink)then return end
|
||||
if(monitors[monY]==nil)then return end
|
||||
local mon = monitors[monY][monX]
|
||||
if(mon==nil)then return end
|
||||
mon.setCursorBlink(blink)
|
||||
end
|
||||
|
||||
local function blit(text, tCol, bCol)
|
||||
if(monitors[monY]==nil)then return end
|
||||
local mon = monitors[monY][monX]
|
||||
if(mon==nil)then return end
|
||||
mon.blit(text, tCol, bCol)
|
||||
local mW, mH = mon.getSize()
|
||||
if(len(text)+x>mW)then
|
||||
local monRight = monitors[monY][monX+1]
|
||||
if(monRight~=nil)then
|
||||
monRight.blit(text, tCol, bCol)
|
||||
monX = monX + 1
|
||||
x = x + len(text)
|
||||
end
|
||||
end
|
||||
calcPosition()
|
||||
end
|
||||
|
||||
return {
|
||||
clear = call("clear"),
|
||||
|
||||
setCursorBlink = function(_blink)
|
||||
blink = _blink
|
||||
cursorBlink()
|
||||
end,
|
||||
|
||||
getCursorBlink = function()
|
||||
return blink
|
||||
end,
|
||||
|
||||
getCursorPos = function()
|
||||
return x, y
|
||||
end,
|
||||
|
||||
setCursorPos = function(newX,newY)
|
||||
x, y = newX, newY
|
||||
calcPosition()
|
||||
cursorBlink()
|
||||
end,
|
||||
|
||||
setTextScale = function(_scale)
|
||||
call("setTextScale", _scale)()
|
||||
calcSize()
|
||||
calcPosition()
|
||||
scale = _scale
|
||||
end,
|
||||
|
||||
getTextScale = function()
|
||||
return scale
|
||||
end,
|
||||
|
||||
blit = function(text,fgCol,bgCol)
|
||||
blit(text,fgCol,bgCol)
|
||||
end,
|
||||
|
||||
write = function(text)
|
||||
text = tostring(text)
|
||||
local l = len(text)
|
||||
blit(text, rep(tHex[fg], l), rep(tHex[bg], l))
|
||||
end,
|
||||
|
||||
getSize = function()
|
||||
return w,h
|
||||
end,
|
||||
|
||||
setBackgroundColor = function(col)
|
||||
call("setBackgroundColor", col)()
|
||||
bg = col
|
||||
end,
|
||||
|
||||
setTextColor = function(col)
|
||||
call("setTextColor", col)()
|
||||
fg = col
|
||||
end,
|
||||
|
||||
calculateClick = function(name, xClick, yClick)
|
||||
local relY = 0
|
||||
for k,v in pairs(monitors)do
|
||||
local relX = 0
|
||||
local maxY = 0
|
||||
for a,b in pairs(v)do
|
||||
local wM,hM = b.getSize()
|
||||
if(b.name==name)then
|
||||
return xClick + relX, yClick + relY
|
||||
end
|
||||
relX = relX + wM
|
||||
if(hM > maxY)then maxY = hM end
|
||||
end
|
||||
relY = relY + maxY
|
||||
end
|
||||
return xClick, yClick
|
||||
end,
|
||||
|
||||
}
|
||||
end
|
||||
390
lib/basalt/libraries/bimg.lua
Normal file
390
lib/basalt/libraries/bimg.lua
Normal file
@@ -0,0 +1,390 @@
|
||||
local sub,rep = string.sub,string.rep
|
||||
|
||||
local function frame(base, manager)
|
||||
local w, h = 0, 0
|
||||
local t,fg,bg = {}, {}, {}
|
||||
local x, y = 1,1
|
||||
|
||||
local data = {}
|
||||
|
||||
local function recalculateSize()
|
||||
for y=1,h do
|
||||
if(t[y]==nil)then
|
||||
t[y] = rep(" ", w)
|
||||
else
|
||||
t[y] = t[y]..rep(" ", w-#t[y])
|
||||
end
|
||||
if(fg[y]==nil)then
|
||||
fg[y] = rep("0", w)
|
||||
else
|
||||
fg[y] = fg[y]..rep("0", w-#fg[y])
|
||||
end
|
||||
if(bg[y]==nil)then
|
||||
bg[y] = rep("f", w)
|
||||
else
|
||||
bg[y] = bg[y]..rep("f", w-#bg[y])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local addText = function(text, _x, _y)
|
||||
x = _x or x
|
||||
y = _y or y
|
||||
if(t[y]==nil)then
|
||||
t[y] = rep(" ", x-1)..text..rep(" ", w-(#text+x))
|
||||
else
|
||||
t[y] = sub(t[y], 1, x-1)..rep(" ", x-#t[y])..text..sub(t[y], x+#text, w)
|
||||
end
|
||||
if(#t[y]>w)then w = #t[y] end
|
||||
if(y > h)then h = y end
|
||||
manager.updateSize(w, h)
|
||||
end
|
||||
|
||||
local addBg = function(b, _x, _y)
|
||||
x = _x or x
|
||||
y = _y or y
|
||||
if(bg[y]==nil)then
|
||||
bg[y] = rep("f", x-1)..b..rep("f", w-(#b+x))
|
||||
else
|
||||
bg[y] = sub(bg[y], 1, x-1)..rep("f", x-#bg[y])..b..sub(bg[y], x+#b, w)
|
||||
end
|
||||
if(#bg[y]>w)then w = #bg[y] end
|
||||
if(y > h)then h = y end
|
||||
manager.updateSize(w, h)
|
||||
end
|
||||
|
||||
local addFg = function(f, _x, _y)
|
||||
x = _x or x
|
||||
y = _y or y
|
||||
if(fg[y]==nil)then
|
||||
fg[y] = rep("0", x-1)..f..rep("0", w-(#f+x))
|
||||
else
|
||||
fg[y] = sub(fg[y], 1, x-1)..rep("0", x-#fg[y])..f..sub(fg[y], x+#f, w)
|
||||
end
|
||||
if(#fg[y]>w)then w = #fg[y] end
|
||||
if(y > h)then h = y end
|
||||
manager.updateSize(w, h)
|
||||
end
|
||||
|
||||
local function setFrame(frm)
|
||||
data = {}
|
||||
t, fg, bg = {}, {}, {}
|
||||
for k,v in pairs(base)do
|
||||
if(type(k)=="string")then
|
||||
data[k] = v
|
||||
else
|
||||
t[k], fg[k], bg[k] = v[1], v[2], v[3]
|
||||
end
|
||||
end
|
||||
manager.updateSize(w, h)
|
||||
end
|
||||
|
||||
if(base~=nil)then
|
||||
if(#base>0)then
|
||||
w = #base[1][1]
|
||||
h = #base
|
||||
setFrame(base)
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
recalculateSize = recalculateSize,
|
||||
setFrame = setFrame,
|
||||
|
||||
getFrame = function()
|
||||
local f = {}
|
||||
|
||||
for k,v in pairs(t)do
|
||||
table.insert(f, {v, fg[k], bg[k]})
|
||||
end
|
||||
|
||||
for k,v in pairs(data)do
|
||||
f[k] = v
|
||||
end
|
||||
|
||||
return f, w, h
|
||||
end,
|
||||
|
||||
getImage = function()
|
||||
local i = {}
|
||||
for k,v in pairs(t)do
|
||||
table.insert(i, {v, fg[k], bg[k]})
|
||||
end
|
||||
return i
|
||||
end,
|
||||
|
||||
setFrameData = function(key, value)
|
||||
if(value~=nil)then
|
||||
data[key] = value
|
||||
else
|
||||
if(type(key)=="table")then
|
||||
data = key
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
setFrameImage = function(imgData)
|
||||
for k,v in pairs(imgData.t)do
|
||||
t[k] = imgData.t[k]
|
||||
fg[k] = imgData.fg[k]
|
||||
bg[k] = imgData.bg[k]
|
||||
end
|
||||
end,
|
||||
|
||||
getFrameImage = function()
|
||||
return {t = t, fg = fg, bg = bg}
|
||||
end,
|
||||
|
||||
getFrameData = function(key)
|
||||
if(key~=nil)then
|
||||
return data[key]
|
||||
else
|
||||
return data
|
||||
end
|
||||
end,
|
||||
|
||||
blit = function(text, fgCol, bgCol, x, y)
|
||||
addText(text, x, y)
|
||||
addFg(fgCol, x, y)
|
||||
addBg(bgCol, x, y)
|
||||
end,
|
||||
|
||||
text = addText,
|
||||
fg = addFg,
|
||||
bg = addBg,
|
||||
|
||||
getSize = function()
|
||||
return w, h
|
||||
end,
|
||||
|
||||
setSize = function(_w, _h)
|
||||
local nt,nfg,nbg = {}, {}, {}
|
||||
for _y=1,_h do
|
||||
if(t[_y]~=nil)then
|
||||
nt[_y] = sub(t[_y], 1, _w)..rep(" ", _w - w)
|
||||
else
|
||||
nt[_y] = rep(" ", _w)
|
||||
end
|
||||
if(fg[_y]~=nil)then
|
||||
nfg[_y] = sub(fg[_y], 1, _w)..rep("0", _w - w)
|
||||
else
|
||||
nfg[_y] = rep("0", _w)
|
||||
end
|
||||
if(bg[_y]~=nil)then
|
||||
nbg[_y] = sub(bg[_y], 1, _w)..rep("f", _w - w)
|
||||
else
|
||||
nbg[_y] = rep("f", _w)
|
||||
end
|
||||
end
|
||||
t, fg, bg = nt, nfg, nbg
|
||||
w, h = _w, _h
|
||||
end,
|
||||
}
|
||||
end
|
||||
|
||||
return function(img)
|
||||
local frames = {}
|
||||
local metadata = {creator="Bimg Library by NyoriE", date=os.date("!%Y-%m-%dT%TZ")}
|
||||
local width,height = 0, 0
|
||||
|
||||
if(img~=nil)then
|
||||
if(img[1][1][1]~=nil)then
|
||||
width,height = metadata.width or #img[1][1][1], metadata.height or #img[1]
|
||||
end
|
||||
end
|
||||
|
||||
local manager = {}
|
||||
|
||||
local function addFrame(id, data)
|
||||
id = id or #frames+1
|
||||
local f = frame(data, manager)
|
||||
table.insert(frames, id, f)
|
||||
if(data==nil)then
|
||||
frames[id].setSize(width, height)
|
||||
end
|
||||
return f
|
||||
end
|
||||
|
||||
local function removeFrame(id)
|
||||
table.remove(frames, id or #frames)
|
||||
end
|
||||
|
||||
local function moveFrame(id, dir)
|
||||
local f = frames[id]
|
||||
if(f~=nil)then
|
||||
local newId = id+dir
|
||||
if(newId>=1)and(newId<=#frames)then
|
||||
table.remove(frames, id)
|
||||
table.insert(frames, newId, f)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
manager = {
|
||||
updateSize = function(w, h, force)
|
||||
local changed = force==true and true or false
|
||||
if(w > width)then changed = true width = w end
|
||||
if(h > height)then changed = true height = h end
|
||||
if(changed)then
|
||||
for k,v in pairs(frames)do
|
||||
v.setSize(width, height)
|
||||
v.recalculateSize()
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
text = function(frame, text, x, y)
|
||||
local f = frames[frame]
|
||||
if(f==nil)then
|
||||
f = addFrame(frame)
|
||||
end
|
||||
f.text(text, x, y)
|
||||
end,
|
||||
|
||||
fg = function(frame, fg, x, y)
|
||||
local f = frames[frame]
|
||||
if(f==nil)then
|
||||
f = addFrame(frame)
|
||||
end
|
||||
f.fg(fg, x, y)
|
||||
end,
|
||||
|
||||
bg = function(frame, bg, x, y)
|
||||
local f = frames[frame]
|
||||
if(f==nil)then
|
||||
f = addFrame(frame)
|
||||
end
|
||||
f.bg(bg, x, y)
|
||||
end,
|
||||
|
||||
blit = function(frame, text, fg, bg, x, y)
|
||||
local f = frames[frame]
|
||||
if(f==nil)then
|
||||
f = addFrame(frame)
|
||||
end
|
||||
f.blit(text, fg, bg, x, y)
|
||||
end,
|
||||
|
||||
setSize = function(w, h)
|
||||
width = w
|
||||
height = h
|
||||
for k,v in pairs(frames)do
|
||||
v.setSize(w, h)
|
||||
end
|
||||
end,
|
||||
|
||||
getFrame = function(id)
|
||||
if(frames[id]~=nil)then
|
||||
return frames[id].getFrame()
|
||||
end
|
||||
end,
|
||||
|
||||
getFrameObjects = function()
|
||||
return frames
|
||||
end,
|
||||
|
||||
getFrames = function()
|
||||
local f = {}
|
||||
for k,v in pairs(frames)do
|
||||
local frame = v.getFrame()
|
||||
table.insert(f, frame)
|
||||
end
|
||||
return f
|
||||
end,
|
||||
|
||||
getFrameObject = function(id)
|
||||
return frames[id]
|
||||
end,
|
||||
|
||||
addFrame = function(id)
|
||||
if(#frames<=1)then
|
||||
if(metadata.animated==nil)then
|
||||
metadata.animated = true
|
||||
end
|
||||
if(metadata.secondsPerFrame==nil)then
|
||||
metadata.secondsPerFrame = 0.2
|
||||
end
|
||||
end
|
||||
return addFrame(id)
|
||||
end,
|
||||
|
||||
removeFrame = removeFrame,
|
||||
|
||||
moveFrame = moveFrame,
|
||||
|
||||
setFrameData = function(id, key, value)
|
||||
if(frames[id]~=nil)then
|
||||
frames[id].setFrameData(key, value)
|
||||
end
|
||||
end,
|
||||
|
||||
getFrameData = function(id, key)
|
||||
if(frames[id]~=nil)then
|
||||
return frames[id].getFrameData(key)
|
||||
end
|
||||
end,
|
||||
|
||||
getSize = function()
|
||||
return width, height
|
||||
end,
|
||||
|
||||
setAnimation = function(anim)
|
||||
metadata.animation = anim
|
||||
end,
|
||||
|
||||
setMetadata = function(key, val)
|
||||
if(val~=nil)then
|
||||
metadata[key] = val
|
||||
else
|
||||
if(type(key)=="table")then
|
||||
metadata = key
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
getMetadata = function(key)
|
||||
if(key~=nil)then
|
||||
return metadata[key]
|
||||
else
|
||||
return metadata
|
||||
end
|
||||
end,
|
||||
|
||||
createBimg = function()
|
||||
local bimg = {}
|
||||
for k,v in pairs(frames)do
|
||||
local f = v.getFrame()
|
||||
table.insert(bimg, f)
|
||||
end
|
||||
for k,v in pairs(metadata)do
|
||||
bimg[k] = v
|
||||
end
|
||||
bimg.width = width
|
||||
bimg.height = height
|
||||
return bimg
|
||||
end,
|
||||
}
|
||||
|
||||
if(img~=nil)then
|
||||
for k,v in pairs(img)do
|
||||
if(type(k)=="string")then
|
||||
metadata[k] = v
|
||||
end
|
||||
end
|
||||
if(metadata.width==nil)or(metadata.height==nil)then
|
||||
width = metadata.width or #img[1][1][1]
|
||||
height = metadata.height or #img[1]
|
||||
manager.updateSize(width, height, true)
|
||||
end
|
||||
|
||||
for k,v in pairs(img)do
|
||||
if(type(k)=="number")then
|
||||
addFrame(k, v)
|
||||
end
|
||||
end
|
||||
else
|
||||
addFrame(1)
|
||||
end
|
||||
|
||||
return manager
|
||||
end
|
||||
87
lib/basalt/libraries/images.lua
Normal file
87
lib/basalt/libraries/images.lua
Normal file
@@ -0,0 +1,87 @@
|
||||
local sub,floor = string.sub,math.floor
|
||||
|
||||
local function loadNFPAsBimg(path)
|
||||
return {[1]={{}, {}, paintutils.loadImage(path)}}, "bimg"
|
||||
end
|
||||
|
||||
local function loadNFP(path)
|
||||
return paintutils.loadImage(path), "nfp"
|
||||
end
|
||||
|
||||
local function loadBIMG(path, binaryMode)
|
||||
local f = fs.open(path, binaryMode and "rb" or "r")
|
||||
if(f==nil)then error("Path - "..path.." doesn't exist!") end
|
||||
local content = textutils.unserialize(f.readAll())
|
||||
|
||||
f.close()
|
||||
if(content~=nil)then
|
||||
return content, "bimg"
|
||||
end
|
||||
end
|
||||
|
||||
local function loadBBF(path)
|
||||
|
||||
end
|
||||
|
||||
local function loadBBFAsBimg(path)
|
||||
|
||||
end
|
||||
|
||||
local function loadImage(path, f, binaryMode)
|
||||
if(sub(path, -4) == ".bimg")then
|
||||
return loadBIMG(path, binaryMode)
|
||||
elseif(sub(path, -3) == ".bbf")then
|
||||
return loadBBF(path, binaryMode)
|
||||
else
|
||||
return loadNFP(path, binaryMode)
|
||||
end
|
||||
-- ...
|
||||
end
|
||||
|
||||
local function loadImageAsBimg(path)
|
||||
if(path:find(".bimg"))then
|
||||
return loadBIMG(path)
|
||||
elseif(path:find(".bbf"))then
|
||||
return loadBBFAsBimg(path)
|
||||
else
|
||||
return loadNFPAsBimg(path)
|
||||
end
|
||||
end
|
||||
|
||||
local function resizeBIMG(source, w, h)
|
||||
local oW, oH = source.width or #source[1][1][1], source.height or #source[1]
|
||||
local newImg = {}
|
||||
for k,v in pairs(source)do
|
||||
if(type(k)=="number")then
|
||||
local frame = {}
|
||||
for y=1, h do
|
||||
local xT,xFG,xBG = "","",""
|
||||
local yR = floor(y / h * oH + 0.5)
|
||||
if(v[yR]~=nil)then
|
||||
for x=1, w do
|
||||
local xR = floor(x / w * oW + 0.5)
|
||||
xT = xT..sub(v[yR][1], xR,xR)
|
||||
xFG = xFG..sub(v[yR][2], xR,xR)
|
||||
xBG = xBG..sub(v[yR][3], xR,xR)
|
||||
end
|
||||
table.insert(frame, {xT, xFG, xBG})
|
||||
end
|
||||
end
|
||||
table.insert(newImg, k, frame)
|
||||
else
|
||||
newImg[k] = v
|
||||
end
|
||||
end
|
||||
newImg.width = w
|
||||
newImg.height = h
|
||||
return newImg
|
||||
end
|
||||
|
||||
return {
|
||||
loadNFP = loadNFP,
|
||||
loadBIMG = loadBIMG,
|
||||
loadImage = loadImage,
|
||||
resizeBIMG = resizeBIMG,
|
||||
loadImageAsBimg = loadImageAsBimg,
|
||||
|
||||
}
|
||||
88
lib/basalt/libraries/process.lua
Normal file
88
lib/basalt/libraries/process.lua
Normal file
@@ -0,0 +1,88 @@
|
||||
local processes = {}
|
||||
local process = {}
|
||||
local processId = 0
|
||||
|
||||
local newPackage = dofile("rom/modules/main/cc/require.lua").make
|
||||
|
||||
function process:new(path, window, newEnv, ...)
|
||||
local args = {...}
|
||||
local newP = setmetatable({ path = path }, { __index = self })
|
||||
newP.window = window
|
||||
window.current = term.current
|
||||
window.redirect = term.redirect
|
||||
newP.processId = processId
|
||||
if(type(path)=="string")then
|
||||
newP.coroutine = coroutine.create(function()
|
||||
local pPath = shell.resolveProgram(path)
|
||||
local env = setmetatable(newEnv, {__index=_ENV})
|
||||
env.shell = shell
|
||||
env.basaltProgram=true
|
||||
env.arg = {[0]=path, table.unpack(args)}
|
||||
if(pPath==nil)then
|
||||
error("The path "..path.." does not exist!")
|
||||
end
|
||||
env.require, env.package = newPackage(env, fs.getDir(pPath))
|
||||
if(fs.exists(pPath))then
|
||||
local file = fs.open(pPath, "r")
|
||||
local content = file.readAll()
|
||||
file.close()
|
||||
local program = load(content, path, "bt", env)
|
||||
if(program~=nil)then
|
||||
return program()
|
||||
end
|
||||
end
|
||||
end)
|
||||
elseif(type(path)=="function")then
|
||||
newP.coroutine = coroutine.create(function()
|
||||
path(table.unpack(args))
|
||||
end)
|
||||
else
|
||||
return
|
||||
end
|
||||
processes[processId] = newP
|
||||
processId = processId + 1
|
||||
return newP
|
||||
end
|
||||
|
||||
function process:resume(event, ...)
|
||||
local cur = term.current()
|
||||
term.redirect(self.window)
|
||||
if(self.filter~=nil)then
|
||||
if(event~=self.filter)then return end
|
||||
self.filter=nil
|
||||
end
|
||||
local ok, result = coroutine.resume(self.coroutine, event, ...)
|
||||
|
||||
if ok then
|
||||
self.filter = result
|
||||
else
|
||||
printError(result)
|
||||
end
|
||||
term.redirect(cur)
|
||||
return ok, result
|
||||
end
|
||||
|
||||
function process:isDead()
|
||||
if (self.coroutine ~= nil) then
|
||||
if (coroutine.status(self.coroutine) == "dead") then
|
||||
table.remove(processes, self.processId)
|
||||
return true
|
||||
end
|
||||
else
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function process:getStatus()
|
||||
if (self.coroutine ~= nil) then
|
||||
return coroutine.status(self.coroutine)
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function process:start()
|
||||
coroutine.resume(self.coroutine)
|
||||
end
|
||||
|
||||
return process
|
||||
6
lib/basalt/libraries/tHex.lua
Normal file
6
lib/basalt/libraries/tHex.lua
Normal file
@@ -0,0 +1,6 @@
|
||||
local cols = {}
|
||||
|
||||
for i = 0, 15 do
|
||||
cols[2^i] = ("%x"):format(i)
|
||||
end
|
||||
return cols
|
||||
343
lib/basalt/libraries/utils.lua
Normal file
343
lib/basalt/libraries/utils.lua
Normal file
@@ -0,0 +1,343 @@
|
||||
local tHex = require("tHex")
|
||||
local sub,find,reverse,rep,insert,len = string.sub,string.find,string.reverse,string.rep,table.insert,string.len
|
||||
|
||||
local function splitString(str, delimiter)
|
||||
local results = {}
|
||||
if str == "" or delimiter == "" then
|
||||
return results
|
||||
end
|
||||
local start = 1
|
||||
local delim_start, delim_end = find(str, delimiter, start)
|
||||
while delim_start do
|
||||
insert(results, sub(str, start, delim_start - 1))
|
||||
start = delim_end + 1
|
||||
delim_start, delim_end = find(str, delimiter, start)
|
||||
end
|
||||
insert(results, sub(str, start))
|
||||
return results
|
||||
end
|
||||
|
||||
local function removeTags(input)
|
||||
return input:gsub("{[^}]+}", "")
|
||||
end
|
||||
|
||||
|
||||
local function wrapText(str, width)
|
||||
str = removeTags(str)
|
||||
if(str=="")or(width==0)then
|
||||
return {""}
|
||||
end
|
||||
local uniqueLines = splitString(str, "\n")
|
||||
local result = {}
|
||||
for k, v in pairs(uniqueLines) do
|
||||
if #v == 0 then
|
||||
table.insert(result, "")
|
||||
else
|
||||
while #v > width do
|
||||
local last_space = width
|
||||
for i = width, 1, -1 do
|
||||
if sub(v, i, i) == " " then
|
||||
last_space = i
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if last_space == width then
|
||||
local line = sub(v, 1, last_space - 1) .. "-"
|
||||
table.insert(result, line)
|
||||
v = sub(v, last_space)
|
||||
else
|
||||
local line = sub(v, 1, last_space - 1)
|
||||
table.insert(result, line)
|
||||
v = sub(v, last_space + 1)
|
||||
end
|
||||
|
||||
if #v <= width then
|
||||
break
|
||||
end
|
||||
end
|
||||
if #v > 0 then
|
||||
table.insert(result, v)
|
||||
end
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
--- Coonverts a string with special tags to a table with colors and text
|
||||
-- @param input The string to convert
|
||||
-- @return A table with the following structure: { {text = "Hello", color = colors.red}, {text = "World", color = colors.blue} }
|
||||
local function convertRichText(input)
|
||||
local parsedResult = {}
|
||||
local currentPosition = 1
|
||||
local rawPosition = 1
|
||||
|
||||
while currentPosition <= #input do
|
||||
local closestColor, closestBgColor
|
||||
local color, bgColor
|
||||
local colorEnd, bgColorEnd
|
||||
|
||||
for colorName, _ in pairs(colors) do
|
||||
local fgPattern = "{fg:" .. colorName.."}"
|
||||
local bgColorPattern = "{bg:" .. colorName.."}"
|
||||
local colorStart, colorEndCandidate = input:find(fgPattern, currentPosition)
|
||||
local bgColorStart, bgColorEndCandidate = input:find(bgColorPattern, currentPosition)
|
||||
|
||||
if colorStart and (not closestColor or colorStart < closestColor) then
|
||||
closestColor = colorStart
|
||||
color = colorName
|
||||
colorEnd = colorEndCandidate
|
||||
end
|
||||
|
||||
if bgColorStart and (not closestBgColor or bgColorStart < closestBgColor) then
|
||||
closestBgColor = bgColorStart
|
||||
bgColor = colorName
|
||||
bgColorEnd = bgColorEndCandidate
|
||||
end
|
||||
end
|
||||
|
||||
local nextPosition
|
||||
if closestColor and (not closestBgColor or closestColor < closestBgColor) then
|
||||
nextPosition = closestColor
|
||||
elseif closestBgColor then
|
||||
nextPosition = closestBgColor
|
||||
else
|
||||
nextPosition = #input + 1
|
||||
end
|
||||
|
||||
local text = input:sub(currentPosition, nextPosition - 1)
|
||||
if #text > 0 then
|
||||
table.insert(parsedResult, {
|
||||
color = nil,
|
||||
bgColor = nil,
|
||||
text = text,
|
||||
position = rawPosition
|
||||
})
|
||||
rawPosition = rawPosition + #text
|
||||
currentPosition = currentPosition + #text
|
||||
end
|
||||
|
||||
if closestColor and (not closestBgColor or closestColor < closestBgColor) then
|
||||
table.insert(parsedResult, {
|
||||
color = color,
|
||||
bgColor = nil,
|
||||
text = "",
|
||||
position = rawPosition,
|
||||
})
|
||||
currentPosition = colorEnd + 1
|
||||
elseif closestBgColor then
|
||||
table.insert(parsedResult, {
|
||||
color = nil,
|
||||
bgColor = bgColor,
|
||||
text = "",
|
||||
position = rawPosition,
|
||||
})
|
||||
currentPosition = bgColorEnd + 1
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
return parsedResult
|
||||
end
|
||||
|
||||
--- Wrapts text with special color tags, like {fg:red} or {bg:blue} to multiple lines
|
||||
--- @param text string Text to wrap
|
||||
--- @param width number Width of the line
|
||||
--- @return table Table of lines
|
||||
local function wrapRichText(text, width)
|
||||
local colorData = convertRichText(text)
|
||||
local formattedLines = {}
|
||||
local x, y = 1, 1
|
||||
local currentColor, currentBgColor
|
||||
|
||||
local function addFormattedEntry(entry)
|
||||
table.insert(formattedLines, {
|
||||
x = x,
|
||||
y = y,
|
||||
text = entry.text,
|
||||
color = entry.color or currentColor,
|
||||
bgColor = entry.bgColor or currentBgColor
|
||||
})
|
||||
end
|
||||
|
||||
for _, entry in ipairs(colorData) do
|
||||
if entry.color then
|
||||
currentColor = entry.color
|
||||
elseif entry.bgColor then
|
||||
currentBgColor = entry.bgColor
|
||||
else
|
||||
local words = splitString(entry.text, " ")
|
||||
|
||||
for i, word in ipairs(words) do
|
||||
local wordLength = #word
|
||||
|
||||
if i > 1 then
|
||||
if x + 1 + wordLength <= width then
|
||||
addFormattedEntry({ text = " " })
|
||||
x = x + 1
|
||||
else
|
||||
x = 1
|
||||
y = y + 1
|
||||
end
|
||||
end
|
||||
|
||||
while wordLength > 0 do
|
||||
local line = word:sub(1, width - x + 1)
|
||||
word = word:sub(width - x + 2)
|
||||
wordLength = #word
|
||||
|
||||
addFormattedEntry({ text = line })
|
||||
|
||||
if wordLength > 0 then
|
||||
x = 1
|
||||
y = y + 1
|
||||
else
|
||||
x = x + #line
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if x > width then
|
||||
x = 1
|
||||
y = y + 1
|
||||
end
|
||||
end
|
||||
|
||||
return formattedLines
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
return {
|
||||
getTextHorizontalAlign = function(text, width, textAlign, replaceChar)
|
||||
text = sub(text, 1, width)
|
||||
local offset = width - len(text)
|
||||
if (textAlign == "right") then
|
||||
text = rep(replaceChar or " ", offset) .. text
|
||||
elseif (textAlign == "center") then
|
||||
text = rep(replaceChar or " ", math.floor(offset / 2)) .. text .. rep(replaceChar or " ", math.floor(offset / 2))
|
||||
text = text .. (len(text) < width and (replaceChar or " ") or "")
|
||||
else
|
||||
text = text .. rep(replaceChar or " ", offset)
|
||||
end
|
||||
return text
|
||||
end,
|
||||
|
||||
getTextVerticalAlign = function(h, textAlign)
|
||||
local offset = 0
|
||||
if (textAlign == "center") then
|
||||
offset = math.ceil(h / 2)
|
||||
if (offset < 1) then
|
||||
offset = 1
|
||||
end
|
||||
end
|
||||
if (textAlign == "bottom") then
|
||||
offset = h
|
||||
end
|
||||
if(offset<1)then offset=1 end
|
||||
return offset
|
||||
end,
|
||||
|
||||
orderedTable = function(t)
|
||||
local newTable = {}
|
||||
for _, v in pairs(t) do
|
||||
newTable[#newTable+1] = v
|
||||
end
|
||||
return newTable
|
||||
end,
|
||||
|
||||
rpairs = function(t)
|
||||
return function(t, i)
|
||||
i = i - 1
|
||||
if i ~= 0 then
|
||||
return i, t[i]
|
||||
end
|
||||
end, t, #t + 1
|
||||
end,
|
||||
|
||||
tableCount = function(t)
|
||||
local n = 0
|
||||
if(t~=nil)then
|
||||
for k,v in pairs(t)do
|
||||
n = n + 1
|
||||
end
|
||||
end
|
||||
return n
|
||||
end,
|
||||
|
||||
splitString = splitString,
|
||||
removeTags = removeTags,
|
||||
|
||||
wrapText = wrapText,
|
||||
|
||||
convertRichText = convertRichText,
|
||||
|
||||
--- Writes text with special color tags
|
||||
--- @param obj object The object to write to
|
||||
--- @param x number X-Position
|
||||
--- @param y number Y-Position
|
||||
--- @param text string The text to write
|
||||
writeRichText = function(obj, x, y, text)
|
||||
local richText = convertRichText(text)
|
||||
if(#richText==0)then
|
||||
obj:addText(x, y, text)
|
||||
return
|
||||
end
|
||||
|
||||
local defaultFG, defaultBG = obj:getForeground(), obj:getBackground()
|
||||
for _,v in pairs(richText)do
|
||||
obj:addText(x+v.position-1, y, v.text)
|
||||
if(v.color~=nil)then
|
||||
obj:addFG(x+v.position-1, y, tHex[colors[v.color] ]:rep(#v.text))
|
||||
defaultFG = colors[v.color]
|
||||
else
|
||||
obj:addFG(x+v.position-1, y, tHex[defaultFG]:rep(#v.text))
|
||||
end
|
||||
if(v.bgColor~=nil)then
|
||||
obj:addBG(x+v.position-1, y, tHex[colors[v.bgColor] ]:rep(#v.text))
|
||||
defaultBG = colors[v.bgColor]
|
||||
else
|
||||
if(defaultBG~=false)then
|
||||
obj:addBG(x+v.position-1, y, tHex[defaultBG]:rep(#v.text))
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
wrapRichText = wrapRichText,
|
||||
|
||||
--- Writes wrapped Text with special tags.
|
||||
--- @param obj object The object to write to
|
||||
--- @param x number X-Position
|
||||
--- @param y number Y-Position
|
||||
--- @param text string Text
|
||||
--- @param width number Width
|
||||
--- @param height number Height
|
||||
writeWrappedText = function(obj, x, y, text, width, height)
|
||||
local wrapped = wrapRichText(text, width)
|
||||
for _,v in pairs(wrapped)do
|
||||
if(v.y>height)then
|
||||
break
|
||||
end
|
||||
if(v.text~=nil)then
|
||||
obj:addText(x+v.x-1, y+v.y-1, v.text)
|
||||
end
|
||||
if(v.color~=nil)then
|
||||
obj:addFG(x+v.x-1, y+v.y-1, tHex[colors[v.color] ]:rep(#v.text))
|
||||
end
|
||||
if(v.bgColor~=nil)then
|
||||
obj:addBG(x+v.x-1, y+v.y-1, tHex[colors[v.bgColor] ]:rep(#v.text))
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
--- Returns a random UUID.
|
||||
--- @return string UUID.
|
||||
uuid = function()
|
||||
return string.gsub(string.format('%x-%x-%x-%x-%x', math.random(0, 0xffff), math.random(0, 0xffff), math.random(0, 0xffff), math.random(0, 0x0fff) + 0x4000, math.random(0, 0x3fff) + 0x8000), ' ', '0')
|
||||
end
|
||||
|
||||
}
|
||||
77
lib/basalt/libraries/xmlParser.lua
Normal file
77
lib/basalt/libraries/xmlParser.lua
Normal file
@@ -0,0 +1,77 @@
|
||||
local XMLNode = {
|
||||
new = function(tag)
|
||||
return {
|
||||
tag = tag,
|
||||
value = nil,
|
||||
attributes = {},
|
||||
children = {},
|
||||
|
||||
addChild = function(self, child)
|
||||
table.insert(self.children, child)
|
||||
end,
|
||||
|
||||
addAttribute = function(self, tag, value)
|
||||
self.attributes[tag] = value
|
||||
end
|
||||
}
|
||||
end
|
||||
}
|
||||
|
||||
local parseAttributes = function(node, s)
|
||||
-- Parse "" style string attributes
|
||||
local _, _ = string.gsub(s, "(%w+)=([\"'])(.-)%2", function(attribute, _, value)
|
||||
node:addAttribute(attribute, "\"" .. value .. "\"")
|
||||
end)
|
||||
-- Parse {} style computed attributes
|
||||
local _, _ = string.gsub(s, "(%w+)={(.-)}", function(attribute, expression)
|
||||
node:addAttribute(attribute, expression)
|
||||
end)
|
||||
end
|
||||
|
||||
local XMLParser = {
|
||||
parseText = function(xmlText)
|
||||
local stack = {}
|
||||
local top = XMLNode.new()
|
||||
table.insert(stack, top)
|
||||
local ni, c, label, xarg, empty
|
||||
local i, j = 1, 1
|
||||
while true do
|
||||
ni, j, c, label, xarg, empty = string.find(xmlText, "<(%/?)([%w_:]+)(.-)(%/?)>", i)
|
||||
if not ni then break end
|
||||
local text = string.sub(xmlText, i, ni - 1);
|
||||
if not string.find(text, "^%s*$") then
|
||||
local lVal = (top.value or "") .. text
|
||||
stack[#stack].value = lVal
|
||||
end
|
||||
if empty == "/" then -- empty element tag
|
||||
local lNode = XMLNode.new(label)
|
||||
parseAttributes(lNode, xarg)
|
||||
top:addChild(lNode)
|
||||
elseif c == "" then -- start tag
|
||||
local lNode = XMLNode.new(label)
|
||||
parseAttributes(lNode, xarg)
|
||||
table.insert(stack, lNode)
|
||||
top = lNode
|
||||
else -- end tag
|
||||
local toclose = table.remove(stack) -- remove top
|
||||
|
||||
top = stack[#stack]
|
||||
if #stack < 1 then
|
||||
error("XMLParser: nothing to close with " .. label)
|
||||
end
|
||||
if toclose.tag ~= label then
|
||||
error("XMLParser: trying to close " .. toclose.tag .. " with " .. label)
|
||||
end
|
||||
top:addChild(toclose)
|
||||
end
|
||||
i = j + 1
|
||||
end
|
||||
local text = string.sub(xmlText, i);
|
||||
if #stack > 1 then
|
||||
error("XMLParser: unclosed " .. stack[#stack].tag)
|
||||
end
|
||||
return top.children
|
||||
end
|
||||
}
|
||||
|
||||
return XMLParser
|
||||
Reference in New Issue
Block a user