-
-
Save kaeza/1a970dec497ffd2e453a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local strfind, strsub, strgsub = string.find, string.sub, string.gsub | |
local strlen, ipairs, tinsert = string.len, ipairs, table.insert | |
local function formspec_unescape(str) | |
return (strgsub(str, "\\(.)", "%1")) | |
end | |
--- | |
-- Parse a string and return a list of formspec elements. | |
-- Has limited detection of malformed data and automatically unescapes | |
-- formspec item parameters. | |
-- Each returned element is a table with the following format: | |
-- { | |
-- type = "label", | |
-- params = { | |
-- "1,2", | |
-- "Hello;] world!", | |
-- }, | |
-- } | |
local function parse_formspec(fs) | |
local items = { } | |
local pos, len = 1, strlen(fs) | |
while pos <= len do | |
-- Search for `type[` | |
local start, startend, type = strfind(fs, "([a-z_]+)%[", pos) | |
if not start then break end | |
pos = startend + 1 | |
startend = startend + 1 | |
start = startend | |
local params | |
local paramstart, paramend | |
while true do | |
-- Search for unescaped `]` | |
local fin, finend, slashes = strfind(fs, "(\\*)%]", startend) | |
if not fin then | |
return nil, "malformed data" | |
end | |
if #slashes%2 == 0 then | |
paramstart, paramend = start, finend-1 | |
params = strsub(fs, paramstart, paramend) | |
break | |
end | |
startend = finend+1 | |
end | |
-- At this point, `type` is the element type (`image`, | |
-- `button`, etc.), and `params` is everything between | |
-- `[` and `]`. | |
local paramlist = { } | |
-- Split parameters by `;`. | |
paramstart, paramend = 1, strlen(params) | |
local paramp = paramstart | |
while paramp <= paramend and paramstart <= paramend do | |
-- Search for next unescaped `;` | |
local sc, scend, slashes = strfind(params, "(\\*);", paramp) | |
if not sc then | |
-- No more `;`s; add remaining data and bail out. | |
tinsert(paramlist, strsub(params, paramstart, paramend)) | |
break | |
end | |
if #slashes%2 == 0 then | |
-- Unescaped `;`: add data up to that point and continue. | |
tinsert(paramlist, strsub(params, paramstart, scend-1)) | |
paramstart = scend+1 | |
paramp = paramstart | |
else | |
-- Escaped `;`: keep searching. | |
paramp = scend+1 | |
end | |
end | |
-- Unescape parameters. | |
for i, v in ipairs(paramlist) do | |
paramlist[i] = formspec_unescape(v) | |
end | |
tinsert(items, { | |
type = type, | |
params = paramlist, | |
}) | |
end | |
return items | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment