/usr/share/lua/5.1/cosmo/fill.lua is in lua-cosmo 13.01.30-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 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | local grammar = require "cosmo.grammar"
if _VERSION == "Lua 5.2" then
_ENV = setmetatable({}, { __index = _G })
else
module(..., package.seeall)
_ENV = _M
end
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
local function unparse_name(parsed_selector)
local name = parsed_selector:match("^env%['([%w_]+)'%]$")
if name then name = "$" .. name end
return name or parsed_selector
end
function interpreter.appl(state, appl)
assert(appl.tag == "appl")
local selector, args, subtemplates = appl.selector, appl.args, appl.subtemplates
local env, out, opts = state.env, state.out, state.opts
local selector_name = unparse_name(selector)
local default
if opts.fallback then
default = subtemplates[1]
end
selector = loadstring("local env = (...); return " .. selector)(env)
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
if not selector and opts.passthrough then
selector = selector_name
end
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, opts = opts }, subtemplates[e.self._template or 1] or default)
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, opts = opts }, subtemplates[e.self._template or 1] or default)
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, opts = opts }, subtemplates[e.self._template or 1] or default)
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 {}
grammar.ast = opts.parser or grammar.default
if type(env) == "string" then env = { it = env } end
interpreter.template({ env = env, out = out, opts = opts }, grammar.ast:match(template))
return concat(out, opts.delim)
end
return _ENV
|