Module:For batched parameters
Module:For batched parameters allows you to expand wikitext with an arbitrary number of parameters written out in groups. Syntax:
{{#invoke:For batched parameters|main|batch size|sep|code}}
This then takes each set of batch size parameters and passes them to the relevant code - the first as {{{1}}}, the second as {{{2}}}, etc. {{{i}}} is also available as the index of the batch.
If the number of parameters is not a multiple of the batch size, then the last batch is run with the extra params not defined.
The module takes an optional |conjunction=conjunction parameter, replacing sep between the second-to-last and last batches.
The code should be wrapped in <nowiki>...</nowiki> tags. Otherwise, it is evaluated before the module is invoked, which may lead to unexpected results.
Example
Simple example
Module:For batched parameters/example1 contains:
{{#invoke:For batched parameters|main|3||<nowiki>* a={{{1}}}, b = {{{2|missing!}}}, c = {{{3|also missing!}}}, i = {{{i}}}</nowiki>
}}
Note the line break after the closing </nowiki> tag. This line break is included in the output.
{{Module:For batched parameters/example1|1|2|3|4|5|6|7|8|9|10}}
produces:
- a=1, b = 2, c = 3, i = 1
- a=4, b = 5, c = 6, i = 2
- a=7, b = 8, c = 9, i = 3
- a=10, b = missing!, c = also missing!, i = 4
Example with default values
The template Module:For batched parameters/example2 contains:
{{#invoke:For batched parameters|main|3||<nowiki>* a={{trim|{{{1}}}}}, b={{trim|{{{2|{{{1}}}}}}}}, c={{trim|{{{3|{{{2|{{{1}}}}}}}}}}}, i={{{i}}}</nowiki>
}}
{{Module:For batched parameters/example2| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 }}
produces:
- a=1, b=2, c=3, i=1
- a=4, b=5, c=6, i=2
- a=7, b=8, c=9, i=3
- a=10, b=10, c=10, i=4
{{Module:For batched parameters/example2| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 }}
produces:
- a=1, b=2, c=3, i=1
- a=4, b=5, c=6, i=2
- a=7, b=8, c=8, i=3
local p = {}
-- Find "{{{x|" where "x" is an arg name
local function findDefStart (code, i, argstosub)
while true do
local s, e, a = code:find("{{{([^{}|]+)|", i)
if not s then return nil end
if argstosub[a] then return s, e, a end
i = e + 1
end
end
-- Skip stuff after "{{{x|", find "}}}"
local function findDefEnd (code, i)
while true do
local s, e = code:find("^[^{}]*", i) -- skip non-braces
i = e + 1
s, e = code:find("^%b{}", i) -- skip balanced braces
if not s then break end
i = e + 1
end
return code:find("^}}}", i)
end
-- Replace "{{{x|...}}}" by "{{{x}}}" where "x" is an arg name.
-- Without this, we'd have to handle both "{{{x}}}" and "{{{x|...}}}"
-- in the main loop, which would be cumbersome and inefficient.
-- All but the last batch are guaranteed to have the full size,
-- so we know that the parameters don't need defaults.
local function dropDefs (code, size)
local argstosub = {}
argstosub["i"] = "{{{i}}}"
for i = 1, size do
argstosub[tostring(i)] = "{{{" .. i .. "}}}"
end
local result = {}
local i = 1
while true do
local s, e, a = findDefStart(code, i, argstosub)
if not s then break end -- no more "{{{x|", done
_, e = findDefEnd(code, e + 1)
if not e then break end -- no "}}}", bad syntax, let wiki deal with it
table.insert(result, code:sub(i, s - 1)) -- append up to "{{{x|"
table.insert(result, argstosub[a]) -- append "{{{x}}}"
i = e + 1
end
table.insert(result, code:sub(i))
return table.concat(result)
end
function p.main(frame)
local size = tonumber(frame.args[1])
local sep = frame.args[2]
local code = frame.args[3] or frame.args.code
local result = {}
local batch = {}
code = mw.text.unstripNoWiki(code)
code = code:gsub('<', '<'):gsub('>', '>')
local cleanCode = dropDefs(code, size)
local idx = 0
for i, value in ipairs(frame:getParent().args) do
table.insert(batch, value)
if #batch == size then
idx = idx + 1
local argstosub = {}
for j, value2 in pairs(batch) do
argstosub[tostring(j)] = value2
end
argstosub["i"] = idx
local actualCode = cleanCode:gsub("{{{([^{}]+)}}}", argstosub)
table.insert(result, frame:preprocess(actualCode))
batch = {}
end
end
if #batch > 0 then
idx = idx + 1
local argstosub = {}
for j, value2 in pairs(batch) do
argstosub[tostring(j)] = value2
end
argstosub["i"] = idx
-- Do the last sub in a child frame and use the original code to handle defaults
local childFrame = frame:newChild{title=frame:getParent().title, args = argstosub}
table.insert(result, childFrame:preprocess(code))
end
if frame.args.conjunction then
return mw.text.listToText(result, sep, frame.args.conjunction)
else
return table.concat(result, sep)
end
end
return p