• Welcome to the Kancolle Wiki!
  • If you have any questions regarding site content, account registration, etc., please visit the KanColle Wiki Discord

Changes

Jump to navigation Jump to search
Testing if Scribunto works, 'cause templates are really stupid =(
--[[
Handles most of the boilerplate necessary to fetch arguments, such as trimming
leading/trailing whitespace, making blank arguments evaluate to false, correctly
choosing between current-frame and parent-frame, etc.

Originally written on the English Wikipedia by Mr. Stradivarius, Jackmcbarn, and Anomie.

Code released under the GPL v2+ as per:
https://en.wikipedia.org/w/index.php?diff=624020648&oldid=624019645
https://en.wikipedia.org/w/index.php?diff=624073793&oldid=624020648

@license GNU GPL v2+
]]

local libraryUtil = require( 'libraryUtil' )

local sandboxSuffixPattern = string.format( '/%s$',
mw.message.new( 'scribunto-template-sandbox-subpage-name' ):plain():gsub("%p", "%%%0")
)

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

local function tidyValDefault( k, v )
if type( v ) == 'string' then
v = v:match( '^%s*(.-)%s*$' )
if v == '' then
return nil
end
end
return v
end

local function tidyValTrimOnly( k, v )
if type( v ) == 'string' then
return v:match( '^%s*(.-)%s*$' )
else
return v
end
end

local function tidyValRemoveBlanksOnly( k, v )
if type( v ) == 'string' and not v:find( '%S' ) then
return nil
else
return v
end
end

local function tidyValNoChange( k, v )
return v
end

return function( options )
libraryUtil.checkType( 'getArgs', 1, options, 'table', true )
local frame = options.frame
if frame == nil then
return {}
end
libraryUtil.checkTypeForNamedArg( 'getArgs', 'frame', frame, 'table' )

--[[
-- Get the argument tables. If we were passed a valid frame object, see if we're being
-- called via a wrapper. If so, then get pargs, the wrapper's arguments (and if
-- wrappersUseFrame is set, the frame's arguments as well). Otherwise, just get fargs,
-- the frame's arguments. If we weren't passed a valid frame object, we are being called
-- from another Lua module or from the debug console, so assume that we were passed a
-- table of args directly, and assign it to a new variable (luaArgs).
--]]
local fargs, pargs, luaArgs
if type( frame.args ) == 'table' and type( frame.getParent ) == 'function' then
if options.wrappers then
local parent = frame:getParent()
local found = false
if parent then
local title = parent:getTitle():gsub( sandboxSuffixPattern, '' )
if options.wrappers == title then
found = true
elseif type( options.wrappers ) == 'table' then
-- If either a key or a value matches, it's a match
if options.wrappers[title] ~= nil then
found = true
else
for _,v in ipairs( options.wrappers ) do
if v == title then
found = true
break
end
end
end
end

if found then
pargs = parent.args
end
end

if not found or options.wrappersUseFrame then
fargs = frame.args
end
else
fargs = frame.args
end
else
luaArgs = frame
end

-- Set the order of precedence of the argument tables. If the variables are nil, nothing
-- will be added to the table, which is how we avoid clashes between the frame/parent
-- args and the Lua args.
local argTables = { pargs }
argTables[#argTables + 1] = fargs
argTables[#argTables + 1] = luaArgs

-- Generate the tidyVal function. If it has been specified by the user, we use that; if
-- not, we choose one of four functions depending on the options chosen. This is so that
-- we don't have to call the options table every time the function is called.
local tidyVal = options.valueFunc
if tidyVal then
libraryUtil.checkTypeForNamedArg( 'getArgs', 'valueFunc', tidyVal, 'function' )
elseif options.trim ~= false then
if options.removeBlanks ~= false then
tidyVal = tidyValDefault
else
tidyVal = tidyValTrimOnly
end
else
if options.removeBlanks ~= false then
tidyVal = tidyValRemoveBlanksOnly
else
tidyVal = tidyValNoChange
end
end

-- Set up the args, fetchedArgs and nilArgs tables. args will be the one accessed from
-- functions, and fetchedArgs will hold the actual arguments. Nil arguments are memoized
-- in nilArgs, and args_mt connects all of them together.
local args, fetchedArgs, nilArgs, args_mt = {}, {}, {}, {}
local donePairs, doneIpairs = false, false

local function mergeArgs( iterator, tables )
-- Accepts multiple tables as input and merges their keys and values into one
-- table using the specified iterator. If a value is already present, it is not
-- overwritten; tables listed earlier have precedence. We are also memoizing nil
-- values, but those values can be overwritten.
for _, t in ipairs( tables ) do
for key, val in iterator( t ) do
if fetchedArgs[key] == nil then
local tidiedVal = tidyVal( key, val )
if tidiedVal == nil then
nilArgs[key] = true
else
fetchedArgs[key] = tidiedVal
end
end
end
end
end

-- Define metatable behaviour. Arguments are memoized in the fetchedArgs table, and are
-- only fetched from the argument tables once. Fetching arguments from the argument
-- tables is the most resource-intensive step in this module, so we try and avoid it
-- where possible. For this reason, nil arguments are also memoized, in the nilArgs
-- table. Also, we keep a record in the metatable of when pairs and ipairs have been
-- called, so we do not run pairs and ipairs on the argument tables more than once. We
-- also do not run ipairs on fargs and pargs if pairs has already been run, as all the
-- arguments will already have been copied over.

function args_mt.__index( t, key )
-- Fetches an argument when the args table is indexed. First we check to see if
-- the value is memoized, and if not we try and fetch it from the argument
-- tables. When we check memoization, we need to check fetchedArgs before
-- nilArgs, as both can be non-nil at the same time. If the argument is not
-- present in fetchedArgs, we also check whether pairs has been run yet. If
-- pairs has already been run, we return nil. This is because all the arguments
-- will have already been copied into fetchedArgs by the mergeArgs function,
-- meaning that any other arguments must be nil.
local val = fetchedArgs[key]
if val ~= nil then
return val
elseif donePairs or nilArgs[key] then
return nil
end
for _, argTable in ipairs( argTables ) do
local argTableVal = tidyVal( key, argTable[key] )
if argTableVal == nil then
nilArgs[key] = true
else
fetchedArgs[key] = argTableVal
return argTableVal
end
end
return nil
end

function args_mt.__newindex( t, key, val )
if val == nil then
-- If the argument is to be overwritten with nil, we need to memoize the
-- nil in nilArgs, so that the value isn't looked up in the argument
-- tables if it is accessed again.
nilArgs[key] = true
end
fetchedArgs[key] = val
end

function args_mt.__pairs()
if not donePairs then
donePairs = true
mergeArgs( pairs, argTables )
end
return pairs( fetchedArgs )
end

function args_mt.__ipairs()
if not doneIpairs and not donePairs then
doneIpairs = true
mergeArgs( ipairs, argTables )
end
return ipairs( fetchedArgs )
end

return setmetatable( args, args_mt )
end
Anonymous user

Navigation menu