function tostr(t) local str = "" for k, v in next, t do if #str > 0 then str = str .. ", " end if type(k) == "number" then str = str .. "[" .. k .. "] = " else str = str .. tostring(k) .. " = " end if type(v) == "table" then str = str .. "{ " .. tostr(v) .. " }" elseif type(v) == "string" then str = str .. '"' .. v .. '"' else str = str .. tostring(v) end end return str end function trim_ws(s) return s:match("^%s*(.*)") end function count_hypens(s) local leftover = s:match("^-*(.*)") return string.len(s) - string.len(leftover) end function pretty_print_slide(slide) io.write("{\n") if slide.transition then io.write(" transition = \"", slide.transition, "\",\n") end for i = 1, #slide do local node = slide[i] for j = 0, node.indent do io.write(" ") end io.write("{ ") io.write(tostr(node)) io.write(" },\n") end io.write("},\n") end function pretty_print_slides(slides) io.write("gSlides = {\n") for i = 1, #slides do pretty_print_slide(slides[i]) end io.write("}\n") end function parse_attr(s, lvalue) local ts = "^<%s*" .. lvalue .. "%s*=%s*(%a+)%s*>$" return s:match(ts) end function flush(slides, block) if #block > 0 then slides[#slides + 1] = block return {} end return block end function parse_file(file) local slides = {} local block = {} for line in file:lines() do local s = trim_ws(line) if #s == 0 then -- done with a block block = flush(slides, block) else local transition_type = parse_attr(s, "transition") local blockstyle = parse_attr(s, "blockstyle") if transition_type then block["transition"] = transition_type elseif blockstyle then block["blockstyle"] = blockstyle else if block.blockstyle == "code" then block[#block + 1] = { text = line } else local n = count_hypens(s) block[#block + 1] = { indent = n, text = trim_ws(s:sub(n + 1, -1)) } end end end end flush(slides, block) return slides end