https://iopwiki.com/index.php?title=Module:Arguments&feed=atom&action=history Module:Arguments - Revision history 2024-03-29T15:49:43Z Revision history for this page on the wiki MediaWiki 1.32.2 https://iopwiki.com/index.php?title=Module:Arguments&diff=7754&oldid=prev Pianoforte: 1 revision imported 2016-12-20T11:41:46Z <p>1 revision imported</p> <table class="diff diff-contentalign-left" data-mw="interface"> <tr class="diff-title" lang="en"> <td colspan="1" style="background-color: #fff; color: #222; text-align: center;">← Older revision</td> <td colspan="1" style="background-color: #fff; color: #222; text-align: center;">Revision as of 11:41, 20 December 2016</td> </tr><tr><td colspan="2" class="diff-notice" lang="en"><div class="mw-diff-empty">(No difference)</div> </td></tr></table> Pianoforte https://iopwiki.com/index.php?title=Module:Arguments&diff=7663&oldid=prev Pianoforte: 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..." 2016-12-19T08:24:03Z <p>Created page with &quot;-- 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...&quot;</p> <table class="diff diff-contentalign-left" data-mw="interface"> <tr class="diff-title" lang="en"> <td colspan="1" style="background-color: #fff; color: #222; text-align: center;">← Older revision</td> <td colspan="1" style="background-color: #fff; color: #222; text-align: center;">Revision as of 08:24, 19 December 2016</td> </tr><tr><td colspan="2" class="diff-notice" lang="en"><div class="mw-diff-empty">(No difference)</div> </td></tr></table> Pianoforte https://iopwiki.com/index.php?title=Module:Arguments&diff=7753&oldid=prev Xaosflux: Changed protection level of Module:Arguments: used in the mediawiki interface ex: MediaWiki:Watchlist-details ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite)) 2015-12-23T16:07:27Z <p>Changed protection level of Module:Arguments: used in the mediawiki interface ex: <a href="/wiki/MediaWiki:Watchlist-details" title="MediaWiki:Watchlist-details">MediaWiki:Watchlist-details</a> ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite))</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 /> &quot;bad value assigned to option 'valueFunc'&quot;<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 &quot;'<br /> .. tostring(key)<br /> .. '&quot;; 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 &quot;'<br /> .. tostring(key)<br /> .. '&quot;; 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> Xaosflux