/usr/share/lua/5.1/cosmo/fill.lua is in liblua5.1-cosmo0 10.04.06-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | local grammar = require "cosmo.grammar"
module(..., package.seeall)
local function is_callable(f)
if type(f) == "function" then return true end
local meta = getmetatable(f)
if meta and meta.__call then return true end
return false
end
local insert = table.insert
local concat = table.concat
local function prepare_env(env, parent)
local __index = function (t, k)
local v = env[k]
if not v then
v = parent[k]
end
return v
end
local __newindex = function (t, k, v)
env[k] = v
end
return setmetatable({ self = env }, { __index = __index, __newindex = __newindex })
end
local interpreter = {}
function interpreter.text(state, text)
assert(text.tag == "text")
insert(state.out, text.text)
end
local function check_selector(name, selector)
if not is_callable(selector) then
error("selector " .. name .. " is not callable but is " .. type(selector))
end
end
function interpreter.appl(state, appl)
assert(appl.tag == "appl")
local selector, args, subtemplates = appl.selector, appl.args, appl.subtemplates
local env, out = state.env, state.out
local selector_name = selector
selector = loadstring("local env = (...); return " .. selector)(env) or function () return '' end
if #subtemplates == 0 then
if args and args ~= "" and args ~= "{}" then
check_selector(selector_name, selector)
selector = selector(loadstring("local env = (...); return " .. args)(env), false)
insert(out, tostring(selector))
else
if is_callable(selector) then
insert(out, tostring(selector()))
else
insert(out, tostring(selector or ""))
end
end
else
if args and args ~= "" and args ~= "{}" then
check_selector(selector_name, selector)
args = loadstring("local env = (...); return " .. args)(env)
for e, literal in coroutine.wrap(selector), args, true do
if literal then
insert(out, tostring(e))
else
if type(e) ~= "table" then
e = prepare_env({ it = tostring(e) }, env)
else
e = prepare_env(e, env)
end
interpreter.template({ env = e, out = out }, subtemplates[e.self._template or 1])
end
end
else
if type(selector) == 'table' then
for _, e in ipairs(selector) do
if type(e) ~= "table" then
e = prepare_env({ it = tostring(e) }, env)
else
e = prepare_env(e, env)
end
interpreter.template({ env = e, out = out }, subtemplates[e.self._template or 1])
end
else
check_selector(selector_name, selector)
for e, literal in coroutine.wrap(selector), nil, true do
if literal then
insert(out, tostring(e))
else
if type(e) ~= "table" then
e = prepare_env({ it = tostring(e) }, env)
else
e = prepare_env(e, env)
end
interpreter.template({ env = e, out = out }, subtemplates[e.self._template or 1])
end
end
end
end
end
end
function interpreter.template(state, template)
if template then
assert(template.tag == "template")
for _, part in ipairs(template.parts) do
interpreter[part.tag](state, part)
end
end
end
function fill(template, env, opts)
opts = opts or {}
local out = opts.out or {}
if type(env) == "string" then env = { it = env } end
interpreter.template({ env = env, out = out }, grammar.ast:match(template))
return concat(out, opts.delim)
end
|