Movatterモバイル変換


[0]ホーム

URL:


Jump to content
WikipediaThe Free Encyclopedia
Search

Module:Params

Permanently protected module
From Wikipedia, the free encyclopedia
Module documentation[view] [edit] [history] [purge]
Ready for useThis module is rated asready for general use. It has reached a mature form and is thought to be relatively bug-free and ready for use wherever appropriate. It is ready to mention on help pages and other Wikipedia resources as an option for new users to learn. To reduce server load and bad output, it should be improved bysandbox testing rather than repeated trial-and-error editing.
ProtectedThis module issubject to page protection. It is ahighly visible module in use by a very large number of pages, or issubstituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it isprotected from editing.
About the latest changes
See theChangeLog
Last update: 29 June 2025
Testcases ·Examples ·Sandbox

The{{#invoke:params}} module is designed to be adopted by those templates that want to have a deep control of their parameters. It is particularly useful tovariadic templates, to which it offers the possibility to count, list, map and propagate the parameters received without knowing their number in advance.

The module offers elegant shortcuts to non variadic templates as well. Outside templates it has virtually no applications; hence, if you plan to make experiments, make sure to do them from within a template, or you will not be able to see much (you can use{{Template sandbox}} for that). Under./testcases you can find helper templates that can be specifically used for testing the module's capabilities in flexible ways. Finally, under./doc/examples you can find some of the examples shown in this documentation page.

information Note: In case your template uses{{#invoke:params}}, please add{{lua|Module:Params}} to its documentation page, so that if breaking changes will be introduced in the future the template will be easily traceable without performingan “in source” search.

Please, do not edit this module without having done extensive testing in themodule's sandbox first.

General usage

Among the possibilities that the module offers there is that of performing a series of actions after novel arguments have been concatenated to templates' incoming parameters. As this makes it necessary to keep the argument slots clean from interference, instead of named arguments in order to specify options this module usespiping functions (i.e. functions that expect to bepiped instead of returning to the caller), ormodifiers. This creates a syntax similar to the following example:

{{#invoke:params|[modifier]|[...]|[modifier]|[...]|function|[...]}}

For instance, as the name suggests, thelist function lists the parameters wherewith a template was called. By default it does not add delimiters, but returns an indistinct blob of text in which keys and values are sticked to each other. However, by using thesetting modifier, we are able to declare a key-value delimiter (p) and an iteration delimiter (i). And so, if we imagined a template named{{example template}} containing the following wikitext,

{{#invoke:params|setting|i/p|<br/>|:|list}}

and such template were called with the following parameters,

{{example template
|Beast of Bodmin =A large feline inhabiting Bodmin Moor
|Morgawr =A sea serpent
|Owlman =A giant owl-like creature
}}

the following result would be produced:

Beast of Bodmin: A large feline inhabiting Bodmin Moor
Morgawr: A sea serpent
Owlman: A giant owl-like creature

We can also do more sophisticated things; for instance, by exploiting the possibility to set a header (h) and a footer (f), we can transform the previous code into a generator ofdefinition lists,

{{#invoke:params|setting|h/p/i/f|<dl><dt>|</dt><dd>|</dd><dt>|</dd></dl>|list}}

thus yielding:

Beast of Bodmin
A large feline inhabiting Bodmin Moor
Morgawr
A sea serpent
Owlman
A giant owl-like creature

By placing thewith_name_matching modifier before thelist function we will be able to filter some parameters out – such as, for instance, all parameter names that do not end with an “n”:

{{#invoke:params|with_name_matching|n$|setting|h/p/i/f|<dl><dt>|</dt><dd>|</dd><dt>|</dd></dl>|list}}

Thus, the previous code will produce:

Beast of Bodmin
A large feline inhabiting Bodmin Moor
Owlman
A giant owl-like creature

This mechanism has the intrinsic advantage that it allows concatenating infinite modifiers. And so, in order to get the accurate result that we want to obtain we could write:

{{#invoke:params|non-sequential|with_name_matching|^B|with_name_matching|n$|with_value_matching|feline|setting|h/p/i/f|<dl><dt>|</dt><dd>|</dd><dt>|</dd></dl>|list}}

The two modifierssequential andnon-sequential refer to a technical jargon used in wikitext: given a parameter list, the subgroup of sequential parameters is constituted by the largest group of consecutive numeric parameters starting from|1= – this is known as the parameters' “sequence”. A parameter list that does not have a first parameter specified does not possess a sequence.

Functions

Here follows the list of functions. You might want to see also§ Modifiers.

self

Functionself(code)
Num. of arguments0
Not affected byAny modifier
See also
{{FULLPAGENAME}}
Brief
Return the name of the current template
Syntax
{{#invoke:params|self}}

This argumentless function guarantees that the name of the template invoking this module is shown, regardless if this is transcluded or not.

As a possible example, if a Wikipedia page namedPage X contained only a transclusion of a template named{{foobar}}, and the latter contained the following wikitext,

{{#invoke:params|self}}{{FULLPAGENAME}}

if we visitedTemplate:Foobar we would see,

Template:FoobarTemplate:Foobar

whereas if we visitedPage X we would see:

Template:FoobarPage X

Therefore by writing

{{#ifeq:{{#invoke:params|self}}|{{FULLPAGENAME}}|Page is not being transcluded|Page is being transcluded}}

it is possible to understand whether a page is being transcluded or not. For most cases the<includeonly>...</includeonly> and<noinclude>...</noinclude> will offer a simpler solution, however there can be cases in which this becomes the way to go.

IfPage X transcluded{{foobar 2}} and the latter were a redirect to{{foobar}}, we would still see

Template:FoobarPage X

A typical use case of this function is that of providing stable links for editing transcluded templates. E.g.:

{{edit|{{#invoke:params|self}}|edit this template}}

Another possible use case is that of transcluding a subtemplate. E.g.:

{{{{#invoke:params|self}}/my subtemplate|foo|bar}}

count

Functioncount(code)
Num. of arguments0
Often preceeded bysequential
Not affected byall_sorted,reassorted,setting,
sorting_sequential_val…,
mapping_by_calling,mapping_by_invoking,mapping_by_magic,mapping_by_replacing
See also
{{#invoke:ParameterCount}}
Brief
Count the number of parameters wherewith a template was called
Syntax
{{#invoke:params|count}}

This function does not take arguments.

The number that this function yields depends on the modifiers that precede it. For instance, in a template that is called with both named and unnamed parameters,

{{#invoke:params|count}}

and

{{#invoke:params|sequential|count}}

will return different results.

concat_and_call

Functionconcat_and_call(code)
Num. of argumentsAd libitum
Not affected byall_sorted,reassorted
See also
combining_by_calling,concat_and_invoke,concat_and_magic,{{#invoke:template wrapper|wrap}}
Brief
Prepend positive numeric arguments to the current parameters, or impose non-numeric or negative numeric arguments, then propagate everything to a custom template
Syntax
{{#invoke:params|concat_and_call|template name|[prepend 1]|[prepend 2]|[...]|[prepend n]|[named item 1=value 1]|[...]|[named item n=value n]|[...]}}

This function comes in handy in case ofwrapper templates. For example, if our{{wrapper template}} had the following code,

{{#invoke:params|concat_and_call|foobar|elbow|earth|room|7=classy|hello=not today}}

and were called with,

{{wrapper template
|one
|two
|three
|hello =world
|wind =spicy
}}

the following call to the{{foobar}} template would be performed:

{{foobar
|elbow
|earth
|room
|7 =classy
|8 =one
|9 =two
|10 =three
|wind =spicy
|hello =not today
}}

By using thecutting modifier it is possible to impose numeric positive parameters instead of prepending them. For instance, the following code echoes all incoming parameters to{{my template}}, with the exception of|3=, which is replaced withhello world:

{{#invoke:params|cutting|3|0|concat_and_call|my template|{{{1|}}}|{{{2|}}}|hello world}}

If the numeric parameters to replace are a limited number, as in the example above, a better alternative might be that of usingimposing.

If no other argument besides thetemplate name is provided this function simply echoes the current parameters to another template.

information Note: All arguments passed to this function except thetemplate name will not be trimmed of their leading and trailing spaces. Theconcat_and_callfunction name itself, however, will be trimmed of its surrounding spaces.

concat_and_invoke

Functionconcat_and_invoke(code)
Num. of argumentsAd libitum
Not affected byall_sorted,reassorted
See also
concat_and_call,concat_and_magic
Brief
Prepend positive numeric arguments to the current parameters, or impose non-numeric or negative numeric arguments, then propagate everything to a custom module
Syntax
{{#invoke:params|concat_and_invoke|module name|function name|[prepend 1]|[prepend 2]|[...]|[prepend n]|[named item 1=value 1]|[...]|[named item n=value n]|[...]}}

Exactly likeconcat_and_call, but invokes a module instead of calling a template.

information Note: All arguments passed to this function except themodule name and thefunction name will not be trimmed of their leading and trailing spaces. Theconcat_and_invokefunction name itself, however, will be trimmed of its surrounding spaces.

concat_and_magic

Functionconcat_and_magic(code)
Num. of argumentsAd libitum
Not affected byall_sorted,reassorted
See also
concat_and_call,concat_and_invoke
Brief
Prepend positive numeric arguments to the current parameters, or impose non-numeric or negative numeric arguments, then propagate everything to a custom parser function
Syntax
{{#invoke:params|concat_and_magic|parser function|[prepend 1]|[prepend 2]|[...]|[prepend n]|[named item 1=value 1]|[...]|[named item n=value n]|[...]}}

Exactly likeconcat_and_call, but calls aparser function instead of a template.

information Note: All arguments passed to this function except the magic word will not be trimmed of their leading and trailing spaces. Theconcat_and_magicfunction name itself, however, will be trimmed of its surrounding spaces.

value_of

Functionvalue_of(code)
Num. of arguments1
Relevantfunction-only variablesh,f,n
Not affected byall_sorted,reassorted
See also
list_values,coins,unique_coins
Brief
Get the value of a single parameter
Syntax
{{#invoke:params|value_of|parameter name}}

Without modifiers this function is similar to writing{{{parameter name|}}}. With modifiers, however, it allows reaching parameters that would be unreachable without knowing their number in advance. For instance, writing

{{#invoke:params|cutting|-2|0|value_of|1}}

will expand to the value of the second-last sequential parameter, independently of how many parameters the template was called with. If no matching parameter is found this function expands to nothing. A header (h), a footer (f), and a fallback text (n) can be declared via thesetting modifier – the strings assigned to the key-value pair delimiter (p), the iteration delimiter (i) and the last iteration delimiter (l) will be ignored.

For instance, the{{If then show}} template could be rewritten as

{{#invoke:params|with_value_not_matching|^%s*$|setting|h/f/n|{{{3|}}}|{{{4|}}}|{{{2|}}}|value_of|1}}

Simplifying, the following wikitext expands to the first parameter that is not empty:

{{#invoke:params|with_value_not_matching||strict|squeezing|value_of|1}}

Whereas the following wikitext expands to the first parameter that is not blank (i.e. neither empty nor containing onlywhitespaces)

{{#invoke:params|with_value_not_matching|^%s*$|squeezing|value_of|1}}

list

Functionlist(code)
Num. of arguments0
SortableYes
Relevantfunction-only variablesh,p,i,l,f,n
See also
list_values
Brief
List the template parameters (both their names and their values)
Syntax
{{#invoke:params|list}}

This function does not take arguments.

If thesetting modifier was not placed earlier, this function will not add delimiters, but will return an indistinct blob of text in which keys and values are sticked to each other. A header (h), a key-value pair delimiter (p), an iteration delimiter (i), a last iteration delimiter (l), a footer (f), and a fallback text (n) can be declared viasetting.

For example, the following code

{{#invoke:params|setting|h/i/p/f/n|'''Parameters passed:'''|);| (|)|'''No parameters were passed'''|list}}

will generate an output similar to the following.

Parameters passed: Owlman (A giant owl-like creature); Beast of Bodmin (A large feline inhabiting Bodmin Moor); Morgawr (A sea serpent)

list_values

Functionlist_values(code)
Num. of arguments0
SortableYes
Often preceeded bysequential
Relevantfunction-only variablesh,i,l,f,n
See also
list,value_of,coins,unique_coins,{{#invoke:separated entries}}
Brief
List the values of the incoming parameters
Syntax
{{#invoke:params|list_values}}

This function does not take arguments.

Thesequential modifier often accompanies this function. If thesetting modifier was not placed earlier, this function will not add delimiters, but will return an indistinct blob of text in which values are sticked to each other. A header (h), an iteration delimiter (i), a last iteration delimiter (l), a footer (f), and a fallback text (n) can be declared viasetting – the string assigned to the key-value pair delimiter (p) will be ignored.

For example, the following code

{{#invoke:params|setting|h/i/p/f/n|'''Parameters passed:'''|);| (|)|'''No parameters were passed'''|list_values}}

will generate an output similar to the following.

Values of parameters passed: A giant owl-like creature; A large feline inhabiting Bodmin Moor; A sea serpent.

coins

Functioncoins(code)
Num. of argumentsAd libitum
SortableYes
Often preceeded bysequential,trimming_values
Relevantfunction-only variablesh,i,l,f,n
See also
unique_coins,list,value_of
Brief
Associate custom strings to possible parameter values and list the custom string when the associated value is present
Syntax
{{#invoke:params|coins|[first coin= value 1]|[second coin= value 2]|[...]|[last coin= value N]}}

This function is identical to theunique_coins function, except that it allows the repetition of identical flags. See there for more information.

unique_coins

Functionunique_coins(code)
Num. of argumentsAd libitum
SortableYes
Often preceeded bysequential,trimming_values
Relevantfunction-only variablesh,i,l,f,n
See also
coins,list,value_of
Brief
Associate custom strings to possible parameter values and list the custom string when the associated value is present, but not more than once
Syntax
{{#invoke:params|unique_coins|[first coin= value 1]|[second coin= value 2]|[...]|[last coin= value N]}}

This function is used to detect the existence of flag parameters. For this reason, it is often accompanied by thesequential modifier (or, equivalently, by...|excluding_non-numeric_names|clearing|...). For a similar function that allows the repetition of identical flags, see thecoins function.

A typical use case of this function is that of constructingURLs. For example, the following template named{{example template}} checks for thehtml,xml,comments andremovenowiki flags in order to append respectively the following strings to the final URL:&wpGenerateRawHtml=1,&wpGenerateXml=1,&wpRemoveComments=0,&wpRemoveNowiki=1.

{{#if:{{{input|}}}|<spanclass="plainlinks">[{{fullurl:Special:ExpandTemplates|wpInput={{urlencode:{{{input}}}|QUERY}}{{#if:{{{title|}}}|&wpContextTitle={{urlencode|{{{title}}}|QUERY}}}}{{#invoke:params|excluding_non-numeric_names|clearing|sequential|trimming_values|unique_coins| html= &wpGenerateRawHtml=1| xml= &wpGenerateXml=1| comments= &wpRemoveComments=0| removenowiki= &wpRemoveNowiki=1}}}}{{#if:{{{label|}}}|{{{label|}}}|Expand<code>{{{input}}}</code>}}]</span>|{{Error|Error: The{{para|input}} parameter is missing.}}}}

And so, when transcluded as,

{{example template|comments|xml| input= Hello world {<nowiki/>{#time:r{{!}}now}<nowiki/>}}}

it will generate the following output:

ExpandHello world {{#time:r|now}}

A copy of the example above is available at {{./doc/examples/link to expanded template}}.

If thesetting modifier was not placed earlier, this function will not add delimiters, but will return an indistinct blob of text in which values are sticked to each other. A header (h), an iteration delimiter (i), a last iteration delimiter (l), a footer (f), and a fallback text (n) can be declared viasetting – the string assigned to the key-value pair delimiter (p) will be ignored.

call_for_each

Functioncall_for_each(code)
Num. of argumentsAd libitum
SortableYes
Relevantfunction-only variablesh,i,l,f,n
See also
call_for_each_value,mapping_by_calling,invoke_for_each,magic_for_each,call_for_each_group,{{#invoke:for loop}},{{for loop}}
Brief
For each parameter passed to the current template, call a custom template with at least two parameters (key and value)
Syntax
{{#invoke:params|call_for_each|template name|[append 1]|[append 2]|[...]|[append n]|[named param 1=value 1]|[...]|[named param n=value n]|[...]}}

Some functions are like shortcuts. TheX_for_each|F functions are similar tomapping_by_X(ing)|F|(names_and_values|)list_values. The latter syntax (i.e. the modifier version) allows avalues_and_names flag to invert the order from key-value to value-key.

All unnamed arguments following thetemplate name will be placed after the key-value pair. Named arguments will be passed verbatim. A header (h), an iteration delimiter (i), a last iteration delimiter (l), a footer (f), and a fallback text (n) can be declared via thesetting modifier – the string assigned to the key-value pair delimiter (p) will be ignored.

Calling a template for each key-value pair with

{{#invoke:params|sequential|call_for_each|foobar}}

will be different from writing

{{#invoke:params|sequential|for_each|{{foobar|$#|$@}}}}

In the first example each key-value pair will be passed to the{{foobar}} template, while in the second example the$# and$@ tokens will be expandedafter the{{foobar}} template has been called. In most cases this will make no difference, however there are several situations where it will lead to nonsensical results.

information Note: All arguments passed to this function except thetemplate name will not be trimmed of their leading and trailing spaces. Thecall_for_eachfunction name itself, however, will be trimmed of its surrounding spaces.

invoke_for_each

Functioninvoke_for_each(code)
Num. of argumentsAd libitum
SortableYes
Relevantfunction-only variablesh,i,l,f,n
See also
invoke_for_each_value,mapping_by_invoking,call_for_each,magic_for_each
Brief
For each parameter passed to the current template, invoke a custom module function with at least two arguments (key and value)
Syntax
{{#invoke:params|invoke_for_each|module name|module function|[append 1]|[append 2]|[...]|[append n]|[named param 1=value 1]|[...]|[named param n=value n]|[...]}}

Exactly likecall_for_each, but invokes a module instead of calling a template.

Invoking a module function for each key-value pair with

{{#invoke:params|sequential|invoke_for_each|foobar|main}}

will be different from writing

{{#invoke:params|sequential|for_each|{{#invoke:foobar|main|$#|$@}}}}

In the first example each key-value pair will be passed to the{{#invoke:foobar|main}} module function, while in the second example the$# and$@ tokens will be expandedafter the module function has been invoked. There might be cases in which this will make no difference, however there are several situations where it will lead to nonsensical results.

information Note: All arguments passed to this function except themodule name and thefunction name will not be trimmed of their leading and trailing spaces. Theinvoke_for_eachfunction name itself, however, will be trimmed of its surrounding spaces.

magic_for_each

Functionmagic_for_each(code)
Num. of argumentsAd libitum
SortableYes
Relevantfunction-only variablesh,i,l,f,n
See also
magic_for_each_value,mapping_by_magic,call_for_each,invoke_for_each
Brief
For each parameter passed to the current template, call a magic word with at least two arguments (key and value)
Syntax
{{#invoke:params|magic_for_each|parser function|[append 1]|[append 2]|[...]|[append n]|[named param 1=value 1]|[...]|[named param n=value n]|[...]}}

Exactly likecall_for_each, but calls aparser function instead of a template.

information Note: All arguments passed to this function except the magic word will not be trimmed of their leading and trailing spaces. Themagic_for_eachfunction name itself, however, will be trimmed of its surrounding spaces.

call_for_each_value

Functioncall_for_each_value(code)
Num. of argumentsAd libitum
SortableYes
Often preceeded bysequential
Relevantfunction-only variablesh,i,l,f,n
See also
call_for_each,mapping_by_calling,invoke_for_each_value,magic_for_each_value,call_for_each_group,{{#invoke:for loop}},{{for loop}}
Brief
For each parameter passed to the current template, call a custom template with at least one parameter (i.e. the parameter's value)
Syntax
{{#invoke:params|call_for_each_value|template name|[append 1]|[append 2]|[...]|[append n]|[named param 1=value 1]|[...]|[named param n=value n]|[...]}}

Thesequential modifier often accompanies this function. All unnamed arguments following thetemplate name will be appended after the value parameter. Named arguments will be passed verbatim. A header (h), an iteration delimiter (i), a last iteration delimiter (l), a footer (f), and a fallback text (n) can be declared via thesetting modifier – the string assigned to the key-value pair delimiter (p) will be ignored.

For example, calling{{tl}} with each parameter can be done by writing

{{#invoke:params|sequential|setting|i|,|call_for_each_value|tl}}

This will be different from writing

{{#invoke:params|sequential|setting|i|,|for_each|{{tl|$@}}}}

In the first example each value will be passed to the{{tl}} template, while in the second example the$@ token will be expandedafter the{{tl}} template has been called. Here this will make no difference, however there are several situations where it will lead to nonsensical results.

information Note: All arguments passed to this function except thetemplate name will not be trimmed of their leading and trailing spaces. Thecall_for_each_valuefunction name itself, however, will be trimmed of its surrounding spaces.

invoke_for_each_value

Functioninvoke_for_each_value(code)
Num. of argumentsAd libitum
SortableYes
Often preceeded bysequential
Relevantfunction-only variablesh,i,l,f,n
See also
call_for_each_value,mapping_by_invoking,invoke_for_each,magic_for_each_value
Brief
For each parameter passed to the current template, invoke a custom module function with at least one argument (i.e. the parameter's value)
Syntax
{{#invoke:params|invoke_for_each_value|module name|module function|[append 1]|[append 2]|[...]|[append n]|[named param 1=value 1]|[...]|[named param n=value n]|[...]}}

Exactly likecall_for_each_value, but invokes a module instead of calling a template.

Invoking a module function for each value with

{{#invoke:params|sequential|invoke_for_each_value|foobar|main}}

will be different from writing

{{#invoke:params|sequential|for_each|{{#invoke:foobar|main|$@}}}}

In the first example each value will be passed to the {{#invoke:foobar|main}} module function, while in the second example the$@ token will be expandedafter the module function has been invoked. There might be cases in which this will make no difference, however there are several situations where it will lead to nonsensical results.

information Note: All arguments passed to this function except themodule name and thefunction name will not be trimmed of their leading and trailing spaces. Theinvoke_for_each_valuefunction name itself, however, will be trimmed of its surrounding spaces.

magic_for_each_value

Functionmagic_for_each_value(code)
Num. of argumentsAd libitum
SortableYes
Often preceeded bysequential
Relevantfunction-only variablesh,i,l,f,n
See also
call_for_each_value,mapping_by_magic,invoke_for_each_value,magic_for_each
Brief
For each parameter passed to the current template, call a magic word with at least one argument (i.e. the parameter's value)
Syntax
{{#invoke:params|magic_for_each_value|parser function|[append 1]|[append 2]|[...]|[append n]|[named param 1=value 1]|[...]|[named param n=value n]|[...]}}

Exactly likecall_for_each_value, but calls aparser function instead of a template.

For example, if a template had the following code,

{{#invoke:params|sequential|setting|ih|&preloadparams%5b%5d{{=}}|magic_for_each_value|urlencode|QUERY}}

and were transcluded as{{example template|hello world|àèìòù|foobar}}, the{{urlencode:...|QUERY}} parser function would be called for each incoming parameter as first argument and withQUERY as second argument, and finally the returned text would be prefixed with&preloadparams%5b%5d=. This would generate,

&preloadparams%5b%5d=hello+world&preloadparams%5b%5d=%C3%A0%C3%A8%C3%AC%C3%B2%C3%B9&preloadparams%5b%5d=foo+bar

which can be used to allow the creation of pageswith preloaded text and parameters.

information Note: All arguments passed to this function except the magic word will not be trimmed of their leading and trailing spaces. Themagic_for_each_valuefunction name itself, however, will be trimmed of its surrounding spaces.

call_for_each_group

Functioncall_for_each_group(code)
Num. of argumentsAd libitum
Often preceeded byall_sorted,reassorted
SortableYes
Relevantfunction-only variablesh,i,l,f,n
See also
grouping_by_calling,call_for_each,call_for_each_value,{{#invoke:for loop}},{{for loop}}
Brief
Call a custom template for each group of parameters that have the same numeric suffix
Syntax
{{#invoke:params|call_for_each_group|template name|[append 1]|[append 2]|[...]|[append n]|[named param 1=value 1]|[...]|[named param n=value n]|[...]}}

The custom template will be repeatedly called with the numeric id of the group (i.e. the numeric suffix) asparameter zero (i.e.{{{0}}}). This will be an empty string for the group of incoming parameters that do not have a numeric suffix. A hyphen before the numeric suffix will be interpreted as a minus sign (and therefore the group id will be treated as a negative number). Numeric incoming parameters will be treated as if their prefix is an empty string (these can be captured using{{{}}} or{{{|fallback text}}} in the callback template). Spaces between the prefix and the numeric suffix will be ignored (therefore writing|foobar123= will be identical to writing|foobar 123= – in case of collisions one of the two values will be discarded). In the unlikely scenario that the prefix is itself a number (e.g.|1 1=,|2 1=, etc.), if this is0 or a negative number it will be decreased by one unit in order to leave the parameter zero undisturbed (so0 will become-1,-1 will become-2, and so on – if needed, you can use...|purging|0|1|... in the callback template to renormalize these numbers).

All unnamed arguments that follow thetemplate name in the invocation of this module will appear as sequential parameters in each call. Named arguments will be passed verbatim. Both named and unnamed arguments passed to this function will be given precedence in case of collisions. Numeric argument names below1 will be decreased by one unit (i.e....|call_for_each_group|example template|0=Hello world|... will become|-1=Hello world in the callback template – see above).

A header (h), an iteration delimiter (i), a last iteration delimiter (l), a footer (f), and a fallback text (n) can be declared via thesetting modifier – the string assigned to the key-value pair delimiter (p) will be ignored.

If you are a module writer, you might recognize some distant similarities between this function andTableTools.affixNums.

For example, if a template named{{foobar}} contained the following code,

{{#invoke:params|reassorted|call_for_each_group|example template|hello|world|foo=bar}}

writing

{{foobar| 1= Lorem| 2= ipsum| bicycle-1= dolor| bicycle1= sit| boat1= amet| car2= consectetur| bicycle2= adipiscing| other= elit| sunscreen= vestibulum|= ultricies| foo1= neque nisl}}

will be equivalent to writing

{{example template| 0=| 1= hello| 2= world|= ultricies| foo= bar| other= elit| sunscreen= vestibulum}}{{example template| 0= -1| 1= hello| 2= world| bicycle= dolor| foo= bar}}{{example template| 0= 1| 1= hello| 2= world|= Lorem| bicycle= sit| boat= amet| foo= bar}}{{example template| 0= 2| 1= hello| 2= world|= ipsum| bicycle= adipiscing| car= consectetur| foo= bar}}

The modifierssequential,non-sequential,all_sorted andreassorted will affect what groups of parameters will be iterated, not what parameters will be grouped. Before calling this function you will likely want to reduce the list of parameters via one of thewith_*_matching group of modifiers (for instance...|with_name_matching|.%-%d+$|or|[^%-]%d+$|call_for_each_group|... leaves only the parameters in which both the prefix and the numeric suffix are not empty strings). Thereassorted modifier often accompanies this function.

red-outlined triangle containing exclamation point Warning In writing templates, there is often the habit of signalingmultilevel substitutions using the{{{|safesubst:}}} notation. This is a dangerous practice, because{{{|safesubst:}}} means “write the parameter with an empty name, otherwise writesafesubst:”. Due to the fact thatcall_for_each_groupcan pass parameters with an empty name, a callback template should never use{{{|safesubst:}}} to notate multilevel substitutions, but should use insteadsafesubst:<noinclude/>. Not following this advice can lead to bugs that are hard to debug.

At {{./doc/examples/list of authors}} you can find an example of how to use this function to list authors the same way{{Cite book}} does. For instance, writing

{{module:params/doc/examples/list of authors| last1= Playfair| first1= I. S. O.| author-link1= Ian Stanley Ord Playfair| last2= Stitt| first2= G. M. S.| last3= Molony| first3= C. J. C.| last4= Toomer| first4= S. E.}}

will generate

Playfair, I. S. O.; Stitt, G. M. S.; Molony, C. J. C. & Toomer, S. E.

See also {{./doc/examples/tablebox}} for an example of how to exploit this function to createinfoboxes, and {{./doc/examples/four cells per row table}} for an example of how to exploit this function to create n-column tables.

information Note: All arguments passed to this function except thetemplate name will not be trimmed of their leading and trailing spaces. Thecall_for_each_groupfunction name itself, however, will be trimmed of its surrounding spaces.

for_each

Functionfor_each(code)
Num. of arguments1
SortableYes
Relevantfunction-only variablesh,i,l,f,n
See also
list,list_values,{{#invoke:for nowiki}},{{for nowiki}},{{expand wikitext}}
Brief
For each parameter passed to the current template, expand all occurrences of$# and$@ within a given text as key and value respectively
Syntax
{{#invoke:params|for_each|wikitext}}

Example:

{{#invoke:params|for_each|Arg name: $#, Arg value: $@}}

The text returned by this function is not expanded further (currently this module does not offer anexpand_for_each function). If you need wikitext expansion, use eitherconcat_and_call to propagate the incoming parameters altogether to the{{for nowiki}} template, ormapping_by_calling to propagate the incoming parameters one by one to{{expand wikitext}}.

Example #1 (wikitext expanded via the{{for nowiki}} template – suggested):

{{#invoke:params|sequential|concat_and_call|for nowiki|<br/>|<nowiki>Parameter value is “{{{1}}}”</nowiki>}}

Example #2 (wikitext expanded via the{{expand wikitext}} template – less efficient but more flexible):

{{#invoke:params|setting|i|<br/>|mapping_by_calling|expand wikitext|names_and_values_as|2|3|let|1|<nowiki>Parameter name is “{{{2}}}”, parameter value is “{{{3}}}”</nowiki>|let|unstrip|yes|list_values}}

information Note: The argument passed to this function will not be trimmed of its leading and trailing spaces. Thefor_eachfunction name itself, however, will be trimmed of its surrounding spaces.

Modifiers (piping functions)

The following aremodifiers, i.e. functions that expect to be piped instead of returning to the caller. Each of them can be followed by either another modifier or a non-piping function. The actions that modifiers do are done sequentially, in the same order chosen during the invocation of this module. Some modifiers, however, after signaling their presence to the modifiers that might follow, add their action to the queue of actions that will be done last (e.g.sequential,non-sequential,all_sorted,reassorted).

sequential

Modifiersequential(code)
Num. of arguments0
RepeatableNo
Conflicts withnon-sequential,all_sorted,reassorted
See also
non-sequential,all_sorted,reassorted,squeezing,filling_the_gaps,clearing
Brief
(IN FUNCTIONS ONLY, DOES NOT AFFECT MODIFIERS) Reduce the parameter list to the subgroup of consecutive parameters that follow|1=
Syntax
{{#invoke:params|sequential|pipe function name}}

Example:

{{#invoke:params|sequential|count}}

This modifier does not take arguments besides the name of the function that will follow.

Usingsequential together withnon-sequential will generate an error.

information Note: Likenon-sequential, thesequential modifier permanently marks a query. For instance, writing{{#invoke:params|sequential|with_name_not_matching|1|...}} will first mark the query as “sequential”, then will discard the first element from the sequence (leaving all the others intact). And so, no matter how many other parameters will be present, nothing will be shown.

non-sequential

Modifiernon-sequential(code)
Num. of arguments0
RepeatableNo
Conflicts withsequential
See also
sequential,all_sorted,reassorted
Brief
(IN FUNCTIONS ONLY, DOES NOT AFFECT MODIFIERS) Reduce the parameter list by discarding the subgroup of consecutive parameters that follow|1=
Syntax
{{#invoke:params|non-sequential|pipe function name}}

Example:

{{#invoke:params|non-sequential|setting|ih/p|{{!}}|{{=}}|list}}

This modifier does not take arguments besides the name of the function that will follow.

Usingnon-sequential together withsequential will generate an error.

information Note: Likesequential, thenon-sequential modifier permanently marks a query, and no matter what transformations will follow (seesqueezing) the parameters' “sequence” will not be shown.

all_sorted

Modifierall_sorted(code)
Num. of arguments0
RepeatableNo
Conflicts withsequential,reassorted
Has no effects oncount,value_of,concat_and_call,concat_and_invoke,concat_and_magic
See also
Natural sort order,reassorted,sequential,sorting_sequential_values
Brief
(IN FUNCTIONS ONLY, DOES NOT AFFECT MODIFIERS) When the time will come, all parameters will be dispatched sorted: first the numeric ones in ascending order, then the rest innatural order
Syntax
{{#invoke:params|all_sorted|pipe function name}}

information Note: This modifier sorts the wayfunctions iterate acrossall parameters based ontheir names. If you want to sortsequential parameters based ontheir values, seesorting_sequential_values.

Example:

{{#invoke:params|all_sorted|setting|ih/p|{{!}}|{{=}}|list}}

This modifier does not take arguments besides the name of the function that will follow.

Normally only sequential parameters are dispatched sorted, whereas non-sequential ones are dispatched randomly. Theall_sorted modifier ensures that nothing is left out of (natural) order. Attention must be paid to the fact that parameters whose name is a negative number will appear first. To avoid this thesqueezing modifier can be used.[1]

Theall_sorted modifier only affects the way parameters are shown, but has no effects on functions that do not iterate or cannot impose an order, such as:

information Note: Theall_sorted modifier cannot be used with functions that propagate several parameters together in a single call, likeconcat_and_call,concat_and_invoke, andconcat_and_magic, because during a call the order of arguments is always lost. For the same reason, it is not possible to guess the order of named parameters a template was transcluded with.

reassorted

Modifierreassorted(code)
Num. of arguments0
RepeatableNo
Conflicts withsequential,all_sorted
Has no effects oncount,value_of,concat_and_call,concat_and_invoke,concat_and_magic
See also
Natural sort order,all_sorted,sequential,sorting_sequential_values
Brief
(IN FUNCTIONS ONLY, DOES NOT AFFECT MODIFIERS) When the time will come, all parameters will be dispatched sorted: first non numeric ones innatural order, then the numeric ones in ascending order
Syntax
{{#invoke:params|reassorted|pipe function name}}

This modifier is identical toall_sorted, but numbers are iterated last (as in “bar, foo, hello, zebra, 1, 2, 3, …”).

information Note: Thereassorted modifier cannot be used with functions that propagate several parameters together in a single call, likeconcat_and_call,concat_and_invoke, andconcat_and_magic, because during a call the order of arguments is always lost. For the same reason, it is not possible to guess the order of named parameters a template was transcluded with.

setting

Modifiersetting(code)
Num. of arguments2–7 (variable)
RepeatableYes
Memory slots
p Key-value delimiter
i Iteration delimiter
l Last iteration delimiter
h Header text
f Footer text
n Fallback text
Brief
Define glue strings
Syntax
{{#invoke:params|setting|directives|...|pipe function name}}

This modifier allows some internal variables to be set and later be used by functions. It takes a variable number of arguments, relying on the first argument to understand how many other arguments to read. A few examples will introduce it better than words:

  • {{#invoke:params|setting|i|{{!}}|list_values}}
    ↳ Set the value ofiteration delimiter to|, then list all values
  • {{#invoke:params|setting|ih|{{!}}|list_values}}
    ↳ Set the value of bothheader text anditeration delimiter to|, then list all values
  • {{#invoke:params|setting|ih/p|{{!}}|{{=}}|list}}
    ↳ Set the value of bothheader text anditeration delimiter to|, setkey-value pair delimiter to=, then list all parameters
  • {{#invoke:params|setting|ih/p/n|{{!}}|{{=}}|No parameters were passed|list}}
    ↳ Set the value of bothheader text anditeration delimiter to|, setkey-value pair delimiter to=, setfallback text toNo parameters were passed, then list all parameters

The first argument is a slash-separated list of lists of slots to assign; one slot is referred by exactly one character and each list of slots maps exactly one argument. A slot indicates which internal variable to set. If more than one slot is aggregated within the same slash-separated list the same text will be assigned to more than one variable.

The slots available are the following:

SlotsVariableDescription
pKey-value pair delimiterThe string of text that will be placed between each parameter name and its value; it is never inserted by functions that only iterate between values, or by functions that pass the key-value pairs to external calls.
iIteration delimiterThe string of text that will be placed between each iteration; it is never inserted unless there are two or more parameters to show whenl is not given, or three or more parameters whenl is given.
lLast iteration delimiterThe string of text that will be placed between the second last and the last iteration; it is never inserted unless there are two or more parameters to show; if omitted defaults toi.
hHeader textThe string of text that will be placed before the iteration begins; it is never inserted if there are no parameters to show.
fFooter textThe string of text that will be placed after the iteration is over; it is never inserted if there are no parameters to show.
nFallback textThe string of text that will be placed if there are no parameters to show.

All space characters in the directives arguments are discarded. Therefore writing{{#invoke:params|setting|ih/p|...}} will be equivalent to writing

{{#invoke:params|setting| ih/ p|...}}

In theory, instead of assigning different slots at once (i.e.{{...|setting|ih/p|{{!}}|{{=}}|...}}), it is possible to write separate invocations ofsetting for each variable, as in{{...|setting|ih|{{!}}|setting|p|{{=}}...}}. This method however will be slightly less efficient.

Sometimes it might be necessary to make the values assigned depend on conditional expressions. For instance, the following imaginary{{Foobar see also}} template uses the#ifexpr parser function to properly show the “and” conjunction and possibly anOxford comma when more than two page names are provided:

{{Hatnote|{{{altphrase|Foobar see also}}}:{{#if:{{{1|}}}|{{#invoke:params|sequential|squeezing|setting|i/l|,|{{#ifexpr:{{#invoke:params|sequential|squeezing|count}} > 2|,}} and|trimming_values|for_each|[[$@]]}}|{{Error|{{tl|Foobar see also}} requires at least one page name}}}}}}

You can find this example at {{./doc/examples/Oxford comma}}. For instance,{{module:params/doc/examples/Oxford comma|Latin|English|German|Italian}} will generate

Foobar see also:Latin,English,German, andItalian

information Note: Thesetting modifier will be trimmed of its surrounding spaces. The directives argument will be stripped of all space characters, including internal spaces. All the other arguments passed to this modifier will be parsed verbatim (i.e. leading and trailing spaces will not be removed).

squeezing

Modifiersqueezing(code)
Num. of arguments0
RepeatableYes
See also
filling_the_gaps,sequential,clearing,TableTools.compressSparseArray
Brief
Rearrange all parameters that have numeric names to form a compact sequence starting from 1, keeping the same order
Syntax
{{#invoke:params|squeezing|pipe function name}}

Example:

{{#invoke:params|squeezing|sequential|setting|i/p|<br/>|:|list}}

This modifier does not take arguments besides the name of the function that will follow. If you are a module writer, you might recognize some similarities between this function andTableTools.compressSparseArray.

The following three concatenations will lead to the same result of discarding all parameters with numeric names:

  1. {{...|excluding_numeric_names|...}}
  2. {{...|with_name_not_matching|^%-?%d+$|...}}
  3. {{...|non-sequential|squeezing|...}}
  4. {{...|squeezing|non-sequential|...}}

The first solution is the most optimized one. Furthermore, in the last two solutions the numeric parameters are discarded just before the final function is invoked (sometimes this might be a wanted result).

filling_the_gaps

Modifierfilling_the_gaps(code)
Num. of arguments0
RepeatableYes
See also
squeezing,sequential,clearing
Brief
Assign an empty string to all undefined numeric parameters between 1 or a lower numeric parameter name provided and the maximum numeric parameter provided
Syntax
{{#invoke:params|filling_the_gaps|pipe function name}}

Example:

{{#invoke:params|filling_the_gaps|sequential|setting|i/p|<br/>|:|list}}

This modifier does not take arguments besides the name of the function that will follow.

Note that when all numeric parameters are lower than 1, the gap between 1 and the maximum numeric parameter will not be filled. The following table provides some examples.

Numeric parameters provided
Before callingfilling_the_gapsAfter callingfilling_the_gaps
11
21, 2
6, 91, 2, 3, 4, 5, 6, 7, 8, 9
-5, -3-5, -4, -3
-5, -3, 1-5, -4, -3, -2, -1, 0, 1
-1-1
-2-2

information Note: There is a safety limit of at most 1024 undefined parameters that can be filled using this modifier.

clearing

Modifierclearing(code)
Num. of arguments0
RepeatableYes
Often accompanied bysequential
See also
sequential,squeezing,filling_the_gaps
Brief
Remove all numeric parameters that are not in the sequence
Syntax
{{#invoke:params|clearing|pipe function name}}

This modifier does not take arguments besides the name of the function that will follow.

Unlikesequential – which affects only the way parameters are shown – this modifier actually removes all non-sequential numeric parameters, albeit leaves non-numeric parameters intact.

Example:

{{#invoke:params|clearing|setting|i/p|<br/>|:|list}}

If you want to remove also non-numeric parameters, add theexcluding_non-numeric_names modifier:

{{#invoke:params|clearing|excluding_non-numeric_names|setting|i/p|<br/>|:|list}}

If you want instead to remove sequential parameters and leave the rest, use{{...|cutting|-1|1|...}}:

{{#invoke:params|cutting|-1|1|setting|i/p|<br/>|:|list}}

cutting

Modifiercutting(code)
Num. of arguments2
RepeatableYes
Often accompanied bysequential
See also
sequential,squeezing,filling_the_gaps,clearing,cropping,purging,backpurging,reversing_numeric_names,sorting_sequential_values
Brief
Remove zero or more parameters from the beginning and the end of theparameters' sequence
Syntax
{{#invoke:params|cutting|left trim|right trim|pipe function name}}

The first argument indicates how many sequential parameters must be removed from the beginning of the parameter sequence, the second argument indicates how many sequential parameters must be removed from the end of the parameter list. If any of the two arguments contains a negative number its absolute value indicates what must be lefton the opposite side – i.e.{{#invoke:params|cutting|-3|0|list}} indicates that the last three arguments must not be discarded.

Example:

{{#invoke:params|cutting|0|2|sequential|call_for_each_value|example template}}

If the absolute value of the sum of the two arguments (left and right cut) is greater than the number ofsequential parameters available, the behavior will be the same as if the sum had been equal to the number of sequential parameters available, both when this is a positive value and when it is a negative value (with opposite results). After the desired sequential parameters have been discarded, all numeric parameters will be shifted accordingly.

In some cases it might be necessary to concatenate more than one invocation of thecutting modifier. For instance, the following code prints the last unnamed parameter passed, but only if at least two parameters were passed:

{{#invoke:params|sequential|cutting|1|0|cutting|-1|0|list_values}}

information Suggestion: Although{{#invoke:params|cutting|-1|1|...}} de facto gets rid of all sequential parameters, in most cases it is clearer and more idiomatic to write{{#invoke:params|non-sequential|...}} to obtain the same effect. The last method however cannot be used when it is important that sequential parameters are removed before a particular modifier is called, becausenon-sequential does not take effect until the final function is invoked. Writing instead{{#invoke:params|sequential|cutting|-1|1|...}} will leave zero arguments to show.

cropping

Modifiercropping(code)
Num. of arguments2
RepeatableYes
Often accompanied bysequential
See also
sequential,squeezing,filling_the_gaps,clearing,cutting,purging,backpurging,reversing_numeric_names,sorting_sequential_values
Brief
Remove zero or more parameters from the beginning and the end of thelist of numeric parameters (not only the sequential ones)
Syntax
{{#invoke:params|cropping|left crop|right crop|pipe function name}}

This modifier is very similar tocutting, but instead of removing arguments from the extremities of the parameters'sequence, arguments will be removed counting from the first and the last numeric arguments given (i.e.|-1000=... and|1000=... in the case of{{foobar|-1000=hello|1=my|1000=darling}}). If any of the two arguments contains a negative number its absolute value indicates what must be lefton the opposite side.

Example:

{{#invoke:params|cropping|2|1|sequential|call_for_each_value|example template}}

For instance, when a template transcluded as{{example template|-2=minus two|0=zero|1=one|2=two|3=three|19=nineteen|20=twenty}} uses thecutting modifier with2 and1 as arguments, as in the example above, the following parameters will be left:

-2: minus two
0: zero
16: nineteen
17: twenty]

If instead the template uses thecropping modifier with2 and1 as arguments, the following parameters will be left:

0: zero
1: one
2: two
3: three
19: nineteen

If the absolute value of the sum of the two arguments (left and right crop) is greater than the difference between the largest and the lowestnumeric parameters available, the behavior will be the same as if the sum had been equal to the number of numeric parameters available, both when this is a positive value and when it is a negative value (with opposite results). Whensequential parameters are present among the discarded parameters, all the remaining numeric parameters greater than zero will be shifted accordingly.

purging

Modifierpurging(code)
Num. of arguments2
RepeatableYes
Often accompanied bysequential
See also
sequential,squeezing,filling_the_gaps,clearing,cutting,cropping,backpurging,reversing_numeric_names,sorting_sequential_values
Brief
Remove zero or more parameters from any point of the list of numeric parameters, shifting everything accordingly
Syntax
{{#invoke:params|purging|start offset|length|pipe function name}}

The first argument indicates at which point in the parameter list the removal must begin, the second argument indicates how many parameters must be discarded among it and what lieson the right side. If the second argument contains zero or a negative number its absolute value indicates what must be leftat the end of the right side of the list of numeric parameters – i.e.{{#invoke:params|purging|5|0|list}} indicates that every numeric argument whose numeric name is greater than4 must be removed.

Example #1 (purge the first parameter):

{{#invoke:params|purging|1|1|call_for_each_value|example template}}

Example #2 (purge the second, third, and four parameters):

{{#invoke:params|purging|2|3|call_for_each_value|example template}}

backpurging

Modifierbackpurging(code)
Num. of arguments2
RepeatableYes
Often accompanied bysequential
See also
sequential,squeezing,filling_the_gaps,clearing,cutting,cropping,purging,reversing_numeric_names,sorting_sequential_values
Brief
Remove zero or more parameters from any point of the list of numeric parameters, moving backwards and shifting everything accordingly
Syntax
{{#invoke:params|backpurging|start offset|length|pipe function name}}

The first argument indicates at which point in the parameter list the removal must begin, the second argument indicates how many parameters must be discarded among it and what lieson the left side. If the second argument contains zero or a negative number its absolute value indicates what must be leftat the end of the left side of the list of numeric parameters – i.e.{{#invoke:params|purging|5|0|list}} indicates that every numeric argument whose numeric name is less than6 must be removed.

Example:

{{#invoke:params|backpurging|3|1|call_for_each_value|example template}}

The following code removes all parameters with negative and zero numeric names, then lists the rest:

{{#invoke:params|backpurging|0|0|for_each|[$#: $@]}}

reversing_numeric_names

Modifierreversing_numeric_names(code)
Num. of arguments0
RepeatableYes
Often accompanied bysequential
See also
sequential,squeezing,filling_the_gaps,clearing,cutting,cropping,purging,backpurging,sorting_sequential_values
Brief
Reverse the order of all numeric parameters (not only sequential ones), making sure that the largest numeric parameter and|1= are swapped
Syntax
{{#invoke:params|reversing_numeric_names|pipe function name}}

This modifier does not take arguments besides the name of the function that will follow.

Example:

{{#invoke:params|reversing_numeric_names|for_each|[$#: $@]}}

information Note: If negative parameters are present this function becomes non-invertible. This means that{{#invoke:params|reversing_numeric_names|reversing_numeric_names|...}} will not restore the original parameter names, but will shift all numeric parameters so that what formerly was the smallest parameter name will now become|1=.

sorting_sequential_values

Modifiersorting_sequential_values(code)
Num. of arguments0 or 1
RepeatableYes
Often accompanied bysequential
See also
sequential,squeezing,filling_the_gaps,clearing,cutting,cropping,purging,backpurging,reversing_numeric_names,all_sorted,reassorted
Brief
Sort the order of sequential values
Syntax
{{#invoke:params|sorting_sequential_values|[criterion]|pipe function name}}

information Note: This modifier sortssequential parameters based ontheir values. If you want to sort the wayfunctions iterate acrossall parameters based ontheir names, seeall_sorted.

This modifier optionally supports one argument to specify the sorting criterion. If this is omitted it is assumed that sequential values must be ordered alphabetically. Currently the only other possible criterion isnaturally, for ordering sequential values innatural sort order.

Example (alphabetical sort order):

{{#invoke:params|sorting_sequential_values|for_each|[$#: $@]}}

Example (natural sort order):

{{#invoke:params|sorting_sequential_values|naturally|for_each|[$#: $@]}}

imposing

Modifierimposing(code)
Num. of arguments2
RepeatableYes
See also
providing,discarding,filling_the_gaps
Brief
Impose a new value to a parameter
Syntax
{{#invoke:params|imposing|name|value|pipe function name}}

Example:

{{#invoke:params|imposing|foo|bar|imposing|hello|world|for_each|[$#: $@]}}

information Note: The value assigned will not be trimmed of its leading and trailing spaces. The name of the parameter and theimposing modifier name itself, however, will be trimmed of their surrounding spaces.

providing

Modifierproviding(code)
Num. of arguments2
RepeatableYes
See also
imposing,discarding,filling_the_gaps
Brief
Assign a new value to a parameter, but only when missing
Syntax
{{#invoke:params|providing|name|value|pipe function name}}

Example:

{{#invoke:params|providing|foo|bar|providing|hello|world|for_each|[$#: $@]}}

information Note: The value assigned will not be trimmed of its leading and trailing spaces. The name of the parameter and theproviding modifier name itself, however, will be trimmed of their surrounding spaces.

discarding

Modifierdiscarding(code)
Num. of arguments1 or 2
RepeatableYes
See also
clearing,cutting,cropping,purging,backpurging
Brief
Discard one or more numeric parameters or one non-numeric parameter
Syntax
{{#invoke:params|discarding|name|[how many]|pipe function name}}

If, and only if, the name of the parameter is numeric, it is possible to add a second argument to indicate how many contiguous parameters must be discarded starting from the first argument. If the discarded parameters is part of the parameters' sequence one or more holes will be created. To avoid creating holes, usepurging orbackpurging.

Example #1 (discard the parameter named|hello=):

{{#invoke:params|discarding|hello|for_each|[$#: $@]}}

Example #2 (discard the parameter named|5=):

{{#invoke:params|discarding|5|for_each|[$#: $@]}}

Example #3 (discard the parameters named|1=,|2=,|3= and|4=):

{{#invoke:params|discarding|1|4|for_each|[$#: $@]}}

It is possible to use this modifier to check for unknown parameters:

{{#ifexpr:{{#invoke:params|discarding|hello|discarding|wind|count}} > 0|{{Error|Error: The only parameters accepted are{{para|hello}} and{{para|wind}}.}}|Everything is good: do something}}

You can find this example at {{./doc/examples/check for unknown parameters}}. For instance,{{module:params/doc/examples/check for unknown parameters|hello=world|wind=surfing}} will generate

Everything is good: do something

For simple cases like this, however, specialized modules are available; you might want to have a look at:

When used to discard single parameters, this modifier is equivalent to writing...|with_name_not_matching|parameter name|strict|.... However, due to the fact thatwith_name_not_matching needs to cross-check for the possible presence ofor keywords, usingdiscarding will be slightly more efficient.

information Note: All arguments passed to this modifier and thediscarding modifier name itself will be trimmed of their surrounding spaces.

excluding_non-numeric_names

Modifierexcluding_non-numeric_names(code)
Num. of arguments0
RepeatableYes
See also
excluding_non-numeric_names,with_name_matching,with_name_not_matching,clearing
Brief
Discard all non-numeric parameters
Syntax
{{#invoke:params|excluding_non-numeric_names|pipe function name}}

This modifier is only syntax sugar for...|with_name_matching|^%-?%d+$|... (but using a slighly faster optimization). For the inverse modifier, seeexcluding_numeric_names. If you want to remove also non-sequential parameters, add theclearing modifier to the pipeline (...|excluding_non-numeric_names|clearing|...).

excluding_numeric_names

Modifierexcluding_numeric_names(code)
Num. of arguments0
RepeatableYes
See also
excluding_non-numeric_names,with_name_matching,with_name_not_matching
Brief
Discard all numeric parameters (not only the sequential ones)
Syntax
{{#invoke:params|excluding_numeric_names|pipe function name}}

This modifier is only syntax sugar for...|with_name_not_matching|^%-?%d+$|... (but using a slighly faster optimization). For the inverse modifier, seeexcluding_non-numeric_names.

with_name_matching

Modifierwith_name_matching(code)
Num. of argumentsAd libitum
RepeatableYes
See also
excluding_numeric_names,excluding_non-numeric_names,with_name_not_matching,with_value_matching,with_value_not_matching
Brief
Discard all parameters whose namedoes not matchany of the given patterns
Syntax
{{#invoke:params|with_name_matching|target 1|[plain flag 1]|[or]|[target 2]|[plain flag 2]|[or]|[...]|[target N]|[plain flag N]|pipe function name}}

Internally this modifier uses Lua'sstring.find() function to find whether parameter names match against given patterns; therefore, unless aplain flag is set, please use the same syntax ofLua patterns. Theplain flag can be eitherplain orstrict or omitted. When omitted it is assumed that the target string is a Lua pattern. The difference betweenplain andstrict is that the latter also requires that the lengths match (this happens only when the two strings are 100% identical). In order to facilitate wikitext scripting in theplain flag argument, thepattern keyword is available too, equivalent to omitting the argument.

To express alogical OR theor keyword is available. To express alogical AND instead, concatenate more invocations ofwith_name_matching.

For the sake of argument we will imagine that we are invokingwith_name_matching from within the{{Infobox artery}} template, and this is being called with the following parameters:

{{Infobox artery
|Name =Pulmonary artery
|Latin =truncus pulmonalis, arteria pulmonalis
|Image ={{Heart diagram 250px}}
|Caption =Anterior (frontal) view of the opened heart. (Pulmonary artery upper right.)
|Image2 =Alveoli diagram.png
|Caption2 =Diagram of the alveoli with both cross-section and external view.
|BranchFrom =[[right ventricle]]
|BranchTo =
|Vein =[[pulmonary vein]]
|Precursor =truncus arteriosus
|Supplies =
}}

Test cases:

  • List only the parameters whose names match against the^Image pattern:
    {{#invoke:params|setting|ih/p|{{!}}|{{=}}|with_name_matching|^Image|list}}
    |Image={{Heart diagram 250px}}|Image2=Alveoli diagram.png
  • List the parameters whose names match against both patterns^Imageand%d+$:
    {{#invoke:params|setting|ih/p|{{!}}|{{=}}|with_name_matching|^Image|with_name_matching|%d+$|list}}
    |Image2=Alveoli diagram.png
  • List the parameters whose names match against either the^Nameor the^Latin$ pattern:
    {{#invoke:params|setting|ih/p|{{!}}|{{=}}|with_name_matching|^Name$|or|^Latin$|list}}
    |Latin=truncus pulmonalis, arteria pulmonalis|Name=Pulmonary artery
  • List the parameters whose names match against either thema plain stringor theme$ pattern:
    {{#invoke:params|setting|ih/p|{{!}}|{{=}}|with_name_matching|ma|plain|or|me$|list}}
    |Image={{Heart diagram 250px}}|Name=Pulmonary artery|Image2=Alveoli diagram.png

Usingwith_name_matching it is easy to emulate the behaviour ofModule:Enumerate (or similar modules). For instance, the following examples creates a bullet list of all the parameters passed of type|foobar1,|foobar2|foobarN:

{{#invoke:params|all_sorted|with_name_matching|^foobar%d+$|setting|ih|*|list_values}}

It is possible to see this example live at {{./doc/examples/enumerate}}.

information Note: Thetarget arguments passed to this modifier will not be trimmed of their leading and trailing spaces. Theor,plain,strict andpattern keywords, and thewith_name_matching modifier name itself, however, will be trimmed of their surrounding spaces.

with_name_not_matching

Modifierwith_name_not_matching(code)
Num. of argumentsAd libitum
RepeatableYes
See also
excluding_numeric_names,excluding_non-numeric_names,with_name_matching,with_value_matching,with_value_not_matching
Brief
Discard all parameters whose namematchesall the given patterns
Syntax
{{#invoke:params|with_name_not_matching|target 1|[plain flag 1]|[and]|[target 2]|[plain flag 2]|[and]|[...]|[target N]|[plain flag N]|pipe function name}}

Internally this modifier uses Lua'sstring.find() function to find whether parameter names match against given patterns; therefore, unless a plain flag is set, please use the same syntax ofLua patterns. The plain flag can be eitherplain orstrict or omitted. When omitted it is assumed that the target string is a Lua pattern. The difference betweenplain andstrict is that the latter also requires that the lengths match (this happens only when the two strings are 100% identical). In order to facilitate wikitext scripting in theplain flag argument, thepattern keyword is available too, equivalent to omitting the argument.

To express alogical OR theor keyword is available. To express alogical AND instead, concatenate more invocations ofwith_name_not_matching.

For the sake of argument we will imagine that we are invokingwith_name_not_matching from within the{{Infobox artery}} template, and this is being transcluded using the same parameters that we had imagined in the previous example atwith_name_matching:

  • List only the parameters whose names do not match against thea pattern:
    {{#invoke:params|setting|ih/p|{{!}}|{{=}}|with_name_not_matching|a|list}}
    |Precursor=truncus arteriosus|Supplies=|Vein=pulmonary vein
  • List the parameters whose names do not match against thea plain stringand do not match against thel plain string either:
    {{#invoke:params|setting|ih/p|{{!}}|{{=}}|with_name_not_matching|a|plain|with_name_not_matching|l|plain|list}}
    |Precursor=truncus arteriosus|Vein=pulmonary vein
  • List the parameters whose names do not match against either thea plain stringor then plain string:
    {{#invoke:params|setting|ih/p|{{!}}|{{=}}|with_name_not_matching|a|plain|or|n|plain|list}}
    |Precursor=truncus arteriosus|Supplies=|Image={{Heart diagram 250px}}|Name=Pulmonary artery|Image2=Alveoli diagram.png|Vein=pulmonary vein

Nota bene* For the sake of efficiency, please don't use this modifier with thestrict flag unless accompanied byor, usediscarding instead!

information Note: Thetarget arguments passed to this modifier will not be trimmed of their leading and trailing spaces. Theor,plain,strict andpattern keywords, and thewith_name_not_matching modifier name itself, however, will be trimmed of their surrounding spaces.

with_value_matching

Modifierwith_value_matching(code)
Num. of argumentsAd libitum
RepeatableYes
See also
with_name_matching,with_name_not_matching,with_value_not_matching
Brief
Discard all parameters whose valuedoes not matchany of the given patterns
Syntax
{{#invoke:params|with_value_matching|target 1|[plain flag 1]|[or]|[target 2]|[plain flag 2]|[or]|[...]|[target N]|[plain flag N]|pipe function name}}

Exactly likewith_name_matching, but applied to parameter values instead of names.

Internally this modifier uses Lua'sstring.find() function to find whether parameter names match against given patterns; therefore, unless a plain flag is set, please use the same syntax ofLua patterns. The plain flag can be eitherplain orstrict or omitted. When omitted it is assumed that the target string is a Lua pattern. The difference betweenplain andstrict is that the latter also requires that the lengths match (this happens only when the two strings are 100% identical). In order to facilitate wikitext scripting in theplain flag argument, thepattern keyword is available too, equivalent to omitting the argument.

Example:

{{#invoke:params|with_value_matching|banana|count}}

information Note: Thetarget arguments passed to this modifier will not be trimmed of their leading and trailing spaces. Theor,plain,strict andpattern keywords, and thewith_value_matching modifier name itself, however, will be trimmed of their surrounding spaces.

with_value_not_matching

Modifierwith_value_not_matching(code)
Num. of argumentsAd libitum
RepeatableYes
See also
with_name_matching,with_name_not_matching,with_value_matching
Brief
Discard all parameters whose valuematchesall the given patterns
Syntax
{{#invoke:params|with_value_not_matching|target 1|[plain flag 1]|[and]|[target 2]|[plain flag 2]|[and]|[...]|[target N]|[plain flag N]|pipe function name}}

Exactly likewith_name_not_matching, but applied to parameter values instead of names.

Internally this modifier uses Lua'sstring.find() function to find whether parameter names match against given patterns; therefore, unless a plain flag is set, please use the same syntax ofLua patterns. The plain flag can be eitherplain orstrict or omitted. When omitted it is assumed that the target string is a Lua pattern. The difference betweenplain andstrict is that the latter also requires that the lengths match (this happens only when the two strings are 100% identical). In order to facilitate wikitext scripting in theplain flag argument, thepattern keyword is available too, equivalent to omitting the argument.

For instance, before callinglist, the following code will get rid of all blank parameters (i.e. parameters whose values contain only zero or more spaces):

{{#invoke:params|with_value_not_matching|^%s*$|setting|hi/p|{{!}}|{{=}}|list}}

A typical use case of this modifier is that of purging all empty incoming parameters before calling another template, especially when thisdistinguishes between empty and undefined parameters.

{{#invoke:params|with_value_not_matching|^%s*$|concat_and_call|my template}}

information Note: Thetarget arguments passed to this modifier will not be trimmed of their leading and trailing spaces. Theor,plain,strict andpattern keywords, and thewith_value_not_matching modifier name itself, however, will be trimmed of their surrounding spaces.

trimming_values

Modifiertrimming_values(code)
Num. of arguments0
RepeatableYes
Brief
Remove leading and trailing spaces from values
Syntax
{{#invoke:params|trimming_values|pipe function name}}

This modifier does not take arguments besides the name of the function that will follow.

Most modifiers are order-dependent, therefore placingtrimming_values in different positions can generate different results. For instance, imagining our{{example template}} being called with the following spaced arguments:{{example template| wanna| be| my| friend| ?}}. If{{example template}} contained the following code,

{{#invoke:params|with_value_matching|%s+$|trimming_values|setting|i/p|{{!}}|{{=}}|list}}

the following text would be printed:1=wanna|2=be|3=my|4=friend|5=?. But if instead it contained the following code,

{{#invoke:params|trimming_values|with_value_matching|%s+$|setting|i/p|{{!}}|{{=}}|list}}

no arguments would be shown.

Order affects also performance, and how many values will be trimmed of their leading and trailing spaces will depend on wheretrimming_values is placed. For instance, if a template were invoked with 50 parameters and its code contained{{#invoke:params|trimming_values|cutting|-1|0|list}}, first all its values would be trimmed of leading and trailing blank spaces and then its first 49 parameters would be discarded. On the other hand, writing{{#invoke:params|cutting|-1|0|trimming_values|list}} would first discard 49 parameters and then trim the only value left, resulting in a more efficient code. As a general rule, placingtrimming_values as the last modifier is usually the best choice.

In most cases placingtrimming_values together withnon-sequential will result in an empty call with no effects, because non-sequential parameters are normally stripped of their leading and trailing spaces by default – this however depends on the caller, and if the current template is being called by a module it is in theory possible in specific conditions for named parameters to retain their leading and trailing spaces (namely in non-sequential numeric parameters).

Usingtrimming_values makes this module behave like many Wikipedia modules behave. For example, if we wanted to emulate {{#invoke:Separated entries|main}}, writing

{{#invoke:params|sequential|squeezing|trimming_values|setting|i|XXXX|list_values}}

will be equivalent to writing,

{{#invoke:separated entries|main|separator=XXXX}}

whereas writing

{{#invoke:params|sequential|squeezing|trimming_values|setting|i/l|XXXX|YYYY|list_values}}

will be equivalent to writing

{{#invoke:separated entries|main|separator=XXXX|conjunction=YYYY}}

The {{./doc/examples/trim and call}} example template shows how to call any arbitrary template trimming all parameters beforehand.

converting_values_to_lowercase

Modifierconverting_values_to_lowercase(code)
Num. of arguments0
RepeatableYes
See also
converting_values_to_uppercase,converting_names_to_lowercase,converting_names_to_uppercase,mapping_by_replacing,renaming_by_replacing
Brief
Convert all parameter values to lower case
Syntax
{{#invoke:params|converting_values_to_lowercase|pipe function name}}

This modifier does not take arguments besides the name of the function that will follow.

This modifier converts all parameter values to lowercase. It is identical to writing...|mapping_by_magic|lc|..., but without the burden of calling a parser function.

converting_values_to_uppercase

Modifierconverting_values_to_uppercase(code)
Num. of arguments0
RepeatableYes
See also
converting_values_to_lowercase,converting_names_to_lowercase,converting_names_to_uppercase,mapping_by_replacing,renaming_by_replacing
Brief
Convert all parameter values to upper case
Syntax
{{#invoke:params|trimming_values|pipe function name}}

This modifier does not take arguments besides the name of the function that will follow.

This modifier converts all parameter values to uppercase. It is identical to writing...|mapping_by_magic|uc|..., but without the burden of calling a parser function.

mapping_by_calling

Modifiermapping_by_calling(code)
Num. of argumentsAd libitum
RepeatableYes
See also
converting_values_to_lowercase,converting_values_to_uppercase,call_for_each,call_for_each_value,mapping_by_invoking,mapping_by_magic,mapping_by_replacing,converting_names_to_lowercase,converting_names_to_uppercase,renaming_by_calling,renaming_by_invoking,renaming_by_magic,renaming_by_replacing,grouping_by_calling
Brief
Map all parameter values, replacing their content with the expansion of a given template repeatedly called with one parameter (the parameter's value)
Syntax
{{#invoke:params|mapping_by_calling|template name|[call style]|[let]|[...]|[number of additional parameters]|[parameter 1]|[parameter 2]|[...]|[parameter N]|pipe function name}}

This modifier (temporarily) changes the content of the parameters the current template is being called with, replacing each of them with the text returned by another template. The latter will be repeatedly called with at least one parameter as first sequential parameter: the parameter's value.

It is possible to pass the parameter's value as a different parameter, or pass the parameter's name as well, by specifying acall style flag immediately after thetemplate name (see below).

If thecall style flag or (if omitted) thetemplate name is followed by one or more groups of three arguments led by thelet keyword (i.e.let|name|value), these will be passed to the mapping template.

If the last group of three arguments or (if omitted) thecall style flag or (if omitted) thetemplate name is followed by a number, this will be parsed as the amount of positional parameters to add. These will always follow the current parameter's name and/or value if any of the latter are passed using a numeric name greater than zero.

In case of collisions, the parameters assigned via thelet keyword will be given precedence over everything else.

For instance, before listing all parameters,

{{#invoke:params|mapping_by_calling|foobar|setting|i/p|{{!}}|{{=}}|list}}

will replace each value with the expansion of{{foobar|VALUE}} (whereVALUE indicates each different value).

On the other hand,

{{#invoke:params|mapping_by_calling|foobar|names_and_values|let|rice|nope|let|curry|lots!|2|hello|world|setting|i/p|{{!}}|{{=}}|list}}

will do the same, but using the expansion of{{foobar|NAME|VALUE|hello|world|rice=nope|curry=lots!}} (whereNAME andVALUE indicate each different name and value).

Possiblecall style flags are:

Call style flagExampleCorresponding call
names_and_values{{#invoke:params|mapping_by_calling|example template|names_and_values|let|foo|bar|2|hello|world|setting|i/p|<br/>||list}}{{example template|NAME|VALUE|hello|world|foo=bar}}
values_and_names{{#invoke:params|mapping_by_calling|example template|values_and_names|let|foo|bar|2|hello|world|setting|i/p|<br/>||list}}{{example template|VALUE|NAME|hello|world|foo=bar}}
names_only{{#invoke:params|mapping_by_calling|example template|names_only|let|foo|bar|2|hello|world|setting|i/p|<br/>||list}}{{example template|NAME|hello|world|foo=bar}}
values_only{{#invoke:params|mapping_by_calling|example template|values_only|let|foo|bar|2|hello|world|setting|i/p|<br/>||list}}{{example template|VALUE|hello|world|foo=bar}}
names_and_values_as|...|...{{#invoke:params|mapping_by_calling|example template|names_and_values_as|my_name|my_value|let|foo|bar|2|hello|world|setting|i/p|<br/>||list}}{{example template|hello|world|my_name=NAME|my_value=VALUE|foo=bar}}
names_only_as|...{{#invoke:params|mapping_by_calling|example template|names_only_as|my_name|let|foo|bar|2|hello|world|setting|i/p|<br/>||list}}{{example template|hello|world|my_name=NAME|foo=bar}}
values_only_as|...{{#invoke:params|mapping_by_calling|example template|values_only_as|my_value|let|foo|bar|2|hello|world|setting|i/p|<br/>||list}}{{example template|hello|world|my_value=VALUE|foo=bar}}
blindly{{#invoke:params|mapping_by_calling|example template|blindly|let|foo|bar|2|hello|world|setting|i/p|<br/>||list}}{{example template|hello|world|foo=bar}}

If thecall style flags argument is omitted it defaults tovalues_only.

information Note: All arguments passed to this modifier except themapping_by_calling modifier name itself, thetemplate name, thecall style flag, thelet keyword, the passed parameter names, and the number of additional parameters will not be trimmed of their leading and trailing spaces.

mapping_by_invoking

Modifiermapping_by_invoking(code)
Num. of argumentsAd libitum
RepeatableYes
See also
converting_values_to_lowercase,converting_values_to_uppercase,invoke_for_each,invoke_for_each_value,mapping_by_calling,mapping_by_magic,mapping_by_replacing,converting_names_to_lowercase,converting_names_to_uppercase,renaming_by_calling,renaming_by_invoking,renaming_by_magic,renaming_by_replacing,grouping_by_calling
Brief
Map all parameter values, replacing their content with the text returned by a given module function repeatedly invoked with at least one argument (the parameter's value)
Syntax
{{#invoke:params|mapping_by_invoking|module name|function name|[call style]|[let]|[...]|[number of additional arguments]|[argument 1]|[argument 2]|[...]|[argument N]|pipe function name}}

This modifier (temporarily) changes the content of the parameters the current template is being called with, replacing each of them with the text returned by a custom module function. The latter will be repeatedly called with at least one argument as first sequential argument: the parameter's value.

It is possible to pass the parameter's value as a different argument, or pass the parameter's name as well, by specifying acall style flag immediately after thefunction name (seemapping_by_calling for the list of possible flags). If omitted, thecall style flags argument defaults tovalues_only.

If thecall style flag or (if omitted) thefunction name is followed by one or more groups of three arguments led by thelet keyword (i.e.let|name|value), these will be passed to the mapping module function.

If the last group of three arguments or (if omitted) thecall style flag or (if omitted) thefunction name is followed by a number, this will be parsed as the amount of positional parameters to add. These will always follow the current parameter's name and/or value if any of the latter are passed using a numeric name greater than zero.

In case of collisions, the arguments assigned via thelet keyword will be given precedence over everything else.

For instance, before listing all parameters,

{{#invoke:params|mapping_by_invoking|foobar|main|setting|i/p|{{!}}|{{=}}|list}}

will replace each value with the expansion of{{#invoke:foobar|main|VALUE}} (whereVALUE indicates each different value).

On the other hand,

{{#invoke:params|mapping_by_invoking|foobar|main|names_and_values|let|rice|nope|let|curry|lots!|2|hello|world|setting|i/p|{{!}}|{{=}}|list}}

will do the same, but using the expansion of{{#invoke:foobar|main|NAME|VALUE|hello|world|rice=nope|curry=lots!}} (whereNAME andVALUE indicate each different name and value).

information Note: All arguments passed to this modifier except themapping_by_invoking modifier name itself, themodule name, thefunction name, thecall style flag, thelet keyword, the passed parameter names, and the number of additional arguments will not be trimmed of their leading and trailing spaces.

mapping_by_magic

Modifiermapping_by_magic(code)
Num. of argumentsAd libitum
RepeatableYes
See also
converting_values_to_lowercase,converting_values_to_uppercase,magic_for_each,magic_for_each_value,mapping_by_calling,mapping_by_invoking,mapping_by_replacing,converting_names_to_lowercase,converting_names_to_uppercase,renaming_by_calling,renaming_by_invoking,renaming_by_magic,renaming_by_replacing,grouping_by_calling
Brief
Map all parameter values, replacing their content with the expansion of a given parser function repeatedly called with at least one argument (the parameter's value)
Syntax
{{#invoke:params|mapping_by_magic|parser function|[call style]|[let]|[...]|[number of additional arguments]|[argument 1]|[argument 2]|[...]|[argument N]|pipe function name}}

This modifier (temporarily) changes the content of the parameters the current template is being called with, replacing each of them with the text returned by aparser function. The latter will be repeatedly called with at least one argument as first sequential argument: the parameter's value.

It is possible to pass the parameter's value as a different argument, or pass the parameter's name as well, by specifying acall style flag immediately after theparser function name (seemapping_by_calling for the list of possible flags). If omitted, thecall style flags argument defaults tovalues_only.

If thecall style flag or (if omitted) thetemplate name is followed by one or more groups of three arguments led by thelet keyword (i.e.let|name|value), these will be passed to the parser function.

If the last group of three arguments or (if omitted) thecall style flag or (if omitted) thetemplate name is followed by a number, this will be parsed as the amount of positional arguments to add. These will always follow the current parameter's name and/or value if any of the latter are passed using a numeric name greater than zero.

In case of collisions, the arguments assigned via thelet keyword will be given precedence over everything else.

For instance, before listing all parameters,

{{#invoke:params|mapping_by_magic|uc|setting|i/p|{{!}}|{{=}}|list}}

will replace each value with the expansion of{{uc:VALUE}} (whereVALUE indicates each different value).

On the other hand,

{{#invoke:params|mapping_by_magic|plural|names_and_values|1|They are many|setting|i/p|{{!}}|{{=}}|list}}

will do the same, but using the expansion of{{plural:NAME|VALUE|They are many}} (whereNAME andVALUE indicate each different name and value).

information Note: All arguments passed to this modifier except themapping_by_magic modifier name itself, the parser function's name, thecall style flag, thelet keyword, the passed parameter names, and the number of additional arguments will not be trimmed of their leading and trailing spaces.

mapping_by_replacing

Modifiermapping_by_replacing(code)
Num. of arguments2–4
RepeatableYes
See also
mapping_by_mixing,converting_values_to_lowercase,converting_values_to_uppercase,mapping_by_calling,mapping_by_invoking,mapping_by_magic,converting_names_to_lowercase,converting_names_to_uppercase,renaming_by_calling,renaming_by_invoking,renaming_by_magic,renaming_by_replacing,renaming_by_mixing,grouping_by_calling,#mixing_names_and_values
Brief
Map all parameter values performingstring substitutions
Syntax
{{#invoke:params|mapping_by_replacing|target|replace|[count]|[plain flag]|pipe function name}}

This modifier (temporarily) changes the content of the parameters the current template is being called with, replacing each of them with the result of a string substitution. Its syntax is very simlar to {{#invoke:string|replace}}.

Internally the modifier uses Lua'sstring.gsub() function to perform substitutions; therefore, unless aplain flag is set, please use the same syntax ofLua patterns. Theplain flag can be eitherplain orstrict or omitted. When omitted it is assumed that the target string is a Lua pattern. The difference betweenplain andstrict is that the latter also requires that the lengths match (this happens only when the two strings are 100% identical). Instrict mode thereplace argument will not accept directives (e.g.%0,%1, etc.). In order to facilitate wikitext scripting in theplain flag argument, thepattern keyword is available too, equivalent to omitting the argument.

Thecount argument prescribes how many substitutions will be performed at most. If blank or omitted, all matches found will be substituted.

This modifier usesstring.gsub() for performance reasons; if you need to usemw.ustring.gsub() instead, you will need to invoke thereplace function fromModule:String via...|mapping_by_invoking|string|replace|....

The following table shows examples of equivalent instructions. Please be aware that invokingmw.ustring.gsub() can be much slower.

string.gsub()mw.ustring.gsub() (viaModule:String)
...|mapping_by_replacing|target|replace|......|mapping_by_invoking|string|replace|4|target|replace||false|...
...|mapping_by_replacing|target|replace|count|......|mapping_by_invoking|string|replace|4|target|replace|count|false|...
...|mapping_by_replacing|target|replace|plain|......|mapping_by_invoking|string|replace|2|target|replace|...
or, equivalently,
...|mapping_by_invoking|string|replace|4|target|replace||true|...
...|mapping_by_replacing|target|replace|count|plain|......|mapping_by_invoking|string|replace|3|target|replace|count|...
or, equivalently,
...|mapping_by_invoking|string|replace|4|target|replace|count|true|...

There is not a corresponding translation for thestrict flag inModule:String. However, as it goes with theplain flag, in that case you won't needmw.ustring.gsub() in the first place.

For example,

...|mapping_by_renaming|foo|bar|1|...

will be equivalent to writing

...|mapping_by_invoking|string|replace|4|foo|bar|1|false|...

The first syntax, however, will be less computationally expensive.

At {{./doc/examples/informal tablebox}} you can find an example on how to exploit this function to create “informal”infoboxes.

information Note: Thetarget andreplace arguments passed to this modifier will not be trimmed of their leading and trailing spaces. Theor,plain,strict andpattern keywords, thecount argument, and themapping_by_replacing modifier name itself, however, will be trimmed of their surrounding spaces.

mapping_by_mixing

Modifiermapping_by_mixing(code)
Num. of arguments1
RepeatableYes
See also
converting_values_to_lowercase,converting_values_to_uppercase,mapping_by_calling,mapping_by_invoking,mapping_by_magic,converting_names_to_lowercase,converting_names_to_uppercase,renaming_by_calling,renaming_by_invoking,renaming_by_magic,renaming_by_replacing,renaming_by_mixing,grouping_by_calling,mixing_names_and_values
Brief
Map all parameter values replacing their current values with the expansion of a custom string containing the$# and$@ placeholders
Syntax
{{#invoke:params|mapping_by_mixing|mixing string|pipe function name}}

This modifier (temporarily) changes the content of the parameters the current template is being called with, replacing each of them with the expansion of a custom string that expects the same syntax as thefor_each function.

For instance, the following code will wrap all parameter values in quotes

...|mapping_by_mixing|“$@”|...

whereas the following code will replace all values with the string[NAME::VALUE], whereNAME andVALUE are each parameter's name and value:

...|mapping_by_mixing|[$#::$@]|...

information Note: Both themixing string argument and themapping_by_mixing modifier name itself will be trimmed of their surrounding spaces.

converting_names_to_lowercase

Modifierconverting_names_to_lowercase(code)
Num. of arguments0
RepeatableYes
See also
converting_values_to_lowercase,converting_values_to_uppercase,converting_names_to_uppercase,mapping_by_replacing,renaming_by_replacing
Brief
Convert all parameter names to lower case
Syntax
{{#invoke:params|converting_names_to_lowercase|pipe function name}}

This modifier does not take arguments besides the name of the function that will follow.

This modifier converts all parameter names to lowercase. It is identical to writing...|renaming_by_magic|lc|..., but without the burden of calling a parser function.

information Note: In case of collisions between identical names, only one parameter, randomly chosen, will be left for a given name.

converting_names_to_uppercase

Modifierconverting_names_to_uppercase(code)
Num. of arguments0
RepeatableYes
See also
converting_values_to_lowercase,converting_values_to_uppercase,converting_names_to_lowercase,mapping_by_replacing,renaming_by_replacing
Brief
Convert all parameter names to upper case
Syntax
{{#invoke:params|trimming_values|pipe function name}}

This modifier does not take arguments besides the name of the function that will follow.

This modifier converts all parameter names to uppercase. It is identical to writing...|renaming_by_magic|uc|..., but without the burden of calling a parser function.

information Note: In case of collisions between identical names, only one parameter, randomly chosen, will be left for a given name.

renaming_by_calling

Modifierrenaming_by_calling(code)
Num. of argumentsAd libitum
RepeatableYes
See also
converting_values_to_lowercase,converting_values_to_uppercase,mapping_by_calling,mapping_by_invoking,mapping_by_magic,mapping_by_replacing,converting_names_to_lowercase,converting_names_to_uppercase,renaming_by_invoking,renaming_by_magic,renaming_by_replacing,grouping_by_calling
Brief
Rename all parameters, replacing their former names with the expansion of a given template repeatedly called with at least one parameter (the parameter's former name)
Syntax
{{#invoke:params|renaming_by_calling|template name|[call style]|[let]|[...]|[number of additional parameters]|[parameter 1]|[parameter 2]|[...]|[parameter N]|pipe function name}}

This modifier works similarly tomapping_by_calling, but instead of replacing parameters' valuesit renames the parameters themselves. Care must be used knowing that if a new name collides with another new name one of the two parameters will be removed without knowing which one. New names and old names do not create collisions. If a name is returned identical it will be considered as “unchanged” and in case of conflicts the renamed one will prevail. Possible leading and trailing spaces in the new names are always stripped. Here, if omitted, thecall style flags argument defaults tonames_only.

For instance, the following example uses{{2x}} to rename all incoming parameters by doubling their names:

{{#invoke:params|setting|h/i/p/f|[|][|:|]|renaming_by_calling|2x|list}}

Same, but adding a hyphen in between:

{{#invoke:params|setting|h/i/p/f|[|][|:|]|renaming_by_calling|2x|1|-|list}}

The following example calls the{{P1}} template to rename all parameters using their value as their new name:

{{#invoke:params|renaming_by_calling|P1|values_only|for_each|[$#: $@]}}

This modifier can be particularly useful for sanitizing parameter names (e.g. collapsing several spaces into single spaces, changing theletter case, and so on).

information Note: All arguments passed to this modifier except therenaming_by_calling modifier name itself, thetemplate name, thecall style flag, thelet keyword, the passed parameter names, and the number of additional arguments will not be trimmed of their leading and trailing spaces.

renaming_by_invoking

Modifierrenaming_by_invoking(code)
Num. of argumentsAd libitum
RepeatableYes
See also
converting_values_to_lowercase,converting_values_to_uppercase,mapping_by_calling,mapping_by_invoking,mapping_by_magic,mapping_by_replacing,converting_names_to_lowercase,converting_names_to_uppercase,renaming_by_calling,renaming_by_magic,renaming_by_replacing,grouping_by_calling
Brief
Rename all parameters, replacing their former names with the text returned by a given module function repeatedly called with at least one argument (the parameter's former name)
Syntax
{{#invoke:params|renaming_by_invoking|module name|function name|[call style]|[let]|[...]|[number of additional arguments]|[argument 1]|[argument 2]|[...]|[argument N]|pipe function name}}

This modifier works similarly tomapping_by_invoking, but instead of replacing parameters' valuesit renames the parameters themselves. Care must be used knowing that if a new name collides with another new name one of the two parameters will be removed without knowing which one. New names and old names do not create collisions. If a name is returned identical it will be considered as “unchanged” and in case of conflicts the renamed one will prevail. Possible leading and trailing spaces in the new names are always stripped. Here, if omitted, thecall style flags argument defaults tonames_only.

For instance, the following example uses {{#invoke:string|replace}} to rename all parameters of type|arg1=,|arg2=, …|argN= into|1=,|2=|N=, thus creating a novel sequence:

{{#invoke:params|sequential|setting|h/i/p/f|[|][|:|]|with_name_matching|^arg%d+$|renaming_by_invoking|string|replace|4|^arg(%d+)$|%1|1|false|list}}

This modifier can be particularly useful for sanitizing parameter names (e.g. collapsing several spaces into single spaces, changing theletter case, and so on).

information Note: All arguments passed to this modifier except therenaming_by_invoking modifier name itself, themodule name, thefunction name, thecall style flag, thelet keyword, the passed parameter names, and the number of additional arguments will not be trimmed of their leading and trailing spaces.

renaming_by_magic

Modifierrenaming_by_magic(code)
Num. of argumentsAd libitum
RepeatableYes
See also
converting_values_to_lowercase,converting_values_to_uppercase,mapping_by_calling,mapping_by_invoking,mapping_by_magic,mapping_by_replacing,converting_names_to_lowercase,converting_names_to_uppercase,renaming_by_calling,renaming_by_invoking,renaming_by_replacing,grouping_by_calling
Brief
Rename all parameters, replacing their former names with the text returned by a given parser function repeatedly called with at least one argument (the parameter's former name)
Syntax
{{#invoke:params|renaming_by_magic|parser function|[call style]|[let]|[...]|[number of additional arguments]|[argument 1]|[argument 2]|[...]|[argument N]|pipe function name}}

This modifier works similarly tomapping_by_magic, but instead of replacing parameters' valuesit renames the parameters themselves. Care must be used knowing that if a new name collides with another new name one of the two parameters will be removed without knowing which one. New names and old names do not create collisions. If a name is returned identical it will be considered as “unchanged” and in case of conflicts the renamed one will prevail. Possible leading and trailing spaces in the new names are always stripped. Here, if omitted, thecall style flags argument defaults tonames_only.

For instance, the following example uses {{#expr}} to transform all numeric parameters into even numbers (you can replace the expression%0 * 2 with any other expression):

{{#invoke:params|all_sorted|excluding_non-numeric_names|renaming_by_replacing|^.*$|%0 * 2|1|renaming_by_magic|#expr|setting|h/i/p/f|[|][|:|]|list}}

information Note: All arguments passed to this modifier except therenaming_by_magic modifier name itself, theparser function name, thecall style flag, thelet keyword, the passed parameter names, and the number of additional arguments will not be trimmed of their leading and trailing spaces.

renaming_by_replacing

Modifierrenaming_by_replacing(code)
Num. of arguments2–4
RepeatableYes
See also
mapping_by_mixing,converting_values_to_lowercase,converting_values_to_uppercase,mapping_by_calling,mapping_by_invoking,mapping_by_magic,mapping_by_replacing,converting_names_to_lowercase,converting_names_to_uppercase,renaming_by_calling,renaming_by_invoking,renaming_by_magic,renaming_by_mixing,grouping_by_calling,#mixing_names_and_values
Brief
Rename all parameters, replacing their former names with the text returned by astring substitutions
Syntax
{{#invoke:params|renaming_by_replacing|target|replace|[count]|[plain flag]|pipe function name}}

This modifier works similarly tomapping_by_replacing, but instead of replacing parameters' valuesit renames the parameters themselves. Care must be used knowing that if a new name collides with another new name one of the two parameters will be removed without knowing which one. New names and old names do not create collisions. If a name is returned identical it will be considered as “unchanged” and in case of conflicts the renamed one will prevail. Possible leading and trailing spaces in the new names are always stripped (however they are not stripped while searching for the name to replace).

Since there can be only one parameter name that matches exactly a literal string, when used with thestrict flag this modifier directly accesses the requested key without looping through the entire list of parameters (so it will be much faster).

For instance, the following example renames all parameters of type|arg1=,|arg2=, …|argN= into|1=,|2=|N=, thus creating a novel sequence:

{{#invoke:params|sequential|setting|h/i/p/f|[|][|:|]|with_name_matching|^arg%d+$|renaming_by_replacing|^arg(%d+)$|%1|1|list}}

This modifier can be particularly useful for sanitizing parameter names (e.g. collapsing several spaces into single spaces, changing theletter case, and so on).

For performance reasons this modifier usesstring.gsub(); if you need to usemw.ustring.gsub() instead, you will need to invoke thereplace function fromModule:String via...|renaming_by_invoking|string|replace|....

The following table shows examples of equivalent instructions. Please be aware that invokingmw.ustring.gsub() can be much slower.

string.gsub()mw.ustring.gsub() (viaModule:String)
...|renaming_by_replacing|target|replace|......|renaming_by_invoking|string|replace|4|target|replace||false|...
...|renaming_by_replacing|target|replace|count|......|renaming_by_invoking|string|replace|4|target|replace|count|false|...
...|renaming_by_replacing|target|replace|plain|......|renaming_by_invoking|string|replace|2|target|replace|...
or, equivalently,
...|renaming_by_invoking|string|replace|4|target|replace||true|...
...|renaming_by_replacing|target|replace|count|plain|......|renaming_by_invoking|string|replace|3|target|replace|count|...
or, equivalently,
...|renaming_by_invoking|string|replace|4|target|replace|count|true|...

There is not a corresponding translation for thestrict flag inModule:String. However, as it goes with theplain flag, in that case you won't needmw.ustring.gsub() in the first place.

information Note: Thetarget andreplace arguments passed to this modifier will not be trimmed of their leading and trailing spaces. Theor,plain,strict andpattern keywords, thecount argument, and themapping_by_replacing modifier name itself, however, will be trimmed of their surrounding spaces.

renaming_by_mixing

Modifierrenaming_by_mixing(code)
Num. of arguments1
RepeatableYes
See also
mapping_by_mixing,converting_values_to_lowercase,converting_values_to_uppercase,mapping_by_calling,mapping_by_invoking,mapping_by_magic,converting_names_to_lowercase,converting_names_to_uppercase,renaming_by_calling,renaming_by_invoking,renaming_by_magic,renaming_by_replacing,grouping_by_calling,mixing_names_and_values
Brief
Rename all parameters, replacing their former names with the expansion of a custom string containing the$# and$@ placeholders
Syntax
{{#invoke:params|renaming_by_mixing|mixing string|pipe function name}}

This modifier (temporarily) changes the content of the parameters the current template is being called with, replacing each of them with the expansion of a custom string that expects the same syntax as thefor_each function.

For instance, the following code will wrap all parameter names in quotes

...|renaming_by_mixing|“$#”|...

whereas the following code will replace all parameter names with the string[NAME::VALUE], whereNAME andVALUE are each parameter's name and value:

...|renaming_by_mixing|[$#::$@]|...

information Note: Themixing string argument passed to this modifier will not be trimmed of its leading and trailing spaces. Therenaming_by_mixing modifier name itself, however, will be trimmed of their surrounding spaces.

grouping_by_calling

Modifiergrouping_by_calling(code)
Num. of argumentsAd libitum
RepeatableYes[2]
See also
converting_values_to_lowercase,converting_values_to_uppercase,call_for_each_group,mapping_by_calling,mapping_by_invoking,mapping_by_magic,mapping_by_replacing,converting_names_to_lowercase,converting_names_to_uppercase,renaming_by_calling,renaming_by_invoking,renaming_by_magic,renaming_by_replacing
Brief
Group the parameters that have the same numeric suffix into novel parameters, whose names will be numbers and whose values will be decided by a custom template
Syntax
{{#invoke:params|grouping_by_calling|template name|[let]|[...]|[number of additional arguments]|[argument 1]|[argument 2]|[...]|[argument N]|pipe function name}}

This is the piping version ofcall_for_each_group. This means that after calling this modifier the old parameters will be (temporarily) gone and the only parameters left will be novel parameters whose names will be numbers (or an empty string if parameters without a numeric suffix were present) and whose content will be decided by a custom template.

Like other modifiers in themapping_* andrenaming_* family, it is possible to impose own parameters on the callback template by using the syntax...|[let]|[...]|[number of additional arguments]|[argument 1]|[argument 2]|[...]|[argument N]|.... Unlike the othermapping_* andrenaming_* modifiers, however (but likecall_for_each_group), sequential parameters here will not be prepended, but willreplace possible parsed parameters.

And so, writing

{{#invoke:params|...|grouping_by_calling|MY TEMPLATE|let|foo|bar|let|hello|world|3|one|two|three|list_values}}

is identical to writing

{{#invoke:params|...|call_for_each_group|MY TEMPLATE|foo=bar|hello=world|one|two|three}}

In the example above the main difference will be that the first solution will allow to pass the newly grouped parameters at once to another template or module (viaconcat_and_call orconcat_and_invoke) or, if needed, perform further fine-tuning operations concerning the new parameters.

Please refer to the documentation ofcall_for_each_group for further information on the parameters passed to the callback template.

information Note: All arguments passed to this modifier except thegrouping_by_calling modifier name itself, thetemplate name, thelet keyword, the passed parameter names, and the number of additional parameters will not be trimmed of their leading and trailing spaces.

parsing

Modifierparsing(code)
Num. of arguments1–6
RepeatableYes
Often accompanied bynew
See also
new,{{#invoke:ArrayList}},{{Array}}
Brief
Create new parameters by parsing a parameter string
Syntax
{{#invoke:params|parsing|string to parse|[trim flag]|[iteration delimiter setter]|[...]|[key-value delimiter setter]|[...]|pipe function name}}

This modifier allows to add an infinity of new parameters by using a parameter string. By default this expects| as separator between parameters and= as separator between keys and values, but it is possible to specify other strings or patterns. The parsed parameters will overwrite existing parameters of the same name. For this reason, thenew directive often accompanies this modifier.

Examples:

  • {{#invoke:params|new|parsing|one{{!}}two{{!}}three{{!}}foo{{=}}bar{{!}}hello{{=}}world|for_each|[$#:$@]}}
    ↳ [1:one][2:two][3:three][hello:world][foo:bar]
  • {{#invoke:params|new|parsing|one, two; three. foo: bar, hello: world|trim_all|splitter_pattern|[,;.]|setter_string|:|for_each|[$#:$@]}}
    ↳ [1:one][2:two][3:three][hello:world][foo:bar]
  • {{#invoke:params|new|parsing|one/two/ three / foo % bar /hello%world|setter_string|%|trim_none|splitter_string|/|for_each|[$#:$@]}}
    ↳ [1:one][2:two][3: three ][hello:world][foo: bar ]

Thetrim flag argument can be placed in any position after thestring to parse (not necessarily in second position) and can have one of the following values:trim_none,trim_named,trim_positional,trim_all. If omitted, it defaults totrim_named.

Theiteration delimiter setter can be placed in any position after thestring to parse (not necessarily in third position), must beimmediately followed by a user-given string, and can be eithersplitter_string orsplitter_pattern. If omitted, the two arguments default tosplitter_string|{{!}}. If the custom string is empty (but not if it is blank but not empty) the string to parse will be assumed not to have any iteration delimiters (this will result in one single parameter being parsed).

Thekey-value delimiter setter can be placed in any position after thestring to parse (not necessarily in fifth position), must beimmediately followed by a user-given string, and can be eithersetter_string orsetter_pattern. If omitted, the two arguments default tosetter_string|{{=}}. If the custom string is empty (but not if it is blank but not empty) the string to parse will be assumed not to have any key-value delimiters (this will result in a sequence-only list of parameters being parsed).

Possible options
Setting a trim flagSetting an iteration delimiterSetting a key-value delimiter
trim_none
trim_named
trim_positional
trim_all
splitter_string|...
splitter_pattern|...
setter_string|...
setter_pattern|...

information Note: All arguments passed to this modifier except theparsing modifier name itself, thetrim flag,iteration delimiter setter andkey-value delimiter setter arguments will not be trimmed of their leading and trailing spaces.

reinterpreting

Modifierreinterpreting(code)
Num. of arguments1–6
RepeatableYes
See also
parsing,{{#invoke:ArrayList}},{{Array}}
Brief
Use the content of a parameter as a parameter string to parse, after removing the parameter itself
Syntax
{{#invoke:params|reinterpreting|parameter name|[trim flag]|[iteration delimiter setter]|[...]|[key-value delimiter setter]|[...]|pipe function name}}

This modifier works exactly likeparsing, but takes the content of a disposable parameter as input. See there for further information. The parameter passed to this modifier will be immediately deleted. The parsed parameters will overwrite existing parameters of the same name.

Example:

{{#invoke:params|new|pulling|1|reinterpreting|1|splitter_string|,|trim_all|concat_and_call|See also}}

An example that shows how to use this function to transclude a custom template with custom parameters is available at {{./doc/examples/constructed transclusion}}.

information Note: All arguments passed to this modifier except thereinterpreting modifier name itself, theparameter name, thetrim flag,iteration delimiter setter andkey-value delimiter setter arguments will not be trimmed of their leading and trailing spaces.

mixing_names_and_values

Modifiermixing_names_and_values(code)
Num. of arguments2
RepeatableYes
See also
mapping_by_mixing,converting_values_to_lowercase,converting_values_to_uppercase,mapping_by_calling,mapping_by_invoking,mapping_by_magic,converting_names_to_lowercase,converting_names_to_uppercase,renaming_by_calling,renaming_by_invoking,renaming_by_magic,renaming_by_replacing,renaming_by_mixing,grouping_by_calling
Brief
Rewrite all parameters, replacing names and values with the expansion of two custom strings containing the$# and$@ placeholders
Syntax
{{#invoke:params|mixing_names_and_values|name mixing string|value mixing string|pipe function name}}

This modifier (temporarily) changes names and values of the parameters the current template is being called with, replacing each of them with the expansion of two custom strings that expect the same syntax as thefor_each function.

For instance, the following code will wrap all parameter names and values in quotes

...|mixing_names_and_values|“$#”|“$@”|...

whereas the following code will replace all names with the stringVALUE/NAME and all values with the string[NAME::VALUE], whereNAME andVALUE are each parameter's name and value:

...|mixing_names_and_values|$@/$#|[$#::$@]|...

information Note: Thevalue mixing string argument passed to this modifier will not be trimmed of its leading and trailing spaces. Thename mixing string argument andmixing_names_and_values modifier name itself, however, will be trimmed of their surrounding spaces.

combining_by_calling

Modifiercombining_by_calling(code)
Num. of arguments2
RepeatableYes
See also
entering_substack,snapshotting,remembering,concat_and_call
Brief
Pass all current parameters to a custom template and save the returned output as a new parameter
Syntax
{{#invoke:params|combining_by_calling|template name|new parameter name|pipe function name}}

This is the piping version ofconcat_and_call. This means that after calling this modifier the old parameters will be (temporarily) gone and the only parameter left will be what is specified in thenew parameter name argument.

Since after using this modifier all parameters will be grouped into one single parameter, to pass additional parameters to the callback template you can safely useimposing orparsing.

For instance, using./testcases/tdummy echo sb as callback template, a template named{{example template}} with the following content,

{{#invoke:params|combining_by_calling|module:params/testcases/tdummy echo sb|my_new_param|for_each|[$#:$@]}}

when transcluded as{{example template|one|two|three|hello=world|foo=bar}} will produce

[my_new_param:[1=one][2=two][3=three][hello=world][foo=bar]]

snapshotting

Modifiersnapshotting(code)
Num. of arguments0
RepeatableYes
Eventually followed byEitherentering_substack orflushing
See also
remembering,entering_substack,pulling,merging_substack,detaching_substack,leaving_substack,flushing
Brief
Push a copy of the current parameter list to the queue of parameter lists
Syntax
{{#invoke:params|snapshotting|pipe function name}}

This modifier does not take arguments besides the name of the function that will follow.

This module has a stacking mechanism that allows to isolate groups of parameters, work separately on them, and then merge them back to the original stack. The modifiers dedicated to this mechanism are:

Every time thesnapshotting modifier is used, the current list of parameters (together with their values) will be copied and added to a queue. When theentering_substack modifier is used, the list of parameters on top of the queue will temporarily become the current parameters, and all other modifiers will affect only this substack. After completing the job, themerging_substack will merge the current substack to the parent stack.

If no parameter lists have been snapshotted before callingentering_substack, the latter will automatically make a snapshot of the current parameters. Once inside a substack, it is possible to enter a subsubstack using the same machinery.

Thedetaching_substack modifier erases the current parameters from the parent stack, allowing the current stack to rename its parameters freely and merge them back to the parent stack, renamed.

It is possible to leave a substack without merging it to the parent by using theleaving_substack modifier. In this case, at some point it will be necessary to callflushing in order to merge the stack previously left unmerged. Alternatively, it will be possible to enter it again by callingentering_substack, and finally merge it viamerging_substack.

An example will probably clarify the mechanism better than anything else:

{{#invoke:params|new|<!-- Ignore the incoming parameters and manually assign some parameters (we will simulate the following incoming parameters: |one|two|three|four|foo=bar|hello=world ...) -->imposing|1|one|imposing|2|two|imposing|3|three|imposing|4|four|imposing|foo|bar|imposing|hello|world|entering_substack|<!-- Enter into a substack (the `snapshotting` modifier will be automatically invoked for us) -->excluding_numeric_names|<!-- Exclude numeric parameters -->detaching_substack|<!-- Remove the current parameters from the parent stack -->renaming_by_replacing|^.*$|This was called “%0”|1|<!-- Rename all parameters -->merging_substack|entering_substack|new|<!-- Enter into a new empty substack -->pulling|1|<!-- Pull the parameter named “1” from the parent stack -->mapping_by_replacing|^.*$|This value once was “%0”|1|<!-- Replace the content of all parameters -->merging_substack|for_each|[$#:$@]}}

The code above will result in:

[1:This value once was “one”][2:two][3:three][4:four][This was called “foo”:bar][This was called “hello”:world]

remembering

Modifierremembering(code)
Num. of arguments0
RepeatableYes
Eventually followed byEitherentering_substack orflushing
See also
snapshotting,entering_substack,pulling,merging_substack,detaching_substack,leaving_substack,flushing
Brief
Push a copy of the original (unmodified) parameter list to the queue of snapshots
Syntax
{{#invoke:params|remembering|pipe function name}}

This modifier does not take arguments besides the name of the function that will follow.

This modifier is somewhat similar tosnapshotting, except that it retrieves the parameters that were originally passed to the calling template before being affected by the module's modifiers. The modifier works also after thenew directive. Seesnapshotting for more information on the stacking mechanism.

entering_substack

Modifierentering_substack(code)
Num. of arguments0
RepeatableYes
May be immediately followed bynew
Eventually followed byEithermerging_substack orleaving_substack followed byflushing
See also
snapshotting,remembering,pulling,merging_substack,detaching_substack,leaving_substack,flushing
Brief
Enter the first stack in the queue of parameter lists, or copy the current parameters into a substack if the queue is empty
Syntax
{{#invoke:params|entering_substack|[new]|pipe function name}}

This modifier does not take arguments besides the name of the function that will follow.

Seesnapshotting for more information on the stacking mechanism. Once in a substack, it is possible to go back to the parent stack using two different modifiers:merging_substack andleaving_substack.

pulling

Modifierpulling(code)
Num. of arguments1
RepeatableYes
Often preceeded bynew
See also
snapshotting,remembering,merging_substack,detaching_substack,leaving_substack,flushing
Brief
Pull a single parameter from the parent stack or from the stack of the original parameters
Syntax
{{#invoke:params|pulling|parameter name|pipe function name}}

Seesnapshotting for more information on the stacking mechanism. If this modifer is not used in a substack, the parameter will be pulled from the original (unmodified) parameter list.

detaching_substack

Modifierdetaching_substack(code)
Num. of arguments0
RepeatableYes
RestrictionsUsable only inside substacks
See also
snapshotting,remembering,entering_substack,pulling,merging_substack,leaving_substack,flushing
Brief
Remove from the parent stack the parameters that are present in the current stack
Syntax
{{#invoke:params|detaching_substack|pipe function name}}

This modifier does not take arguments besides the name of the function that will follow.

This modifer can only be used in a substack. Seesnapshotting for more information on the stacking mechanism.

leaving_substack

Modifierleaving_substack(code)
Num. of arguments0
RepeatableYes
RestrictionsUsable only inside substacks
See also
snapshotting,remembering,entering_substack,pulling,merging_substack,detaching_substack,flushing
Brief
Leave the current substack without merging it, and return to the parent stack
Syntax
{{#invoke:params|leaving_substack|pipe function name}}

This modifier does not take arguments besides the name of the function that will follow.

This modifer can only be used in a substack. Seesnapshotting for more information on the stacking mechanism.

Seeflushing for an example of how to use this modifier.

merging_substack

Modifiermerging_substack(code)
Num. of arguments0
RepeatableYes
RestrictionsUsable only inside substacks
See also
snapshotting,remembering,entering_substack,pulling,detaching_substack,leaving_substack,flushing
Brief
Leave the current stack after merging it with the parent stack, then return to the latter
Syntax
{{#invoke:params|merging_substack|pipe function name}}

This modifier does not take arguments besides the name of the function that will follow.

This modifer can only be used in a substack. Seesnapshotting for more information on the stacking mechanism.

flushing

Modifierflushing(code)
Num. of arguments0
RepeatableYes
See also
snapshotting,remembering,entering_substack,pulling,merging_substack,detaching_substack,leaving_substack
Brief
Merge the first stack in the queue of snapshotted parameters with the current stack.
Syntax
{{#invoke:params|flushing|pipe function name}}

This modifier does not take arguments besides the name of the function that will follow.

This modifier is used in conjunction with eitherleaving_substack orsnapshotting. Seesnapshotting for more information on the stacking mechanism.

In the following wrapper of an{{example template}}, the three parameters|1=,|2=, and|3= are used as aliases for|title=,|author=, and|language= respectively. Theflushing modifier ensures that in case both are present, the named alias will have the precedence over the positional alias.

{{#invoke:params|entering_substack|discarding|1|discarding|2|discarding|3|leaving_substack|renaming_by_replacing|1|title|strict|renaming_by_replacing|2|author|strict|renaming_by_replacing|3|language|strict|flushing|concat_and_call|example template}}

new

Modifiernew(code)
Num. of arguments0
RepeatableNo
RestrictionsFirst position only
See also
parsing,imposing,providing,discarding
Brief
Get rid of all the incoming parameters and create a new (empty) parameter stack
Syntax
{{#invoke:params|new|pipe function name}}

This modifier does not take arguments besides the name of the function that will follow.

This modifier can only appear in first position, or if substacks are present, immediately after theentering_substack directive. When in first position its main purpose is that of extending the facilities offered by this module (e.g.mapping_by_replacing,with_value_matching, etc.) to custom lists of strings, independently of the incoming parameters. When inside a stack, it signals that the snapshot of the current parameters must be ignored for that stack. The existence of thenew modifier also facilitates debugging the module.

The newly created parameter stack can be populated viaparsing,imposing orproviding. The incoming parameters can always be retrieved back using theremembering andpulling modifiers.

Examples:

  • {{#invoke:params|new|imposing|1|foo|imposing|2|bar|mapping_by_replacing|^.|!%1|list_values}}
    ↳ !foo!bar

Subpages

The complete list of subpages is availablehere.

Notes

  1. ^To be precise, the order will not be strictly alphabetical, because this would imply that a template called with the following parameters{{foobar|-4=you|9=wanna|.=me?|11=marry|-8=do}} would see them reordered as follows:{{foobar|-8=do|-4=you|.=me?|9=wanna|11=marry}} (with the dot in the middle between negative and positive numbers). To avoid this,numbers are always displayed first (i.e.{{foobar|-8=do|-4=you|9=wanna|11=marry|.=me?}}).
  2. ^Unless followed byrenaming_by_replacing in few bizarre situations, there is virtually no use in calling this modifier more than once.

See also

The abovedocumentation istranscluded fromModule:Params/doc.(edit |history)
Editors can experiment in this module'ssandbox(edit |diff) andtestcases(edit) pages.
Subpages of this module.

---                                        ------     LOCAL ENVIRONMENT                  ------    ________________________________    ------                                        -----[[ Abstract utilities ]]-------------------------------- Helper function for `string.gsub()` (for managing zero-padded numbers)localfunctionzero_padded(str)return('%03d%s'):format(#str,str)end-- Helper function for `table.sort()` (for natural sorting)localfunctionnatural_sort(var1,var2)returntostring(var1):gsub('%d+',zero_padded)<tostring(var2):gsub('%d+',zero_padded)end-- Return a copy or a reference to a tablelocalfunctioncopy_or_ref_table(src,refonly)ifrefonlythenreturnsrcendnewtab={}forkey,valinpairs(src)donewtab[key]=valendreturnnewtabend-- Remove some numeric elements from a table, shifting everything to the leftlocalfunctionremove_numeric_keys(tbl,idx,len)localcache={}localtmp=idx+len-1forkey,valinpairs(tbl)doiftype(key)=='number'andkey>=idxthenifkey>tmpthencache[key-len]=valendtbl[key]=nilendendforkey,valinpairs(cache)dotbl[key]=valendend-- Make a reduced copy of a table (shifting in both directions if necessary)localfunctioncopy_table_reduced(tbl,idx,len)localret={}localtmp=idx+len-1ifidx>0thenforkey,valinpairs(tbl)doiftype(key)~='number'orkey<idxthenret[key]=valelseifkey>tmpthenret[key-len]=valendendelseiftmp>0thenlocalnshift=1-idxforkey,valinpairs(tbl)doiftype(key)~='number'thenret[key]=valelseifkey>tmpthenret[key-tmp]=valelseifkey<idxthenret[key+nshift]=valendendelseforkey,valinpairs(tbl)doiftype(key)~='number'orkey>tmpthenret[key]=valelseifkey<idxthenret[key+len]=valendendendreturnretend-- Make an expanded copy of a table (shifting in both directions if necessary)--[[local function copy_table_expanded (tbl, idx, len)local ret = {}local tmp = idx + len - 1if idx > 0 thenfor key, val in pairs(tbl) doif type(key) ~= 'number' or key < idx thenret[key] = valelse ret[key + len] = val endendelseif tmp > 0 thenlocal nshift = idx - 1for key, val in pairs(tbl) doif type(key) ~= 'number' then ret[key] = valelseif key > 0 then ret[key + tmp] = valelseif key < 1 then ret[key + nshift] = val endendelsefor key, val in pairs(tbl) doif type(key) ~= 'number' or key > tmp thenret[key] = valelse ret[key - len] = val endendendreturn retend]]---- Move a key from a table to another, but only if under a different name and-- always parsing numeric strings as numberslocalfunctionsteal_if_renamed(val,src,skey,dest,dkey)localrealkey=tonumber(dkey)ordkey:match'^%s*(.-)%s*$'ifskey~=realkeythendest[realkey]=valsrc[skey]=nilendend--[[ Public strings ]]---------------------------- Special match keywords (functions and modifiers MUST avoid these names)localmkeywords={['or']=0,pattern=1,plain=2,strict=3}-- Sort functions (functions and modifiers MUST avoid these names)localsortfunctions={--alphabetically = false, -- Simply uncommenting enables the optionnaturally=natural_sort}-- Callback styles for the `mapping_*` and `renaming_*` class of modifiers-- (functions and modifiers MUST avoid these names)--[[Meanings of the columns:  col[1] = Loop type (0-3)  col[2] = Number of module arguments that the style requires (1-3)  col[3] = Minimum number of sequential parameters passed to the callback  col[4] = Name of the callback parameter where to place each parameter name  col[5] = Name of the callback parameter where to place each parameter value  col[6] = Argument in the modifier's invocation that will override `col[4]`  col[7] = Argument in the modifier's invocation that will override `col[5]`A value of `-1` indicates that no meaningful value is stored (i.e. `nil`)]]--localmapping_styles={names_and_values={3,2,2,1,2,-1,-1},values_and_names={3,2,2,2,1,-1,-1},values_only={1,2,1,-1,1,-1,-1},names_only={2,2,1,1,-1,-1,-1},names_and_values_as={3,4,0,-1,-1,2,3},names_only_as={2,3,0,-1,-1,2,-1},values_only_as={1,3,0,-1,-1,-1,2},blindly={0,2,0,-1,-1,-1,-1}}-- Memory slots (functions and modifiers MUST avoid these names)localmemoryslots={i='itersep',l='lastsep',p='pairsep',h='header',f='footer',n='ifngiven'}-- Possible trimming modes for the `parsing` modifierlocaltrim_parse_opts={trim_none={false,false},trim_positional={false,true},trim_named={true,false},trim_all={true,true}}-- Possible string modes for the iteration separator in the `parsing` and-- `reinterpreting` modifierslocalisep_parse_opts={splitter_pattern=false,splitter_string=true}-- Possible string modes for the key-value separator in the `parsing` and-- `reinterpreting` modifierslocalpsep_parse_opts={setter_pattern=false,setter_string=true}-- Functions and modifiers MUST avoid these names too: `let`--[[ Module's private environment ]]------------------------------------------ Hard-coded name of the module (to avoid going through `frame:getTitle()`)localmodulename='Module:Params'-- The functions listed here declare that they don't need the `frame.args`-- metatable to be copied into a regular table; if they are modifiers they also-- guarantee that they will make their own (modified) copy availablelocalrefpipe={call_for_each_group=true,coins=true,count=true,for_each=true,list=true,list_values=true,value_of=true}-- The functions listed here declare that they don't need the-- `frame:getParent().args` metatable to be copied into a regular table; if-- they are modifiers they also guarantee that they will make their own-- (modified) copy availablelocalrefparams={call_for_each_group=true,combining_by_calling=true,concat_and_call=true,concat_and_invoke=true,concat_and_magic=true,converting_names_to_uppercase=true,converting_names_to_lowercase=true,count=true,--inserting = true,grouping_by_calling=true,mixing_names_and_values=true,renaming_by_mixing=true,--renaming_to_values = true,--swapping_names_and_values = true,value_of=true,with_name_matching=true}-- Maximum number of numeric parameters that can be filled, if missing (we-- chose an arbitrary number for this constant; you can discuss about its-- optimal value at Module talk:Params)localmaxfill=1024-- The private table of functionslocallibrary={}-- Functions and modifiers that can only be invoked in first positionlocalstatic_iface={}-- Create a new contextlocalfunctioncontext_new(frame)localctx={}ctx.frame=framectx.oparams=frame.argsctx.firstposonly=static_ifacectx.iterfunc=pairsctx.sorttype=0ctx.n_parents=0ctx.n_children=0ctx.n_available=maxfillreturnctxend-- Move to the next action within the user-given listlocalfunctioncontext_iterate(ctx,n_forward)localnextfnifctx.pipe[n_forward]~=nilthennextfn=ctx.pipe[n_forward]:match'^%s*(.*%S)'endifnextfn==nilthenerror(modulename..': You must specify a function to call',0)endiflibrary[nextfn]==nilthenifctx.firstposonly[nextfn]==nilthenerror(modulename..': The function ‘'..nextfn..'’ does not exist',0)elseerror(modulename..': The ‘'..nextfn..'’ directive can only appear in first position',0)endendremove_numeric_keys(ctx.pipe,1,n_forward)returnlibrary[nextfn]end-- Main looplocalfunctionmain_loop(ctx,start_with)localfn=start_withrepeatfn=fn(ctx)untilnotfnifctx.n_parents>0thenerror(modulename..': One or more ‘merging_substack’ directives are missing',0)endifctx.n_children>0thenerror(modulename..', For some of the snapshots either the ‘flushing’ directive is missing or a group has not been properly closed with ‘merging_substack’',0)endend-- Add a new stack of parameters to `ctx.children`localfunctionpush_cloned_stack(ctx,tbl)localnewparams={}localcurrsnap=ctx.n_children+1ifctx.children==nilthenctx.children={newparams}elsectx.children[currsnap]=newparamsendforkey,valinpairs(tbl)donewparams[key]=valendctx.n_children=currsnapend-- Parse optional user arguments of type `...|[let]|[...][number of additional-- parameters]|[parameter 1]|[parameter 2]|[...]`localfunctionload_child_opts(src,start_from,append_after)localnameslocaltmplocaltbl={}localpin=start_fromifsrc[pin]~=nilandsrc[pin]:match'^%s*let%s*$'thennames={}repeattmp=src[pin+1]or''names[tonumber(tmp)ortmp:match'^%s*(.-)%s*$'or'']=src[pin+2]pin=pin+3untilsrc[pin]==nilornotsrc[pin]:match'^%s*let%s*$'endtmp=tonumber(src[pin])iftmp~=niltheniftmp<0thentmp=-1endlocalshf=append_after-pinforidx=pin+1,pin+tmpdotbl[idx+shf]=src[idx]endpin=pin+tmp+1endifnames~=nilthenforkey,valinpairs(names)dotbl[key]=valendendreturntbl,pinend-- Load the optional arguments of some of the `mapping_*` and `renaming_*`-- class of modifierslocalfunctionload_callback_opts(src,n_skip,default_style)localstylelocalshflocaltmp=src[n_skip+1]iftmp~=nilthenstyle=mapping_styles[tmp:match'^%s*(.-)%s*$']endifstyle==nilthenstyle=default_styleshf=n_skip-1elseshf=n_skipendlocaln_exist=style[3]localkarg=style[4]localvarg=style[5]tmp=style[6]iftmp>-1thentmp=src[tmp+shf]karg=tonumber(tmp)ifkarg==nilthenkarg=tmp:match'^%s*(.-)%s*$'elsen_exist=math.max(n_exist,karg)endendtmp=style[7]iftmp>-1thentmp=src[tmp+shf]varg=tonumber(tmp)ifvarg==nilthenvarg=tmp:match'^%s*(.-)%s*$'elsen_exist=math.max(n_exist,varg)endendlocaldest,nargs=load_child_opts(src,style[2]+shf,n_exist)tmp=style[1]if(tmp==3ortmp==2)anddest[karg]~=nilthentmp=tmp-2endif(tmp==3ortmp==1)anddest[varg]~=nilthentmp=tmp-1endreturndest,nargs,tmp,karg,vargend-- Parse the arguments of some of the `mapping_*` and `renaming_*` class of-- modifierslocalfunctionload_replace_args(opts,fname)ifopts[1]==nilthenerror(modulename..', ‘'..fname..'’: No pattern string was given',0)endifopts[2]==nilthenerror(modulename..', ‘'..fname..'’: No replacement string was given',0)endlocalptn=opts[1]localrepl=opts[2]localargc=3localnmax=tonumber(opts[3])ifnmax~=nilor(opts[3]or''):match'^%s*$'~=nilthenargc=4endlocalflg=opts[argc]ifflg~=nilthenflg=mkeywords[flg:match'^%s*(.-)%s*$']endifflg==0thenflg=nilelseifflg~=nilthenargc=argc+1endreturnptn,repl,nmax,flg==3,argc,(nmax~=nilandnmax<1)or(flg==3andptn==repl)end-- Parse the arguments of the `with_*_matching` class of modifierslocalfunctionload_pattern_args(opts,fname)localstate=0localcnt=1localkeywlocalnptns=0localptns={}for_,valinipairs(opts)doifstate==0thennptns=nptns+1ptns[nptns]={val,false,false}state=-1elsekeyw=val:match'^%s*(.*%S)'ifkeyw==nilormkeywords[keyw]==nilor(state>0andmkeywords[keyw]>0)thenbreakelsestate=mkeywords[keyw]ifstate>1thenptns[nptns][2]=trueendifstate==3thenptns[nptns][3]=trueendendendcnt=cnt+1endifstate==0thenerror(modulename..', ‘'..fname..'’: No pattern was given',0)endreturnptns,nptns,cntend-- Load the optional arguments of the `parsing` and `reinterpreting` modifierslocalfunctionload_parse_opts(opts,start_from)localargc=start_fromlocaltmplocaloptslots={true,true,true}localnoptslots=3localtrimn=truelocaltrimu=falselocaliplain=truelocalpplain=truelocalisp='|'localpsp='='repeatnoptslots=noptslots-1tmp=opts[argc]iftmp==nilthenbreakendtmp=tmp:match'^%s*(.-)%s*$'ifoptslots[1]~=nilandtrim_parse_opts[tmp]~=nilthentmp=trim_parse_opts[tmp]trimn=tmp[1]trimu=tmp[2]optslots[1]=nilelseifoptslots[2]~=nilandisep_parse_opts[tmp]~=nilthenargc=argc+1iplain=isep_parse_opts[tmp]isp=opts[argc]optslots[2]=nilelseifoptslots[3]~=nilandpsep_parse_opts[tmp]~=nilthenargc=argc+1pplain=psep_parse_opts[tmp]psp=opts[argc]optslots[3]=nilelsebreakendargc=argc+1untilnoptslots<1returnisp,iplain,psp,pplain,trimn,trimu,argcend-- Map parameters' values using a custom callback and a referenced tablelocalvalue_maps={[0]=function(tbl,margs,karg,varg,fn)forkeyinpairs(tbl)dotbl[key]=fn()endend,[1]=function(tbl,margs,karg,varg,fn)forkey,valinpairs(tbl)domargs[varg]=valtbl[key]=fn()endend,[2]=function(tbl,margs,karg,varg,fn)forkeyinpairs(tbl)domargs[karg]=keytbl[key]=fn()endend,[3]=function(tbl,margs,karg,varg,fn)forkey,valinpairs(tbl)domargs[karg]=keymargs[varg]=valtbl[key]=fn()endend}-- Private table for `map_names()`localname_thieves={[0]=function(cache,tbl,rargs,karg,varg,fn)forkey,valinpairs(tbl)dosteal_if_renamed(val,tbl,key,cache,fn())endend,[1]=function(cache,tbl,rargs,karg,varg,fn)forkey,valinpairs(tbl)dorargs[varg]=valsteal_if_renamed(val,tbl,key,cache,fn())endend,[2]=function(cache,tbl,rargs,karg,varg,fn)forkey,valinpairs(tbl)dorargs[karg]=keysteal_if_renamed(val,tbl,key,cache,fn())endend,[3]=function(cache,tbl,rargs,karg,varg,fn)forkey,valinpairs(tbl)dorargs[karg]=keyrargs[varg]=valsteal_if_renamed(val,tbl,key,cache,fn())endend}-- Map parameters' names using a custom callback and a referenced tablelocalfunctionmap_names(tbl,rargs,karg,varg,looptype,fn)localcache={}name_thieves[looptype](cache,tbl,rargs,karg,varg,fn)forkey,valinpairs(cache)dotbl[key]=valendend-- Return a new table that contains `src` regrouped according to the numeric-- suffixes in its keyslocalfunctionmake_groups(src)-- NOTE: `src` might be the original metatable!localtmplocalprefixlocalgidlocalgroups={}forkey,valinpairs(src)do-- `key` must only be a string or a number...gid=tonumber(key)ifgid==nilthenprefix,gid=key:match'^%s*(.-)%s*(%-?%d*)%s*$'gid=tonumber(gid)or''elseprefix=''endifgroups[gid]==nilthengroups[gid]={}endtmp=tonumber(prefix)iftmp~=niltheniftmp<1thenprefix=tmp-1elseprefix=tmpendendgroups[gid][prefix]=valendreturngroupsend-- Split into parts a string containing the `$#` and `$@` placeholders and-- return the information as a skeleton table, a canvas table and a lengthlocalfunctionparse_placeholder_string(target)localskel={}localcanvas={}localidx=1locals_pos=1locale_pos=string.find(target,'%$[@#]',1,false)whilee_pos~=nildocanvas[idx]=target:sub(s_pos,e_pos-1)skel[idx+1]=target:sub(e_pos,e_pos+1)=='$@'idx=idx+2s_pos=e_pos+2e_pos=string.find(target,'%$[@#]',s_pos,false)endif(s_pos>target:len())thenidx=idx-1elsecanvas[idx]=target:sub(s_pos)endreturnskel,canvas,idxend-- Populate a table by parsing a parameter stringlocalfunctionparse_parameter_string(tbl,str,isp,ipl,psp,ppl,trn,tru)localkeylocalvallocalspos1localspos2localpos1localpos2localpos3=0localidx=1locallenplone=#str+1ifisp==nilorisp==''thenifpsp==nilorpsp==''theniftruthentbl[idx]=str:match'^%s*(.-)%s*$'elsetbl[idx]=strendreturntblendspos1,spos2=str:find(psp,1,ppl)ifspos1==nilthenkey=idxiftruthenval=str:match'^%s*(.-)%s*$'elseval=strendidx=idx+1elsekey=str:sub(1,spos1-1)key=tonumber(key)orkey:match'^%s*(.-)%s*$'val=str:sub(spos2+1)iftrnthenval=val:match'^%s*(.-)%s*$'endendtbl[key]=valreturntblendifpsp==nilorpsp==''thenrepeatpos1=pos3+1pos2,pos3=str:find(isp,pos1,ipl)val=str:sub(pos1,(pos2orlenplone)-1)iftruthenval=val:match'^%s*(.-)%s*$'endtbl[idx]=validx=idx+1untilpos2==nilreturntblendrepeatpos1=pos3+1pos2,pos3=str:find(isp,pos1,ipl)val=str:sub(pos1,(pos2orlenplone)-1)spos1,spos2=val:find(psp,1,ppl)ifspos1==nilthenkey=idxiftruthenval=val:match'^%s*(.-)%s*$'endidx=idx+1elsekey=val:sub(1,spos1-1)key=tonumber(key)orkey:match'^%s*(.-)%s*$'val=val:sub(spos2+1)iftrnthenval=val:match'^%s*(.-)%s*$'endendtbl[key]=valuntilpos2==nilreturntblend-- Concatenate the numeric keys from the table of parameters to the numeric-- keys from the table of options; non-numeric keys from the table of options-- will prevail over colliding non-numeric keys from the table of parameterslocalfunctionconcat_params(ctx)localtbl=ctx.paramslocalnmax=table.maxn(ctx.pipe)localretval={}ifctx.subset==1then-- We need only the sequenceforkey,valinipairs(tbl)doretval[key+nmax]=valendelseifctx.subset==-1thenforkeyinipairs(tbl)dotbl[key]=nilendendforkey,valinpairs(tbl)doiftype(key)=='number'andkey>0thenretval[key+nmax]=valelseretval[key]=valendendendforkey,valinpairs(ctx.pipe)doretval[key]=valendreturnretvalend-- Flush the parameters by calling a custom function for each value (after this-- function has been invoked `ctx.params` will be no longer usable)localfunctionflush_params(ctx,fn)localtbl=ctx.paramsifctx.subset==1thenforkey,valinipairs(tbl)dofn(key,val)endreturnendifctx.subset==-1thenforkey,valinipairs(tbl)dotbl[key]=nilendendifctx.sorttype>0thenlocalnums={}localwords={}localnn=0localnw=0forkey,valinpairs(tbl)doiftype(key)=='number'thennn=nn+1nums[nn]=keyelsenw=nw+1words[nw]=keyendendtable.sort(nums)table.sort(words,natural_sort)ifctx.sorttype==2thenforidx=1,nwdofn(words[idx],tbl[words[idx]])endforidx=1,nndofn(nums[idx],tbl[nums[idx]])endreturnendforidx=1,nndofn(nums[idx],tbl[nums[idx]])endforidx=1,nwdofn(words[idx],tbl[words[idx]])endreturnendifctx.subset~=-1thenforkey,valinipairs(tbl)dofn(key,val)tbl[key]=nilendendforkey,valinpairs(tbl)dofn(key,val)endend--[[ Modifiers ]]--------------------------------- Syntax:  #invoke:params|sequential|pipe tolibrary.sequential=function(ctx)ifctx.subset==-1thenerror(modulename..': The two directives ‘non-sequential’ and ‘sequential’ are in contradiction with each other',0)endifctx.sorttype>0thenerror(modulename..': The ‘all_sorted’ and ‘reassorted’ directives are redundant when followed by ‘sequential’',0)endctx.iterfunc=ipairsctx.subset=1returncontext_iterate(ctx,1)end-- Syntax:  #invoke:params|non-sequential|pipe tolibrary['non-sequential']=function(ctx)ifctx.subset==1thenerror(modulename..': The two directives ‘sequential’ and ‘non-sequential’ are in contradiction with each other',0)endctx.iterfunc=pairsctx.subset=-1returncontext_iterate(ctx,1)end-- Syntax:  #invoke:params|all_sorted|pipe tolibrary.all_sorted=function(ctx)ifctx.subset==1thenerror(modulename..': The ‘all_sorted’ directive is redundant after ‘sequential’',0)endifctx.sorttype==2thenerror(modulename..': The two directives ‘reassorted’ and ‘sequential’ are in contradiction with each other',0)endctx.sorttype=1returncontext_iterate(ctx,1)end-- Syntax:  #invoke:params|reassorted|pipe tolibrary.reassorted=function(ctx)ifctx.subset==1thenerror(modulename..': The ‘reassorted’ directive is redundant after ‘sequential’',0)endifctx.sorttype==1thenerror(modulename..': The two directives ‘sequential’ and ‘reassorted’ are in contradiction with each other',0)endctx.sorttype=2returncontext_iterate(ctx,1)end-- Syntax:  #invoke:params|setting|directives|...|pipe tolibrary.setting=function(ctx)localopts=ctx.pipelocalcmd=opts[1]ifcmd~=nilthencmd=cmd:gsub('%s+',''):gsub('/+','/'):match'^/*(.*[^/])'endifcmd==nilthenerror(modulename..', ‘setting’: No directive was given',0)endlocalsep=string.byte('/')localargc=2localdest={}localvnamelocalchrforidx=1,#cmddochr=cmd:byte(idx)ifchr==septhenforkey,valinipairs(dest)doctx[val]=opts[argc]dest[key]=nilendargc=argc+1elsevname=memoryslots[string.char(chr)]ifvname==nilthenerror(modulename..', ‘setting’: Unknown slot ‘'..string.char(chr)..'’',0)endtable.insert(dest,vname)endendforkey,valinipairs(dest)doctx[val]=opts[argc]endreturncontext_iterate(ctx,argc+1)end-- Syntax:  #invoke:params|squeezing|pipe tolibrary.squeezing=function(ctx)localtbl=ctx.paramslocalstore={}localindices={}localnewlen=0forkey,valinpairs(tbl)doiftype(key)=='number'thennewlen=newlen+1indices[newlen]=keystore[key]=valtbl[key]=nilendendtable.sort(indices)foridx=1,newlendotbl[idx]=store[indices[idx]]endreturncontext_iterate(ctx,1)end-- Syntax:  #invoke:params|filling_the_gaps|pipe tolibrary.filling_the_gaps=function(ctx)localtbl=ctx.paramslocalnmin=1localnmax=nillocalnnums=-1localtmp={}forkey,valinpairs(tbl)doiftype(key)=='number'thenifnmax==nilthenifkey<nminthennmin=keyendnmax=keyelseifkey>nmaxthennmax=keyelseifkey<nminthennmin=keyendnnums=nnums+1tmp[key]=valendendifnmax~=nilandnmax-nmin>nnumsthenctx.n_available=ctx.n_available+nmin+nnums-nmaxifctx.n_available<0thenerror(modulename..', ‘filling_the_gaps’: It is possible to fill at most '..tostring(maxfill)..' parameters',0)endforidx=nmin,nmax,1dotbl[idx]=''endforkey,valinpairs(tmp)dotbl[key]=valendendreturncontext_iterate(ctx,1)end-- Syntax:  #invoke:params|clearing|pipe tolibrary.clearing=function(ctx)localtbl=ctx.paramslocalnumerics={}forkey,valinpairs(tbl)doiftype(key)=='number'thennumerics[key]=valtbl[key]=nilendendforkey,valinipairs(numerics)dotbl[key]=valendreturncontext_iterate(ctx,1)end-- Syntax:  #invoke:params|cutting|left cut|right cut|pipe tolibrary.cutting=function(ctx)locallcut=tonumber(ctx.pipe[1])iflcut==nilthenerror(modulename..', ‘cutting’: Left cut must be a number',0)endlocalrcut=tonumber(ctx.pipe[2])ifrcut==nilthenerror(modulename..', ‘cutting’: Right cut must be a number',0)endlocaltbl=ctx.paramslocallen=#tbliflcut<0thenlcut=len+lcutendifrcut<0thenrcut=len+rcutendlocaltot=lcut+rcutiftot>0thenlocalcache={}iftot>=lenthenforkeyinipairs(tbl)dotbl[key]=nilendtot=lenelseforidx=len-rcut+1,len,1dotbl[idx]=nilendforidx=1,lcut,1dotbl[idx]=nilendendforkey,valinpairs(tbl)doiftype(key)=='number'andkey>0thenifkey>lenthencache[key-tot]=valelsecache[key-lcut]=valendtbl[key]=nilendendforkey,valinpairs(cache)dotbl[key]=valendendreturncontext_iterate(ctx,3)end-- Syntax:  #invoke:params|cropping|left crop|right crop|pipe tolibrary.cropping=function(ctx)locallcut=tonumber(ctx.pipe[1])iflcut==nilthenerror(modulename..', ‘cropping’: Left crop must be a number',0)endlocalrcut=tonumber(ctx.pipe[2])ifrcut==nilthenerror(modulename..', ‘cropping’: Right crop must be a number',0)endlocaltbl=ctx.paramslocalnminlocalnmaxforkeyinpairs(tbl)doiftype(key)=='number'thenifnmin==nilthennmin=keynmax=keyelseifkey>nmaxthennmax=keyelseifkey<nminthennmin=keyendendendifnmin~=nilthenlocallen=nmax-nmin+1iflcut<0thenlcut=len+lcutendifrcut<0thenrcut=len+rcutendiflcut+rcut-len>-1thenforkeyinpairs(tbl)doiftype(key)=='number'thentbl[key]=nilendendelseiflcut+rcut>0thenforidx=nmax-rcut+1,nmaxdotbl[idx]=nilendforidx=nmin,nmin+lcut-1dotbl[idx]=nilendlocallshift=nmin+lcut-1iflshift>0thenforidx=lshift+1,nmax,1dotbl[idx-lshift]=tbl[idx]tbl[idx]=nilendendendendreturncontext_iterate(ctx,3)end-- Syntax:  #invoke:params|purging|start offset|length|pipe tolibrary.purging=function(ctx)localidx=tonumber(ctx.pipe[1])ifidx==nilthenerror(modulename..', ‘purging’: Start offset must be a number',0)endlocallen=tonumber(ctx.pipe[2])iflen==nilthenerror(modulename..', ‘purging’: Length must be a number',0)endlocaltbl=ctx.paramsiflen<1thenlen=len+table.maxn(tbl)ifidx>lenthenreturncontext_iterate(ctx,3)endlen=len-idx+1endctx.params=copy_table_reduced(tbl,idx,len)returncontext_iterate(ctx,3)end-- Syntax:  #invoke:params|backpurging|start offset|length|pipe tolibrary.backpurging=function(ctx)locallast=tonumber(ctx.pipe[1])iflast==nilthenerror(modulename..', ‘backpurging’: Start offset must be a number',0)endlocallen=tonumber(ctx.pipe[2])iflen==nilthenerror(modulename..', ‘backpurging’: Length must be a number',0)endlocalidxlocaltbl=ctx.paramsiflen>0thenidx=last-len+1elseforkeyinpairs(tbl)doiftype(key)=='number'and(idx==nilorkey<idx)thenidx=keyendendifidx==nilthenreturncontext_iterate(ctx,3)endidx=idx-leniflast<idxthenreturncontext_iterate(ctx,3)endlen=last-idx+1endctx.params=copy_table_reduced(ctx.params,idx,len)returncontext_iterate(ctx,3)end-- Syntax:  #invoke:params|reversing_numeric_names|pipe tolibrary.reversing_numeric_names=function(ctx)localtbl=ctx.paramslocalnumerics={}localnmax=0forkey,valinpairs(tbl)doiftype(key)=='number'thennumerics[key]=valtbl[key]=nilifkey>nmaxthennmax=keyendendendforkey,valinpairs(numerics)dotbl[nmax-key+1]=valendreturncontext_iterate(ctx,1)end-- Syntax:  #invoke:params|pivoting_numeric_names|pipe to--[[library.pivoting_numeric_names = function (ctx)local tbl = ctx.paramslocal shift = #tbl + 1if shift < 2 then return library.reversing_numeric_names(ctx) endlocal numerics = {}for key, val in pairs(tbl) doif type(key) == 'number' thennumerics[key] = valtbl[key] = nilendendfor key, val in pairs(numerics) do tbl[shift - key] = val endreturn context_iterate(ctx, 1)end]]---- Syntax:  #invoke:params|mirroring_numeric_names|pipe to--[[library.mirroring_numeric_names = function (ctx)local tbl = ctx.paramslocal numerics = {}local nmaxlocal nminfor key, val in pairs(tbl) doif type(key) == 'number' thennumerics[key] = valtbl[key] = nilif nmax == nil thennmax = keynmin = keyelseif key > nmax then nmax = keyelseif key < nmin then nmin = key endendendfor key, val in pairs(numerics) do tbl[nmax + nmin - key] = val endreturn context_iterate(ctx, 1)end]]---- Syntax:  #invoke:params|swapping_numeric_names|pipe to--[[library.swapping_numeric_names = function (ctx)local tbl = ctx.paramslocal cache = {}local nsize = 0local tmpfor key in pairs(tbl) doif type(key) == 'number' thennsize = nsize + 1cache[nsize] = keyendendtable.sort(cache)for idx = math.floor(nsize / 2), 1, -1 dotmp = tbl[cache[idx] ]tbl[cache[idx] ] = tbl[cache[nsize - idx + 1] ]tbl[cache[nsize - idx + 1] ] = tmpendreturn context_iterate(ctx, 1)end]]---- Syntax:  #invoke:params|sorting_sequential_values|[criterion]|pipe tolibrary.sorting_sequential_values=function(ctx)localsortfnifctx.pipe[1]~=nilthensortfn=sortfunctions[ctx.pipe[1]]endifsortfnthentable.sort(ctx.params,sortfn)elsetable.sort(ctx.params)end-- i.e. either `false` or `nil`ifsortfn==nilthenreturncontext_iterate(ctx,1)endreturncontext_iterate(ctx,2)end-- Syntax:  #invoke:params|inserting|position|how many|...|pipe to--[[library.inserting = function (ctx)-- NOTE: `ctx.params` might be the original metatable! As a modifier,-- this function MUST create a copy of it before returninglocal idx = tonumber(ctx.pipe[1])if idx == nil then error(modulename ..', ‘inserting’: Position must be a number', 0) endlocal len = tonumber(ctx.pipe[2])if len == nil or len < 1 then error(modulename ..', ‘inserting’: The amount must be a number greater than zero', 0) endlocal opts = ctx.pipelocal tbl = copy_table_expanded(ctx.params, idx, len)for key = idx, idx + len - 1 do tbl[key] = opts[key - idx + 3] endctx.params = tblreturn context_iterate(ctx, len + 3)end]]---- Syntax:  #invoke:params|imposing|name|value|pipe tolibrary.imposing=function(ctx)ifctx.pipe[1]==nilthenerror(modulename..', ‘imposing’: Missing parameter name to impose',0)endlocalkey=ctx.pipe[1]:match'^%s*(.-)%s*$'ctx.params[tonumber(key)orkey]=ctx.pipe[2]returncontext_iterate(ctx,3)end-- Syntax:  #invoke:params|providing|name|value|pipe tolibrary.providing=function(ctx)ifctx.pipe[1]==nilthenerror(modulename..', ‘providing’: Missing parameter name to provide',0)endlocalkey=ctx.pipe[1]:match'^%s*(.-)%s*$'key=tonumber(key)orkeyifctx.params[key]==nilthenctx.params[key]=ctx.pipe[2]endreturncontext_iterate(ctx,3)end-- Syntax:  #invoke:params|discarding|name|[how many]|pipe tolibrary.discarding=function(ctx)ifctx.pipe[1]==nilthenerror(modulename..', ‘discarding’: Missing parameter name to discard',0)endlocalkey=ctx.pipe[1]locallen=tonumber(ctx.pipe[2])iflen==nilthenctx.params[tonumber(key)orkey:match'^%s*(.-)%s*$']=nilreturncontext_iterate(ctx,2)endkey=tonumber(key)ifkey==nilthenerror(modulename..', ‘discarding’: A range was provided, but the initial parameter name is not numeric',0)endiflen<1thenerror(modulename..', ‘discarding’: A range can only be a number greater than zero',0)endforidx=key,key+len-1doctx.params[idx]=nilendreturncontext_iterate(ctx,3)end-- Syntax:  #invoke:params|excluding_non-numeric_names|pipe tolibrary['excluding_non-numeric_names']=function(ctx)localtmp=ctx.paramsforkey,valinpairs(tmp)doiftype(key)~='number'thentmp[key]=nilendendreturncontext_iterate(ctx,1)end-- Syntax:  #invoke:params|excluding_numeric_names|pipe tolibrary.excluding_numeric_names=function(ctx)localtmp=ctx.paramsforkey,valinpairs(tmp)doiftype(key)=='number'thentmp[key]=nilendendreturncontext_iterate(ctx,1)end-- Syntax:  #invoke:params|with_name_matching|target 1|[plain flag 1]|[or]--            |[target 2]|[plain flag 2]|[or]|[...]|[target N]|[plain flag--            N]|pipe tolibrary.with_name_matching=function(ctx)-- NOTE: `ctx.params` might be the original metatable! As a modifier,-- this function MUST create a copy of it before returninglocaltargets,nptns,argc=load_pattern_args(ctx.pipe,targets,'with_name_matching')localtmplocalptnlocaltbl=ctx.paramslocalnewparams={}foridx=1,nptnsdoptn=targets[idx]ifptn[3]thentmp=tonumber(ptn[1])orptn[1]newparams[tmp]=tbl[tmp]elseforkey,valinpairs(tbl)doiftostring(key):find(ptn[1],1,ptn[2])thennewparams[key]=valendendendendctx.params=newparamsreturncontext_iterate(ctx,argc)end-- Syntax:  #invoke:params|with_name_not_matching|target 1|[plain flag 1]--            |[and]|[target 2]|[plain flag 2]|[and]|[...]|[target N]|[plain--            flag N]|pipe tolibrary.with_name_not_matching=function(ctx)localtargets,nptns,argc=load_pattern_args(ctx.pipe,targets,'with_name_not_matching')localtbl=ctx.paramsifnptns==1andtargets[1][3]thenlocaltmp=targets[1][1]tbl[tonumber(tmp)ortmp]=nilreturncontext_iterate(ctx,argc)endlocalyesmatchlocalptnforkeyinpairs(tbl)doyesmatch=trueforidx=1,nptnsdoptn=targets[idx]ifptn[3]theniftostring(key)~=ptn[1]thenyesmatch=falsebreakendelseifnottostring(key):find(ptn[1],1,ptn[2])thenyesmatch=falsebreakendendifyesmatchthentbl[key]=nilendendreturncontext_iterate(ctx,argc)end-- Syntax:  #invoke:params|with_value_matching|target 1|[plain flag 1]|[or]--            |[target 2]|[plain flag 2]|[or]|[...]|[target N]|[plain flag--            N]|pipe tolibrary.with_value_matching=function(ctx)localtbl=ctx.paramslocaltargets,nptns,argc=load_pattern_args(ctx.pipe,targets,'with_value_matching')localnomatchlocalptnforkey,valinpairs(tbl)donomatch=trueforidx=1,nptnsdoptn=targets[idx]ifptn[3]thenifval==ptn[1]thennomatch=falsebreakendelseifval:find(ptn[1],1,ptn[2])thennomatch=falsebreakendendifnomatchthentbl[key]=nilendendreturncontext_iterate(ctx,argc)end-- Syntax:  #invoke:params|with_value_not_matching|target 1|[plain flag 1]--            |[and]|[target 2]|[plain flag 2]|[and]|[...]|[target N]|[plain--            flag N]|pipe tolibrary.with_value_not_matching=function(ctx)localtbl=ctx.paramslocaltargets,nptns,argc=load_pattern_args(ctx.pipe,targets,'with_value_not_matching')localyesmatchlocalptnforkey,valinpairs(tbl)doyesmatch=trueforidx=1,nptnsdoptn=targets[idx]ifptn[3]thenifval~=ptn[1]thenyesmatch=falsebreakendelseifnotval:find(ptn[1],1,ptn[2])thenyesmatch=falsebreakendendifyesmatchthentbl[key]=nilendendreturncontext_iterate(ctx,argc)end-- Syntax:  #invoke:params|trimming_values|pipe tolibrary.trimming_values=function(ctx)localtbl=ctx.paramsforkey,valinpairs(tbl)dotbl[key]=val:match'^%s*(.-)%s*$'endreturncontext_iterate(ctx,1)end-- Syntax:  #invoke:params|converting_values_to_lowercase|pipe tolibrary.converting_values_to_lowercase=function(ctx)localtbl=ctx.paramsforkey,valinpairs(tbl)dotbl[key]=val:lower()endreturncontext_iterate(ctx,1)end-- Syntax:  #invoke:params|converting_values_to_uppercase|pipe tolibrary.converting_values_to_uppercase=function(ctx)localtbl=ctx.paramsforkey,valinpairs(tbl)dotbl[key]=val:upper()endreturncontext_iterate(ctx,1)end-- Syntax:  #invoke:params|mapping_by_calling|template name|[call--            style]|[let]|[...][number of additional parameters]|[parameter--            1]|[parameter 2]|[...]|[parameter N]|pipe tolibrary.mapping_by_calling=function(ctx)localopts=ctx.pipelocaltnameifopts[1]~=nilthentname=opts[1]:match'^%s*(.*%S)'endiftname==nilthenerror(modulename..', ‘mapping_by_calling’: No template name was provided',0)endlocalmargs,argc,looptype,karg,varg=load_callback_opts(opts,1,mapping_styles.values_only)localmodel={title=tname,args=margs}value_maps[looptype](ctx.params,margs,karg,varg,function()returnctx.frame:expandTemplate(model)end)returncontext_iterate(ctx,argc)end-- Syntax:  #invoke:params|mapping_by_invoking|module name|function--            name|[call style]|[let]|[...]|[number of additional--            arguments]|[argument 1]|[argument 2]|[...]|[argument N]|pipe tolibrary.mapping_by_invoking=function(ctx)localopts=ctx.pipelocalmnamelocalfnameifopts[1]~=nilthenmname=opts[1]:match'^%s*(.*%S)'endifmname==nilthenerror(modulename..', ‘mapping_by_invoking’: No module name was provided',0)endifopts[2]~=nilthenfname=opts[2]:match'^%s*(.*%S)'endiffname==nilthenerror(modulename..', ‘mapping_by_invoking’: No function name was provided',0)endlocalmargs,argc,looptype,karg,varg=load_callback_opts(opts,2,mapping_styles.values_only)localmodel={title='Module:'..mname,args=margs}localmfunc=require(model.title)[fname]ifmfunc==nilthenerror(modulename..', ‘mapping_by_invoking’: The function ‘'..fname..'’ does not exist',0)endvalue_maps[looptype](ctx.params,margs,karg,varg,function()returntostring(mfunc(ctx.frame:newChild(model)))end)returncontext_iterate(ctx,argc)end-- Syntax:  #invoke:params|mapping_by_magic|parser function|[call--            style]|[let]|[...][number of additional arguments]|[argument--            1]|[argument 2]|[...]|[argument N]|pipe tolibrary.mapping_by_magic=function(ctx)localopts=ctx.pipelocalmagicifopts[1]~=nilthenmagic=opts[1]:match'^%s*(.*%S)'endifmagic==nilthenerror(modulename..', ‘mapping_by_magic’: No parser function was provided',0)endlocalmargs,argc,looptype,karg,varg=load_callback_opts(opts,1,mapping_styles.values_only)value_maps[looptype](ctx.params,margs,karg,varg,function()returnctx.frame:callParserFunction(magic,margs)end)returncontext_iterate(ctx,argc)end-- Syntax:  #invoke:params|mapping_by_replacing|target|replace|[count]|[plain--            flag]|pipe tolibrary.mapping_by_replacing=function(ctx)localptn,repl,nmax,is_strict,argc,die=load_replace_args(ctx.pipe,'mapping_by_replacing')ifdiethenreturncontext_iterate(ctx,argc)endlocaltbl=ctx.paramsifis_strictthenforkey,valinpairs(tbl)doifval==ptnthentbl[key]=replendendelseifflg==2then-- Copied from Module:String's `str._escapePattern()`ptn=ptn:gsub('[%(%)%.%%%+%-%*%?%[%^%$%]]','%%%0')endforkey,valinpairs(tbl)dotbl[key]=val:gsub(ptn,repl,nmax)endendreturncontext_iterate(ctx,argc)end-- Syntax:  #invoke:params|mapping_by_mixing|mixing string|pipe tolibrary.mapping_by_mixing=function(ctx)ifctx.pipe[1]==nilthenerror(modulename..', ‘mapping_by_mixing’: No mixing string was provided',0)endlocalmix=ctx.pipe[1]localtbl=ctx.paramsifmix=='$#'thenforkeyinpairs(tbl)dotbl[key]=keyendreturncontext_iterate(ctx,2)endlocalskel,cnv,n_parts=parse_placeholder_string(mix)forkey,valinpairs(tbl)doforidx=2,n_parts,2doifskel[idx]thencnv[idx]=valelsecnv[idx]=tostring(key)endendtbl[key]=table.concat(cnv)endreturncontext_iterate(ctx,2)end-- Syntax:  #invoke:params|mapping_to_names|pipe to--[[library.mapping_to_names = function (ctx)local tbl = ctx.paramsfor key in pairs(tbl) do tbl[key] = key endreturn context_iterate(ctx, 1)end]]---- Syntax:  #invoke:params|converting_names_to_lowercase|pipe tolibrary.converting_names_to_lowercase=function(ctx)-- NOTE: `ctx.params` might be the original metatable! As a modifier,-- this function MUST create a copy of it before returninglocalcache={}forkey,valinpairs(ctx.params)doiftype(key)=='string'thencache[key:lower()]=valelsecache[key]=valendendctx.params=cachereturncontext_iterate(ctx,1)end-- Syntax:  #invoke:params|converting_names_to_uppercase|pipe tolibrary.converting_names_to_uppercase=function(ctx)-- NOTE: `ctx.params` might be the original metatable! As a modifier,-- this function MUST create a copy of it before returninglocalcache={}forkey,valinpairs(ctx.params)doiftype(key)=='string'thencache[key:upper()]=valelsecache[key]=valendendctx.params=cachereturncontext_iterate(ctx,1)end-- Syntax:  #invoke:params|renaming_by_calling|template name|[call--            style]|[let]|[...][number of additional parameters]|[parameter--            1]|[parameter 2]|[...]|[parameter N]|pipe tolibrary.renaming_by_calling=function(ctx)localopts=ctx.pipelocaltnameifopts[1]~=nilthentname=opts[1]:match'^%s*(.*%S)'endiftname==nilthenerror(modulename..', ‘renaming_by_calling’: No template name was provided',0)endlocalrargs,argc,looptype,karg,varg=load_callback_opts(opts,1,mapping_styles.names_only)localmodel={title=tname,args=rargs}map_names(ctx.params,rargs,karg,varg,looptype,function()returnctx.frame:expandTemplate(model)end)returncontext_iterate(ctx,argc)end-- Syntax:  #invoke:params|renaming_by_invoking|module name|function--            name|[call style]|[let]|[...]|[number of additional--            arguments]|[argument 1]|[argument 2]|[...]|[argument N]|pipe tolibrary.renaming_by_invoking=function(ctx)localopts=ctx.pipelocalmnamelocalfnameifopts[1]~=nilthenmname=opts[1]:match'^%s*(.*%S)'endifmname==nilthenerror(modulename..', ‘renaming_by_invoking’: No module name was provided',0)endifopts[2]~=nilthenfname=opts[2]:match'^%s*(.*%S)'endiffname==nilthenerror(modulename..', ‘renaming_by_invoking’: No function name was provided',0)endlocalrargs,argc,looptype,karg,varg=load_callback_opts(opts,2,mapping_styles.names_only)localmodel={title='Module:'..mname,args=rargs}localmfunc=require(model.title)[fname]ifmfunc==nilthenerror(modulename..', ‘renaming_by_invoking’: The function ‘'..fname..'’ does not exist',0)endmap_names(ctx.params,rargs,karg,varg,looptype,function()localtmp=mfunc(ctx.frame:newChild(model))returntonumber(tmp)ortostring(tmp)end)returncontext_iterate(ctx,argc)end-- Syntax:  #invoke:params|renaming_by_magic|parser function|[call--            style]|[let]|[...][number of additional arguments]|[argument--            1]|[argument 2]|[...]|[argument N]|pipe tolibrary.renaming_by_magic=function(ctx)localopts=ctx.pipelocalmagicifopts[1]~=nilthenmagic=opts[1]:match'^%s*(.*%S)'endifmagic==nilthenerror(modulename..', ‘renaming_by_magic’: No parser function was provided',0)endlocalrargs,argc,looptype,karg,varg=load_callback_opts(opts,1,mapping_styles.names_only)map_names(ctx.params,rargs,karg,varg,looptype,function()returnctx.frame:callParserFunction(magic,rargs)end)returncontext_iterate(ctx,argc)end-- Syntax:  #invoke:params|renaming_by_replacing|target|replace|[count]|[plain--            flag]|pipe tolibrary.renaming_by_replacing=function(ctx)localptn,repl,nmax,is_strict,argc,die=load_replace_args(ctx.pipe,'renaming_by_replacing')ifdiethenreturncontext_iterate(ctx,argc)endlocaltbl=ctx.paramsifis_strictthenlocalkey=tonumber(ptn)orptn:match'^%s*(.-)%s*$'localval=tbl[key]ifval~=nilthentbl[key]=niltbl[tonumber(repl)orrepl:match'^%s*(.-)%s*$']=valendelseifflg==2then-- Copied from Module:String's `str._escapePattern()`ptn=ptn:gsub('[%(%)%.%%%+%-%*%?%[%^%$%]]','%%%0')endlocalcache={}forkey,valinpairs(tbl)dosteal_if_renamed(val,tbl,key,cache,tostring(key):gsub(ptn,repl,nmax))endforkey,valinpairs(cache)dotbl[key]=valendendreturncontext_iterate(ctx,argc)end-- Syntax:  #invoke:params|renaming_by_mixing|mixing string|pipe tolibrary.renaming_by_mixing=function(ctx)-- NOTE: `ctx.params` might be the original metatable! As a modifier,-- this function MUST create a copy of it before returningifctx.pipe[1]==nilthenerror(modulename..', ‘renaming_by_mixing’: No mixing string was provided',0)endlocalmix=ctx.pipe[1]:match'^%s*(.-)%s*$'localcache={}ifmix=='$@'thenfor_,valinpairs(ctx.params)docache[val]=valendelselocalskel,canvas,n_parts=parse_placeholder_string(mix)localtmpforkey,valinpairs(ctx.params)doforidx=2,n_parts,2doifskel[idx]thencanvas[idx]=valelsecanvas[idx]=tostring(key)endendtmp=table.concat(canvas)cache[tonumber(tmp)ortmp]=valendendctx.params=cachereturncontext_iterate(ctx,2)end-- Syntax:  #invoke:params|renaming_to_values|pipe to--[[library.renaming_to_values = function (ctx)-- NOTE: `ctx.params` might be the original metatable! As a modifier,-- this function MUST create a copy of it before returninglocal cache = {}for _, val in pairs(ctx.params) do cache[val] = val endctx.params = cachereturn context_iterate(ctx, 1)end]]---- Syntax:  #invoke:params|grouping_by_calling|template--            name|[let]|[...]|[number of additional arguments]|[argument--            1]|[argument 2]|[...]|[argument N]|pipe tolibrary.grouping_by_calling=function(ctx)-- NOTE: `ctx.params` might be the original metatable! As a modifier,-- this function MUST create a copy of it before returninglocalopts=ctx.pipelocaltmpifopts[1]~=nilthentmp=opts[1]:match'^%s*(.*%S)'endiftmp==nilthenerror(modulename..', ‘grouping_by_calling’: No template name was provided',0)endlocalmodel={title=tmp}localtmp,argc=load_child_opts(opts,2,0)localgargs={}forkey,valinpairs(tmp)doiftype(key)=='number'andkey<1thengargs[key-1]=valelsegargs[key]=valendendlocalgroups=make_groups(ctx.params)forgid,groupinpairs(groups)doforkey,valinpairs(gargs)dogroup[key]=valendgroup[0]=gidmodel.args=groupgroups[gid]=ctx.frame:expandTemplate(model)endctx.params=groupsreturncontext_iterate(ctx,argc)end-- Syntax:  #invoke:params|parsing|string to parse|[trim flag]|[iteration--            delimiter setter]|[...]|[key-value delimiter setter]|[...]|pipe tolibrary.parsing=function(ctx)localopts=ctx.pipeifopts[1]==nilthenerror(modulename..', ‘parsing’: No string to parse was provided',0)endlocalisep,iplain,psep,pplain,trimnamed,trimunnamed,argc=load_parse_opts(opts,2)parse_parameter_string(ctx.params,opts[1],isep,iplain,psep,pplain,trimnamed,trimunnamed)returncontext_iterate(ctx,argc)end-- Syntax:  #invoke:params|reinterpreting|parameter to reinterpret|[trim--            flag]|[iteration delimiter setter]|[...]|[key-value delimiter--            setter]|[...]|pipe tolibrary.reinterpreting=function(ctx)localopts=ctx.pipeifopts[1]==nilthenerror(modulename..', ‘reinterpreting’: No parameter to reinterpret was provided',0)endlocalisep,iplain,psep,pplain,trimnamed,trimunnamed,argc=load_parse_opts(opts,2)localtbl=ctx.paramslocaltmp=tonumber(opts[1])oropts[1]:match'^%s*(.-)%s*$'localstr=tbl[tmp]ifstr~=nilthentbl[tmp]=nilparse_parameter_string(tbl,str,isep,iplain,psep,pplain,trimnamed,trimunnamed)endreturncontext_iterate(ctx,argc)end-- Syntax:  #invoke:params|mixing_names_and_values|mixing string|pipe tolibrary.mixing_names_and_values=function(ctx)-- NOTE: `ctx.params` might be the original metatable! As a modifier,-- this function MUST create a copy of it before returningifctx.pipe[1]==nilthenerror(modulename..', ‘mixing_names_and_values’: No mixing string was provided for parameter names',0)endifctx.pipe[2]==nilthenerror(modulename..', ‘mixing_names_and_values’: No mixing string was provided for parameter values',0)endlocalmix_k=ctx.pipe[1]:match'^%s*(.-)%s*$'localmix_v=ctx.pipe[2]localcache={}ifmix_k=='$@'andmix_v=='$@'thenfor_,valinpairs(ctx.params)docache[val]=valendelseifmix_k=='$@'andmix_v=='$#'thenforkey,valinpairs(ctx.params)docache[val]=keyendelseifmix_k=='$#'andmix_v=='$#'thenfor_,valinpairs(ctx.params)docache[key]=keyendelselocalskel_k,cnv_k,n_parts_k=parse_placeholder_string(mix_k)localskel_v,cnv_v,n_parts_v=parse_placeholder_string(mix_v)localtmpforkey,valinpairs(ctx.params)dotmp=tostring(key)foridx=2,n_parts_k,2doifskel_k[idx]thencnv_k[idx]=valelsecnv_k[idx]=tmpendendforidx=2,n_parts_v,2doifskel_v[idx]thencnv_v[idx]=valelsecnv_v[idx]=tmpendendtmp=table.concat(cnv_k)cache[tonumber(tmp)ortmp]=table.concat(cnv_v)endendctx.params=cachereturncontext_iterate(ctx,3)end-- Syntax:  #invoke:params|swapping_names_and_values|pipe to--[[library.swapping_names_and_values = function (ctx)-- NOTE: `ctx.params` might be the original metatable! As a modifier,-- this function MUST create a copy of it before returninglocal cache = {}for key, val in pairs(ctx.params) do cache[val] = key endctx.params = cachereturn context_iterate(ctx, 1)end]]---- Syntax:  #invoke:params|combining_by_calling|template name|new parameter--            name|pipe tolibrary.combining_by_calling=function(ctx)-- NOTE: `ctx.params` might be the original metatable! As a modifier,-- this function MUST create a copy of it before returninglocaltname=ctx.pipe[1]iftname~=nilthentname=tname:match'^%s*(.*%S)'elseerror(modulename..', ‘combining_by_calling’: No template name was provided',0)endlocalmerge_into=ctx.pipe[2]ifmerge_into==nilthenerror(modulename..', ‘combining_by_calling’: No parameter name was provided',0)endmerge_into=tonumber(merge_into)ormerge_into:match'^%s*(.-)%s*$'ctx.params={[merge_into]=ctx.frame:expandTemplate{title=tname,args=ctx.params}}returncontext_iterate(ctx,3)end-- Syntax:  #invoke:params|snapshotting|pipe tolibrary.snapshotting=function(ctx)push_cloned_stack(ctx,ctx.params)returncontext_iterate(ctx,1)end-- Syntax:  #invoke:params|remembering|pipe tolibrary.remembering=function(ctx)push_cloned_stack(ctx,ctx.oparams)returncontext_iterate(ctx,1)end-- Syntax:  #invoke:params|entering_substack|[new]|pipe tolibrary.entering_substack=function(ctx)localtbl=ctx.paramslocalncurrparent=ctx.n_parents+1ifctx.parents==nilthenctx.parents={tbl}elsectx.parents[ncurrparent]=tblendctx.n_parents=ncurrparentifctx.pipe[1]~=nilandctx.pipe[1]:match'^%s*new%s*$'thenctx.params={}returncontext_iterate(ctx,2)endlocalcurrsnap=ctx.n_childrenifcurrsnap>0thenctx.params=ctx.children[currsnap]ctx.children[currsnap]=nilctx.n_children=currsnap-1elselocalnewparams={}forkey,valinpairs(tbl)donewparams[key]=valendctx.params=newparamsendreturncontext_iterate(ctx,1)end-- Syntax:  #invoke:params|pulling|parameter name|pipe tolibrary.pulling=function(ctx)localopts=ctx.pipeifopts[1]==nilthenerror(modulename..', ‘pulling’: No parameter to pull was provided',0)endlocalparentlocaltmp=ctx.n_parentsiftmp<1thenparent=ctx.oparamselseparent=ctx.parents[tmp]endtmp=tonumber(opts[1])oropts[1]:match'^%s*(.-)%s*$'ifparent[tmp]~=nilthenctx.params[tmp]=parent[tmp]endreturncontext_iterate(ctx,2)end-- Syntax:  #invoke:params|detaching_substack|pipe tolibrary.detaching_substack=function(ctx)localncurrparent=ctx.n_parentsifncurrparent<1thenerror(modulename..', ‘detaching_substack’: No substack has been created',0)endlocalparent=ctx.parents[ncurrparent]forkeyinpairs(ctx.params)doparent[key]=nilendreturncontext_iterate(ctx,1)end-- Syntax:  #invoke:params|leaving_substack|pipe tolibrary.leaving_substack=function(ctx)localncurrparent=ctx.n_parentsifncurrparent<1thenerror(modulename..', ‘leaving_substack’: No substack has been created',0)endlocalcurrsnap=ctx.n_children+1ifctx.children==nilthenctx.children={ctx.params}elsectx.children[currsnap]=ctx.paramsendctx.params=ctx.parents[ncurrparent]ctx.parents[ncurrparent]=nilctx.n_parents=ncurrparent-1ctx.n_children=currsnapreturncontext_iterate(ctx,1)end-- Syntax:  #invoke:params|merging_substack|pipe tolibrary.merging_substack=function(ctx)localncurrparent=ctx.n_parentsifncurrparent<1thenerror(modulename..', ‘merging_substack’: No substack has been created',0)endlocalparent=ctx.parents[ncurrparent]localchild=ctx.paramsctx.params=parentctx.parents[ncurrparent]=nilctx.n_parents=ncurrparent-1forkey,valinpairs(child)doparent[key]=valendreturncontext_iterate(ctx,1)end-- Syntax:  #invoke:params|flushing|pipe tolibrary.flushing=function(ctx)ifctx.n_children<1thenerror(modulename..', ‘flushing’: There are no substacks to flush',0)endlocalparent=ctx.paramslocalcurrsnap=ctx.n_childrenforkey,valinpairs(ctx.children[currsnap])doparent[key]=valendctx.children[currsnap]=nilctx.n_children=currsnap-1returncontext_iterate(ctx,1)end--[[ Functions ]]--------------------------------- Syntax:  #invoke:params|countlibrary.count=function(ctx)-- NOTE: `ctx.pipe` and `ctx.params` might be the original metatables!localretval=0for_inctx.iterfunc(ctx.params)doretval=retval+1endifctx.subset==-1thenretval=retval-#ctx.paramsendctx.text=retvalreturnfalseend-- Syntax:  #invoke:args|concat_and_call|template name|[prepend 1]|[prepend 2]--            |[...]|[item n]|[named item 1=value 1]|[...]|[named item n=value--            n]|[...]library.concat_and_call=function(ctx)-- NOTE: `ctx.params` might be the original metatable!localopts=ctx.pipelocaltnameifopts[1]~=nilthentname=opts[1]:match'^%s*(.*%S)'endiftname==nilthenerror(modulename..', ‘concat_and_call’: No template name was provided',0)endremove_numeric_keys(opts,1,1)ctx.text=ctx.frame:expandTemplate{title=tname,args=concat_params(ctx)}returnfalseend-- Syntax:  #invoke:args|concat_and_invoke|module name|function name|[prepend--            1]|[prepend 2]|[...]|[item n]|[named item 1=value 1]|[...]|[named--            item n=value n]|[...]library.concat_and_invoke=function(ctx)-- NOTE: `ctx.params` might be the original metatable!localopts=ctx.pipelocalmnamelocalfnameifopts[1]~=nilthenmname=opts[1]:match'^%s*(.*%S)'endifmname==nilthenerror(modulename..', ‘concat_and_invoke’: No module name was provided',0)endifopts[2]~=nilthenfname=opts[2]:match'^%s*(.*%S)'endiffname==nilthenerror(modulename..', ‘concat_and_invoke’: No function name was provided',0)endremove_numeric_keys(opts,1,2)localmfunc=require('Module:'..mname)[fname]ifmfunc==nilthenerror(modulename..', ‘concat_and_invoke’: The function ‘'..fname..'’ does not exist',0)endctx.text=mfunc(ctx.frame:newChild{title='Module:'..fname,args=concat_params(ctx)})returnfalseend-- Syntax:  #invoke:args|concat_and_magic|parser function|[prepend 1]|[prepend--            2]|[...]|[item n]|[named item 1=value 1]|[...]|[named item n=--            value n]|[...]library.concat_and_magic=function(ctx)-- NOTE: `ctx.params` might be the original metatable!localopts=ctx.pipelocalmagicifopts[1]~=nilthenmagic=opts[1]:match'^%s*(.*%S)'endifmagic==nilthenerror(modulename..', ‘concat_and_magic’: No parser function was provided',0)endremove_numeric_keys(opts,1,1)ctx.text=ctx.frame:callParserFunction(magic,concat_params(ctx))returnfalseend-- Syntax:  #invoke:params|value_of|parameter namelibrary.value_of=function(ctx)-- NOTE: `ctx.pipe` and `ctx.params` might be the original metatables!localopts=ctx.pipelocalkstrifopts[1]~=nilthenkstr=opts[1]:match'^%s*(.*%S)'endifkstr==nilthenerror(modulename..', ‘value_of’: No parameter name was provided',0)endlocalknum=tonumber(kstr)locallen=#ctx.params-- No worries: unused when in first positionlocalval=ctx.params[knumorkstr]ifval~=niland(ctx.subset~=-1orknum==nilorknum>lenorknum<1)and(ctx.subset~=1or(knum~=nilandknum<=lenandknum>0))thenctx.text=(ctx.headeror'')..val..(ctx.footeror'')returnfalseendctx.text=ctx.ifngivenor''returnfalseend-- Syntax:  #invoke:params|listlibrary.list=function(ctx)-- NOTE: `ctx.pipe` might be the original metatable!localkvs=ctx.pairsepor''localpps=ctx.itersepor''localret={}localnss=0flush_params(ctx,function(key,val)ret[nss+1]=ppsret[nss+2]=keyret[nss+3]=kvsret[nss+4]=valnss=nss+4end)ifnss>0thenifnss>4andctx.lastsep~=nilthenret[nss-3]=ctx.lastsependret[1]=ctx.headeror''ifctx.footer~=nilthenret[nss+1]=ctx.footerendctx.text=table.concat(ret)returnfalseendctx.text=ctx.ifngivenor''returnfalseend-- Syntax:  #invoke:params|list_valueslibrary.list_values=function(ctx)-- NOTE: `ctx.pipe` might be the original metatable!-- NOTE: `library.coins()` and `library.unique_coins()` rely on uslocalpps=ctx.itersepor''localret={}localnss=0flush_params(ctx,function(key,val)ret[nss+1]=ppsret[nss+2]=valnss=nss+2end)ifnss>0thenifnss>2andctx.lastsep~=nilthenret[nss-1]=ctx.lastsependret[1]=ctx.headeror''ifctx.footer~=nilthenret[nss+1]=ctx.footerendctx.text=table.concat(ret)returnfalseendctx.text=ctx.ifngivenor''returnfalseend-- Syntax:  #invoke:params|coins|[first coin = value 1]|[second coin = value--            2]|[...]|[last coin = value N]library.coins=function(ctx)-- NOTE: `ctx.pipe` might be the original metatable!localopts=ctx.pipelocaltbl=ctx.paramsforkey,valinpairs(tbl)dotbl[key]=opts[tonumber(val)orval]endreturnlibrary.list_values(ctx)end-- Syntax:  #invoke:params|unique_coins|[first coin = value 1]|[second coin =--            value 2]|[...]|[last coin = value N]library.unique_coins=function(ctx)localopts=ctx.pipelocaltbl=ctx.paramslocaltmpforkey,valinpairs(tbl)dotmp=tonumber(val)orvaltbl[key]=opts[tmp]opts[tmp]=nilendreturnlibrary.list_values(ctx)end-- Syntax:  #invoke:params|for_each|wikitextlibrary.for_each=function(ctx)-- NOTE: `ctx.pipe` might be the original metatable!localtxt=ctx.pipe[1]or''localpps=ctx.itersepor''localret={}localnss=0localskel,cnv,n_parts=parse_placeholder_string(txt)flush_params(ctx,function(key,val)foridx=2,n_parts,2doifskel[idx]thencnv[idx]=valelsecnv[idx]=tostring(key)endendret[nss+1]=ppsret[nss+2]=table.concat(cnv)nss=nss+2end)ifnss>0thenifnss>2andctx.lastsep~=nilthenret[nss-1]=ctx.lastsependret[1]=ctx.headeror''ifctx.footer~=nilthenret[nss+1]=ctx.footerendctx.text=table.concat(ret)returnfalseendctx.text=ctx.ifngivenor''returnfalseend-- Syntax:  #invoke:params|call_for_each|template name|[append 1]|[append 2]--            |[...]|[append n]|[named param 1=value 1]|[...]|[named param--            n=value n]|[...]library.call_for_each=function(ctx)localopts=ctx.pipelocaltnameifopts[1]~=nilthentname=opts[1]:match'^%s*(.*%S)'endiftname==nilthenerror(modulename..', ‘call_for_each’: No template name was provided',0)endlocalmodel={title=tname,args=opts}localccs=ctx.itersepor''localret={}localnss=0table.insert(opts,1,true)flush_params(ctx,function(key,val)opts[1]=keyopts[2]=valret[nss+1]=ccsret[nss+2]=ctx.frame:expandTemplate(model)nss=nss+2end)ifnss>0thenifnss>2andctx.lastsep~=nilthenret[nss-1]=ctx.lastsependret[1]=ctx.headeror''ifctx.footer~=nilthenret[nss+1]=ctx.footerendctx.text=table.concat(ret)returnfalseendctx.text=ctx.ifngivenor''returnfalseend-- Syntax:  #invoke:params|invoke_for_each|module name|module function|[append--            1]|[append 2]|[...]|[append n]|[named param 1=value 1]|[...]--            |[named param n=value n]|[...]library.invoke_for_each=function(ctx)localopts=ctx.pipelocalmnamelocalfnameifopts[1]~=nilthenmname=opts[1]:match'^%s*(.*%S)'endifmname==nilthenerror(modulename..', ‘invoke_for_each’: No module name was provided',0)endifopts[2]~=nilthenfname=opts[2]:match'^%s*(.*%S)'endiffname==nilthenerror(modulename..', ‘invoke_for_each’: No function name was provided',0)endlocalmodel={title='Module:'..mname,args=opts}localmfunc=require(model.title)[fname]localccs=ctx.itersepor''localret={}localnss=0flush_params(ctx,function(key,val)opts[1]=keyopts[2]=valret[nss+1]=ccsret[nss+2]=mfunc(ctx.frame:newChild(model))nss=nss+2end)ifnss>0thenifnss>2andctx.lastsep~=nilthenret[nss-1]=ctx.lastsependret[1]=ctx.headeror''ifctx.footer~=nilthenret[nss+1]=ctx.footerendctx.text=table.concat(ret)returnfalseendctx.text=ctx.ifngivenor''returnfalseend-- Syntax:  #invoke:params|magic_for_each|parser function|[append 1]|[append 2]--            |[...]|[append n]|[named param 1=value 1]|[...]|[named param--            n=value n]|[...]library.magic_for_each=function(ctx)localopts=ctx.pipelocalmagicifopts[1]~=nilthenmagic=opts[1]:match'^%s*(.*%S)'endifmagic==nilthenerror(modulename..', ‘magic_for_each’: No parser function was provided',0)endlocalccs=ctx.itersepor''localret={}localnss=0table.insert(opts,1,true)flush_params(ctx,function(key,val)opts[1]=keyopts[2]=valret[nss+1]=ccsret[nss+2]=ctx.frame:callParserFunction(magic,opts)nss=nss+2end)ifnss>0thenifnss>2andctx.lastsep~=nilthenret[nss-1]=ctx.lastsependret[1]=ctx.headeror''ifctx.footer~=nilthenret[nss+1]=ctx.footerendctx.text=table.concat(ret)returnfalseendctx.text=ctx.ifngivenor''returnfalseend-- Syntax:  #invoke:params|call_for_each_value|template name|[append 1]|[append--            2]|[...]|[append n]|[named param 1=value 1]|[...]|[named param--            n=value n]|[...]library.call_for_each_value=function(ctx)localopts=ctx.pipelocaltnameifopts[1]~=nilthentname=opts[1]:match'^%s*(.*%S)'endiftname==nilthenerror(modulename..', ‘call_for_each_value’: No template name was provided',0)endlocalmodel={title=tname,args=opts}localccs=ctx.itersepor''localret={}localnss=0flush_params(ctx,function(key,val)opts[1]=valret[nss+1]=ccsret[nss+2]=ctx.frame:expandTemplate(model)nss=nss+2end)ifnss>0thenifnss>2andctx.lastsep~=nilthenret[nss-1]=ctx.lastsependret[1]=ctx.headeror''ifctx.footer~=nilthenret[nss+1]=ctx.footerendctx.text=table.concat(ret)returnfalseendctx.text=ctx.ifngivenor''returnfalseend-- Syntax:  #invoke:params|invoke_for_each_value|module name|[append 1]|[append--            2]|[...]|[append n]|[named param 1=value 1]|[...]|[named param--            n=value n]|[...]library.invoke_for_each_value=function(ctx)localopts=ctx.pipelocalmnamelocalfnameifopts[1]~=nilthenmname=opts[1]:match'^%s*(.*%S)'endifmname==nilthenerror(modulename..', ‘invoke_for_each_value’: No module name was provided',0)endifopts[2]~=nilthenfname=opts[2]:match'^%s*(.*%S)'endiffname==nilthenerror(modulename..', ‘invoke_for_each_value’: No function name was provided',0)endlocalmodel={title='Module:'..mname,args=opts}localmfunc=require(model.title)[fname]localccs=ctx.itersepor''localret={}localnss=0remove_numeric_keys(opts,1,1)flush_params(ctx,function(key,val)opts[1]=valret[nss+1]=ccsret[nss+2]=mfunc(ctx.frame:newChild(model))nss=nss+2end)ifnss>0thenifnss>2andctx.lastsep~=nilthenret[nss-1]=ctx.lastsependret[1]=ctx.headeror''ifctx.footer~=nilthenret[nss+1]=ctx.footerendctx.text=table.concat(ret)returnfalseendctx.text=ctx.ifngivenor''returnfalseend-- Syntax:  #invoke:params|magic_for_each_value|parser function|[append 1]--            |[append 2]|[...]|[append n]|[named param 1=value 1]|[...]|[named--            param n=value n]|[...]library.magic_for_each_value=function(ctx)localopts=ctx.pipelocalmagicifopts[1]~=nilthenmagic=opts[1]:match'^%s*(.*%S)'endifmagic==nilthenerror(modulename..', ‘magic_for_each_value’: No parser function was provided',0)endlocalccs=ctx.itersepor''localret={}localnss=0flush_params(ctx,function(key,val)opts[1]=valret[nss+1]=ccsret[nss+2]=ctx.frame:callParserFunction(magic,opts)nss=nss+2end)ifnss>0thenifnss>2andctx.lastsep~=nilthenret[nss-1]=ctx.lastsependret[1]=ctx.headeror''ifctx.footer~=nilthenret[nss+1]=ctx.footerendctx.text=table.concat(ret)returnfalseendctx.text=ctx.ifngivenor''returnfalseend-- Syntax:  #invoke:params|call_for_each_group|template name|[append 1]|[append--            2]|[...]|[append n]|[named param 1=value 1]|[...]|[named param--            n=value n]|[...]library.call_for_each_group=function(ctx)-- NOTE: `ctx.pipe` and `ctx.params` might be the original metatables!localopts=ctx.pipelocaltmpifopts[1]~=nilthentmp=opts[1]:match'^%s*(.*%S)'endiftmp==nilthenerror(modulename..', ‘call_for_each_group’: No template name was provided',0)endlocalmodel={title=tmp}localccs=ctx.itersepor''localnss=0localret={}opts={}forkey,valinpairs(ctx.pipe)doiftype(key)=='number'thenopts[key-1]=valelseopts[key]=valendendctx.pipe=optsctx.params=make_groups(ctx.params)flush_params(ctx,function(gid,group)forkey,valinpairs(opts)dogroup[key]=valendgroup[0]=gidmodel.args=groupret[nss+1]=ccsret[nss+2]=ctx.frame:expandTemplate(model)nss=nss+2end)ifnss>0thenifnss>2andctx.lastsep~=nilthenret[nss-1]=ctx.lastsependret[1]=ctx.headeror''ifctx.footer~=nilthenret[nss+1]=ctx.footerendctx.text=table.concat(ret)returnfalseendctx.text=ctx.ifngivenor''returnfalseend---                                        ------     PUBLIC ENVIRONMENT                 ------    ________________________________    ------                                        -----[[ First-position-only modifiers ]]------------------------------------------- Syntax:  #invoke:params|new|pipe tostatic_iface.new=function(frame)localctx=context_new(frame:getParent())ctx.pipe=copy_or_ref_table(frame.args,false)ctx.params={}main_loop(ctx,context_iterate(ctx,1))returnctx.textend--[[ First-position-only functions ]]------------------------------------------- Syntax:  #invoke:params|selfstatic_iface.self=function(frame)returnframe:getParent():getTitle()end--[[ Public metatable of functions ]]-----------------------------------------returnsetmetatable({},{__index=function(_,query)localfname=query:match'^%s*(.*%S)'iffname==nilthenerror(modulename..': You must specify a function to call',0)endlocalfunc=static_iface[fname]iffunc~=nilthenreturnfuncendfunc=library[fname]iffunc==nilthenerror(modulename..': The function ‘'..fname..'’ does not exist',0)endreturnfunction(frame)localctx=context_new(frame:getParent())ctx.pipe=copy_or_ref_table(frame.args,refpipe[fname])ctx.params=copy_or_ref_table(ctx.oparams,refparams[fname])main_loop(ctx,func)returnctx.textendend})
Retrieved from "https://en.wikipedia.org/w/index.php?title=Module:Params&oldid=1297865432"
Categories:
Hidden category:

[8]ページ先頭

©2009-2025 Movatter.jp