Jump to content

User:BrandonXLF/Help:Infinite parameters

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by BrandonXLF (talk | contribs) at 05:54, 2 September 2024. The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

Wikitext does not have support for infinite parameters, so templates that use infinite parameters make use of Lua modules.

Custom modules

One way to support infinite parameters is to write a custom Lua modules that implements the template. This is done by modules like Module:Jct, Module:Infobox, Module:List, and Module:Template link general. There are many different strategies for supporting infinite parameters in Lua, some of which are demonstrated below.

Sequential parameters

Using ipairs

ipairs is a built in module that can be used to iterate over sequential numbered (unnamed) parameters.

local p = {}

function p.main(frame)
    local args = frame:getParent().args
    local out = ''

    for i, v in ipairs(args) do
        if out then out = out .. ', ' end
        out = out .. i .. ' is ' .. v
    end

    return out
end

return p

When a template with {{#invoke:__MODULE__|main}} is called with {{__TEMPLATE__|A|B|C}}, the output 1 is A, 2 is B, 3 is C would be produced.

Using while

Using a while loop works great when there is a prefix in front of the parameter number as ipairs will not work in those situations. The definition of i can also be set to start with a different number besides 1.

local p = {}

function p.main(frame)
    local args = frame:getParent().args
    local out = ''
    local i = 1

    while args['prefix' .. i] do
        if out then out = out .. ', ' end
        out = out .. 'prefix' .. i .. ' is ' .. v
        i = i + 1
    end

    return out
end

return p

When a template with {{#invoke:__MODULE__|main}} is called with {{__TEMPLATE__|prefix1=A|prefix2=B|prefix3=c}}, the output 1 is A, 2 is B, 3 is C would be produced.

Non-sequential parameters

There are several templates like {{Infobox}} that need to support non-sequential parameters. This is commonly achieved with Module:TableTools, which contains functions like sparseIpairs for working with sparse arrays. The example below can skip over nil values, whereas the ipairs example stops at the first nil value.

local TableTools = require('Module:TableTools')
local p = {}

function p.main(frame)
    local args = frame:getParent().args
    local out = ''

    for i, v in TableTools.sparseIpairs(args) do
        if out then out = out .. ', ' end
        out = out .. i .. ' is ' .. v
    end

    return out
end

return p

When a template with {{#invoke:__MODULE__|main}} is called with {{__TEMPLATE__|A|B|100=C}}, the output 1 is A, 2 is B, 100 is C would be produced despite parameters 3 to 99 not being defined.

Using pairs and table.sort

When an existing method like those in Module:TableTools don't work (due to having prefixed parameter names or other issues), iterating over all arguments with pairs, recording the number of the ones you're interested in, sorting the array of said numbers with table.sort, and then using ipairs to go over that sorted array is a common method as shown below.

local p = {}

function p.main(frame)
    local args = frame:getParent().args
    local out = ''

    -- Traverse all arguments and record item argument numbers
    local argNums = {}
    for k, _ in pairs(args) do
	    local num = tostring(k):match('^item([1-9]%d*)$')
		if num then table.insert(argNums, tonumber(num)) end
    end

    table.sort(argNums) -- Sort the found argument numbers
    
    for _, num in ipairs(argNums) do
        if out then out = out .. ', ' end
        out = out .. 'item' .. num .. ' is ' .. args['item' .. num]
    end

    return out
end

return p

When a template with {{#invoke:__MODULE__|main}} is called with {{__TEMPLATE__|item1=A|item2=B|item100=C}}, the output item1 is A, item2 is B, item100 is C would be produced despite parameters item3 to item99 not being defined.

Using metamodules

If you'd like to avoid writing an entire Lua module, there are metamodules that exist to help aid in adding infinite parameter support for functions.

Arbitrary wikitext

These modules work by taking wikitext in <nowiki>...</nowiki> and expanding it while passing it the appropriate parameters. Examples of using the various modules that support arbitrary wikitext are below.

Unnamed parameters

If the template __TEMPLATE__ is defined with the code below:

{{#invoke:For nowiki|template|<br>|<nowiki><code>{{{i}}}</code> is {{2x|{{{1}}}|, }}</nowiki>}}

Then,

{{__TEMPLATE__|A|B|C}}
produces 1 is A, A
2 is B, B
3 is C, C

If the template __TEMPLATE__ is defined with the code below:

{{#if:{{{1|}}}|<code>1</code> is {{2x|{{{1}}}|, }}}}{{#invoke:ArgRest|main|<nowiki><br><code>?</code> is {{2x|{{{2}}}|, }}</nowiki>|2}}

Then,

{{__TEMPLATE__|A|B|C}}
produces

1 is A, A
? is B, B
? is C, C

If the template __TEMPLATE__ is defined with the code below:

{{#invoke:Params|setting|i|<br>|sequential|for_each|<code>$#</code> is {{2x|$@|, }}}}

Then,

{{__TEMPLATE__|A|B|C}}
produces 1 is A, A
2 is B, B
3 is C, C

Named parameters

If the template __TEMPLATE__ is defined with the code below:

{{#invoke:For nowiki/sandbox|template|prefix=item|<br>|
<nowiki><code>item{{{i}}}</code> is {{{1}}}{{#if:{{{extra{{{i}}}|}}}|{{sp}}and <code>extra{{{i}}}</code> is {{{extra{{{i}}}}}}}}</nowiki>}}

Then,

{{__TEMPLATE__
| item1 = A
| extra1 = Apple
| item2 = B
| extra2 = Orange
| item3 = C
}}
produces

If the template __TEMPLATE__ is defined with the code below:

{{#if:{{{item1|}}}|<code>item1</code> is {{{item1}}}{{#if:{{{extra1|}}}|{{sp}}and <code>extra1</code> is {{{extra1}}}}}}}{{#invoke:ArgRest|main|<nowiki><br><code>item?</code> is {{{item2}}}{{#if:{{{extra2|}}}|{{sp}}and <code>extra?</code> is {{{extra2}}}}}</nowiki>|item2}}

Then,

{{__TEMPLATE__
| item1 = A
| extra1 = Apple
| item2 = B
| extra2 = Orange
| item3 = C
}}
produces item1 is A and extra1 is Apple
item? is B and extra? is Orange
item? is C

If the template __TEMPLATE__ is defined with the code below:

{{#invoke:params|setting|i|<br>|all_sorted|call_for_each_group|__CHILD_TEMPLATE__}}

And the template __CHILD_TEMPLATE__ is defined with the code below:

<code>item?</code> is {{{item}}}{{#if:{{{extra|}}}|{{sp}} and <code>extra?</code> is {{{extra}}}}}

Then,

{{__TEMPLATE__
| item1 = A
| extra1 = Apple
| item2 = B
| extra2 = Orange
| item3 = C
}}
produces item? is A and extra? is Apple
item? is B and extra? is Orange
item? is C

Fixed output format

These modules are more specialized and limited than the ones above. Examples for using them are below.

Unnamed parameters

If the template __TEMPLATE__ is defined with the code below:

{{#invoke:Separated entries|main|separator=&#32;also&#32;|conjunction=&#32;and finally&#32;}}

Then,

{{__TEMPLATE__|A|B|C}}
produces A also B and finally C

If the template __TEMPLATE__ is defined with the code below:

{{#invoke:Enumerate|main}}

Then,

{{__TEMPLATE__|A|B|C}}
produces
  • A
  • B
  • C

Named parameters

If the template __TEMPLATE__ is defined with the code below:

{{#invoke:Enumerate|main|item}}

Then,

{{__TEMPLATE__|item1=A|item2=B|item3=C}}
produces
  • A
  • B
  • C

See also