Module:Template invoke
Allow for easy invocation of utility modules via templates, which is a surprisingly difficult task. Invoke with {{#invoke:template invoke|exec|<module name>}} and it will call that module using the arguments passed to the template. The first argument is the function to invoke, the rest are passed to that function.
local p = {}
function p.exec(frame)
parent = frame:getParent()
local mname = frame.args['1'] -- Module name passed via invocation
local m = require("Module:" .. mname)
local fname = parent.args['1'] -- All else is implicit
if fname == nil then
error("No " .. mname .. " method provided")
end
local fn = m[fname]
if fn == nil then
error("No such method " .. fname .. " in Module:" .. mname)
end
-- Move all the arguments, MW uses string indices
-- so table.remove doesn't work
local nargs = {}
for k, v in pairs(parent.args) do
local n = tonumber(k)
if n == nil then
nargs[k] = v
elseif n == 1 then
-- Do nothing, equivalent to nargs[k] = nil
else
nargs[(n - 1) .. ""] = v
end
end
-- frame.arg has a metatable which is just a cache without reference to
-- the underlying table, but it also performs key type coercion so we
-- need to replicate that
setmetatable(nargs, {
__index = function(obj, name)
return rawget(obj, name .. "")
end
})
parent.args = nargs
return fn(parent)
end
return p