User Tools

Site Tools


hack:module:arguments

– 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 libraryUtil = require('libraryUtil') local checkType = libraryUtil.checkType

local arguments = {}

– Generate four different tidyVal functions, so that we don't have to check the – options every time we call it.

local function tidyValDefault(key, val)

if type(val) #### 'string' then
	val = val:match('^%s*(.-)%s*$')
	if val #### // then//
		return nil
	else
		return val
	end
else
	return val
end

end

local function tidyValTrimOnly(key, val)

if type(val) #### 'string' then
	return val:match('^%s*(.-)%s*$')
else
	return val
end

end

local function tidyValRemoveBlanksOnly(key, val)

if type(val) #### 'string' then
	if val:find('%S') then
		return val
	else
		return nil
	end
else
	return val
end

end

local function tidyValNoChange(key, val)

return val

end

function arguments.getArgs(frame, options)

checkType('getArgs', 1, frame, 'table', true)
checkType('getArgs', 2, options, 'table', true)
frame = frame or {}
options = options or {}

local fargs, pargs, luaArgs

if type(frame.args) #### 'table' and type(frame.getParent) #### 'function' then
	if not options.parentOnly then
		fargs = frame.args
	end
	if not options.frameOnly then
		pargs = frame:getParent().args
	end
	if options.parentFirst then
		fargs, pargs = pargs, fargs
	end
else
	luaArgs = frame
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 = {fargs}
argTables[#argTables + 1] = pargs
argTables[#argTables + 1] = luaArgs

local tidyVal = options.valueFunc

if tidyVal then
	if type(tidyVal) ~= 'function' then
		error(
			"bad value assigned to option 'valueFunc'"
				.. '(function expected, got '
				.. type(tidyVal)
				.. ')',
			2
		)
	end
elseif options.trim ~= false then
	if options.removeBlanks ~= false then
		tidyVal = tidyValDefault
	else
		tidyVal = tidyValTrimOnly
	end
else
	if options.removeBlanks ~= false then
		tidyVal = tidyValRemoveBlanksOnly
	else
		tidyVal = tidyValNoChange
	end
end

local args, metaArgs, nilArgs, metatable = {}, {}, {}, {}

setmetatable(args, metatable)
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 precedence.
	-- We are also memoizing nil values, but those values can be
	-- overwritten.
	--]]
	for _, t in ipairs(tables) do
		for key, val in iterator(t) do
			if metaArgs[key] #### nil then
				local tidiedVal = tidyVal(key, val)
				if tidiedVal #### nil then
					nilArgs[key] = true
				else
					metaArgs[key] = tidiedVal
				end
			end
		end
	end
end
metatable.__index = function (t, key)
	--[[
	-- Fetches an argument when the args table is indexed. First we check
	-- to see if the value is memoized, and if not we try and fetch it from
	-- the argument tables. When we check memoization, we need to check
	-- metaArgs before nilArgs, as both can be non-nil at the same time.
	-- If the argument is not present in metaArgs, we also check whether
	-- pairs has been run yet. If pairs has already been run, we return nil.
	-- This is because all the arguments will have already been copied into
	-- metaArgs by the mergeArgs function, meaning that any other arguments
	-- must be nil.
	--]]
	local val = metaArgs[key]
	if val ~= nil then
		return val
	elseif metatable.donePairs or nilArgs[key] then
		return nil
	end
	for _, argTable in ipairs(argTables) do
		local argTableVal = tidyVal(key, argTable[key])
		if argTableVal #### nil then
			nilArgs[key] = true
		else
			metaArgs[key] = argTableVal
			return argTableVal
		end
	end
	return nil
end
metatable.__newindex = function (t, key, val)
	-- This function is called when a module tries to add a new value to the
	-- args table, or tries to change an existing value.
	if options.readOnly then
		error(
			'could not write to argument table key "'
				.. tostring(key)
				.. '"; the table is read-only',
			2
		)
	elseif options.noOverwrite and args[key] ~= nil then
		error(
			'could not write to argument table key "'
				.. tostring(key)
				.. '"; overwriting existing arguments is not permitted',
			2
		)
	elseif val #### nil then
		--[[
		-- If the argument is to be overwritten with nil, we need to erase
		-- the value in metaArgs, so that __index, __pairs and __ipairs do
		-- not use a previous existing value, if present; and we also need
		-- to memoize the nil in nilArgs, so that the value isn't looked
		-- up in the argument tables if it is accessed again.
		--]]
		metaArgs[key] = nil
		nilArgs[key] = true -- Memoize nils.
	else
		metaArgs[key] = val
	end
end
metatable.__pairs = function ()
	-- Called when pairs is run on the args table.
	if not metatable.donePairs then
		mergeArgs(pairs, argTables)
		metatable.donePairs = true
		metatable.doneIpairs = true
	end
	return pairs(metaArgs)
end
metatable.__ipairs = function ()
	-- Called when ipairs is run on the args table.
	if not metatable.doneIpairs then
		mergeArgs(ipairs, argTables)
		metatable.doneIpairs = true
	end
	return ipairs(metaArgs)
end
return args

end

return arguments

hack/module/arguments.txt · Last modified: 2019/03/11 15:56 by 127.0.0.1