| 1 | module("templates", package.seeall) |
| 2 | |
| 3 | local tpl = {}; |
| 4 | local tpl_mt = { __index = tpl }; |
| 5 | |
| 6 | local tplutil = {}; |
| 7 | local tplutil_mt = { __index = tplutil }; |
| 8 | |
| 9 | function tpl:saverender(fn, vars) |
| 10 | local f, err = io.open(fn, "w+"); |
| 11 | if not f then return f,err; end |
| 12 | f:write(self:render(vars)); |
| 13 | f:close(); |
| 14 | return true |
| 15 | end |
| 16 | |
| 17 | function tpl:render(vars) |
| 18 | local tpl = self.tpl or self.file:read("*a"); |
| 19 | self.tpl = tpl; |
| 20 | |
| 21 | if not vars then return tpl; end |
| 22 | |
| 23 | return (tpl:gsub("%b{}", function (cap) |
| 24 | local v = cap:match("^%{%{%s*(.-)%s*%}%}*$") |
| 25 | |
| 26 | if not v then return cap; end |
| 27 | local chunk, err = loadstring("return "..v); |
| 28 | if not chunk then |
| 29 | chunk, err = loadstring(v); |
| 30 | if not chunk then error(err); end |
| 31 | end |
| 32 | setfenv(chunk, vars); |
| 33 | local ok, ret = pcall(chunk); |
| 34 | if not ok then error(ret); end |
| 35 | do return ret or ""; end |
| 36 | |
| 37 | local v = cap:match("^%{%{%s*([%w_%.]+)%s*%}%}*$") |
| 38 | if v then |
| 39 | local _vars = vars; |
| 40 | local ret, subs = v:gsub("(%w+)%.", function (var) if _vars then _vars = _vars[var]; end end); |
| 41 | if _vars and _vars ~= vars then return _vars[v:match("%w+$")] or cap; end |
| 42 | return vars[v] or cap; |
| 43 | end |
| 44 | |
| 45 | local v = cap:match("^%{*[%w_]+%(.*%}*$"); |
| 46 | if v then |
| 47 | local chunk, err = loadstring("return "..v:sub(2,-2)); |
| 48 | if not chunk then error("error in template: "..tostring(err)); end |
| 49 | setfenv(chunk, setmetatable(vars, tplutil_mt)); |
| 50 | local success, ret = pcall(chunk); |
| 51 | if success then |
| 52 | return ret; |
| 53 | else |
| 54 | error("error in template: "..ret); |
| 55 | end |
| 56 | end |
| 57 | end)); |
| 58 | end |
| 59 | |
| 60 | -- -- -- -- |
| 61 | local function escape(s) return s; end |
| 62 | |
| 63 | function tplutil.kvlist(t) |
| 64 | if #t > 0 then |
| 65 | -- Assume an array |
| 66 | if type(t[1]) == "table" then |
| 67 | -- Assume a table of tables |
| 68 | else |
| 69 | -- Assume a straight list |
| 70 | end |
| 71 | else |
| 72 | -- assume a k->v list |
| 73 | local b = { "<table>" }; |
| 74 | |
| 75 | end |
| 76 | end |
| 77 | |
| 78 | function tplutil.ulist(t) |
| 79 | -- assume a list/array |
| 80 | local b = { "<ul>\n" }; |
| 81 | for _, v in ipairs(t) do |
| 82 | table.insert(b, " <li>"..escape(v).."</li>\n"); |
| 83 | end |
| 84 | table.insert(b, "</ul>\n"); |
| 85 | return table.concat(b); |
| 86 | end |
| 87 | |
| 88 | function init(file) |
| 89 | local f, err = io.open(file); |
| 90 | if not f then return nil, "Couldn't open template file: "..err; end |
| 91 | return setmetatable({ file = f }, tpl_mt); |
| 92 | end |
| 93 | |
| 94 | function load(template) |
| 95 | return setmetatable({ tpl = template }, tpl_mt); |
| 96 | end |