Module:Lua call: Difference between revisions
Jump to navigation
Jump to search
imported>HouseBlaster m HouseBlaster moved page Module:LuaCall to Module:Lua call: expand module name in the spirit of WP:TPN |
imported>Uzume strict |
||
Line 1: | Line 1: | ||
require[[strict]] | |||
local p={} | local p={} | ||
function p.main(frame) | function p.main(frame) | ||
local parent = frame.getParent(frame) or {} | local parent = frame.getParent(frame) or {} | ||
local | local explist = {} | ||
local | local fnname, varlist | ||
local vars = {} | |||
for k, v in pairs(_G) do | |||
vars[k] = v -- transfer every global directly to our variable table | |||
end | |||
for k, v in pairs(parent.args or {}) do | for k, v in pairs(parent.args or {}) do | ||
vars[k] = tonumber(v) or v -- transfer every parameter directly to our variable table | |||
end | end | ||
for k, v in pairs(frame.args or {}) do | for k, v in pairs(frame.args or {}) do | ||
vars[k] = tonumber(v) or v -- transfer every parameter directly to our variable table | |||
end | end | ||
--- Alas Scribunto does NOT implement coroutines, according to | --- Alas Scribunto does NOT implement coroutines, according to | ||
--- | --- https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#string.format | ||
--- this will not stop us from trying to implement one single lousy function call | --- this will not stop us from trying to implement one single lousy function call | ||
if | if vars[1] then | ||
fnname, varlist = mw.ustring.match(vars[1], "^%s*(%a[^%s%(]*)%(([^%)]*)%)%s*$") | |||
end | end | ||
if | if varlist then | ||
local | local expn = 0 | ||
repeat | repeat | ||
expn = expn + 1 | |||
explist[expn] = vars[mw.ustring.match(varlist, "([^%,]+)")] | |||
varlist = mw.ustring.match(varlist, "[^%,]+,(.*)$") | |||
until not | until not varlist | ||
end | end | ||
local | local scopetab = vars | ||
while mw.ustring.match( | while mw.ustring.match(fnname, "%.") do | ||
local scopekey | |||
scopekey, fnname = mw.ustring.match(fnname, "^(%a[^%.]*)%.(.*)$") | |||
scopetab = scopetab[scopekey] | |||
end | end | ||
local | local fn = scopetab[fnname] | ||
if type( | if type(fn) ~= "function" then --XXX: What about callable tables? | ||
return tostring( | return tostring(fn) | ||
else | else | ||
local output = {fn(unpack(explist))} | |||
return | return output[vars.reserved_return or 1] | ||
end | end | ||
end | end | ||
Line 83: | Line 89: | ||
-- | -- | ||
-- Example: | -- Example: | ||
-- {{#invoke: | -- {{#invoke:Lua call|call|mw.log|a|1|2|3}} will return results of mw.log('a', 1, 2, 3) | ||
-- {{#invoke: | -- {{#invoke:Lua call|call|mw.logObject|\a|321|\321| \321 }} will return results of mw.logObject('a', 321, '321', ' \\321 ') | ||
-- | -- | ||
-- This example show the debugging to see which Unicode characters are allowed in template parameters, | -- This example show the debugging to see which Unicode characters are allowed in template parameters, | ||
-- {{#invoke: | -- {{#invoke:Lua call|call|mw.ustring.codepoint|{{#invoke:Lua call|call|mw.ustring.char|0x0061}}}} return 97 | ||
-- {{#invoke: | -- {{#invoke:Lua call|call|mw.ustring.codepoint|{{#invoke:Lua call|call|mw.ustring.char|0x0000}}}} return 65533 | ||
-- {{#invoke: | -- {{#invoke:Lua call|call|mw.ustring.codepoint|{{#invoke:Lua call|call|mw.ustring.char|0x0001}}}} return 65533 | ||
-- {{#invoke: | -- {{#invoke:Lua call|call|string.format|0x%04x|{{#invoke:Lua call|call|mw.ustring.codepoint|{{#invoke:Lua call|call|mw.ustring.char|0x0002}}}}}} return 0xfffd | ||
-- {{#invoke: | -- {{#invoke:Lua call|call|string.format|0x%04x|{{#invoke:Lua call|call|mw.ustring.codepoint|{{#invoke:Lua call|call|mw.ustring.char|0x007e}}}}}} return 0x007e | ||
-- {{#invoke: | -- {{#invoke:Lua call|call|string.format|0x%04x|{{#invoke:Lua call|call|mw.ustring.codepoint|{{#invoke:Lua call|call|mw.ustring.char|0x007f}}}}}} return 0x007f | ||
-- {{#invoke: | -- {{#invoke:Lua call|call|string.format|0x%04x|{{#invoke:Lua call|call|mw.ustring.codepoint|{{#invoke:Lua call|call|mw.ustring.char|0x0080}}}}}} return 0x0080 | ||
-- {{#invoke: | -- {{#invoke:Lua call|call|string.format|0x%04x|{{#invoke:Lua call|call|mw.ustring.codepoint|{{#invoke:Lua call|call|mw.ustring.char|0x00a0}}}}}} return 0x00a0 | ||
-- | -- | ||
------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | ||
Line 110: | Line 116: | ||
-- | -- | ||
-- Example: | -- Example: | ||
-- {{#invoke: | -- {{#invoke:Lua call|get| math.pi }} will return value of math.pi | ||
-- {{#invoke: | -- {{#invoke:Lua call|get|math|pi}} will return value of math.pi | ||
-- {{#invoke: | -- {{#invoke:Lua call|get| math |pi}} will return value of _G[' math '].pi | ||
-- {{#invoke: | -- {{#invoke:Lua call|get|_G| math.pi }} will return value of _G[' math.pi '] | ||
-- {{#invoke: | -- {{#invoke:Lua call|get|obj.a.5.c}} will return value of obj.a['5'].c | ||
-- {{#invoke: | -- {{#invoke:Lua call|get|obj|a|5|c}} will return value of obj.a[5].c | ||
-- | -- | ||
------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ |
Latest revision as of 04:17, 30 July 2025
Documentation for this module may be created at Module:Lua call/doc
require[[strict]]
local p={}
function p.main(frame)
local parent = frame.getParent(frame) or {}
local explist = {}
local fnname, varlist
local vars = {}
for k, v in pairs(_G) do
vars[k] = v -- transfer every global directly to our variable table
end
for k, v in pairs(parent.args or {}) do
vars[k] = tonumber(v) or v -- transfer every parameter directly to our variable table
end
for k, v in pairs(frame.args or {}) do
vars[k] = tonumber(v) or v -- transfer every parameter directly to our variable table
end
--- Alas Scribunto does NOT implement coroutines, according to
--- https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#string.format
--- this will not stop us from trying to implement one single lousy function call
if vars[1] then
fnname, varlist = mw.ustring.match(vars[1], "^%s*(%a[^%s%(]*)%(([^%)]*)%)%s*$")
end
if varlist then
local expn = 0
repeat
expn = expn + 1
explist[expn] = vars[mw.ustring.match(varlist, "([^%,]+)")]
varlist = mw.ustring.match(varlist, "[^%,]+,(.*)$")
until not varlist
end
local scopetab = vars
while mw.ustring.match(fnname, "%.") do
local scopekey
scopekey, fnname = mw.ustring.match(fnname, "^(%a[^%.]*)%.(.*)$")
scopetab = scopetab[scopekey]
end
local fn = scopetab[fnname]
if type(fn) ~= "function" then --XXX: What about callable tables?
return tostring(fn)
else
local output = {fn(unpack(explist))}
return output[vars.reserved_return or 1]
end
end
local function tonumberOrString(v)
return tonumber(v) or v:gsub("^\\", "", 1)
end
local function callWithTonumberOrStringOnPairs(f, ...)
local args = {}
for _, v in ... do
table.insert(args, tonumberOrString(v))
end
return (f(unpack(args)))
end
--[[
------------------------------------------------------------------------------------
-- ipairsAtOffset
-- This is an iterator for arrays. It can be used like ipairs, but with
-- specified i as first index to iterate. i is an offset from 1
--
------------------------------------------------------------------------------------
--]]
local function ipairsAtOffset(t, i)
local f, s, i0 = ipairs(t)
return f, s, i0+i
end
local function get(s)
local G = _G; for _ in mw.text.gsplit(
mw.text.trim(s, '%s'), '%s*%.%s*'
) do
G = G[_]
end
return G
end
--[[
------------------------------------------------------------------------------------
-- call
--
-- This function is usually useful for debugging template parameters.
-- Prefix parameter with backslash (\) to force interpreting parameter as string.
-- The leading backslash will be removed before passed to Lua function.
--
-- Example:
-- {{#invoke:Lua call|call|mw.log|a|1|2|3}} will return results of mw.log('a', 1, 2, 3)
-- {{#invoke:Lua call|call|mw.logObject|\a|321|\321| \321 }} will return results of mw.logObject('a', 321, '321', ' \\321 ')
--
-- This example show the debugging to see which Unicode characters are allowed in template parameters,
-- {{#invoke:Lua call|call|mw.ustring.codepoint|{{#invoke:Lua call|call|mw.ustring.char|0x0061}}}} return 97
-- {{#invoke:Lua call|call|mw.ustring.codepoint|{{#invoke:Lua call|call|mw.ustring.char|0x0000}}}} return 65533
-- {{#invoke:Lua call|call|mw.ustring.codepoint|{{#invoke:Lua call|call|mw.ustring.char|0x0001}}}} return 65533
-- {{#invoke:Lua call|call|string.format|0x%04x|{{#invoke:Lua call|call|mw.ustring.codepoint|{{#invoke:Lua call|call|mw.ustring.char|0x0002}}}}}} return 0xfffd
-- {{#invoke:Lua call|call|string.format|0x%04x|{{#invoke:Lua call|call|mw.ustring.codepoint|{{#invoke:Lua call|call|mw.ustring.char|0x007e}}}}}} return 0x007e
-- {{#invoke:Lua call|call|string.format|0x%04x|{{#invoke:Lua call|call|mw.ustring.codepoint|{{#invoke:Lua call|call|mw.ustring.char|0x007f}}}}}} return 0x007f
-- {{#invoke:Lua call|call|string.format|0x%04x|{{#invoke:Lua call|call|mw.ustring.codepoint|{{#invoke:Lua call|call|mw.ustring.char|0x0080}}}}}} return 0x0080
-- {{#invoke:Lua call|call|string.format|0x%04x|{{#invoke:Lua call|call|mw.ustring.codepoint|{{#invoke:Lua call|call|mw.ustring.char|0x00a0}}}}}} return 0x00a0
--
------------------------------------------------------------------------------------
--]]
function p.call(frame)
return callWithTonumberOrStringOnPairs(get(frame.args[1]),
ipairsAtOffset(frame.args, 1)
)
end
--local TableTools = require('Module:TableTools')
--[[
------------------------------------------------------------------------------------
-- get
--
-- Example:
-- {{#invoke:Lua call|get| math.pi }} will return value of math.pi
-- {{#invoke:Lua call|get|math|pi}} will return value of math.pi
-- {{#invoke:Lua call|get| math |pi}} will return value of _G[' math '].pi
-- {{#invoke:Lua call|get|_G| math.pi }} will return value of _G[' math.pi ']
-- {{#invoke:Lua call|get|obj.a.5.c}} will return value of obj.a['5'].c
-- {{#invoke:Lua call|get|obj|a|5|c}} will return value of obj.a[5].c
--
------------------------------------------------------------------------------------
--]]
function p.get(frame)
-- #frame.args always return 0, regardless of number of unnamed
-- template parameters, so check manually instead
if frame.args[2] == nil then
-- not do tonumber() for this args style,
-- always treat it as string,
-- so 'obj.1' will mean obj['1'] rather obj[1]
return get(frame.args[1])
else
local G = _G
for _, v in ipairs(frame.args) do
G = G[tonumberOrString(v)]
end
return G
end
end
--[[
------------------------------------------------------------------------------------
-- invoke
--
-- This function is used by Template:Invoke
--
------------------------------------------------------------------------------------
--]]
function p.invoke(frame)
local pframe, usedpargs = frame:getParent(), {}
-- get module and function names from parent args if not provided
local pfargs = setmetatable({frame.args[1], frame.args[2]}, {__index = table})
if not pfargs[1] then
pfargs[1], usedpargs[1] = pframe.args[1], true
if not pfargs[2] then
pfargs[2], usedpargs[2] = pframe.args[2], true
end
elseif not pfargs[2] then
pfargs[2], usedpargs[1] = pframe.args[1], true
end
-- repack sequential args
for i, v in ipairs(pframe.args) do
if not usedpargs[i] then
pfargs:insert(v)
usedpargs[i] = true
end
end
-- copy other args
for k, v in pairs(pframe.args) do
if not pfargs[k] and not usedpargs[k] then
pfargs[k], usedpargs[k] = v, true
end
end
-- #invoke off parent frame so the new frame has the same parent
return pframe:callParserFunction{name = '#invoke', args = pfargs}
end
return p