https://mw.lojban.org/index.php?title=Module:Arguments&feed=atom&action=historyModule:Arguments - Revision history2024-03-28T15:13:02ZRevision history for this page on the wikiMediaWiki 1.38.4https://mw.lojban.org/index.php?title=Module:Arguments&diff=117345&oldid=prevGleki: 1 revision imported2015-09-03T14:30:42Z<p>1 revision imported</p>
<p><b>New page</b></p><div>-- This module provides easy processing of arguments passed to Scribunto from<br />
-- #invoke. It is intended for use by other Lua modules, and should not be<br />
-- called from #invoke directly.<br />
<br />
local libraryUtil = require('libraryUtil')<br />
local checkType = libraryUtil.checkType<br />
<br />
local arguments = {}<br />
<br />
-- Generate four different tidyVal functions, so that we don't have to check the<br />
-- options every time we call it.<br />
<br />
local function tidyValDefault(key, val)<br />
if type(val) == 'string' then<br />
val = val:match('^%s*(.-)%s*$')<br />
if val == '' then<br />
return nil<br />
else<br />
return val<br />
end<br />
else<br />
return val<br />
end<br />
end<br />
<br />
local function tidyValTrimOnly(key, val)<br />
if type(val) == 'string' then<br />
return val:match('^%s*(.-)%s*$')<br />
else<br />
return val<br />
end<br />
end<br />
<br />
local function tidyValRemoveBlanksOnly(key, val)<br />
if type(val) == 'string' then<br />
if val:find('%S') then<br />
return val<br />
else<br />
return nil<br />
end<br />
else<br />
return val<br />
end<br />
end<br />
<br />
local function tidyValNoChange(key, val)<br />
return val<br />
end<br />
<br />
local function matchesTitle(given, title)<br />
local tp = type( given )<br />
return (tp == 'string' or tp == 'number') and mw.title.new( given ).prefixedText == title<br />
end<br />
<br />
local translate_mt = { __index = function(t, k) return k end }<br />
<br />
function arguments.getArgs(frame, options)<br />
checkType('getArgs', 1, frame, 'table', true)<br />
checkType('getArgs', 2, options, 'table', true)<br />
frame = frame or {}<br />
options = options or {}<br />
<br />
--[[<br />
-- Set up argument translation.<br />
--]]<br />
options.translate = options.translate or {}<br />
if getmetatable(options.translate) == nil then<br />
setmetatable(options.translate, translate_mt)<br />
end<br />
if options.backtranslate == nil then<br />
options.backtranslate = {}<br />
for k,v in pairs(options.translate) do<br />
options.backtranslate[v] = k<br />
end<br />
end<br />
if options.backtranslate and getmetatable(options.backtranslate) == nil then<br />
setmetatable(options.backtranslate, {<br />
__index = function(t, k)<br />
if options.translate[k] ~= k then<br />
return nil<br />
else<br />
return k<br />
end<br />
end<br />
})<br />
end<br />
<br />
--[[<br />
-- Get the argument tables. If we were passed a valid frame object, get the<br />
-- frame arguments (fargs) and the parent frame arguments (pargs), depending<br />
-- on the options set and on the parent frame's availability. If we weren't<br />
-- passed a valid frame object, we are being called from another Lua module<br />
-- or from the debug console, so assume that we were passed a table of args<br />
-- directly, and assign it to a new variable (luaArgs).<br />
--]]<br />
local fargs, pargs, luaArgs<br />
if type(frame.args) == 'table' and type(frame.getParent) == 'function' then<br />
if options.wrappers then<br />
--[[<br />
-- The wrappers option makes Module:Arguments look up arguments in<br />
-- either the frame argument table or the parent argument table, but<br />
-- not both. This means that users can use either the #invoke syntax<br />
-- or a wrapper template without the loss of performance associated<br />
-- with looking arguments up in both the frame and the parent frame.<br />
-- Module:Arguments will look up arguments in the parent frame<br />
-- if it finds the parent frame's title in options.wrapper;<br />
-- otherwise it will look up arguments in the frame object passed<br />
-- to getArgs.<br />
--]]<br />
local parent = frame:getParent()<br />
if not parent then<br />
fargs = frame.args<br />
else<br />
local title = parent:getTitle():gsub('/sandbox$', '')<br />
local found = false<br />
if matchesTitle(options.wrappers, title) then<br />
found = true<br />
elseif type(options.wrappers) == 'table' then<br />
for _,v in pairs(options.wrappers) do<br />
if matchesTitle(v, title) then<br />
found = true<br />
break<br />
end<br />
end<br />
end<br />
<br />
-- We test for false specifically here so that nil (the default) acts like true.<br />
if found or options.frameOnly == false then<br />
pargs = parent.args<br />
end<br />
if not found or options.parentOnly == false then<br />
fargs = frame.args<br />
end<br />
end<br />
else<br />
-- options.wrapper isn't set, so check the other options.<br />
if not options.parentOnly then<br />
fargs = frame.args<br />
end<br />
if not options.frameOnly then<br />
local parent = frame:getParent()<br />
pargs = parent and parent.args or nil<br />
end<br />
end<br />
if options.parentFirst then<br />
fargs, pargs = pargs, fargs<br />
end<br />
else<br />
luaArgs = frame<br />
end<br />
<br />
-- Set the order of precedence of the argument tables. If the variables are<br />
-- nil, nothing will be added to the table, which is how we avoid clashes<br />
-- between the frame/parent args and the Lua args.<br />
local argTables = {fargs}<br />
argTables[#argTables + 1] = pargs<br />
argTables[#argTables + 1] = luaArgs<br />
<br />
--[[<br />
-- Generate the tidyVal function. If it has been specified by the user, we<br />
-- use that; if not, we choose one of four functions depending on the<br />
-- options chosen. This is so that we don't have to call the options table<br />
-- every time the function is called.<br />
--]]<br />
local tidyVal = options.valueFunc<br />
if tidyVal then<br />
if type(tidyVal) ~= 'function' then<br />
error(<br />
"bad value assigned to option 'valueFunc'"<br />
.. '(function expected, got '<br />
.. type(tidyVal)<br />
.. ')',<br />
2<br />
)<br />
end<br />
elseif options.trim ~= false then<br />
if options.removeBlanks ~= false then<br />
tidyVal = tidyValDefault<br />
else<br />
tidyVal = tidyValTrimOnly<br />
end<br />
else<br />
if options.removeBlanks ~= false then<br />
tidyVal = tidyValRemoveBlanksOnly<br />
else<br />
tidyVal = tidyValNoChange<br />
end<br />
end<br />
<br />
--[[<br />
-- Set up the args, metaArgs and nilArgs tables. args will be the one<br />
-- accessed from functions, and metaArgs will hold the actual arguments. Nil<br />
-- arguments are memoized in nilArgs, and the metatable connects all of them<br />
-- together.<br />
--]]<br />
local args, metaArgs, nilArgs, metatable = {}, {}, {}, {}<br />
setmetatable(args, metatable)<br />
<br />
local function mergeArgs(tables)<br />
--[[<br />
-- Accepts multiple tables as input and merges their keys and values<br />
-- into one table. If a value is already present it is not overwritten;<br />
-- tables listed earlier have precedence. We are also memoizing nil<br />
-- values, which can be overwritten if they are 's' (soft).<br />
--]]<br />
for _, t in ipairs(tables) do<br />
for key, val in pairs(t) do<br />
if metaArgs[key] == nil and nilArgs[key] ~= 'h' then<br />
local tidiedVal = tidyVal(key, val)<br />
if tidiedVal == nil then<br />
nilArgs[key] = 's'<br />
else<br />
metaArgs[key] = tidiedVal<br />
end<br />
end<br />
end<br />
end<br />
end<br />
<br />
--[[<br />
-- Define metatable behaviour. Arguments are memoized in the metaArgs table,<br />
-- and are only fetched from the argument tables once. Fetching arguments<br />
-- from the argument tables is the most resource-intensive step in this<br />
-- module, so we try and avoid it where possible. For this reason, nil<br />
-- arguments are also memoized, in the nilArgs table. Also, we keep a record<br />
-- in the metatable of when pairs and ipairs have been called, so we do not<br />
-- run pairs and ipairs on the argument tables more than once. We also do<br />
-- not run ipairs on fargs and pargs if pairs has already been run, as all<br />
-- the arguments will already have been copied over.<br />
--]]<br />
<br />
metatable.__index = function (t, key)<br />
--[[<br />
-- Fetches an argument when the args table is indexed. First we check<br />
-- to see if the value is memoized, and if not we try and fetch it from<br />
-- the argument tables. When we check memoization, we need to check<br />
-- metaArgs before nilArgs, as both can be non-nil at the same time.<br />
-- If the argument is not present in metaArgs, we also check whether<br />
-- pairs has been run yet. If pairs has already been run, we return nil.<br />
-- This is because all the arguments will have already been copied into<br />
-- metaArgs by the mergeArgs function, meaning that any other arguments<br />
-- must be nil.<br />
--]]<br />
if type(key) == 'string' then<br />
key = options.translate[key]<br />
end<br />
local val = metaArgs[key]<br />
if val ~= nil then<br />
return val<br />
elseif metatable.donePairs or nilArgs[key] then<br />
return nil<br />
end<br />
for _, argTable in ipairs(argTables) do<br />
local argTableVal = tidyVal(key, argTable[key])<br />
if argTableVal ~= nil then<br />
metaArgs[key] = argTableVal<br />
return argTableVal<br />
end<br />
end<br />
nilArgs[key] = 'h'<br />
return nil<br />
end<br />
<br />
metatable.__newindex = function (t, key, val)<br />
-- This function is called when a module tries to add a new value to the<br />
-- args table, or tries to change an existing value.<br />
if type(key) == 'string' then<br />
key = options.translate[key]<br />
end<br />
if options.readOnly then<br />
error(<br />
'could not write to argument table key "'<br />
.. tostring(key)<br />
.. '"; the table is read-only',<br />
2<br />
)<br />
elseif options.noOverwrite and args[key] ~= nil then<br />
error(<br />
'could not write to argument table key "'<br />
.. tostring(key)<br />
.. '"; overwriting existing arguments is not permitted',<br />
2<br />
)<br />
elseif val == nil then<br />
--[[<br />
-- If the argument is to be overwritten with nil, we need to erase<br />
-- the value in metaArgs, so that __index, __pairs and __ipairs do<br />
-- not use a previous existing value, if present; and we also need<br />
-- to memoize the nil in nilArgs, so that the value isn't looked<br />
-- up in the argument tables if it is accessed again.<br />
--]]<br />
metaArgs[key] = nil<br />
nilArgs[key] = 'h'<br />
else<br />
metaArgs[key] = val<br />
end<br />
end<br />
<br />
local function translatenext(invariant)<br />
local k, v = next(invariant.t, invariant.k)<br />
invariant.k = k<br />
if k == nil then<br />
return nil<br />
elseif type(k) ~= 'string' or not options.backtranslate then<br />
return k, v<br />
else<br />
local backtranslate = options.backtranslate[k]<br />
if backtranslate == nil then<br />
-- Skip this one. This is a tail call, so this won't cause stack overflow<br />
return translatenext(invariant)<br />
else<br />
return backtranslate, v<br />
end<br />
end<br />
end<br />
<br />
metatable.__pairs = function ()<br />
-- Called when pairs is run on the args table.<br />
if not metatable.donePairs then<br />
mergeArgs(argTables)<br />
metatable.donePairs = true<br />
end<br />
return translatenext, { t = metaArgs }<br />
end<br />
<br />
local function inext(t, i)<br />
-- This uses our __index metamethod<br />
local v = t[i + 1]<br />
if v ~= nil then<br />
return i + 1, v<br />
end<br />
end<br />
<br />
metatable.__ipairs = function (t)<br />
-- Called when ipairs is run on the args table.<br />
return inext, t, 0<br />
end<br />
<br />
return args<br />
end<br />
<br />
return arguments</div>Glekihttps://mw.lojban.org/index.php?title=Module:Arguments&diff=112969&oldid=prevGleki: 1 revision imported2015-04-20T08:51:06Z<p>1 revision imported</p>
<p><b>New page</b></p><div>-- This module provides easy processing of arguments passed to Scribunto from<br />
-- #invoke. It is intended for use by other Lua modules, and should not be<br />
-- called from #invoke directly.<br />
<br />
local libraryUtil = require('libraryUtil')<br />
local checkType = libraryUtil.checkType<br />
<br />
local arguments = {}<br />
<br />
-- Generate four different tidyVal functions, so that we don't have to check the<br />
-- options every time we call it.<br />
<br />
local function tidyValDefault(key, val)<br />
if type(val) == 'string' then<br />
val = val:match('^%s*(.-)%s*$')<br />
if val == '' then<br />
return nil<br />
else<br />
return val<br />
end<br />
else<br />
return val<br />
end<br />
end<br />
<br />
local function tidyValTrimOnly(key, val)<br />
if type(val) == 'string' then<br />
return val:match('^%s*(.-)%s*$')<br />
else<br />
return val<br />
end<br />
end<br />
<br />
local function tidyValRemoveBlanksOnly(key, val)<br />
if type(val) == 'string' then<br />
if val:find('%S') then<br />
return val<br />
else<br />
return nil<br />
end<br />
else<br />
return val<br />
end<br />
end<br />
<br />
local function tidyValNoChange(key, val)<br />
return val<br />
end<br />
<br />
local function matchesTitle(given, title)<br />
local tp = type( given )<br />
return (tp == 'string' or tp == 'number') and mw.title.new( given ).prefixedText == title<br />
end<br />
<br />
function arguments.getArgs(frame, options)<br />
checkType('getArgs', 1, frame, 'table', true)<br />
checkType('getArgs', 2, options, 'table', true)<br />
frame = frame or {}<br />
options = options or {}<br />
<br />
--[[<br />
-- Get the argument tables. If we were passed a valid frame object, get the<br />
-- frame arguments (fargs) and the parent frame arguments (pargs), depending<br />
-- on the options set and on the parent frame's availability. If we weren't<br />
-- passed a valid frame object, we are being called from another Lua module<br />
-- or from the debug console, so assume that we were passed a table of args<br />
-- directly, and assign it to a new variable (luaArgs).<br />
--]]<br />
local fargs, pargs, luaArgs<br />
if type(frame.args) == 'table' and type(frame.getParent) == 'function' then<br />
if options.wrappers then<br />
--[[<br />
-- The wrappers option makes Module:Arguments look up arguments in<br />
-- either the frame argument table or the parent argument table, but<br />
-- not both. This means that users can use either the #invoke syntax<br />
-- or a wrapper template without the loss of performance associated<br />
-- with looking arguments up in both the frame and the parent frame.<br />
-- Module:Arguments will look up arguments in the parent frame<br />
-- if it finds the parent frame's title in options.wrapper;<br />
-- otherwise it will look up arguments in the frame object passed<br />
-- to getArgs.<br />
--]]<br />
local parent = frame:getParent()<br />
if not parent then<br />
fargs = frame.args<br />
else<br />
local title = parent:getTitle():gsub('/sandbox$', '')<br />
local found = false<br />
if matchesTitle(options.wrappers, title) then<br />
found = true<br />
elseif type(options.wrappers) == 'table' then<br />
for _,v in pairs(options.wrappers) do<br />
if matchesTitle(v, title) then<br />
found = true<br />
break<br />
end<br />
end<br />
end<br />
<br />
-- We test for false specifically here so that nil (the default) acts like true.<br />
if found or options.frameOnly == false then<br />
pargs = parent.args<br />
end<br />
if not found or options.parentOnly == false then<br />
fargs = frame.args<br />
end<br />
end<br />
else<br />
-- options.wrapper isn't set, so check the other options.<br />
if not options.parentOnly then<br />
fargs = frame.args<br />
end<br />
if not options.frameOnly then<br />
local parent = frame:getParent()<br />
pargs = parent and parent.args or nil<br />
end<br />
end<br />
if options.parentFirst then<br />
fargs, pargs = pargs, fargs<br />
end<br />
else<br />
luaArgs = frame<br />
end<br />
<br />
-- Set the order of precedence of the argument tables. If the variables are<br />
-- nil, nothing will be added to the table, which is how we avoid clashes<br />
-- between the frame/parent args and the Lua args. <br />
local argTables = {fargs}<br />
argTables[#argTables + 1] = pargs<br />
argTables[#argTables + 1] = luaArgs<br />
<br />
--[[<br />
-- Generate the tidyVal function. If it has been specified by the user, we<br />
-- use that; if not, we choose one of four functions depending on the<br />
-- options chosen. This is so that we don't have to call the options table<br />
-- every time the function is called.<br />
--]]<br />
local tidyVal = options.valueFunc<br />
if tidyVal then<br />
if type(tidyVal) ~= 'function' then<br />
error(<br />
"bad value assigned to option 'valueFunc'"<br />
.. '(function expected, got '<br />
.. type(tidyVal)<br />
.. ')',<br />
2<br />
)<br />
end<br />
elseif options.trim ~= false then<br />
if options.removeBlanks ~= false then<br />
tidyVal = tidyValDefault<br />
else<br />
tidyVal = tidyValTrimOnly<br />
end<br />
else<br />
if options.removeBlanks ~= false then<br />
tidyVal = tidyValRemoveBlanksOnly<br />
else<br />
tidyVal = tidyValNoChange<br />
end<br />
end<br />
<br />
--[[<br />
-- Set up the args, metaArgs and nilArgs tables. args will be the one<br />
-- accessed from functions, and metaArgs will hold the actual arguments. Nil<br />
-- arguments are memoized in nilArgs, and the metatable connects all of them<br />
-- together.<br />
--]]<br />
local args, metaArgs, nilArgs, metatable = {}, {}, {}, {}<br />
setmetatable(args, metatable)<br />
<br />
local function mergeArgs(tables)<br />
--[[<br />
-- Accepts multiple tables as input and merges their keys and values<br />
-- into one table. If a value is already present it is not overwritten;<br />
-- tables listed earlier have precedence. We are also memoizing nil<br />
-- values, which can be overwritten if they are 's' (soft).<br />
--]]<br />
for _, t in ipairs(tables) do<br />
for key, val in pairs(t) do<br />
if metaArgs[key] == nil and nilArgs[key] ~= 'h' then<br />
local tidiedVal = tidyVal(key, val)<br />
if tidiedVal == nil then<br />
nilArgs[key] = 's'<br />
else<br />
metaArgs[key] = tidiedVal<br />
end<br />
end<br />
end<br />
end<br />
end<br />
<br />
--[[<br />
-- Define metatable behaviour. Arguments are memoized in the metaArgs table,<br />
-- and are only fetched from the argument tables once. Fetching arguments<br />
-- from the argument tables is the most resource-intensive step in this<br />
-- module, so we try and avoid it where possible. For this reason, nil<br />
-- arguments are also memoized, in the nilArgs table. Also, we keep a record<br />
-- in the metatable of when pairs and ipairs have been called, so we do not<br />
-- run pairs and ipairs on the argument tables more than once. We also do<br />
-- not run ipairs on fargs and pargs if pairs has already been run, as all<br />
-- the arguments will already have been copied over.<br />
--]]<br />
<br />
metatable.__index = function (t, key)<br />
--[[<br />
-- Fetches an argument when the args table is indexed. First we check<br />
-- to see if the value is memoized, and if not we try and fetch it from<br />
-- the argument tables. When we check memoization, we need to check<br />
-- metaArgs before nilArgs, as both can be non-nil at the same time.<br />
-- If the argument is not present in metaArgs, we also check whether<br />
-- pairs has been run yet. If pairs has already been run, we return nil.<br />
-- This is because all the arguments will have already been copied into<br />
-- metaArgs by the mergeArgs function, meaning that any other arguments<br />
-- must be nil.<br />
--]]<br />
local val = metaArgs[key]<br />
if val ~= nil then<br />
return val<br />
elseif metatable.donePairs or nilArgs[key] then<br />
return nil<br />
end<br />
for _, argTable in ipairs(argTables) do<br />
local argTableVal = tidyVal(key, argTable[key])<br />
if argTableVal ~= nil then<br />
metaArgs[key] = argTableVal<br />
return argTableVal<br />
end<br />
end<br />
nilArgs[key] = 'h'<br />
return nil<br />
end<br />
<br />
metatable.__newindex = function (t, key, val)<br />
-- This function is called when a module tries to add a new value to the<br />
-- args table, or tries to change an existing value.<br />
if options.readOnly then<br />
error(<br />
'could not write to argument table key "'<br />
.. tostring(key)<br />
.. '"; the table is read-only',<br />
2<br />
)<br />
elseif options.noOverwrite and args[key] ~= nil then<br />
error(<br />
'could not write to argument table key "'<br />
.. tostring(key)<br />
.. '"; overwriting existing arguments is not permitted',<br />
2<br />
)<br />
elseif val == nil then<br />
--[[<br />
-- If the argument is to be overwritten with nil, we need to erase<br />
-- the value in metaArgs, so that __index, __pairs and __ipairs do<br />
-- not use a previous existing value, if present; and we also need<br />
-- to memoize the nil in nilArgs, so that the value isn't looked<br />
-- up in the argument tables if it is accessed again.<br />
--]]<br />
metaArgs[key] = nil<br />
nilArgs[key] = 'h'<br />
else<br />
metaArgs[key] = val<br />
end<br />
end<br />
<br />
metatable.__pairs = function ()<br />
-- Called when pairs is run on the args table.<br />
if not metatable.donePairs then<br />
mergeArgs(argTables)<br />
metatable.donePairs = true<br />
end<br />
return pairs(metaArgs)<br />
end<br />
<br />
local function inext(t, i)<br />
-- This uses our __index metamethod<br />
local v = t[i + 1]<br />
if v ~= nil then<br />
return i + 1, v<br />
end<br />
end<br />
<br />
metatable.__ipairs = function (t)<br />
-- Called when ipairs is run on the args table.<br />
return inext, t, 0<br />
end<br />
<br />
return args<br />
end<br />
<br />
return arguments</div>Glekihttps://mw.lojban.org/index.php?title=Module:Arguments&diff=110509&oldid=prevGleki: 1 revision imported2014-12-18T08:40:09Z<p>1 revision imported</p>
<p><b>New page</b></p><div>-- This module provides easy processing of arguments passed to Scribunto from<br />
-- #invoke. It is intended for use by other Lua modules, and should not be<br />
-- called from #invoke directly.<br />
<br />
local libraryUtil = require('libraryUtil')<br />
local checkType = libraryUtil.checkType<br />
<br />
local arguments = {}<br />
<br />
-- Generate four different tidyVal functions, so that we don't have to check the<br />
-- options every time we call it.<br />
<br />
local function tidyValDefault(key, val)<br />
if type(val) == 'string' then<br />
val = val:match('^%s*(.-)%s*$')<br />
if val == '' then<br />
return nil<br />
else<br />
return val<br />
end<br />
else<br />
return val<br />
end<br />
end<br />
<br />
local function tidyValTrimOnly(key, val)<br />
if type(val) == 'string' then<br />
return val:match('^%s*(.-)%s*$')<br />
else<br />
return val<br />
end<br />
end<br />
<br />
local function tidyValRemoveBlanksOnly(key, val)<br />
if type(val) == 'string' then<br />
if val:find('%S') then<br />
return val<br />
else<br />
return nil<br />
end<br />
else<br />
return val<br />
end<br />
end<br />
<br />
local function tidyValNoChange(key, val)<br />
return val<br />
end<br />
<br />
function arguments.getArgs(frame, options)<br />
checkType('getArgs', 1, frame, 'table', true)<br />
checkType('getArgs', 2, options, 'table', true)<br />
frame = frame or {}<br />
options = options or {}<br />
<br />
--[[<br />
-- Get the argument tables. If we were passed a valid frame object, get the<br />
-- frame arguments (fargs) and the parent frame arguments (pargs), depending<br />
-- on the options set and on the parent frame's availability. If we weren't<br />
-- passed a valid frame object, we are being called from another Lua module<br />
-- or from the debug console, so assume that we were passed a table of args<br />
-- directly, and assign it to a new variable (luaArgs).<br />
--]]<br />
local fargs, pargs, luaArgs<br />
if type(frame.args) == 'table' and type(frame.getParent) == 'function' then<br />
if options.wrappers then<br />
--[[<br />
-- The wrappers option makes Module:Arguments look up arguments in<br />
-- either the frame argument table or the parent argument table, but<br />
-- not both. This means that users can use either the #invoke syntax<br />
-- or a wrapper template without the loss of performance associated<br />
-- with looking arguments up in both the frame and the parent frame.<br />
-- Module:Arguments will look up arguments in the parent frame<br />
-- if it finds the parent frame's title in options.wrapper;<br />
-- otherwise it will look up arguments in the frame object passed<br />
-- to getArgs.<br />
--]]<br />
local parent = frame:getParent()<br />
if not parent then<br />
fargs = frame.args<br />
else<br />
local title = parent:getTitle():gsub('/sandbox$', '')<br />
local found = false<br />
if type(options.wrappers) == 'table' then<br />
for _,v in pairs(options.wrappers) do<br />
if v == title then<br />
found = true<br />
break<br />
end<br />
end<br />
elseif options.wrappers == title then<br />
found = true<br />
end<br />
<br />
-- We test for false specifically here so that nil (the default) acts like true.<br />
if found or options.frameOnly == false then<br />
pargs = parent.args<br />
end<br />
if not found or options.parentOnly == false then<br />
fargs = frame.args<br />
end<br />
end<br />
else<br />
-- options.wrapper isn't set, so check the other options.<br />
if not options.parentOnly then<br />
fargs = frame.args<br />
end<br />
if not options.frameOnly then<br />
local parent = frame:getParent()<br />
pargs = parent and parent.args or nil<br />
end<br />
end<br />
if options.parentFirst then<br />
fargs, pargs = pargs, fargs<br />
end<br />
else<br />
luaArgs = frame<br />
end<br />
<br />
-- Set the order of precedence of the argument tables. If the variables are<br />
-- nil, nothing will be added to the table, which is how we avoid clashes<br />
-- between the frame/parent args and the Lua args. <br />
local argTables = {fargs}<br />
argTables[#argTables + 1] = pargs<br />
argTables[#argTables + 1] = luaArgs<br />
<br />
--[[<br />
-- Generate the tidyVal function. If it has been specified by the user, we<br />
-- use that; if not, we choose one of four functions depending on the<br />
-- options chosen. This is so that we don't have to call the options table<br />
-- every time the function is called.<br />
--]]<br />
local tidyVal = options.valueFunc<br />
if tidyVal then<br />
if type(tidyVal) ~= 'function' then<br />
error(<br />
"bad value assigned to option 'valueFunc'"<br />
.. '(function expected, got '<br />
.. type(tidyVal)<br />
.. ')',<br />
2<br />
)<br />
end<br />
elseif options.trim ~= false then<br />
if options.removeBlanks ~= false then<br />
tidyVal = tidyValDefault<br />
else<br />
tidyVal = tidyValTrimOnly<br />
end<br />
else<br />
if options.removeBlanks ~= false then<br />
tidyVal = tidyValRemoveBlanksOnly<br />
else<br />
tidyVal = tidyValNoChange<br />
end<br />
end<br />
<br />
--[[<br />
-- Set up the args, metaArgs and nilArgs tables. args will be the one<br />
-- accessed from functions, and metaArgs will hold the actual arguments. Nil<br />
-- arguments are memoized in nilArgs, and the metatable connects all of them<br />
-- together.<br />
--]]<br />
local args, metaArgs, nilArgs, metatable = {}, {}, {}, {}<br />
setmetatable(args, metatable)<br />
<br />
local function mergeArgs(iterator, tables)<br />
--[[<br />
-- Accepts multiple tables as input and merges their keys and values<br />
-- into one table using the specified iterator. If a value is already<br />
-- present it is not overwritten; tables listed earlier have precedence.<br />
-- We are also memoizing nil values, which can be overwritten if they<br />
-- are 's' (soft).<br />
--]]<br />
for _, t in ipairs(tables) do<br />
for key, val in iterator(t) do<br />
if metaArgs[key] == nil and nilArgs[key] ~= 'h' then<br />
local tidiedVal = tidyVal(key, val)<br />
if tidiedVal == nil then<br />
nilArgs[key] = 's'<br />
else<br />
metaArgs[key] = tidiedVal<br />
end<br />
end<br />
end<br />
end<br />
end<br />
<br />
--[[<br />
-- Define metatable behaviour. Arguments are memoized in the metaArgs table,<br />
-- and are only fetched from the argument tables once. Fetching arguments<br />
-- from the argument tables is the most resource-intensive step in this<br />
-- module, so we try and avoid it where possible. For this reason, nil<br />
-- arguments are also memoized, in the nilArgs table. Also, we keep a record<br />
-- in the metatable of when pairs and ipairs have been called, so we do not<br />
-- run pairs and ipairs on the argument tables more than once. We also do<br />
-- not run ipairs on fargs and pargs if pairs has already been run, as all<br />
-- the arguments will already have been copied over.<br />
--]]<br />
<br />
metatable.__index = function (t, key)<br />
--[[<br />
-- Fetches an argument when the args table is indexed. First we check<br />
-- to see if the value is memoized, and if not we try and fetch it from<br />
-- the argument tables. When we check memoization, we need to check<br />
-- metaArgs before nilArgs, as both can be non-nil at the same time.<br />
-- If the argument is not present in metaArgs, we also check whether<br />
-- pairs has been run yet. If pairs has already been run, we return nil.<br />
-- This is because all the arguments will have already been copied into<br />
-- metaArgs by the mergeArgs function, meaning that any other arguments<br />
-- must be nil.<br />
--]]<br />
local val = metaArgs[key]<br />
if val ~= nil then<br />
return val<br />
elseif metatable.donePairs or nilArgs[key] then<br />
return nil<br />
end<br />
for _, argTable in ipairs(argTables) do<br />
local argTableVal = tidyVal(key, argTable[key])<br />
if argTableVal ~= nil then<br />
metaArgs[key] = argTableVal<br />
return argTableVal<br />
end<br />
end<br />
nilArgs[key] = 'h'<br />
return nil<br />
end<br />
<br />
metatable.__newindex = function (t, key, val)<br />
-- This function is called when a module tries to add a new value to the<br />
-- args table, or tries to change an existing value.<br />
if options.readOnly then<br />
error(<br />
'could not write to argument table key "'<br />
.. tostring(key)<br />
.. '"; the table is read-only',<br />
2<br />
)<br />
elseif options.noOverwrite and args[key] ~= nil then<br />
error(<br />
'could not write to argument table key "'<br />
.. tostring(key)<br />
.. '"; overwriting existing arguments is not permitted',<br />
2<br />
)<br />
elseif val == nil then<br />
--[[<br />
-- If the argument is to be overwritten with nil, we need to erase<br />
-- the value in metaArgs, so that __index, __pairs and __ipairs do<br />
-- not use a previous existing value, if present; and we also need<br />
-- to memoize the nil in nilArgs, so that the value isn't looked<br />
-- up in the argument tables if it is accessed again.<br />
--]]<br />
metaArgs[key] = nil<br />
nilArgs[key] = 'h'<br />
else<br />
metaArgs[key] = val<br />
end<br />
end<br />
<br />
metatable.__pairs = function ()<br />
-- Called when pairs is run on the args table.<br />
if not metatable.donePairs then<br />
mergeArgs(pairs, argTables)<br />
metatable.donePairs = true<br />
metatable.doneIpairs = true<br />
end<br />
return pairs(metaArgs)<br />
end<br />
<br />
metatable.__ipairs = function ()<br />
-- Called when ipairs is run on the args table.<br />
if not metatable.doneIpairs then<br />
mergeArgs(ipairs, argTables)<br />
metatable.doneIpairs = true<br />
end<br />
return ipairs(metaArgs)<br />
end<br />
<br />
return args<br />
end<br />
<br />
return arguments</div>Glekihttps://mw.lojban.org/index.php?title=Module:Arguments&diff=109456&oldid=prevGleki: 1 revision imported2014-10-08T14:01:42Z<p>1 revision imported</p>
<p><b>New page</b></p><div>-- This module provides easy processing of arguments passed to Scribunto from<br />
-- #invoke. It is intended for use by other Lua modules, and should not be<br />
-- called from #invoke directly.<br />
<br />
local libraryUtil = require('libraryUtil')<br />
local checkType = libraryUtil.checkType<br />
<br />
local arguments = {}<br />
<br />
-- Generate four different tidyVal functions, so that we don't have to check the<br />
-- options every time we call it.<br />
<br />
local function tidyValDefault(key, val)<br />
if type(val) == 'string' then<br />
val = val:match('^%s*(.-)%s*$')<br />
if val == '' then<br />
return nil<br />
else<br />
return val<br />
end<br />
else<br />
return val<br />
end<br />
end<br />
<br />
local function tidyValTrimOnly(key, val)<br />
if type(val) == 'string' then<br />
return val:match('^%s*(.-)%s*$')<br />
else<br />
return val<br />
end<br />
end<br />
<br />
local function tidyValRemoveBlanksOnly(key, val)<br />
if type(val) == 'string' then<br />
if val:find('%S') then<br />
return val<br />
else<br />
return nil<br />
end<br />
else<br />
return val<br />
end<br />
end<br />
<br />
local function tidyValNoChange(key, val)<br />
return val<br />
end<br />
<br />
function arguments.getArgs(frame, options)<br />
checkType('getArgs', 1, frame, 'table', true)<br />
checkType('getArgs', 2, options, 'table', true)<br />
frame = frame or {}<br />
options = options or {}<br />
<br />
--[[<br />
-- Get the argument tables. If we were passed a valid frame object, get the<br />
-- frame arguments (fargs) and the parent frame arguments (pargs), depending<br />
-- on the options set and on the parent frame's availability. If we weren't<br />
-- passed a valid frame object, we are being called from another Lua module<br />
-- or from the debug console, so assume that we were passed a table of args<br />
-- directly, and assign it to a new variable (luaArgs).<br />
--]]<br />
local fargs, pargs, luaArgs<br />
if type(frame.args) == 'table' and type(frame.getParent) == 'function' then<br />
if options.wrappers then<br />
--[[<br />
-- The wrappers option makes Module:Arguments look up arguments in<br />
-- either the frame argument table or the parent argument table, but<br />
-- not both. This means that users can use either the #invoke syntax<br />
-- or a wrapper template without the loss of performance associated<br />
-- with looking arguments up in both the frame and the parent frame.<br />
-- Module:Arguments will look up arguments in the parent frame<br />
-- if it finds the parent frame's title in options.wrapper;<br />
-- otherwise it will look up arguments in the frame object passed<br />
-- to getArgs.<br />
--]]<br />
local parent = frame:getParent()<br />
if not parent then<br />
fargs = frame.args<br />
else<br />
local title = parent:getTitle():gsub('/sandbox$', '')<br />
local found = false<br />
if type(options.wrappers) == 'table' then<br />
for _,v in pairs(options.wrappers) do<br />
if v == title then<br />
found = true<br />
break<br />
end<br />
end<br />
elseif options.wrappers == title then<br />
found = true<br />
end<br />
<br />
-- We test for false specifically here so that nil (the default) acts like true.<br />
if found or options.frameOnly == false then<br />
pargs = parent.args<br />
end<br />
if not found or options.parentOnly == false then<br />
fargs = frame.args<br />
end<br />
end<br />
else<br />
-- options.wrapper isn't set, so check the other options.<br />
if not options.parentOnly then<br />
fargs = frame.args<br />
end<br />
if not options.frameOnly then<br />
local parent = frame:getParent()<br />
pargs = parent and parent.args or nil<br />
end<br />
end<br />
if options.parentFirst then<br />
fargs, pargs = pargs, fargs<br />
end<br />
else<br />
luaArgs = frame<br />
end<br />
<br />
-- Set the order of precedence of the argument tables. If the variables are<br />
-- nil, nothing will be added to the table, which is how we avoid clashes<br />
-- between the frame/parent args and the Lua args. <br />
local argTables = {fargs}<br />
argTables[#argTables + 1] = pargs<br />
argTables[#argTables + 1] = luaArgs<br />
<br />
--[[<br />
-- Generate the tidyVal function. If it has been specified by the user, we<br />
-- use that; if not, we choose one of four functions depending on the<br />
-- options chosen. This is so that we don't have to call the options table<br />
-- every time the function is called.<br />
--]]<br />
local tidyVal = options.valueFunc<br />
if tidyVal then<br />
if type(tidyVal) ~= 'function' then<br />
error(<br />
"bad value assigned to option 'valueFunc'"<br />
.. '(function expected, got '<br />
.. type(tidyVal)<br />
.. ')',<br />
2<br />
)<br />
end<br />
elseif options.trim ~= false then<br />
if options.removeBlanks ~= false then<br />
tidyVal = tidyValDefault<br />
else<br />
tidyVal = tidyValTrimOnly<br />
end<br />
else<br />
if options.removeBlanks ~= false then<br />
tidyVal = tidyValRemoveBlanksOnly<br />
else<br />
tidyVal = tidyValNoChange<br />
end<br />
end<br />
<br />
--[[<br />
-- Set up the args, metaArgs and nilArgs tables. args will be the one<br />
-- accessed from functions, and metaArgs will hold the actual arguments. Nil<br />
-- arguments are memoized in nilArgs, and the metatable connects all of them<br />
-- together.<br />
--]]<br />
local args, metaArgs, nilArgs, metatable = {}, {}, {}, {}<br />
setmetatable(args, metatable)<br />
<br />
local function mergeArgs(iterator, tables)<br />
--[[<br />
-- Accepts multiple tables as input and merges their keys and values<br />
-- into one table using the specified iterator. If a value is already<br />
-- present it is not overwritten; tables listed earlier have precedence.<br />
-- We are also memoizing nil values, but those values can be<br />
-- overwritten.<br />
--]]<br />
for _, t in ipairs(tables) do<br />
for key, val in iterator(t) do<br />
if metaArgs[key] == nil then<br />
local tidiedVal = tidyVal(key, val)<br />
if tidiedVal == nil then<br />
nilArgs[key] = true<br />
else<br />
metaArgs[key] = tidiedVal<br />
end<br />
end<br />
end<br />
end<br />
end<br />
<br />
--[[<br />
-- Define metatable behaviour. Arguments are memoized in the metaArgs table,<br />
-- and are only fetched from the argument tables once. Fetching arguments<br />
-- from the argument tables is the most resource-intensive step in this<br />
-- module, so we try and avoid it where possible. For this reason, nil<br />
-- arguments are also memoized, in the nilArgs table. Also, we keep a record<br />
-- in the metatable of when pairs and ipairs have been called, so we do not<br />
-- run pairs and ipairs on the argument tables more than once. We also do<br />
-- not run ipairs on fargs and pargs if pairs has already been run, as all<br />
-- the arguments will already have been copied over.<br />
--]]<br />
<br />
metatable.__index = function (t, key)<br />
--[[<br />
-- Fetches an argument when the args table is indexed. First we check<br />
-- to see if the value is memoized, and if not we try and fetch it from<br />
-- the argument tables. When we check memoization, we need to check<br />
-- metaArgs before nilArgs, as both can be non-nil at the same time.<br />
-- If the argument is not present in metaArgs, we also check whether<br />
-- pairs has been run yet. If pairs has already been run, we return nil.<br />
-- This is because all the arguments will have already been copied into<br />
-- metaArgs by the mergeArgs function, meaning that any other arguments<br />
-- must be nil.<br />
--]]<br />
local val = metaArgs[key]<br />
if val ~= nil then<br />
return val<br />
elseif metatable.donePairs or nilArgs[key] then<br />
return nil<br />
end<br />
for _, argTable in ipairs(argTables) do<br />
local argTableVal = tidyVal(key, argTable[key])<br />
if argTableVal == nil then<br />
nilArgs[key] = true<br />
else<br />
metaArgs[key] = argTableVal<br />
return argTableVal<br />
end<br />
end<br />
return nil<br />
end<br />
<br />
metatable.__newindex = function (t, key, val)<br />
-- This function is called when a module tries to add a new value to the<br />
-- args table, or tries to change an existing value.<br />
if options.readOnly then<br />
error(<br />
'could not write to argument table key "'<br />
.. tostring(key)<br />
.. '"; the table is read-only',<br />
2<br />
)<br />
elseif options.noOverwrite and args[key] ~= nil then<br />
error(<br />
'could not write to argument table key "'<br />
.. tostring(key)<br />
.. '"; overwriting existing arguments is not permitted',<br />
2<br />
)<br />
elseif val == nil then<br />
--[[<br />
-- If the argument is to be overwritten with nil, we need to erase<br />
-- the value in metaArgs, so that __index, __pairs and __ipairs do<br />
-- not use a previous existing value, if present; and we also need<br />
-- to memoize the nil in nilArgs, so that the value isn't looked<br />
-- up in the argument tables if it is accessed again.<br />
--]]<br />
metaArgs[key] = nil<br />
nilArgs[key] = true<br />
else<br />
metaArgs[key] = val<br />
end<br />
end<br />
<br />
metatable.__pairs = function ()<br />
-- Called when pairs is run on the args table.<br />
if not metatable.donePairs then<br />
mergeArgs(pairs, argTables)<br />
metatable.donePairs = true<br />
metatable.doneIpairs = true<br />
end<br />
return pairs(metaArgs)<br />
end<br />
<br />
metatable.__ipairs = function ()<br />
-- Called when ipairs is run on the args table.<br />
if not metatable.doneIpairs then<br />
mergeArgs(ipairs, argTables)<br />
metatable.doneIpairs = true<br />
end<br />
return ipairs(metaArgs)<br />
end<br />
<br />
return args<br />
end<br />
<br />
return arguments</div>Glekihttps://mw.lojban.org/index.php?title=Module:Arguments&diff=96299&oldid=prevGleki: 1 revision2014-06-09T09:53:32Z<p>1 revision</p>
<p><b>New page</b></p><div>-- This module provides easy processing of arguments passed to Scribunto from<br />
-- #invoke. It is intended for use by other Lua modules, and should not be<br />
-- called from #invoke directly.<br />
<br />
local libraryUtil = require('libraryUtil')<br />
local checkType = libraryUtil.checkType<br />
<br />
local arguments = {}<br />
<br />
-- Generate four different tidyVal functions, so that we don't have to check the<br />
-- options every time we call it.<br />
<br />
local function tidyValDefault(key, val)<br />
if type(val) == 'string' then<br />
val = val:match('^%s*(.-)%s*$')<br />
if val == '' then<br />
return nil<br />
else<br />
return val<br />
end<br />
else<br />
return val<br />
end<br />
end<br />
<br />
local function tidyValTrimOnly(key, val)<br />
if type(val) == 'string' then<br />
return val:match('^%s*(.-)%s*$')<br />
else<br />
return val<br />
end<br />
end<br />
<br />
local function tidyValRemoveBlanksOnly(key, val)<br />
if type(val) == 'string' then<br />
if val:find('%S') then<br />
return val<br />
else<br />
return nil<br />
end<br />
else<br />
return val<br />
end<br />
end<br />
<br />
local function tidyValNoChange(key, val)<br />
return val<br />
end<br />
<br />
function arguments.getArgs(frame, options)<br />
checkType('getArgs', 1, frame, 'table', true)<br />
checkType('getArgs', 2, options, 'table', true)<br />
frame = frame or {}<br />
options = options or {}<br />
<br />
--[[<br />
-- Get the argument tables. If we were passed a valid frame object, get the<br />
-- frame arguments (fargs) and the parent frame arguments (pargs), depending<br />
-- on the options set and on the parent frame's availability. If we weren't<br />
-- passed a valid frame object, we are being called from another Lua module<br />
-- or from the debug console, so assume that we were passed a table of args<br />
-- directly, and assign it to a new variable (luaArgs).<br />
--]]<br />
local fargs, pargs, luaArgs<br />
if type(frame.args) == 'table' and type(frame.getParent) == 'function' then<br />
if options.wrappers then<br />
--[[<br />
-- The wrappers option makes Module:Arguments look up arguments in<br />
-- either the frame argument table or the parent argument table, but<br />
-- not both. This means that users can use either the #invoke syntax<br />
-- or a wrapper template without the loss of performance associated<br />
-- with looking arguments up in both the frame and the parent frame.<br />
-- Module:Arguments will look up arguments in the parent frame<br />
-- if it finds the parent frame's title in options.wrapper;<br />
-- otherwise it will look up arguments in the frame object passed<br />
-- to getArgs.<br />
--]]<br />
local parent = frame:getParent()<br />
if not parent then<br />
fargs = frame.args<br />
else<br />
local title = parent:getTitle():gsub('/sandbox$', '')<br />
local found = false<br />
if type(options.wrappers) == 'table' then<br />
for _,v in pairs(options.wrappers) do<br />
if v == title then<br />
found = true<br />
break<br />
end<br />
end<br />
elseif options.wrappers == title then<br />
found = true<br />
end<br />
if found then<br />
pargs = parent.args<br />
else<br />
fargs = frame.args<br />
end<br />
end<br />
else<br />
-- options.wrapper isn't set, so check the other options.<br />
if not options.parentOnly then<br />
fargs = frame.args<br />
end<br />
if not options.frameOnly then<br />
local parent = frame:getParent()<br />
pargs = parent and parent.args or nil<br />
end<br />
if options.parentFirst then<br />
fargs, pargs = pargs, fargs<br />
end<br />
end<br />
else<br />
luaArgs = frame<br />
end<br />
<br />
-- Set the order of precedence of the argument tables. If the variables are<br />
-- nil, nothing will be added to the table, which is how we avoid clashes<br />
-- between the frame/parent args and the Lua args. <br />
local argTables = {fargs}<br />
argTables[#argTables + 1] = pargs<br />
argTables[#argTables + 1] = luaArgs<br />
<br />
--[[<br />
-- Generate the tidyVal function. If it has been specified by the user, we<br />
-- use that; if not, we choose one of four functions depending on the<br />
-- options chosen. This is so that we don't have to call the options table<br />
-- every time the function is called.<br />
--]]<br />
local tidyVal = options.valueFunc<br />
if tidyVal then<br />
if type(tidyVal) ~= 'function' then<br />
error(<br />
"bad value assigned to option 'valueFunc'"<br />
.. '(function expected, got '<br />
.. type(tidyVal)<br />
.. ')',<br />
2<br />
)<br />
end<br />
elseif options.trim ~= false then<br />
if options.removeBlanks ~= false then<br />
tidyVal = tidyValDefault<br />
else<br />
tidyVal = tidyValTrimOnly<br />
end<br />
else<br />
if options.removeBlanks ~= false then<br />
tidyVal = tidyValRemoveBlanksOnly<br />
else<br />
tidyVal = tidyValNoChange<br />
end<br />
end<br />
<br />
--[[<br />
-- Set up the args, metaArgs and nilArgs tables. args will be the one<br />
-- accessed from functions, and metaArgs will hold the actual arguments. Nil<br />
-- arguments are memoized in nilArgs, and the metatable connects all of them<br />
-- together.<br />
--]]<br />
local args, metaArgs, nilArgs, metatable = {}, {}, {}, {}<br />
setmetatable(args, metatable)<br />
<br />
local function mergeArgs(iterator, tables)<br />
--[[<br />
-- Accepts multiple tables as input and merges their keys and values<br />
-- into one table using the specified iterator. If a value is already<br />
-- present it is not overwritten; tables listed earlier have precedence.<br />
-- We are also memoizing nil values, but those values can be<br />
-- overwritten.<br />
--]]<br />
for _, t in ipairs(tables) do<br />
for key, val in iterator(t) do<br />
if metaArgs[key] == nil then<br />
local tidiedVal = tidyVal(key, val)<br />
if tidiedVal == nil then<br />
nilArgs[key] = true<br />
else<br />
metaArgs[key] = tidiedVal<br />
end<br />
end<br />
end<br />
end<br />
end<br />
<br />
--[[<br />
-- Define metatable behaviour. Arguments are memoized in the metaArgs table,<br />
-- and are only fetched from the argument tables once. Fetching arguments<br />
-- from the argument tables is the most resource-intensive step in this<br />
-- module, so we try and avoid it where possible. For this reason, nil<br />
-- arguments are also memoized, in the nilArgs table. Also, we keep a record<br />
-- in the metatable of when pairs and ipairs have been called, so we do not<br />
-- run pairs and ipairs on the argument tables more than once. We also do<br />
-- not run ipairs on fargs and pargs if pairs has already been run, as all<br />
-- the arguments will already have been copied over.<br />
--]]<br />
<br />
metatable.__index = function (t, key)<br />
--[[<br />
-- Fetches an argument when the args table is indexed. First we check<br />
-- to see if the value is memoized, and if not we try and fetch it from<br />
-- the argument tables. When we check memoization, we need to check<br />
-- metaArgs before nilArgs, as both can be non-nil at the same time.<br />
-- If the argument is not present in metaArgs, we also check whether<br />
-- pairs has been run yet. If pairs has already been run, we return nil.<br />
-- This is because all the arguments will have already been copied into<br />
-- metaArgs by the mergeArgs function, meaning that any other arguments<br />
-- must be nil.<br />
--]]<br />
local val = metaArgs[key]<br />
if val ~= nil then<br />
return val<br />
elseif metatable.donePairs or nilArgs[key] then<br />
return nil<br />
end<br />
for _, argTable in ipairs(argTables) do<br />
local argTableVal = tidyVal(key, argTable[key])<br />
if argTableVal == nil then<br />
nilArgs[key] = true<br />
else<br />
metaArgs[key] = argTableVal<br />
return argTableVal<br />
end<br />
end<br />
return nil<br />
end<br />
<br />
metatable.__newindex = function (t, key, val)<br />
-- This function is called when a module tries to add a new value to the<br />
-- args table, or tries to change an existing value.<br />
if options.readOnly then<br />
error(<br />
'could not write to argument table key "'<br />
.. tostring(key)<br />
.. '"; the table is read-only',<br />
2<br />
)<br />
elseif options.noOverwrite and args[key] ~= nil then<br />
error(<br />
'could not write to argument table key "'<br />
.. tostring(key)<br />
.. '"; overwriting existing arguments is not permitted',<br />
2<br />
)<br />
elseif val == nil then<br />
--[[<br />
-- If the argument is to be overwritten with nil, we need to erase<br />
-- the value in metaArgs, so that __index, __pairs and __ipairs do<br />
-- not use a previous existing value, if present; and we also need<br />
-- to memoize the nil in nilArgs, so that the value isn't looked<br />
-- up in the argument tables if it is accessed again.<br />
--]]<br />
metaArgs[key] = nil<br />
nilArgs[key] = true<br />
else<br />
metaArgs[key] = val<br />
end<br />
end<br />
<br />
metatable.__pairs = function ()<br />
-- Called when pairs is run on the args table.<br />
if not metatable.donePairs then<br />
mergeArgs(pairs, argTables)<br />
metatable.donePairs = true<br />
metatable.doneIpairs = true<br />
end<br />
return pairs(metaArgs)<br />
end<br />
<br />
metatable.__ipairs = function ()<br />
-- Called when ipairs is run on the args table.<br />
if not metatable.doneIpairs then<br />
mergeArgs(ipairs, argTables)<br />
metatable.doneIpairs = true<br />
end<br />
return ipairs(metaArgs)<br />
end<br />
<br />
return args<br />
end<br />
<br />
return arguments</div>Glekihttps://mw.lojban.org/index.php?title=Module:Arguments&diff=84247&oldid=prevGleki: 1 revision2014-02-28T19:42:25Z<p>1 revision</p>
<table style="background-color: #fff; color: #202122;" data-mw="interface">
<col class="diff-marker" />
<col class="diff-content" />
<col class="diff-marker" />
<col class="diff-content" />
<tr class="diff-title" lang="en">
<td colspan="2" style="background-color: #fff; color: #202122; text-align: center;">← Older revision</td>
<td colspan="2" style="background-color: #fff; color: #202122; text-align: center;">Revision as of 19:42, 28 February 2014</td>
</tr>
<!-- diff cache key mediawiki:diff::1.12:old-84246:rev-84247 -->
</table>Glekihttps://mw.lojban.org/index.php?title=Module:Arguments&diff=84246&oldid=prev86.135.251.105: Created page with "-- 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 di..."2014-02-02T12:52:03Z<p>Created page with "-- 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 di..."</p>
<table style="background-color: #fff; color: #202122;" data-mw="interface">
<col class="diff-marker" />
<col class="diff-content" />
<col class="diff-marker" />
<col class="diff-content" />
<tr class="diff-title" lang="en">
<td colspan="2" style="background-color: #fff; color: #202122; text-align: center;">← Older revision</td>
<td colspan="2" style="background-color: #fff; color: #202122; text-align: center;">Revision as of 12:52, 2 February 2014</td>
</tr><tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1">Line 1:</td>
<td colspan="2" class="diff-lineno">Line 1:</td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>-- This module provides easy processing of arguments passed to Scribunto from #invoke.</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>-- This module provides easy processing of arguments passed to Scribunto from #invoke.</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>-- It is intended for use by other Lua modules, and should not be called from #invoke directly.</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>-- It is intended for use by other Lua modules, and should not be called from #invoke directly.</div></td></tr>
<tr><td class="diff-marker" data-marker="−"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> </div></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div><ins style="font-weight: bold; text-decoration: none;"> </ins></div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>local libraryUtil = require('libraryUtil')</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>local libraryUtil = require('libraryUtil')</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>local checkType = libraryUtil.checkType</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>local checkType = libraryUtil.checkType</div></td></tr>
<tr><td class="diff-marker" data-marker="−"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> </div></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div><ins style="font-weight: bold; text-decoration: none;"> </ins></div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>local arguments = {}</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>local arguments = {}</div></td></tr>
<tr><td class="diff-marker" data-marker="−"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> </div></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div><ins style="font-weight: bold; text-decoration: none;"> </ins></div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>local nilArg = {} -- Used for memoizing nil arguments in metaArgs.</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>local nilArg = {} -- Used for memoizing nil arguments in metaArgs.</div></td></tr>
<tr><td class="diff-marker" data-marker="−"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> </div></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div><ins style="font-weight: bold; text-decoration: none;"> </ins></div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>-- Generate four different tidyVal functions, so that we don't have to check the options every time we call it.</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>-- Generate four different tidyVal functions, so that we don't have to check the options every time we call it.</div></td></tr>
<tr><td class="diff-marker" data-marker="−"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> </div></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div><ins style="font-weight: bold; text-decoration: none;"> </ins></div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>local function tidyValDefault(key, val)</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>local function tidyValDefault(key, val)</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> if type(val) == 'string' then</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> if type(val) == 'string' then</div></td></tr>
<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l23">Line 23:</td>
<td colspan="2" class="diff-lineno">Line 23:</td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>end</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>end</div></td></tr>
<tr><td class="diff-marker" data-marker="−"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> </div></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div><ins style="font-weight: bold; text-decoration: none;"> </ins></div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>local function tidyValTrimOnly(key, val)</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>local function tidyValTrimOnly(key, val)</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> if type(val) == 'string' then</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> if type(val) == 'string' then</div></td></tr>
<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l31">Line 31:</td>
<td colspan="2" class="diff-lineno">Line 31:</td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>end</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>end</div></td></tr>
<tr><td class="diff-marker" data-marker="−"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> </div></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div><ins style="font-weight: bold; text-decoration: none;"> </ins></div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>local function tidyValRemoveBlanksOnly(key, val)</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>local function tidyValRemoveBlanksOnly(key, val)</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> if type(val) == 'string' then</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> if type(val) == 'string' then</div></td></tr>
<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l43">Line 43:</td>
<td colspan="2" class="diff-lineno">Line 43:</td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>end</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>end</div></td></tr>
<tr><td class="diff-marker" data-marker="−"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> </div></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div><ins style="font-weight: bold; text-decoration: none;"> </ins></div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>local function tidyValNoChange(key, val)</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>local function tidyValNoChange(key, val)</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> return val</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> return val</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>end</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>end</div></td></tr>
<tr><td class="diff-marker" data-marker="−"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> </div></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div><ins style="font-weight: bold; text-decoration: none;"> </ins></div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>function arguments.getArgs(frame, options)</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>function arguments.getArgs(frame, options)</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> checkType('getArgs', 1, frame, 'table', true)</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> checkType('getArgs', 1, frame, 'table', true)</div></td></tr>
<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l53">Line 53:</td>
<td colspan="2" class="diff-lineno">Line 53:</td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> frame = frame or {}</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> frame = frame or {}</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> options = options or {}</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> options = options or {}</div></td></tr>
<tr><td class="diff-marker" data-marker="−"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> </div></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div><ins style="font-weight: bold; text-decoration: none;"> </ins></div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- Get the arguments from the frame object if available. If the frame object is not available, we are being called</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- Get the arguments from the frame object if available. If the frame object is not available, we are being called</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- from another Lua module or from the debug console, so assign the args to a new variable so we can differentiate them.</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- from another Lua module or from the debug console, so assign the args to a new variable so we can differentiate them.</div></td></tr>
<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l70">Line 70:</td>
<td colspan="2" class="diff-lineno">Line 70:</td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> luaArgs = frame</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> luaArgs = frame</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td></tr>
<tr><td class="diff-marker" data-marker="−"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> </div></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div><ins style="font-weight: bold; text-decoration: none;"> </ins></div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- Set up the args and metaArgs tables. args will be the one accessed from functions, and metaArgs will hold the actual arguments.</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- Set up the args and metaArgs tables. args will be the one accessed from functions, and metaArgs will hold the actual arguments.</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- The metatable connects the two together.</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- The metatable connects the two together.</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> local args, metaArgs, metatable = {}, {}, {}</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> local args, metaArgs, metatable = {}, {}, {}</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> setmetatable(args, metatable)</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> setmetatable(args, metatable)</div></td></tr>
<tr><td class="diff-marker" data-marker="−"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> </div></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div><ins style="font-weight: bold; text-decoration: none;"> </ins></div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- Generate the tidyVal function. If it has been specified by the user, we use that; if not, we choose one of four functions</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- Generate the tidyVal function. If it has been specified by the user, we use that; if not, we choose one of four functions</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- depending on the options chosen. This is so that we don't have to call the options table every time the function is called.</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- depending on the options chosen. This is so that we don't have to call the options table every time the function is called.</div></td></tr>
<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l96">Line 96:</td>
<td colspan="2" class="diff-lineno">Line 96:</td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td></tr>
<tr><td class="diff-marker" data-marker="−"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> </div></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div><ins style="font-weight: bold; text-decoration: none;"> </ins></div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> local function mergeArgs(iterator, tables)</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> local function mergeArgs(iterator, tables)</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- Accepts multiple tables as input and merges their keys and values into one table using the specified iterator.</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- Accepts multiple tables as input and merges their keys and values into one table using the specified iterator.</div></td></tr>
<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l115">Line 115:</td>
<td colspan="2" class="diff-lineno">Line 115:</td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td></tr>
<tr><td class="diff-marker" data-marker="−"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> </div></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div><ins style="font-weight: bold; text-decoration: none;"> </ins></div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- Set the order of precedence of the argument tables. If the variables are nil, nothing will be added to the table,</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- Set the order of precedence of the argument tables. If the variables are nil, nothing will be added to the table,</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- which is how we avoid clashes between the frame/parent args and the Lua args. </div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- which is how we avoid clashes between the frame/parent args and the Lua args. </div></td></tr>
<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l121">Line 121:</td>
<td colspan="2" class="diff-lineno">Line 121:</td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> argTables[#argTables + 1] = pargs</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> argTables[#argTables + 1] = pargs</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> argTables[#argTables + 1] = luaArgs</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> argTables[#argTables + 1] = luaArgs</div></td></tr>
<tr><td class="diff-marker" data-marker="−"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> </div></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div><ins style="font-weight: bold; text-decoration: none;"> </ins></div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> --[[</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> --[[</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- Define metatable behaviour. Arguments are memoized in the metaArgs table, and are only fetched from the</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- Define metatable behaviour. Arguments are memoized in the metaArgs table, and are only fetched from the</div></td></tr>
<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l129">Line 129:</td>
<td colspan="2" class="diff-lineno">Line 129:</td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- pargs if pairs has already been run, as all the arguments will already have been copied over.</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> -- pargs if pairs has already been run, as all the arguments will already have been copied over.</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> --]]</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> --]]</div></td></tr>
<tr><td class="diff-marker" data-marker="−"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> </div></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div><ins style="font-weight: bold; text-decoration: none;"> </ins></div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> metatable.__index = function (t, key)</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> metatable.__index = function (t, key)</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> local val = metaArgs[key]</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> local val = metaArgs[key]</div></td></tr>
<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l150">Line 150:</td>
<td colspan="2" class="diff-lineno">Line 150:</td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> return nil</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> return nil</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td></tr>
<tr><td class="diff-marker" data-marker="−"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> </div></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div><ins style="font-weight: bold; text-decoration: none;"> </ins></div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> metatable.__newindex = function (t, key, val)</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> metatable.__newindex = function (t, key, val)</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> if options.readOnly then</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> if options.readOnly then</div></td></tr>
<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l162">Line 162:</td>
<td colspan="2" class="diff-lineno">Line 162:</td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td></tr>
<tr><td class="diff-marker" data-marker="−"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> </div></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div><ins style="font-weight: bold; text-decoration: none;"> </ins></div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> metatable.__pairs = function ()</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> metatable.__pairs = function ()</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> if not metatable.donePairs then</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> if not metatable.donePairs then</div></td></tr>
<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l177">Line 177:</td>
<td colspan="2" class="diff-lineno">Line 177:</td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td></tr>
<tr><td class="diff-marker" data-marker="−"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> </div></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div><ins style="font-weight: bold; text-decoration: none;"> </ins></div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> metatable.__ipairs = function ()</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> metatable.__ipairs = function ()</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> if not metatable.doneIpairs then</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> if not metatable.doneIpairs then</div></td></tr>
<tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l193">Line 193:</td>
<td colspan="2" class="diff-lineno">Line 193:</td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end, nil, 0</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end, nil, 0</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> end</div></td></tr>
<tr><td class="diff-marker" data-marker="−"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> </div></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div><ins style="font-weight: bold; text-decoration: none;"> </ins></div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> return args</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div> return args</div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>end</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>end</div></td></tr>
<tr><td class="diff-marker" data-marker="−"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;"><div> </div></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div><ins style="font-weight: bold; text-decoration: none;"> </ins></div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>return arguments</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div>return arguments</div></td></tr>
<!-- diff cache key mediawiki:diff::1.12:old-83199:rev-84246 -->
</table>86.135.251.105https://mw.lojban.org/index.php?title=Module:Arguments&diff=83199&oldid=prevGleki: 1 revision2014-01-29T16:17:11Z<p>1 revision</p>
<p><b>New page</b></p><div>-- This module provides easy processing of arguments passed to Scribunto from #invoke.<br />
-- It is intended for use by other Lua modules, and should not be called from #invoke directly.<br />
<br />
local libraryUtil = require('libraryUtil')<br />
local checkType = libraryUtil.checkType<br />
<br />
local arguments = {}<br />
<br />
local nilArg = {} -- Used for memoizing nil arguments in metaArgs.<br />
<br />
-- Generate four different tidyVal functions, so that we don't have to check the options every time we call it.<br />
<br />
local function tidyValDefault(key, val)<br />
if type(val) == 'string' then<br />
val = val:match('^%s*(.-)%s*$')<br />
if val == '' then<br />
return nil<br />
else<br />
return val<br />
end<br />
else<br />
return val<br />
end<br />
end<br />
<br />
local function tidyValTrimOnly(key, val)<br />
if type(val) == 'string' then<br />
return val:match('^%s*(.-)%s*$')<br />
else<br />
return val<br />
end<br />
end<br />
<br />
local function tidyValRemoveBlanksOnly(key, val)<br />
if type(val) == 'string' then<br />
if val:find('%S') then<br />
return val<br />
else<br />
return nil<br />
end<br />
else<br />
return val<br />
end<br />
end<br />
<br />
local function tidyValNoChange(key, val)<br />
return val<br />
end<br />
<br />
function arguments.getArgs(frame, options)<br />
checkType('getArgs', 1, frame, 'table', true)<br />
checkType('getArgs', 2, options, 'table', true)<br />
frame = frame or {}<br />
options = options or {}<br />
<br />
-- Get the arguments from the frame object if available. If the frame object is not available, we are being called<br />
-- from another Lua module or from the debug console, so assign the args to a new variable so we can differentiate them.<br />
local fargs, pargs, luaArgs<br />
if type(frame.args) == 'table' and type(frame.getParent) == 'function' then<br />
if not options.parentOnly then<br />
fargs = frame.args<br />
end<br />
if not options.frameOnly then<br />
pargs = frame:getParent().args<br />
end<br />
if options.parentFirst then<br />
fargs, pargs = pargs, fargs<br />
end<br />
else<br />
luaArgs = frame<br />
end<br />
<br />
-- Set up the args and metaArgs tables. args will be the one accessed from functions, and metaArgs will hold the actual arguments.<br />
-- The metatable connects the two together.<br />
local args, metaArgs, metatable = {}, {}, {}<br />
setmetatable(args, metatable)<br />
<br />
-- Generate the tidyVal function. If it has been specified by the user, we use that; if not, we choose one of four functions<br />
-- depending on the options chosen. This is so that we don't have to call the options table every time the function is called.<br />
local tidyVal = options.valueFunc<br />
if tidyVal then<br />
if type(tidyVal) ~= 'function' then<br />
error("bad value assigned to option 'valueFunc' (function expected, got " .. type(tidyVal) .. ')', 2)<br />
end<br />
elseif options.trim ~= false then<br />
if options.removeBlanks ~= false then<br />
tidyVal = tidyValDefault<br />
else<br />
tidyVal = tidyValTrimOnly<br />
end<br />
else<br />
if options.removeBlanks ~= false then<br />
tidyVal = tidyValRemoveBlanksOnly<br />
else<br />
tidyVal = tidyValNoChange<br />
end<br />
end<br />
<br />
local function mergeArgs(iterator, tables)<br />
-- Accepts multiple tables as input and merges their keys and values into one table using the specified iterator.<br />
-- If a value is already present it is not overwritten; tables listed earlier have precedence.<br />
-- We are also memoizing nil values, but those values can be overwritten.<br />
for _, t in ipairs(tables) do<br />
for key, val in iterator(t) do<br />
local metaArgsVal = metaArgs[key]<br />
if metaArgsVal == nil or metaArgsVal == nilArg then<br />
local tidiedVal = tidyVal(key, val)<br />
if tidiedVal == nil then<br />
metaArgs[key] = nilArg<br />
else<br />
metaArgs[key] = tidiedVal<br />
end<br />
end<br />
end<br />
end<br />
end<br />
<br />
-- Set the order of precedence of the argument tables. If the variables are nil, nothing will be added to the table,<br />
-- which is how we avoid clashes between the frame/parent args and the Lua args. <br />
local argTables = {fargs}<br />
argTables[#argTables + 1] = pargs<br />
argTables[#argTables + 1] = luaArgs<br />
<br />
--[[<br />
-- Define metatable behaviour. Arguments are memoized in the metaArgs table, and are only fetched from the<br />
-- argument tables once. Nil arguments are also memoized using the nilArg variable in order to increase<br />
-- performance. Also, we keep a record in the metatable of when pairs and ipairs have been called, so we<br />
-- do not run pairs and ipairs on fargs and pargs more than once. We also do not run ipairs on fargs and<br />
-- pargs if pairs has already been run, as all the arguments will already have been copied over.<br />
--]]<br />
<br />
metatable.__index = function (t, key)<br />
local val = metaArgs[key]<br />
if val ~= nil then<br />
if val == nilArg then<br />
return nil<br />
else<br />
return val<br />
end<br />
end<br />
for _, argTable in ipairs(argTables) do<br />
local argTableVal = tidyVal(key, argTable[key])<br />
if argTableVal == nil then<br />
metaArgs[key] = nilArg<br />
else<br />
metaArgs[key] = argTableVal<br />
return argTableVal<br />
end<br />
end<br />
return nil<br />
end<br />
<br />
metatable.__newindex = function (t, key, val)<br />
if options.readOnly then<br />
error('could not write to argument table key "' .. tostring(key) .. '"; the table is read-only', 2)<br />
elseif options.noOverwrite and args[key] ~= nil then<br />
error('could not write to argument table key "' .. tostring(key) .. '"; overwriting existing arguments is not permitted', 2)<br />
elseif val == nil then<br />
metaArgs[key] = nilArg -- Memoize nils.<br />
else<br />
metaArgs[key] = val<br />
end<br />
end<br />
<br />
metatable.__pairs = function ()<br />
if not metatable.donePairs then<br />
mergeArgs(pairs, argTables)<br />
metatable.donePairs = true<br />
metatable.doneIpairs = true<br />
end<br />
return function (t, k)<br />
local nk, val = next(metaArgs, k)<br />
if val == nilArg then<br />
val = nil<br />
end<br />
return nk, val<br />
end<br />
end<br />
<br />
metatable.__ipairs = function ()<br />
if not metatable.doneIpairs then<br />
mergeArgs(ipairs, argTables)<br />
metatable.doneIpairs = true<br />
end<br />
return function (t, i)<br />
local val = metaArgs[i + 1]<br />
if val == nil then<br />
return nil<br />
elseif val == nilArg then<br />
val = nil<br />
end<br />
return i + 1, val<br />
end, nil, 0<br />
end<br />
<br />
return args<br />
end<br />
<br />
return arguments</div>Gleki