| Thismodule is rated asready for general use. It has reached a mature state, is considered relatively stable and bug-free, and may be used wherever appropriate. It can be mentioned onhelp pages and other Wikipedia resources as an option for new users. To minimise server load and avoid disruptive output, improvements should be developed throughsandbox testing rather than repeated trial-and-error editing. |
| This module is currently under extended confirmed protection. Extended confirmed protection prevents edits from all unregistered editors and registered users with fewer than 30 days tenure and 500 edits. Thepolicy on community use specifies that extended confirmed protection can be applied to combat disruption, if semi-protection has proven to be ineffective. Extended confirmed protection may also be applied to enforcearbitration sanctions. Please discuss any changes on thetalk page; you maysubmit an edit request to ask for uncontroversial changes supported byconsensus. |
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 very few 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./examples you can find some of the examples shown in this documentation page.
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.
Among the possibilities that the module offers there is that of performing a series of actions after additional 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:
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:
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:
This mechanism has the intrinsic advantage that it allows the concatenation of 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}}
Most modifiers immediately affect what follows, while others add their action to the queue of actions that will be done last, thus affecting only the wayfunctions behave (e.g.sequential,non-sequential,all_sorted,reassorted – these are called “flag modifiers”). A rule of thumb in the nomenclature is the following:
sequential)new directive – e.g.squeezing)list_values)The two flag modifierssequential andnon-sequential refer to a technical jargon used in wikitext: given a parameter list, the subgroup ofsequential 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.
Normally on Wikipedia, when templates are written across multiple lines inblock style, by convention the pipe sign (|) is written on the left side of each new line, as in the following example:
{{cite book| last= Bloggs| first= Joe| author-link= Joe Bloggs| date= 1974| title= Book of Bloggs}}
Doing the same with{{#invoke:params}} however is often impossible, because the module tends to preserve trailing spaces and new lines in all its arguments except in modifier and function names (and, accordingly, a newline character would be parsed as belonging to the last parameter of each line). Because of this, the only safe and meaningful way to invoke this module inblock style is by appending the pipe signat the end of the line, right before a modifier name or a function name, as in the following example:
{{#invoke:params|all_sorted|excluding_non-numeric_names|mapping_by_replacing|[^abdlp]+||mapping_by_replacing|a|⏒||plain|mapping_by_replacing|b|⏑||plain|mapping_by_replacing|d|⏔||plain|mapping_by_replacing|l|‒||plain|mapping_by_replacing|p|⏖||plain|trimming_values|mapping_by_replacing|%s+| |setting|h/i/f|<big> | || </big>|list_values}}
Here follows the list of functions. You might want to see also§ Flag modifiers and§ Modifiers.
self| Num. of arguments | 0 |
|---|---|
| Not affected by | Any modifier |
| See also | |
{{#invoke:TEMPLATENAME|main}},{{FULLPAGENAME}} | |
{{#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| Num. of arguments | 0 |
|---|---|
| Often preceeded by | sequential |
| Not affected by | all_sorted,reassorted,setting,sorting_sequential_val…,mapping_by_calling,mapping_by_invoking,mapping_by_magic,mapping_by_replacing |
| See also | |
{{#invoke:ParameterCount}} | |
{{#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| Num. of arguments | Ad libitum |
|---|---|
| Not affected by | all_sorted,reassorted |
| See also | |
combining_by_calling,concat_and_invoke,concat_and_magic,{{#invoke:template wrapper|wrap}} | |
{{#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 tocutting might beimposing.
If no other argument besides thetemplate name is provided this function simply echoes the current parameters to another template.
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| Num. of arguments | Ad libitum |
|---|---|
| Not affected by | all_sorted,reassorted |
| See also | |
concat_and_call,concat_and_magic | |
{{#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.
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| Num. of arguments | Ad libitum |
|---|---|
| Not affected by | all_sorted,reassorted |
| See also | |
concat_and_call,concat_and_invoke | |
{{#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.
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| Num. of arguments | 1 |
|---|---|
| Relevantfunction-only variables | h,f,n |
| Not affected by | all_sorted,reassorted |
| See also | |
list_values,list_maybe_with_names,coins,unique_coins | |
{{#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), the last iteration delimiter (l) and the "serial-comma-like" last iteration delimiter (s) 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| Num. of arguments | 0 |
|---|---|
| Sortable | Yes |
| Relevantfunction-only variables | h,p,i,l,f,n |
| See also | |
list_values,list_maybe_with_names | |
{{#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 "serial-comma-like" last iteration delimiter (s), 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.
list_values| Num. of arguments | 0 |
|---|---|
| Sortable | Yes |
| Often preceeded by | sequential |
| Relevantfunction-only variables | h,i,l,f,n |
| See also | |
list,list_maybe_with_names,value_of,coins,unique_coins,{{#invoke:separated entries}} | |
{{#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 "serial-comma-like" last iteration delimiter (s), 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/f/n|'''Values of parameters passed:'''|;|.|'''No parameters were passed'''|list_values}}
will generate an output similar to the following.
list_maybe_with_names| Num. of arguments | 0 |
|---|---|
| Sortable | Yes |
| Often preceeded by | sequential |
| Relevantfunction-only variables | h,i,l,f,n |
| See also | |
list,list_values,value_of,coins,unique_coins,{{#invoke:separated entries}} | |
{{#invoke:params|list_maybe_with_names}}This function does not take arguments. It is a combination oflist andlist_values: if a parameter belongs to the parameter sequence only its value will be shown, otherwise both its name and its value will be shown. 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 "serial-comma-like" last iteration delimiter (s), a footer (f), and a fallback text (n) can be declared viasetting.
For example, the following code in{{My template}},
{{#invoke:params|setting|h/i/p/f/n|'''Parameters passed:'''|;|→|.|'''No parameters were passed'''|list_maybe_with_names}}
when transcluded as{{My template|one|two|three|four|foo=bar|hello=world}}, will generate an output similar to the following.
This function is particularly useful to mimic the natural transclusion of templates.
coins| Num. of arguments | Ad libitum |
|---|---|
| Sortable | Yes |
| Often preceeded by | sequential,trimming_values |
| Relevantfunction-only variables | h,i,l,f,n |
| See also | |
unique_coins,list_values,value_of | |
{{#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| Num. of arguments | Ad libitum |
|---|---|
| Sortable | Yes |
| Often preceeded by | sequential,trimming_values |
| Relevantfunction-only variables | h,i,l,f,n |
| See also | |
coins,list_values,value_of | |
{{#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:
A copy of the example above is available at {{./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 "serial-comma-like" last iteration delimiter (s), 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| Num. of arguments | Ad libitum |
|---|---|
| Sortable | Yes |
| Relevantfunction-only variables | h,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}} | |
{{#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 "serial-comma-like" last iteration delimiter (s), 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.
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| Num. of arguments | Ad libitum |
|---|---|
| Sortable | Yes |
| Relevantfunction-only variables | h,i,l,f,n |
| See also | |
invoke_for_each_value,mapping_by_invoking,call_for_each,magic_for_each | |
{{#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.
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| Num. of arguments | Ad libitum |
|---|---|
| Sortable | Yes |
| Relevantfunction-only variables | h,i,l,f,n |
| See also | |
magic_for_each_value,mapping_by_magic,call_for_each,invoke_for_each | |
{{#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.
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| Num. of arguments | Ad libitum |
|---|---|
| Sortable | Yes |
| Often preceeded by | sequential |
| Relevantfunction-only variables | h,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}} | |
{{#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 "serial-comma-like" last iteration delimiter (s), 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.
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| Num. of arguments | Ad libitum |
|---|---|
| Sortable | Yes |
| Often preceeded by | sequential |
| Relevantfunction-only variables | h,i,l,f,n |
| See also | |
call_for_each_value,mapping_by_invoking,invoke_for_each,magic_for_each_value | |
{{#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.
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| Num. of arguments | Ad libitum |
|---|---|
| Sortable | Yes |
| Often preceeded by | sequential |
| Relevantfunction-only variables | h,i,l,f,n |
| See also | |
call_for_each_value,mapping_by_magic,invoke_for_each_value,magic_for_each | |
{{#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.
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| Num. of arguments | Ad libitum |
|---|---|
| Often preceeded by | all_sorted,reassorted |
| Sortable | Yes |
| Relevantfunction-only variables | h,i,l,f,n |
| See also | |
grouping_by_calling,call_for_each,call_for_each_value,{{#invoke:for loop}},{{for loop}} | |
{{#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 "serial-comma-like" last iteration delimiter (s), 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.
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 {{./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
See also {{./examples/tablebox}} for an example of how to exploit this function to createinfoboxes, and {{./examples/four cells per row table}} for an example of how to exploit this function to create n-column tables.
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| Num. of arguments | 1 |
|---|---|
| Sortable | Yes |
| Relevantfunction-only variables | h,i,l,f,n |
| See also | |
list,list_values,list_maybe_with_names,{{#invoke:for nowiki}},{{for nowiki}},{{expand wikitext}} | |
$# and$@ within a given text as key and value respectively{{#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}}
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.
The following areflag modifiers, i.e. functions that add their action to the queue of actions thatwill be done last, and which expect to be piped instead of returning to the caller. Each of them can be followed by either another flag modifier or amodifier or anon-piping function. The order in which flag modifiers appear has no consequences. The actions that flags do affects only functions, but do not affect modifiers.
sequential| Num. of arguments | 0 |
|---|---|
| Repeatable | No |
| Conflicts with | non-sequential,all_sorted,reassorted |
| See also | |
non-sequential,all_sorted,reassorted,squeezing,filling_the_gaps,clearing | |
|1={{#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.
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| Num. of arguments | 0 |
|---|---|
| Repeatable | No |
| Conflicts with | sequential |
| See also | |
sequential,all_sorted,reassorted | |
|1={{#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.
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| Num. of arguments | 0 |
|---|---|
| Repeatable | No |
| Conflicts with | sequential,reassorted |
| Has no effects on | count,value_of,concat_and_call,concat_and_invoke,concat_and_magic |
| See also | |
Natural sort order,reassorted,sequential,sorting_sequential_values | |
{{#invoke:params|all_sorted|pipe function name}}
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:
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| Num. of arguments | 0 |
|---|---|
| Repeatable | No |
| Conflicts with | sequential,all_sorted |
| Has no effects on | count,value_of,concat_and_call,concat_and_invoke,concat_and_magic |
| See also | |
Natural sort order,all_sorted,sequential,sorting_sequential_values | |
{{#invoke:params|reassorted|pipe function name}}This modifier is similar toall_sorted, but numbers are iterated last (as in "bar, foo, hello, zebra, 1, 2, 3, …").
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.
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 aflag modifier or anon-piping function. The actions that modifiers do are done sequentially, in the same order chosen during the invocation of this module.
setting| Num. of arguments | 2–7 (variable) | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Repeatable | Yes | ||||||||||||||
| Memory slots | |||||||||||||||
| |||||||||||||||
{{#invoke:params|setting|directives|...|pipe function name}}This modifier allows some internal variables to be set and later be used (currently only 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}}|, then list all values{{#invoke:params|setting|ih|{{!}}|list_values}}|, then list all values{{#invoke:params|setting|ih/p|{{!}}|{{=}}|list}}|, setkey-value pair delimiter to=, then list all parameters{{#invoke:params|setting|ih/p/n|{{!}}|{{=}}|No parameters were passed|list}}|, setkey-value pair delimiter to=, setfallback text toNo parameters were passed, then list all parametersThe 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:
| Slots | Variable | Description |
|---|---|---|
p | Key-value pair delimiter | The 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. |
i | Iteration delimiter | The 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. |
l | Last iteration delimiter | The 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 it defaults toi. |
s | "Serial-comma-like" last iteration delimiter | The string of text that will be placed between the second last and the last iteration when there are three or more parameters to show; if omitted it defaults tol. |
h | Header text | The string of text that will be placed before the iteration begins; it is never inserted if there are no parameters to show. |
f | Footer text | The string of text that will be placed after the iteration is over; it is never inserted if there are no parameters to show. |
n | Fallback text | The string of text that will be placed if there are no parameters to show. |
All space characters in thedirectives argument 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.
Thes slot has been created with theOxford comma in mind. For instance, the following imaginary{{Foobar see also}} template adds a comma before the "and" conjunction when more than two page names are provided:
{{Hatnote|{{{altphrase|Foobar see also}}}:{{#if:{{{1|}}}|{{#invoke:params|sequential|trimming_values|with_value_not_matching||strict|squeezing|setting|i/l/s|,| and|, and|for_each|[[$@]]}}|{{Error|{{tl|Foobar see also}} requires at least one page name}}}}}}
You can find this example at {{./examples/Oxford comma}}. For instance,{{module:params/doc/examples/Oxford comma|Latin|English|German|Italian}} will generate
Note: Thesetting modifier will be trimmed of its surrounding spaces. Thedirectives 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| Num. of arguments | 0 |
|---|---|
| Repeatable | Yes |
| See also | |
filling_the_gaps,sequential,clearing,TableTools.compressSparseArray | |
{{#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:
{{...|excluding_numeric_names|...}}{{...|with_name_not_matching|^%-?%d+$|...}}{{...|non-sequential|squeezing|...}}{{...|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| Num. of arguments | 0 |
|---|---|
| Repeatable | Yes |
| See also | |
squeezing,sequential,clearing | |
{{#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 lowest numeric parameter will not be filled. The following table provides some examples.
Before callingfilling_the_gaps | After callingfilling_the_gaps |
|---|---|
|1=... | |1=... |
|2=... | |1=,|2=... |
|6=...,|9=... | |1=,|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=... |
Note: There is a safety limit of at most 1024 undefined parameters that can be filled using this modifier.
clearing| Num. of arguments | 0 |
|---|---|
| Repeatable | Yes |
| Often accompanied by | sequential |
| See also | |
sequential,squeezing,filling_the_gaps | |
{{#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| Num. of arguments | 2 |
|---|---|
| Repeatable | Yes |
| Often accompanied by | sequential |
| See also | |
sequential,squeezing,filling_the_gaps,clearing,cropping,purging,backpurging,reversing_numeric_names,sorting_sequential_values | |
{{#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 other positive 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}}
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| Num. of arguments | 2 |
|---|---|
| Repeatable | Yes |
| Often accompanied by | sequential |
| See also | |
sequential,squeezing,filling_the_gaps,clearing,cutting,purging,backpurging,reversing_numeric_names,sorting_sequential_values | |
{{#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, the following parameters are left:
If instead the template were to use thecropping modifier with2 and1 as arguments, as in the example above, the following parameters would be left:
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| Num. of arguments | 2 |
|---|---|
| Repeatable | Yes |
| Often accompanied by | sequential |
| See also | |
sequential,squeezing,filling_the_gaps,clearing,cutting,cropping,backpurging,reversing_numeric_names,sorting_sequential_values | |
{{#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| Num. of arguments | 2 |
|---|---|
| Repeatable | Yes |
| Often accompanied by | sequential |
| See also | |
sequential,squeezing,filling_the_gaps,clearing,cutting,cropping,purging,reversing_numeric_names,sorting_sequential_values | |
{{#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| Num. of arguments | 0 |
|---|---|
| Repeatable | Yes |
| Often accompanied by | sequential |
| See also | |
sequential,squeezing,filling_the_gaps,clearing,cutting,cropping,purging,backpurging,sorting_sequential_values | |
|1= are swapped{{#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|[$#: $@]}}
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| Num. of arguments | 0 or 1 |
|---|---|
| Repeatable | Yes |
| Often accompanied by | sequential |
| See also | |
sequential,squeezing,filling_the_gaps,clearing,cutting,cropping,purging,backpurging,reversing_numeric_names,all_sorted,reassorted | |
{{#invoke:params|sorting_sequential_values|[criterion]|pipe function name}}
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| Num. of arguments | 2 |
|---|---|
| Repeatable | Yes |
| See also | |
providing,discarding,filling_the_gaps | |
{{#invoke:params|imposing|name|value|pipe function name}}Example:
{{#invoke:params|imposing|foo|bar|imposing|hello|world|for_each|[$#: $@]}}
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| Num. of arguments | 2 |
|---|---|
| Repeatable | Yes |
| See also | |
imposing,discarding,filling_the_gaps | |
{{#invoke:params|providing|name|value|pipe function name}}Example:
{{#invoke:params|providing|foo|bar|providing|hello|world|for_each|[$#: $@]}}
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| Num. of arguments | 1 or 2 |
|---|---|
| Repeatable | Yes |
| See also | |
clearing,cutting,cropping,purging,backpurging | |
{{#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 {{./examples/check for unknown parameters}}. For instance,{{module:params/doc/examples/check for unknown parameters|hello=world|wind=surfing}} will generate
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.
Note: All arguments passed to this modifier and thediscarding modifier name itself will be trimmed of their surrounding spaces.
excluding_non-numeric_names| Num. of arguments | 0 |
|---|---|
| Repeatable | Yes |
| See also | |
excluding_non-numeric_names,with_name_matching,with_name_not_matching,clearing | |
{{#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| Num. of arguments | 0 |
|---|---|
| Repeatable | Yes |
| See also | |
excluding_non-numeric_names,with_name_matching,with_name_not_matching | |
{{#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| Num. of arguments | Ad libitum |
|---|---|
| Repeatable | Yes |
| See also | |
excluding_numeric_names,excluding_non-numeric_names,with_name_not_matching,with_value_matching,with_value_not_matching | |
{{#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:
^Image pattern:{{#invoke:params|setting|ih/p|{{!}}|{{=}}|with_name_matching|^Image|list}}^Imageand%d+$:{{#invoke:params|setting|ih/p|{{!}}|{{=}}|with_name_matching|^Image|with_name_matching|%d+$|list}}^Nameor the^Latin$ pattern:{{#invoke:params|setting|ih/p|{{!}}|{{=}}|with_name_matching|^Name$|or|^Latin$|list}}ma plain stringor theme$ pattern:{{#invoke:params|setting|ih/p|{{!}}|{{=}}|with_name_matching|ma|plain|or|me$|list}}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 {{./examples/enumerate}}.
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| Num. of arguments | Ad libitum |
|---|---|
| Repeatable | Yes |
| See also | |
excluding_numeric_names,excluding_non-numeric_names,with_name_matching,with_value_matching,with_value_not_matching | |
{{#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:
a pattern:{{#invoke:params|setting|ih/p|{{!}}|{{=}}|with_name_not_matching|a|list}}a 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}}a plain stringor then plain string:{{#invoke:params|setting|ih/p|{{!}}|{{=}}|with_name_not_matching|a|plain|or|n|plain|list}}
* For the sake of efficiency, please don't use this modifier with thestrict flag unless accompanied byor, usediscarding instead!
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| Num. of arguments | Ad libitum |
|---|---|
| Repeatable | Yes |
| See also | |
with_name_matching,with_name_not_matching,with_value_not_matching | |
{{#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}}
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| Num. of arguments | Ad libitum |
|---|---|
| Repeatable | Yes |
| See also | |
with_name_matching,with_name_not_matching,with_value_matching | |
{{#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}}
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| Num. of arguments | 0 |
|---|---|
| Repeatable | Yes |
{{#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 other Wikipedia modules behave. For example, if we wanted to emulate {{#invoke:Separated entries|main}}, writing
{{#invoke:params|sequential|trimming_values|with_value_not_matching||strict|squeezing|setting|i|XXXX|list_values}}
will be equivalent to writing,
{{#invoke:separated entries|main|separator=XXXX}}
whereas writing
{{#invoke:params|sequential|trimming_values|with_value_not_matching||strict|squeezing|setting|i/l|XXXX|YYYY|list_values}}
will be equivalent to writing
{{#invoke:separated entries|main|separator=XXXX|conjunction=YYYY}}
The {{./examples/trim and call}} example template shows how to call any arbitrary template trimming all parameters beforehand.
mapping_to_lowercase| Num. of arguments | 0 |
|---|---|
| Repeatable | Yes |
| See also | |
mapping_to_uppercase,renaming_to_lowercase,renaming_to_uppercase,mapping_by_replacing,renaming_by_replacing | |
{{#invoke:params|mapping_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.
mapping_to_uppercase| Num. of arguments | 0 |
|---|---|
| Repeatable | Yes |
| See also | |
mapping_to_lowercase,renaming_to_lowercase,renaming_to_uppercase,mapping_by_replacing,renaming_by_replacing | |
{{#invoke:params|mapping_to_uppercase|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| Num. of arguments | Ad libitum |
|---|---|
| Repeatable | Yes |
| See also | |
mapping_to_lowercase,mapping_to_uppercase,call_for_each,call_for_each_value,mapping_by_invoking,mapping_by_magic,mapping_by_replacing,renaming_to_lowercase,renaming_to_uppercase,renaming_by_calling,renaming_by_invoking,renaming_by_magic,renaming_by_replacing,grouping_by_calling | |
{{#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 flag | Example | Corresponding 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.
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| Num. of arguments | Ad libitum |
|---|---|
| Repeatable | Yes |
| See also | |
mapping_to_lowercase,mapping_to_uppercase,invoke_for_each,invoke_for_each_value,mapping_by_calling,mapping_by_magic,mapping_by_replacing,renaming_to_lowercase,renaming_to_uppercase,renaming_by_calling,renaming_by_invoking,renaming_by_magic,renaming_by_replacing,grouping_by_calling | |
{{#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).
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| Num. of arguments | Ad libitum |
|---|---|
| Repeatable | Yes |
| See also | |
mapping_to_lowercase,mapping_to_uppercase,magic_for_each,magic_for_each_value,mapping_by_calling,mapping_by_invoking,mapping_by_replacing,renaming_to_lowercase,renaming_to_uppercase,renaming_by_calling,renaming_by_invoking,renaming_by_magic,renaming_by_replacing,grouping_by_calling | |
{{#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).
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| Num. of arguments | 2–4 |
|---|---|
| Repeatable | Yes |
| See also | |
mapping_by_mixing,mapping_to_lowercase,mapping_to_uppercase,mapping_by_calling,mapping_by_invoking,mapping_by_magic,renaming_to_lowercase,renaming_to_uppercase,renaming_by_calling,renaming_by_invoking,renaming_by_magic,renaming_by_replacing,renaming_by_mixing,grouping_by_calling,mixing_names_and_values | |
{{#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 {{./examples/informal tablebox}} you can find an example on how to exploit this function to create "informal"infoboxes.
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| Num. of arguments | 1 |
|---|---|
| Repeatable | Yes |
| See also | |
mapping_to_lowercase,mapping_to_uppercase,mapping_by_calling,mapping_by_invoking,mapping_by_magic,renaming_to_lowercase,renaming_to_uppercase,renaming_by_calling,renaming_by_invoking,renaming_by_magic,renaming_by_replacing,renaming_by_mixing,grouping_by_calling,mixing_names_and_values | |
$# and$@ placeholders{{#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|[$#::$@]|...
Note: Both themixing string argument and themapping_by_mixing modifier name itself will be trimmed of their surrounding spaces.
renaming_to_lowercase| Num. of arguments | 0 |
|---|---|
| Repeatable | Yes |
| See also | |
mapping_to_lowercase,mapping_to_uppercase,renaming_to_uppercase,mapping_by_replacing,renaming_by_replacing | |
{{#invoke:params|renaming_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.
Note: In case of collisions between identical names, only one parameter, randomly chosen, will be left for a given name.
renaming_to_uppercase| Num. of arguments | 0 |
|---|---|
| Repeatable | Yes |
| See also | |
mapping_to_lowercase,mapping_to_uppercase,renaming_to_lowercase,mapping_by_replacing,renaming_by_replacing | |
{{#invoke:params|renaming_to_uppercase|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.
Note: In case of collisions between identical names, only one parameter, randomly chosen, will be left for a given name.
renaming_by_calling| Num. of arguments | Ad libitum |
|---|---|
| Repeatable | Yes |
| See also | |
mapping_to_lowercase,mapping_to_uppercase,mapping_by_calling,mapping_by_invoking,mapping_by_magic,mapping_by_replacing,renaming_to_lowercase,renaming_to_uppercase,renaming_by_invoking,renaming_by_magic,renaming_by_replacing,grouping_by_calling | |
{{#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).
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| Num. of arguments | Ad libitum |
|---|---|
| Repeatable | Yes |
| See also | |
mapping_to_lowercase,mapping_to_uppercase,mapping_by_calling,mapping_by_invoking,mapping_by_magic,mapping_by_replacing,renaming_to_lowercase,renaming_to_uppercase,renaming_by_calling,renaming_by_magic,renaming_by_replacing,grouping_by_calling | |
{{#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|rep}} to rename all parameters of type|a=,|b=, …|z= into|aaa=,|bbb= …|zzz=:
{{#invoke:params|setting|h/i/p/f|[|][|:|]|with_name_matching|^%a$|renaming_by_invoking|string|rep|1|3|list}}
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| Num. of arguments | Ad libitum |
|---|---|
| Repeatable | Yes |
| See also | |
mapping_to_lowercase,mapping_to_uppercase,mapping_by_calling,mapping_by_invoking,mapping_by_magic,mapping_by_replacing,renaming_to_lowercase,renaming_to_uppercase,renaming_by_calling,renaming_by_invoking,renaming_by_replacing,grouping_by_calling | |
{{#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}}
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| Num. of arguments | 2–4 |
|---|---|
| Repeatable | Yes |
| See also | |
mapping_by_mixing,mapping_to_lowercase,mapping_to_uppercase,mapping_by_calling,mapping_by_invoking,mapping_by_magic,mapping_by_replacing,renaming_to_lowercase,renaming_to_uppercase,renaming_by_calling,renaming_by_invoking,renaming_by_magic,renaming_by_mixing,grouping_by_calling,#mixing_names_and_values | |
{{#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.
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| Num. of arguments | 1 |
|---|---|
| Repeatable | Yes |
| See also | |
mapping_by_mixing,mapping_to_lowercase,mapping_to_uppercase,mapping_by_calling,mapping_by_invoking,mapping_by_magic,renaming_to_lowercase,renaming_to_uppercase,renaming_by_calling,renaming_by_invoking,renaming_by_magic,renaming_by_replacing,grouping_by_calling,mixing_names_and_values | |
$# and$@ placeholders{{#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|[$#::$@]|...
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| Num. of arguments | Ad libitum |
|---|---|
| Repeatable | Yes[2] |
| See also | |
mapping_to_lowercase,mapping_to_uppercase,call_for_each_group,mapping_by_calling,mapping_by_invoking,mapping_by_magic,mapping_by_replacing,renaming_to_lowercase,renaming_to_uppercase,renaming_by_calling,renaming_by_invoking,renaming_by_magic,renaming_by_replacing | |
{{#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.
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| Num. of arguments | 1–6 |
|---|---|
| Repeatable | Yes |
| Often accompanied by | new |
| See also | |
new,{{#invoke:ArrayList}},{{Array}} | |
{{#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|[$#:$@]}}{{#invoke:params|new|parsing|one, two; three. foo: bar, hello: world|trim_all|splitter_pattern|[,;.]|setter_string|:|for_each|[$#:$@]}}{{#invoke:params|new|parsing|one/two/ three / foo % bar /hello%world|setter_string|%|trim_none|splitter_string|/|for_each|[$#:$@]}}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).
| Setting a trim flag | Setting an iteration delimiter | Setting a key-value delimiter |
|---|---|---|
trim_nonetrim_namedtrim_positionaltrim_all | splitter_string|...splitter_pattern|... | setter_string|...setter_pattern|... |
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| Num. of arguments | 1–6 |
|---|---|
| Repeatable | Yes |
| See also | |
parsing,{{#invoke:ArrayList}},{{Array}} | |
{{#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 {{./examples/constructed transclusion}}.
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| Num. of arguments | 2 |
|---|---|
| Repeatable | Yes |
| See also | |
mapping_by_mixing,mapping_to_lowercase,mapping_to_uppercase,mapping_by_calling,mapping_by_invoking,mapping_by_magic,renaming_to_lowercase,renaming_to_uppercase,renaming_by_calling,renaming_by_invoking,renaming_by_magic,renaming_by_replacing,renaming_by_mixing,grouping_by_calling | |
$# and$@ placeholders{{#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|$@/$#|[$#::$@]|...
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| Num. of arguments | 2 |
|---|---|
| Repeatable | Yes |
| See also | |
entering_substack,snapshotting,remembering,concat_and_call | |
{{#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
snapshotting| Num. of arguments | 0 |
|---|---|
| Repeatable | Yes |
| Eventually followed by | Eitherentering_substack orflushing |
| See also | |
remembering,entering_substack,pulling,merging_substack,detaching_substack,dropping_substack,leaving_substack,flushing | |
{{#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:
snapshottingrememberingentering_substackpullingdetaching_substackdropping_substackleaving_substackmerging_substackflushingEvery 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. It is also possible to drop and discard a substack completely viadropping_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:
remembering| Num. of arguments | 0 |
|---|---|
| Repeatable | Yes |
| Eventually followed by | Eitherentering_substack orflushing |
| See also | |
snapshotting,entering_substack,pulling,merging_substack,detaching_substack,dropping_substack,leaving_substack,flushing | |
{{#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| Num. of arguments | 0 |
|---|---|
| Repeatable | Yes |
| May be immediately followed by | new |
| Eventually followed by | Eithermerging_substack orleaving_substack followed byflushing |
| See also | |
snapshotting,remembering,pulling,merging_substack,detaching_substack,dropping_substack,leaving_substack,flushing | |
{{#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 three different modifiers:merging_substack,leaving_substack anddropping_substack.
pulling| Num. of arguments | 1 |
|---|---|
| Repeatable | Yes |
| Often preceeded by | new |
| See also | |
snapshotting,remembering,merging_substack,detaching_substack,dropping_substack,leaving_substack,flushing | |
{{#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| Num. of arguments | 0 |
|---|---|
| Repeatable | Yes |
| Restrictions | Usable only inside substacks |
| See also | |
snapshotting,remembering,entering_substack,pulling,dropping_substack,merging_substack,leaving_substack,flushing | |
{{#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.
dropping_substack| Num. of arguments | 0 |
|---|---|
| Repeatable | Yes |
| Restrictions | Usable only inside substacks |
| See also | |
snapshotting,remembering,entering_substack,pulling,merging_substack,leaving_substack,flushing | |
{{#invoke:params|dropping_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| Num. of arguments | 0 |
|---|---|
| Repeatable | Yes |
| Restrictions | Usable only inside substacks |
| See also | |
snapshotting,remembering,entering_substack,pulling,merging_substack,detaching_substack,dropping_substack,flushing | |
{{#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| Num. of arguments | 0 |
|---|---|
| Repeatable | Yes |
| Restrictions | Usable only inside substacks |
| See also | |
snapshotting,remembering,entering_substack,pulling,detaching_substack,dropping_substack,leaving_substack,flushing | |
{{#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| Num. of arguments | 0 |
|---|---|
| Repeatable | Yes |
| See also | |
snapshotting,remembering,entering_substack,pulling,merging_substack,detaching_substack,dropping_substack,leaving_substack | |
{{#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| Num. of arguments | 0 |
|---|---|
| Repeatable | No |
| Restrictions | First position only |
| See also | |
parsing,imposing,providing,discarding | |
{{#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}}The complete list of subpages is availablehere.
{{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?}}).renaming_by_replacing in few bizarre situations, there is virtually no use in calling this modifier more than once.require[[strict]]--- ------ 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)ifrefonlythenreturnsrcendlocalnewtab={}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=dkey:match'^%s*(.-)%s*$'ifrealkey=='0'orrealkey:find'^%-?[1-9]%d*$'~=nilthenrealkey=tonumber(realkey)endifskey~=realkeythendest[realkey]=valsrc[skey]=nilendend-- Given a table, create two new tables containing the sorted list of keyslocalfunctionget_key_list_sorted(ctx,tbl,sort_fn)localnums={}localwords={}localnn=0localnw=0forkey,valinpairs(tbl)doiftype(key)=='number'thennn=nn+1nums[nn]=keyelsenw=nw+1words[nw]=keyendendtable.sort(nums)table.sort(words,sort_fn)returnnums,words,nn,nwend--[[ 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={h='header',f='footer',i='itersep',l='lastsep',n='ifngiven',p='pairsep',s='oxfordsep'}-- 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,list_maybe_with_names=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,renaming_to_uppercase=true,renaming_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*$'andsrc[pin+1]~=nilandsrc[pin+2]~=nilthennames={}repeattmp=src[pin+1]:match'^%s*(.-)%s*$'iftmp=='0'ortmp:find'^%-?[1-9]%d*$'~=nilthentmp=tonumber(tmp)endnames[tmp]=src[pin+2]pin=pin+3untilsrc[pin]==nilornotsrc[pin]:match'^%s*let%s*$'orsrc[pin+1]==nilorsrc[pin+2]==nilendtmp=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>-1thenkarg=src[tmp+shf]:match'^%s*(.-)%s*$'ifkarg=='0'orkarg:find'^%-?[1-9]%d*$'~=nilthenkarg=tonumber(karg)n_exist=math.max(n_exist,karg)endendtmp=style[7]iftmp>-1thenvarg=src[tmp+shf]:match'^%s*(.-)%s*$'ifvarg=='0'orvarg:find'^%-?[1-9]%d*$'~=nilthenvarg=tonumber(varg)n_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,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!localprefixlocalgidlocalgroups={}forkey,valinpairs(src)do-- `key` must only be a string or a number...iftype(key)=='string'thenprefix,gid=key:match'^%s*(.-)%s*(%-?%d*)%s*$'gid=tonumber(gid)or''elseprefix=''gid=keyendifgroups[gid]==nilthengroups[gid]={}endifprefix=='0'orprefix:find'^%-?[1-9]%d*$'~=nilthenprefix=tonumber(prefix)ifprefix<1thenprefix=prefix-1endendgroups[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):match'^%s*(.-)%s*$'ifkey=='0'orkey:find'^%-?[1-9]%d*$'~=nilthenkey=tonumber(key)endval=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):match'^%s*(.-)%s*$'ifkey=='0'orkey:find'^%-?[1-9]%d*$'~=nilthenkey=tonumber(key)endval=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,words,nn,nw=get_key_list_sorted(ctx,tbl,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-- Flush the parameters by calling one of two custom functions for each value-- (after this function has been invoked `ctx.params` will be no longer usable)localfunctionmixed_flush_params(ctx,fn_seq,fn_oth)ifctx.subset==1thenforkey,valinipairs(ctx.params)dofn_seq(key,val)endreturnendifctx.subset==-1thenflush_params(ctx,fn_oth)returnendlocaltbl=ctx.paramsifctx.sorttype>0thenlocalnums,words,nn,nw=get_key_list_sorted(ctx,tbl,natural_sort)localsequence={}forkey,valinipairs(tbl)dosequence[key]=valendifctx.sorttype==2thenforidx=1,nwdofn_oth(words[idx],tbl[words[idx]])endendforidx=1,nndoifsequence[nums[idx]]thenfn_seq(nums[idx],sequence[nums[idx]])elsefn_oth(nums[idx],tbl[nums[idx]])endendifctx.sorttype~=2thenforidx=1,nwdofn_oth(words[idx],tbl[words[idx]])endendreturnendifctx.subset~=-1thenforkey,valinipairs(tbl)dofn_seq(key,val)tbl[key]=nilendendforkey,valinpairs(tbl)dofn_oth(key,val)endend-- Finalize and return a concatenated listlocalfunctionfinalize_and_return_concatenated_list(ctx,lst,len,modsize)iflen>0thenlocaltmp=ctx.oxfordseporctx.lastsepiftmp~=nilandlen>modsize*2thenlst[len-modsize+1]=tmpelseiflen>modsizeandctx.lastsep~=nilthenlst[len-modsize+1]=ctx.lastsependlst[1]=ctx.headeror''ifctx.footer~=nilthenlst[len+1]=ctx.footerendctx.text=table.concat(lst)elsectx.text=ctx.ifngivenor''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|scoring|new parameter name|pipe to--[[library.scoring = function (ctx)if ctx.pipe[1] == nil then error(modulename ..', ‘scoring’: No parameter name was provided', 0) endlocal retval = 0for _ in pairs(ctx.params) do retval = retval + 1 endctx.params[ctx.pipe[1]:match'^%s*(.-)%s*$'] = tostring(retval)return context_iterate(ctx, 2)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*$'ifkey=='0'orkey:find'^%-?[1-9]%d*$'thenkey=tonumber(key)endctx.params[key]=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*$'ifkey=='0'orkey:find'^%-?[1-9]%d*$'~=nilthenkey=tonumber(key)endifctx.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)endlocalkeylocallen=tonumber(ctx.pipe[2])iflen==nilthenkey=ctx.pipe[1]:match'^%s*(.-)%s*$'ifkey=='0'orkey:find'^%-?[1-9]%d*$'~=nilthenkey=tonumber(key)endctx.params[key]=nilreturncontext_iterate(ctx,2)endkey=tonumber(ctx.pipe[1])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,'with_name_matching')localtmplocalptnlocaltbl=ctx.paramslocalnewparams={}foridx=1,nptnsdoptn=targets[idx]ifptn[3]thentmp=ptn[1]iftmp=='0'ortmp:find'^%-?[1-9]%d*$'~=nilthentmp=tonumber(tmp)endnewparams[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,'with_name_not_matching')localtbl=ctx.paramsifnptns==1andtargets[1][3]thenlocaltmp=targets[1][1]iftmp=='0'ortmp:find'^%-?[1-9]%d*$'~=nilthentbl[tonumber(tmp)]=nilelsetbl[tmp]=nilendreturncontext_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,'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,'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|mapping_to_lowercase|pipe tolibrary.mapping_to_lowercase=function(ctx)localtbl=ctx.paramsforkey,valinpairs(tbl)dotbl[key]=val:lower()endreturncontext_iterate(ctx,1)end-- Syntax: #invoke:params|mapping_to_uppercase|pipe tolibrary.mapping_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,flg,argc,die=load_replace_args(ctx.pipe,'mapping_by_replacing')ifdiethenreturncontext_iterate(ctx,argc)endlocaltbl=ctx.paramsifflg==3thenforkey,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]=tostring(key)endreturncontext_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|renaming_to_lowercase|pipe tolibrary.renaming_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|renaming_to_uppercase|pipe tolibrary.renaming_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()returntostring(mfunc(ctx.frame:newChild(model)))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,flg,argc,die=load_replace_args(ctx.pipe,'renaming_by_replacing')ifdiethenreturncontext_iterate(ctx,argc)endlocaltbl=ctx.paramsifflg==3thenptn=ptn:match'^%s*(.-)%s*$'ifptn=='0'orptn:find'^%-?[1-9]%d*$'~=nilthenptn=tonumber(ptn)endlocalval=tbl[ptn]ifval~=nilthentbl[ptn]=nilrepl=repl:match'^%s*(.-)%s*$'ifrepl=='0'orrepl:find'^%-?[1-9]%d*$'~=nilthenrepl=tonumber(repl)endtbl[repl]=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={}localtmpifmix=='$@'thenfor_,valinpairs(ctx.params)dotmp=val:match'^%s*(.-)%s*$'iftmp=='0'ortmp:find'^%-?[1-9]%d*$'~=nilthencache[tonumber(tmp)]=valelsecache[tmp]=valendendelselocalskel,canvas,n_parts=parse_placeholder_string(mix)forkey,valinpairs(ctx.params)doforidx=2,n_parts,2doifskel[idx]thencanvas[idx]=valelsecanvas[idx]=tostring(key)endendtmp=table.concat(canvas):match'^%s*(.-)%s*$'iftmp=='0'ortmp:find'^%-?[1-9]%d*$'~=nilthencache[tonumber(tmp)]=valelsecache[tmp]=valendendendctx.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=opts[1]:match'^%s*(.-)%s*$'iftmp=='0'ortmp:find'^%-?[1-9]%d*$'~=nilthentmp=tonumber(tmp)endlocalstr=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={}localtmpifmix_k=='$@'andmix_v=='$@'thenfor_,valinpairs(ctx.params)dotmp=val:match'^%s*(.-)%s*$'iftmp=='0'ortmp:find'^%-?[1-9]%d*$'~=nilthencache[tonumber(tmp)]=valelsecache[tmp]=valendendelseifmix_k=='$@'andmix_v=='$#'thenforkey,valinpairs(ctx.params)dotmp=val:match'^%s*(.-)%s*$'iftmp=='0'ortmp:find'^%-?[1-9]%d*$'~=nilthencache[tonumber(tmp)]=tostring(key)elsecache[tmp]=tostring(key)endendelseifmix_k=='$#'andmix_v=='$#'thenfor_,valinpairs(ctx.params)docache[key]=tostring(key)endelselocalskel_k,cnv_k,n_parts_k=parse_placeholder_string(mix_k)localskel_v,cnv_v,n_parts_v=parse_placeholder_string(mix_v)forkey,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):match'^%s*(.-)%s*$'iftmp=='0'ortmp:find'^%-?[1-9]%d*$'~=nilthentmp=tonumber(tmp)endcache[tmp]=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=merge_into:match'^%s*(.-)%s*$'ifmerge_into=='0'ormerge_into:find'^%-?[1-9]%d*$'~=nilthenmerge_into=tonumber(merge_into)endctx.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=opts[1]:match'^%s*(.-)%s*$'iftmp=='0'ortmp:find'^%-?[1-9]%d*$'~=nilthentmp=tonumber(tmp)endifparent[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|dropping_substack|pipe tolibrary.dropping_substack=function(ctx)localncurrparent=ctx.n_parentsifncurrparent<1thenerror(modulename..', ‘dropping_substack’: No substack has been created',0)endctx.params=ctx.parents[ncurrparent]ctx.parents[ncurrparent]=nilctx.n_parents=ncurrparent-1returncontext_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:'..mname,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.pipeifopts[1]==nilthenerror(modulename..', ‘value_of’: No parameter name was provided',0)endlocalvallocalkey=opts[1]:match'^%s*(.-)%s*$'ifkey=='0'orkey:find'^%-?[1-9]%d*$'~=nilthenkey=tonumber(key)val=ctx.params[key]-- No worries: #ctx.params is unused if the modifier in first positionifval~=niland(ctx.subset~=-1orkey>#ctx.paramsorkey<1)and(ctx.subset~=1or(key<=#ctx.paramsandkey>0))thenctx.text=(ctx.headeror'')..val..(ctx.footeror'')elsectx.text=ctx.ifngivenor''endelseval=ctx.params[key]ifctx.subset~=1andval~=nilthenctx.text=(ctx.headeror'')..val..(ctx.footeror'')elsectx.text=ctx.ifngivenor''endendreturnfalseend-- 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)finalize_and_return_concatenated_list(ctx,ret,nss,4)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)finalize_and_return_concatenated_list(ctx,ret,nss,2)returnfalseend-- Syntax: #invoke:params|list_maybe_with_nameslibrary.list_maybe_with_names=function(ctx)-- NOTE: `ctx.pipe` might be the original metatable!localkvs=ctx.pairsepor''localpps=ctx.itersepor''localret={}localnss=0mixed_flush_params(ctx,function(key,val)ret[nss+1]=ppsret[nss+2]=''ret[nss+3]=''ret[nss+4]=valnss=nss+4end,function(key,val)ret[nss+1]=ppsret[nss+2]=keyret[nss+3]=kvsret[nss+4]=valnss=nss+4end)finalize_and_return_concatenated_list(ctx,ret,nss,4)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.paramslocaltmpforkey,valinpairs(tbl)dotmp=val:match'^%s*(.-)%s*$'iftmp=='0'ortmp:find'^%-?[1-9]%d*$'~=nilthentbl[key]=opts[tonumber(tmp)]elsetbl[key]=opts[tmp]endendreturnlibrary.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=val:match'^%s*(.-)%s*$'iftmp=='0'ortmp:find'^%-?[1-9]%d*$'~=nilthentmp=tonumber(tmp)endtbl[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)finalize_and_return_concatenated_list(ctx,ret,nss,2)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)finalize_and_return_concatenated_list(ctx,ret,nss,2)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)finalize_and_return_concatenated_list(ctx,ret,nss,2)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)finalize_and_return_concatenated_list(ctx,ret,nss,2)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)finalize_and_return_concatenated_list(ctx,ret,nss,2)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)finalize_and_return_concatenated_list(ctx,ret,nss,2)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)finalize_and_return_concatenated_list(ctx,ret,nss,2)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)finalize_and_return_concatenated_list(ctx,ret,nss,2)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})