module("templates", package.seeall)
local tpl = {};
local tpl_mt = { __index = tpl };
local tplutil = {};
local tplutil_mt = { __index = tplutil };
function tpl:saverender(fn, vars)
local f, err = io.open(fn, "w+");
if not f then return f,err; end
f:write(self:render(vars));
f:close();
return true
end
function tpl:render(vars)
local tpl = self.tpl or self.file:read("*a");
self.tpl = tpl;
if not vars then return tpl; end
return (tpl:gsub("%b{}", function (cap)
local v = cap:match("^%{%{%s*(.-)%s*%}%}*$")
if not v then return cap; end
local chunk, err = loadstring("return "..v);
if not chunk then
chunk, err = loadstring(v);
if not chunk then error(err); end
end
setfenv(chunk, vars);
local ok, ret = pcall(chunk);
if not ok then error(ret); end
do return ret or ""; end
local v = cap:match("^%{%{%s*([%w_%.]+)%s*%}%}*$")
if v then
local _vars = vars;
local ret, subs = v:gsub("(%w+)%.", function (var) if _vars then _vars = _vars[var]; end end);
if _vars and _vars ~= vars then return _vars[v:match("%w+$")] or cap; end
return vars[v] or cap;
end
local v = cap:match("^%{*[%w_]+%(.*%}*$");
if v then
local chunk, err = loadstring("return "..v:sub(2,-2));
if not chunk then error("error in template: "..tostring(err)); end
setfenv(chunk, setmetatable(vars, tplutil_mt));
local success, ret = pcall(chunk);
if success then
return ret;
else
error("error in template: "..ret);
end
end
end));
end
-- -- -- --
local function escape(s) return s; end
function tplutil.kvlist(t)
if #t > 0 then
-- Assume an array
if type(t[1]) == "table" then
-- Assume a table of tables
else
-- Assume a straight list
end
else
-- assume a k->v list
local b = { "<table>" };
end
end
function tplutil.ulist(t)
-- assume a list/array
local b = { "<ul>\n" };
for _, v in ipairs(t) do
table.insert(b, " <li>"..escape(v).."</li>\n");
end
table.insert(b, "</ul>\n");
return table.concat(b);
end
function init(file)
local f, err = io.open(file);
if not f then return nil, "Couldn't open template file: "..err; end
return setmetatable({ file = f }, tpl_mt);
end
function load(template)
return setmetatable({ tpl = template }, tpl_mt);
end