Module:Arguments: Difference between revisions

From Path of Exile Wiki
Jump to navigation Jump to search
en>Mr. Stradivarius
(add a more detailed comment about metatable behaviour)
en>Mr. Stradivarius
(check fargs and pargs before writing new values to args if options.noOverwrite is set)
Line 88: Line 88:


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

Revision as of 07:17, 9 December 2013

Module documentation[view] [edit] [history] [purge]


This is a meta module.

This module is meant to be used only by other modules. It should not be invoked in wikitext.

This module was adapted from Module:Arguments on Wikipedia.
Adaptation is noted for reference and attribution only. This module may differ from the original in function or in usage. The documentation on Wikipedia may be helpful in understanding this module.


-- 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 assume arguments are passed directly in.
	local fargs, pargs
	if frame == mw.getCurrentFrame() then
		fargs = frame.args
		pargs = frame:getParent().args
	else
		fargs = type(frame) == 'table' and frame or {}
		pargs = {}
	end

	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 functions 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, ...)
		-- 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.
		local tables = {...}
		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 frame args and parent args.
	local firstArgs, secondArgs = fargs, pargs
	if options.parentFirst then
		firstArgs, secondArgs = pargs, fargs
	end

	--[[
	-- 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
	-- 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
			local firstVal = tidyVal(key, firstArgs[key])
			if firstVal ~= nil then
				return firstVal
			else
				return tidyVal(key, secondArgs[key])
			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, firstArgs, secondArgs)
			metatable.donePairs = true
			metatable.doneIpairs = true
		end
		return pairs(metaArgs)
	end

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

return arguments