Skip to content

Instantly share code, notes, and snippets.

@sfan5

sfan5/formspecconvert.lua Secret

Created Apr 9, 2016
Embed
What would you like to do?
local function formspec_escape(text)
text = string.gsub(text,"\\","\\\\")
text = string.gsub(text,"%]","\\]")
text = string.gsub(text,"%[","\\[")
text = string.gsub(text,";","\\;")
text = string.gsub(text,",","\\,")
return text
end
local function assert_fields(tbl, names, i)
for _, name in ipairs(names) do
local found = false
for fieldname, _ in ipairs(tbl) do
if fieldname == name then
found = true
end
end
if not found then
error("Element " .. i .. " has no '" .. name .. "' field")
end
end
end
local function assert_type(tbl, eln, ex, i)
if type(tbl[eln]) ~= ex then
error("The '" .. eln .. "' field of Element " .. i .. " is of type '" .. type(tbl[eln])
.. "', expected was '" .. ex .. "'")
end
end
local function boolstr(b)
if b == true then
return "true"
else
return "false"
end
end
local conv_tbl = {
-- Type additional Check Func args arg types template
{"invsize", true, {"w", "h"}, {"number", "number"}, "size[{w},{h}]"},
{"size", true, {"w", "h"}, {"number", "number"}, "size[{w},{h}]"},
{"list", function(t) return t.startingitemindex == nil end,
{"inventorylocation", "listname", "x", "y", "w", "h"},
{"string", "string", "number", "number", "number", "number"},
"list[{inventorylocation};{listname};{x},{y};{w},{h}]"},
{"list", function(t) return t.startingitemindex ~= nil end,
{"inventorylocation", "listname", "x", "y", "w", "h", "startingitemindex"},
{"string", "string", "number", "number", "number", "number", "number"},
"list[{inventorylocation};{listname};{x},{y};{w},{h};{startingitemindex}]"},
{"image", true, {"x", "y", "w", "h", "texturename"},
{"number", "number", "number", "number", "string"},
"image[{x},{y};{w},{h};{texturename}]"},
{"item_image", true, {"x", "y", "w", "h", "itemname"},
{"number", "number", "number", "number", "string"},
"item_image[{x},{y};{w},{h};{itemname}]"},
{"background", true, {"x", "y", "w", "h", "texturename"},
{"number", "number", "number", "number", "string"},
"background[{x},{y};{w},{h};{texturename}]"},
{"pwdfield", true, {"x", "y", "w", "h", "name", "label"},
{"number", "number", "number", "number", "string", "string"},
"pwdfield[{x},{y};{w},{h};{name};{label}]"},
{"field", function(t) return t.x ~= nil end,
{"x", "y", "w", "h", "name", "label", "default"},
{"number", "number", "number", "number", "string", "string", "string"},
"field[{x},{y};{w},{h};{name};{label};{default}]"},
{"field", function(t) return t.x == nil end,
{"name", "label", "default"},
{"string", "string", "string"},
"field[{name};{label};{default}]"},
{"textarea", true, {"x", "y", "w", "h", "name", "label", "default"},
{"number", "number", "number", "number", "string", "string", "string"},
"textarea[{x},{y};{w},{h};{name};{label};{default}]"},
{"label", true, {"x", "y", "label"}, {"number", "number", "string"},
"label[{x},{y};{label}]"},
{"vertlabel", true, {"x", "y", "label"}, {"number", "number", "string"},
"vertlabel[{x},{y};{label}]"},
{"button", true, {"x", "y", "w", "h", "name", "label"},
{"number", "number", "number", "number", "string", "string"},
"button[{x},{y};{w},{h};{name};{label}]"},
{"image_button", function(t, i)
if t.noclip == nil and (t.drawborder ~= nil or t.pressed ~= nil) then
error("Element " .. i .. " does have 'drawborder' or 'pressed' field but not 'noclip'")
end
if t.drawborder == nil and t.pressed ~= nil then
error("Element " .. i .. " does have 'pressed' field but not 'drawborder'")
end
return t.noclip == nil and t.drawborder == nil and t.pressed == nil
end,
{"x", "y", "w", "h", "texturename", "name", "label"},
{"number", "number", "number", "number", "string", "string", "string"},
"image_button[{x},{y};{w},{h};{texturename};{name};{label}]"},
{"image_button", function(t)
return t.noclip ~= nil and t.drawborder == nil and t.pressed == nil
end,
{"x", "y", "w", "h", "texturename", "name", "label", "noclip"},
{"number", "number", "number", "number", "string",
"string", "string", "boolean"},
"image_button[{x},{y};{w},{h};{texturename};{name};{label};{noclip};true]"},
{"image_button", function(t)
return t.noclip ~= nil and t.drawborder ~= nil and t.pressed == nil
end,
{"x", "y", "w", "h", "texturename", "name", "label", "noclip", "drawborder"},
{"number", "number", "number", "number", "string",
"string", "string", "boolean", "boolean"},
"image_button[{x},{y};{w},{h};{texturename};{name};{label};{noclip};{drawborder}]"},
{"image_button", function(t)
return t.noclip ~= nil and t.drawborder ~= nil and t.pressed ~= nil
end,
{"x", "y", "w", "h", "texturename", "name", "label", "noclip", "drawborder", "pressed"},
{"number", "number", "number", "number", "string",
"string", "string", "boolean", "boolean", "string"},
"image_button[{x},{y};{w},{h};{texturename};{name};{label};{noclip};{drawborder};{pressed}]"},
{"item_image_button", true,
{"x", "y", "w", "h", "itemname", "name", "label"},
{"number", "number", "number", "number", "string", "string", "string"},
"item_image_button[{x},{y};{w},{h};{itemname};{name};{label}]"},
{"button_exit", true, {"x", "y", "w", "h", "name", "label"},
{"number", "number", "number", "number", "string", "string"},
"button_exit[{x},{y};{w},{h};{name};{label}]"},
{"image_button_exit", true,
{"x", "y", "w", "h", "texturename", "name", "label"},
{"number", "number", "number", "number", "string", "string", "string"},
"image_button_exit[{x},{y};{w},{h};{texturename};{name};{label}]"},
{"textlist", function(t) return t.tranparent == nil end,
{"x", "y", "w", "h", "name", "list"},
{"number", "number", "number", "number", "string", {"table", colors=true}},
"textlist[{x},{y};{w},{h};{name};{list}]"},
{"textlist", function(t) return t.tranparent ~= nil end,
{"x", "y", "w", "h", "name", "list", "transparent"},
{"number", "number", "number", "number", "string", {"table", colors=true}, "boolean"},
"textlist[{x},{y};{w},{h};{name};{list};{transparent}]"},
{"tabheader", true, {"x", "y", "name", "captions",
"current_tab", "transparent", "drawborder"},
{"number", "number", "string", "table", "number",
"boolean", "boolean"},
"tabheader[{x},{y};{name};{captions};{current_tab};{transparent};{drawborder}]"},
{"box", true, {"x", "y", "w", "h", "color"},
{"number", "number", "number", "number", {"string", color=true}},
"box[{x},{y};{w},{h};{color}]"},
{"dropdown", true, {"x", "y", "w", "name", "items", "index"},
{"number", "number", "number", "string", "table", "number"},
"dropdown[{x},{y};{w};{name};{items};{index}]"},
{"checkbox", function(t) return t.selected == nil end,
{"x", "y", "name", "label"},
{"number", "number", "string", "string"},
"checkbox[{x},{y};{name};{label}]"},
{"checkbox", function(t) return t.selected ~= nil end,
{"x", "y", "name", "label", "selected"},
{"number", "number", "string", "string", "boolean"},
"checkbox[{x},{y};{name};{label};{selected}]"},
}
function formspectable2formspecstring(tbl)
local outstring = ""
if type(tbl) ~= "table" then
error("Expected 'table' for first argument, got '" .. type(tbl) .. "'")
end
for i, el in ipairs(tbl) do
if type(el) ~= "table" then
error("Element " .. i .. " is not of type 'table', but '" .. type(el) .. "'")
end
local t = tbl[1]
if t == nil then
error("Element " .. i .. " has no type field")
end
local processed = false
for _, conv in conv_tbl do
if t == conv[1] then
if type(conv[2]) == "boolean" and conv[2] == true then
conv[2] = function(t) return true end
end
if conv[2](tbl, i) then
processed = true
assert_fields(tbl, conv[3], i)
for j, ftype in conv[4] do
if type(ftype) == "table" then
ftype = ftype[1]
end
assert_type(tbl, conv[3][j], ftype, i)
end
local out = conv[5]
for j, fname in conv[3] do
if type(tbl[fname]) == "string" then
if type(conv[4][j]) == "table" and conv[4][j].color then
_col = tbl[fname]
if #_col ~= 6 then
error("Argument " .. j .. " of Element " .. i .. " is " .. #_col .." characters long, expected was 6")
end
for l in 1, #_col do
_cc = string.byte(_col, l)
if (_cc >= 48 and _cc <= 57) or (_cc >= 65 and _cc <= 70) or (_cc >= 97 and _cc <= 102) then
--Character valid
else
error("Character " .. l .. " of Argument " .. j .. " of Element " .. i .. " is " .. string.char(_cc) .. ", expected was one of 0123456789ABCDEFabcdef")
end
end
end
out = out:gsub("{" .. fname .. "}", formspec_escape(tbl[fname]))
elseif type(tbl[fname]) == "number" then
out = out:gsub("{" .. fname .. "}", tbl[fname])
elseif type(tbl[fname]) == "boolean" then
out = out:gsub("{" .. fname .. "}", boolstr(tbl[fname]))
elseif type(tbl[fname]) == "table" then
local out2 = ""
for k, tv in ipairs(tbl[fname]) do
if type(tv) == "string" then
if type(conv[4][j]) == "table" and conv[4][j].colors and tv:sub(1,1) == "#" then
tv = "#" .. tv
end
out2 = out2 .. formspec_escape(tv)
elseif type(tv) == "number" then
out2 = out2 .. tv
elseif type(tv) == "boolean" then
out2 = out2 .. boolstr(tv)
elseif type(tv) == "table" and type(conv[4][j]) == "table" and conv[4][j].colors then
_col = tv.color
_txt = tv.text
if _col == nil then
error("Element " .. i .. ", Argument " .. j .. " has no 'color' field")
elseif _txt == nil then
error("Element " .. i .. ", Argument " .. j .. " has no 'text' field")
end
if type(_col) ~= "string" then
error("The 'color' field of Element " .. i .. ", Argument " .. j .. " is of type '" .. type(_col) .. "', expected was 'string'")
elseif type(_txt) ~= "string" then
error("The 'text' field of Element " .. i .. ", Argument " .. j .. " is of type '" .. type(_col) .. "', expected was 'string'")
end
if #_col ~= 6 then
error("The 'color' field of Element " .. i .. ", Argument " .. j .. " is " .. #_col .." characters long, expected was 6")
end
for l in 1, #_col do
_cc = string.byte(_col, l)
if (_cc >= 48 and _cc <= 57) or (_cc >= 65 and _cc <= 70) or (_cc >= 97 and _cc <= 102) then
--Character valid
else
error("Character " .. l .. " of the 'color' field of Element " .. i .. ", Argument " .. j .. " is " .. string.char(_cc) .. ", expected was one of 0123456789ABCDEFabcdef")
end
end
out2 = out2 .. "#" .. _col .. formspec_escape(tv)
else
error("Cannot serialize " .. type(tv) .. " in table Element " .. i .. ", Argument " .. j)
end
if not k == #tbl[fname] then
out2 = out2 .. ","
end
end
out = out:gsub("{" .. fname .. "}", out2)
end
end
outstring = outstring .. out
end
end
end
if not processed then
error("Element " .. i .. " has unknown type '" .. t .. "'")
end
end
return outstring
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.