Module:Arguments: Difference between revisions

From Greyhawk Wiki
Jump to navigation Jump to search
check fargs and pargs before writing new values to args if options.noOverwrite is set
use an array to hold argument tables rather than firstArgs and secondArgs variables
Line 8: Line 8:


-- Get the arguments from the frame object if available. If the frame object is not available, we are being called
-- Get the arguments from the frame object if available. If the frame object is not available, we are being called
-- from another Lua module or from the debug console, so assume arguments are passed directly in.
-- from another Lua module or from the debug console, so put the args in a special table so we can differentiate them.
local fargs, pargs
local fargs, pargs, luaArgs
if frame == mw.getCurrentFrame() then
if frame == mw.getCurrentFrame() then
fargs = frame.args
fargs = frame.args
pargs = frame:getParent().args
pargs = frame:getParent().args
else
else
fargs = type(frame) == 'table' and frame or {}
luaArgs = type(frame) == 'table' and frame or {}
pargs = {}
end
end


-- Set up the args and metaArgs tables. args will be the one accessed from functions, and metaArgs will hold the actual arguments.
-- The metatable connects the two together.
local args, metaArgs, metatable = {}, {}, {}
local args, metaArgs, metatable = {}, {}, {}
setmetatable(args, metatable)
setmetatable(args, metatable)
Line 36: Line 37:
end
end


-- Use a user-generated functions to tidy the values if specified.
-- Use a user-generated function to tidy the values if specified.
local valueFunc = options.valueFunc
local valueFunc = options.valueFunc
if valueFunc then
if valueFunc then
Line 47: Line 48:
end
end


local function mergeArgs(iterator, ...)
local function mergeArgs(iterator, tables)
-- Accepts multiple tables as input and merges their keys and values into one table using the specified iterator.
-- Accepts multiple tables as input and merges their keys and values into one table using the specified iterator.
-- If a value is already present it is not overwritten; tables listed earlier have precendence.
-- If a value is already present it is not overwritten; tables listed earlier have precendence.
local tables = {...}
for _, t in ipairs(tables) do
for _, t in ipairs(tables) do
for key, val in iterator(t) do
for key, val in iterator(t) do
Line 60: Line 60:
end
end


-- Set the order of precedence of frame args and parent args.
-- Set the order of precedence of the argument tables. If the variables are nil, nothing will be added to the table,
local firstArgs, secondArgs = fargs, pargs
-- which is how we avoid clashes between the frame/parent args and the Lua args.
local argTables = {}
if options.parentFirst then
if options.parentFirst then
firstArgs, secondArgs = pargs, fargs
table.insert(argTables, pargs)
table.insert(argTables, fargs)
else
table.insert(argTables, fargs)
table.insert(argTables, pargs)
end
end
table.insert(argTables, luaArgs)


--[[
--[[
-- Define metatable behaviour. Arguments are stored in the metaArgs table, and are only fetched from the
-- Define metatable behaviour. Arguments are stored in the metaArgs table, and are only fetched from the
-- fargs and pargs tables once. Also, we keep a record in the metatable of when pairs and ipairs have
-- argument tables once. Also, we keep a record in the metatable of when pairs and ipairs have been called,
-- been called, so we do not run pairs and ipairs on fargs and pargs more than once. We also do not run
-- so we do not run pairs and ipairs on fargs and pargs more than once. We also do not run ipairs on fargs
-- ipairs on fargs and pargs if pairs has already been run, as all the arguments will already have been
-- and pargs if pairs has already been run, as all the arguments will already have been copied over.
-- copied over.
--]]
--]]
metatable.__index = function (t, key)
metatable.__index = function (t, key)
Line 78: Line 83:
return val
return val
else
else
local firstVal = tidyVal(key, firstArgs[key])
for i, argTable in ipairs(argTables) do
if firstVal ~= nil then
local argTableVal = tidyVal(argTable[key])
return firstVal
if argTableVal ~= nil then
else
metaArgs[key] = argTableVal
return tidyVal(key, secondArgs[key])
return argTableVal
end
end
end
end
end
Line 95: Line 101:
metatable.__pairs = function ()
metatable.__pairs = function ()
if not metatable.donePairs then
if not metatable.donePairs then
mergeArgs(pairs, firstArgs, secondArgs)
mergeArgs(pairs, argTables)
metatable.donePairs = true
metatable.donePairs = true
metatable.doneIpairs = true
metatable.doneIpairs = true
Line 104: Line 110:
metatable.__ipairs = function ()
metatable.__ipairs = function ()
if not metatable.doneIpairs then
if not metatable.doneIpairs then
mergeArgs(ipairs, firstArgs, secondArgs)
mergeArgs(ipairs, argTables)
metatable.doneIpairs = true
metatable.doneIpairs = true
end
end

Revision as of 07:03, 9 December 2013

-- This module provides easy processing of arguments passed to Scribunto from #invoke. -- It is intended for use by other Lua modules, and should not be called from #invoke directly.

local arguments = {}

function arguments.getArgs(frame, options) options = type(options) == 'table' and options or {}

-- Get the arguments from the frame object if available. If the frame object is not available, we are being called -- from another Lua module or from the debug console, so put the args in a special table so we can differentiate them. local fargs, pargs, luaArgs if frame == mw.getCurrentFrame() then fargs = frame.args pargs = frame:getParent().args else luaArgs = type(frame) == 'table' and frame or {} end

-- Set up the args and metaArgs tables. args will be the one accessed from functions, and metaArgs will hold the actual arguments. -- The metatable connects the two together. local args, metaArgs, metatable = {}, {}, {} setmetatable(args, metatable)

local function tidyVal(key, val) -- Processes a value according to the options given to getArguments. Can trim whitespace and remove blanks. -- Keys are not used here, but they can be used by user-generated functions, so defining it here to avoid breakage. if type(val) == 'string' then if options.trim ~= false then val = mw.text.trim(val) end if options.removeBlanks == false or mw.ustring.find(val, '%S') then return val end else return val end end

-- Use a user-generated function to tidy the values if specified. local valueFunc = options.valueFunc if valueFunc then local valueFuncType = type(valueFunc) if valueFuncType == 'function' then tidyVal = valueFunc else error('type error in option "valueFunc": expected function, got ' .. valueFuncType, 2) end end

local function mergeArgs(iterator, tables) -- Accepts multiple tables as input and merges their keys and values into one table using the specified iterator. -- If a value is already present it is not overwritten; tables listed earlier have precendence. for _, t in ipairs(tables) do for key, val in iterator(t) do if metaArgs[key] == nil then metaArgs[key] = tidyVal(key, val) end end end end

-- Set the order of precedence of the argument tables. If the variables are nil, nothing will be added to the table, -- which is how we avoid clashes between the frame/parent args and the Lua args. local argTables = {} if options.parentFirst then table.insert(argTables, pargs) table.insert(argTables, fargs) else table.insert(argTables, fargs) table.insert(argTables, pargs) end table.insert(argTables, luaArgs)

--[[ -- Define metatable behaviour. Arguments are stored in the metaArgs table, and are only fetched from the -- argument tables once. Also, we keep a record in the metatable of when pairs and ipairs have been called, -- so we do not run pairs and ipairs on fargs and pargs more than once. We also do not run ipairs on fargs -- and pargs if pairs has already been run, as all the arguments will already have been copied over. --]] metatable.__index = function (t, key) local val = metaArgs[key] if val ~= nil then return val else for i, argTable in ipairs(argTables) do local argTableVal = tidyVal(argTable[key]) if argTableVal ~= nil then metaArgs[key] = argTableVal return argTableVal end end end end

metatable.__newindex = function (t, key, val) if not options.readOnly and (not options.noOverwrite or args[key] == nil) then metaArgs[key] = val end end

metatable.__pairs = function () if not metatable.donePairs then mergeArgs(pairs, argTables) metatable.donePairs = true metatable.doneIpairs = true end return pairs(metaArgs) end

metatable.__ipairs = function () if not metatable.doneIpairs then mergeArgs(ipairs, argTables) metatable.doneIpairs = true end return ipairs(metaArgs) end

return args end

return arguments