This module is rated as ready for general use. It has reached a mature form and is thought to be relatively bug-free and ready for use wherever appropriate. It is ready to mention on help pages and other Wikipedia resources as an option for new users to learn. To reduce server load and bad output, it should be improved by sandbox testing rather than repeated trial-and-error editing. |
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 to
variadic templates, to which it offers the possibility to count, list, map and propagate the parameters received without knowing their number in advance.
The module offers elegant shortcuts to non variadic templates as well. Outside templates it has virtually no applications; hence, if you plan to make experiments, make sure to do them from within a template, or you will not be able to see much (you can use {{ Template sandbox}} for that). Under ./testcases you can find helper templates that can be specifically used for testing the module's capabilities in flexible ways (see in particular the {{ ./testcases/tmulti}} template).
Note: In case your template uses this module, please add {{
lua
Among the possibilities that the module offers there is that of performing a series of actions after novel arguments have been concatenated to templates' incoming parameters. As this makes it necessary to keep the argument slots clean from interference, instead of named arguments in order to specify options this module uses piping functions (i.e. functions that expect to be piped instead of returning to the caller), or modifiers. This creates a syntax similar to the following example:
{{#invoke:params|[modifier]|[...]|[modifier]|[...]|function|[...]}}
For instance, as the name suggests, the
list
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 the
setting
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 arguments,
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 of
definition lists,
{{#invoke:params|setting|h/p/i/f|<dl><dt>|</dt><dd>|</dd><dt>|</dd></dl>|list}}
thus yielding:
By placing the
with_name_matching
modifier before the
list
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 to concatenate infinite modifiers. And so, in order to get the accurate result that we want to obtain we could write:
{{#invoke:params|non-sequential|with_name_matching|^B|with_name_matching|n$|with_value_matching|feline|setting|h/p/i/f|<dl><dt>|</dt><dd>|</dd><dt>|</dd></dl>|list}}
The two modifiers
sequential
and
non-sequential
refer to a technical jargon used in wikitext: given a parameter list, the subgroup of sequential parameters is constituted by the largest group of consecutive numerical parameters starting from
Here follows the list of functions. You might want to see also § Modifiers.
self
Num. of arguments | 0 |
---|---|
Not affected by | Any modifier |
See also | |
{{
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 named Page X
contained only a transclusion of a template named {{foobar}}
, and the latter contained the following wikitext,
{{#invoke:params|self}}
{{FULLPAGENAME}}
if we visited Template:Foobar
we would see,
Template:Foobar Template:Foobar
whereas if we visited Page X
we would see:
Template:Foobar Page 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.
If Page X
transcluded {{foobar 2}}
and the latter were a redirect to {{foobar}}
, we would still see
Template:Foobar Page X
A typical use case of this function is that of providing stable links for editing transcluded templates. E.g.:
{{|{{#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 ,
setting ,
sorting_sequential_val… ,
mapping_by_calling ,
mapping_by_invoking ,
mapping_blindly_by_cal… ,
mapping_blindly_by_inv… |
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 arguments,
{{#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 |
See also | |
concat_and_invoke ,
concat_and_magic |
{{#invoke:params|concat_and_call|template name|[prepend 1]|[prepend 2]|[...]|[prepend n]|[named item 1=value 1]|[...]|[named item n=value n]|[...]}}
For example, if our {{example template}}
had the following code,
{{#invoke:params|concat_and_call|foobar|elbow|earth|room|7=classy|hello=not today}}
and were called with,
the following call to the {{foobar}}
template would be performed:
By using the
cutting
modifier it is possible to impose numerical 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 with hello world
:
{{#invoke:params|cutting|3|0|concat_and_call|my template|{{{1|}}}|{{{2|}}}|hello world}}
If no other argument besides the template name are provided this function simply echoes the current parameters to another template.
Note: All arguments passed to this function except the template name are not trimmed of their leading and trailing spaces. The concat_and_call
function name itself, however, will be trimmed of its surrounding spaces.
concat_and_invoke
Num. of arguments | Ad libitum |
---|---|
Not affected by |
all_sorted |
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 like
concat_and_call
, but invokes a module instead of calling a template.
Note: All arguments passed to this function except the module name and the function name are not trimmed of their leading and trailing spaces. The concat_and_invoke
function name itself, however, will be trimmed of its surrounding spaces.
concat_and_magic
Num. of arguments | Ad libitum |
---|---|
Not affected by |
all_sorted |
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 like
concat_and_call
, but calls a
parser function instead of a template.
Note: All arguments passed to this function except the magic word are not trimmed of their leading and trailing spaces. The concat_and_magic
function name itself, however, will be trimmed of its surrounding spaces.
value_of
Num. of arguments | 1 |
---|---|
Relevant runtime variables | h , f , n |
Not affected by |
all_sorted |
See also | |
list_values |
{{#invoke:params|value_of|parameter name}}
Without modifiers this function is similar to writing {{{parameter name|}}}
. With modifiers, however, it allows to reach 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 the
setting
modifier – the strings assigned to the key-value pair delimiter (p
), the iteration delimiter (i
) and the last iteration delimiter (l
) will be ignored.
For instance, the {{ If then show}} template could be rewritten as
{{#invoke:params|with_value_not_matching|^%s*$|setting|h/f/n|{{{3|}}}|{{{4|}}}|{{{2|}}}|value_of|1}}
Simplifying, the following wikitext expands to the first parameter that is not empty:
{{#invoke:params|with_value_not_matching||strict|squeezing|value_of|1}}
Whereas the following wikitext expands to the first parameter that is not blank (i.e. neither empty nor containing only whitespaces)
{{#invoke:params|with_value_not_matching|^%s*$|squeezing|value_of|1}}
list
Num. of arguments | Ad libitum |
---|---|
Sortable | Yes |
Relevant runtime variables | h , p , i , l , f , n |
See also | |
list_values |
{{#invoke:params|list}}
This function does not take arguments.
If the
setting
modifier was not placed earlier, this function will not add delimiters, but will return an indistinct blob of text in which keys and values are sticked to each other. A header (h
), a key-value pair delimiter (p
), an iteration delimiter (i
), a last iteration delimiter (l
), a footer (f
), and a fallback text (n
) can be declared via
setting
.
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 | Ad libitum |
---|---|
Sortable | Yes |
Often preceeded by |
sequential |
Relevant runtime variables | h , i , l , f , n |
See also | |
list ,
value_of , {{
#invoke:separated entries}} |
{{#invoke:params|list_values}}
This function does not take arguments.
The
sequential
modifier often accompanies this function. If the
setting
modifier was not placed earlier, this function will not add delimiters, but will return an indistinct blob of text in which values are sticked to each other. A header (h
), an iteration delimiter (i
), a last iteration delimiter (l
), a footer (f
), and a fallback text (n
) can be declared via
setting
– the string assigned to the key-value pair delimiter (p
) will be ignored.
For example, the following code
{{#invoke:params|setting|h/i/p/f/n|'''Parameters passed:''' |); | (|)|'''No parameters were passed'''|list_values}}
will generate an output similar to the following.
call_for_each
Num. of arguments | Ad libitum |
---|---|
Sortable | Yes |
Relevant runtime variables | h , i , l , f , n |
See also | |
call_for_each_value ,
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]|[...] }}
All unnamed arguments following the template name will be placed after the key-value pair. Named arguments will be passed verbatim. A header (h
), an iteration delimiter (i
), a last iteration delimiter (l
), a footer (f
), and a fallback text (n
) can be declared via the
setting
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 expanded after 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 the template name are not trimmed of their leading and trailing spaces. The call_for_each
function name itself, however, will be trimmed of its surrounding spaces.
invoke_for_each
Num. of arguments | Ad libitum |
---|---|
Sortable | Yes |
Relevant runtime variables | h , i , l , f , n |
See also | |
invoke_for_each_value ,
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 like
call_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 expanded after 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 the module name and the function name are not trimmed of their leading and trailing spaces. The invoke_for_each
function name itself, however, will be trimmed of its surrounding spaces.
magic_for_each
Num. of arguments | Ad libitum |
---|---|
Sortable | Yes |
Relevant runtime variables | h , i , l , f , n |
See also | |
magic_for_each_value ,
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 like
call_for_each
, but calls a
parser function instead of a template.
Note: All arguments passed to this function except the magic word are not trimmed of their leading and trailing spaces. The magic_for_each
function 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 |
Relevant runtime variables | h , i , l , f , n |
See also | |
call_for_each ,
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]|[...]}}
The
sequential
modifier often accompanies this function. All unnamed arguments following the template name will be appended after the value parameter. Named arguments will be passed verbatim. A header (h
), an iteration delimiter (i
), a last iteration delimiter (l
), a footer (f
), and a fallback text (n
) can be declared via the
setting
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 expanded after 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 the template name are not trimmed of their leading and trailing spaces. The call_for_each_value
function 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 |
Relevant runtime variables | h , i , l , f , n |
See also | |
call_for_each_value ,
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 like
call_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 expanded after 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 the module name and the function name are not trimmed of their leading and trailing spaces. The invoke_for_each_value
function 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 |
Relevant runtime variables | h , i , l , f , n |
See also | |
call_for_each_value ,
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 like
call_for_each_value
, but calls a
parser 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 with QUERY
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 pages with preloaded text and parameters.
Note: All arguments passed to this function except the magic word are not trimmed of their leading and trailing spaces. The magic_for_each_value
function name itself, however, will be trimmed of its surrounding spaces.
call_for_each_group
Num. of arguments | Ad libitum |
---|---|
Often preceeded by |
all_sorted |
Sortable | Yes |
Relevant runtime variables | h , i , l , f , n |
See also | |
call_for_each ,
call_for_each_value , {{
#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]|[...] }}
The custom template will be repeatedly called with the numerical id of the group (i.e. the numerical suffix) as argument zero (i.e. {{{0}}}
). This will be an empty string for the group of incoming parameters that do not have a numerical suffix. A hyphen before the numerical suffix will be interpreted as a minus sign (and therefore the group id will be treated as a negative number). Numerical 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 numerical 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 is 0
or a negative number it will be decreased by one unit in order to leave the parameter zero undisturbed (so 0
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 the template 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. Numerical argument names below 1
will be decreased by one unit (i.e. ...|call_for_each_group|0=Hello world|...
will become |-1=Hello world
in the callback template – see above).
A header (h
), an iteration delimiter (i
), a last iteration delimiter (l
), a footer (f
), and a fallback text (n
) can be declared via the
setting
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 and
TableTools.affixNums
.
For example, if a template named {{foobar}}
contained the following code,
{{#invoke:params|all_sorted|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
| 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
}}{{example template
| 0 =
| 1 = hello
| 2 = world
| = ultricies
| foo = bar
| other = elit
| sunscreen = vestibulum
}}
The modifiers
sequential
,
non-sequential
and
all_sorted
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 the with_*_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 numerical suffix are not empty strings). The
all_sorted
modifier often accompanies this function.
Warning In writing templates there is often the habit of signaling
multilevel substitutions using the {{{|safesubst:}}}
notation. This is a dangerous practice, because {{{|safesubst:}}}
means “write the parameter with an empty name, otherwise write safesubst:
”. Due to the fact that call_for_each_group
can pass parameters with an empty name, a callback template should never use {{{|safesubst:}}}
to notate multilevel substitutions, but should use instead safesubst:<noinclude />
. Not following this advice can lead to bugs that are hard to debug.
At {{ ./doc/examples/list of authors}} you can find an example of how to use this function to list authors the same way {{ Cite book}} does. For instance, writing
{{module:params/doc/examples/list of authors
| last1 = Playfair
| first1 = I. S. O.
| author-link1 = Ian Stanley Ord Playfair
| last2 = Stitt
| first2 = G. M. S.
| last3 = Molony
| first3 = C. J. C.
| last4 = Toomer
| first4 = S. E.
}}
will generate
Playfair, I. S. O.; Stitt, G. M. S.; Molony, C. J. C. & Toomer, S. E.
Note: All arguments passed to this function except the template name are not trimmed of their leading and trailing spaces. The call_for_each_group
function name itself, however, will be trimmed of its surrounding spaces.
for_each
Num. of arguments | 1 |
---|---|
Sortable | Yes |
Relevant runtime variables | h , i , l , f , n |
See also | |
list ,
list_values , {{
#invoke:for nowiki}} , {{
for nowiki}} |
$#
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 an expand_for_each
function). If you need wikitext expansion, use
concat_and_call
to propagate the incoming parameters altogether to the {{
for nowiki}} template. Example:
{{#invoke:params|sequential|concat_and_call|for nowiki|[separator]|<nowiki>{{{i}}} is {{urlencode:{{{1}}}|QUERY}}</nowiki>}}
Note: The argument passed to this function is not trimmed of its leading and trailing spaces. The for_each
function name itself, however, will be trimmed of its surrounding spaces.
The following are modifiers, i.e. functions that expect to be piped instead of returning to the caller. Each of them can be followed by either another modifier or a non-piping function. The actions that modifiers do are done sequentially, in the same order chosen during the invocation of this module. Some modifiers, however, after signaling their presence to the modifiers that might follow, add their action to the queue of actions that will be done last (e.g.
sequential
,
non-sequential
,
all_sorted
).
sequential
Num. of arguments | 0 |
---|---|
Repeatable | No |
Conflicts with |
non-sequential ,
all_sorted |
See also | |
non-sequential ,
all_sorted ,
squeezing ,
filling_the_gaps ,
clearing |
{{#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.
Using sequential
together with
non-sequential
will generate an error.
Note: Like
non-sequential
, the sequential
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 |
{{#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.
Using non-sequential
together with
sequential
will generate an error.
Note: Like
sequential
, the non-sequential
modifier permanently marks a query, and no matter what transformations will follow (see
squeezing
) the parameters' “sequence” will not be shown.
all_sorted
Num. of arguments | 0 |
---|---|
Repeatable | No |
Conflicts with |
sequential |
Has no effects on |
count ,
value_of ,
concat_and_call ,
concat_and_invoke ,
concat_and_magic |
See also | |
Natural sort order,
sequential ,
sorting_sequential_values |
{{#invoke:params|all_sorted|pipe function name}}
Note: This function sorts the way functions iterate across all parameters based on their names. If you want to sort sequential parameters based on their values, see
sorting_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. The all_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 the
squeezing
modifier can be used.
[1]
The all_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: The all_sorted
modifier cannot be used with functions that propagate several parameters together in a single call, like
concat_and_call
,
concat_and_invoke
, and
concat_and_magic
, because during a call the order of arguments is always lost. For the same reason, it is not possible to guess the order of named parameters a template was transcluded with.
setting
Num. of arguments | 2–7 (variable) | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Repeatable | Yes | ||||||||||||
Memory slots | |||||||||||||
|
{{#invoke:params|setting|directives|...|pipe function name}}
This modifier allows to set some internal variables that will be used by functions. It takes a variable number of arguments, relying on the first argument to understand how many other arguments to read. A few examples will introduce it better than words:
{{#invoke:params|setting|i|{{!}}|list_values}}
|
, then list all values{{#invoke:params|setting|ih|{{!}}|list_values}}
|
, then list all values{{#invoke:params|setting|ih/p|{{!}}|{{=}}|list}}
|
, set key-value pair delimiter to =
, then list all parameters{{#invoke:params|setting|ih/p/n|{{!}}|{{=}}|No parameters were passed|list}}
|
, set key-value pair delimiter to =
, set fallback text to No 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 when l is not given, or three or more parameters when l 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 defaults to i .
|
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 the directives arguments are discarded. Therefore writing {{#invoke:params|setting|ih/p|...}}
is equivalent to writing
{{#invoke:params|setting| i
h / p |...}}
In theory, instead of assigning different slots at once (i.e. {{...|setting|ih/p|{{!}}|{{=}}|...}}
), it is possible to write separate invocations of setting
for each variable, as in {{...|setting|ih|{{!}}|setting|p|{{=}}...}}
. This method however will be slightly less efficient.
Sometimes it might be necessary to make the values assigned depend on conditional expressions. For instance, the following imaginary {{Foobar see also}}
template uses the
#ifexpr
parser function to properly show the “and” conjunction and possibly an
Oxford comma when more than two page names are provided:
{{Hatnote|{{{altphrase|Foobar see also}}}: {{#if:{{{1|}}}
|{{#invoke:params|sequential|squeezing|setting|i/l|, |{{#ifexpr:{{#invoke:params|sequential|squeezing|count}} > 2|,}} and |trimming_values|for_each|[[$@]]}}
|{{Error|{{tl|Foobar see also}} requires at least one page name}}
}}}}
You can find this example at {{
./doc/examples/Oxford comma}}. E.g., {{module:params/doc/examples/Oxford comma|Latin|English|German|Italian}}
will generate
Note: The setting
modifier will be trimmed of its surrounding spaces. The directives argument will be stripped of all space characters, including internal spaces. All the other arguments passed to this modifier will be parsed verbatim (i.e. leading and trailing spaces will not be removed).
squeezing
Num. of arguments | 0 |
---|---|
Repeatable | Yes |
See also | |
filling_the_gaps ,
sequential ,
clearing |
{{#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.
The following three concatenations will lead to the same result of discarding all parameters with numerical names:
{{...|non-sequential|squeezing|...}}
{{...|squeezing|non-sequential|...}}
{{...|with_name_not_matching|^%-?%d+$|...}}
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 numerical parameters are lower than 1, the gap between 1 and the maximum numerical parameter will not be filled. The following table provides some examples.
Before calling filling_the_gaps
|
After calling filling_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 function.
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.
Unlike
sequential
– which affects only the way parameters are shown – this modifier actually removes all non-sequential numerical parameters, albeit leaves non-numerical parameters intact.
Example:
{{#invoke:params|clearing|setting|i/p|<br />|: |list}}
If you want to remove also non-numerical parameters, add the
with_name_matching
modifier:
{{#invoke:params|clearing|with_name_matching|^%d+$|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 ,
rotating ,
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 left on 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 of sequential 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 numerical parameters will be shifted accordingly.
In some cases it might be necessary to concatenate more than one invocation of the cutting
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, because
non-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 ,
rotating ,
sorting_sequential_values |
{{#invoke:params|cropping|left crop|right crop|pipe function name}}
This function is very similar to
cutting
, but instead of removing arguments from the extremities of the parameters' sequence, arguments will be removed counting from the first and the last numerical 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 left on 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}}
invokes the
cutting
function with 2
and 1
as arguments, as in the example above, the following parameters will be left:
If instead the template invokes the
cropping
function with 2
and 1
as arguments, the following parameters will 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 lowest numerical parameters available, the behavior will be the same as if the sum had been equal to the number of numerical parameters available, both when this is a positive value and when it is a negative value (with opposite results). When sequential parameters are present among the discarded parameters, all the remaining numerical 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 ,
rotating ,
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 lies on the right side. If the second argument contains zero or a negative number its absolute value indicates what must be left at the end of the right side of the list of numerical parameters – i.e. {{#invoke:params|purging|5|0|list}}
indicates that every numerical argument whose numerical name is greater than 4
must be removed.
Example:
{{#invoke:params|purging|2|1|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 ,
rotating ,
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 lies on the left side. If the second argument contains zero or a negative number its absolute value indicates what must be left at the end of the left side of the list of numerical parameters – i.e. {{#invoke:params|purging|5|0|list}}
indicates that every numerical argument whose numerical name is less than 6
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 numerical names, then lists the rest:
{{#invoke:params|backpurging|0|0|for_each|[$#: $@]}}
rotating
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|rotating|pipe function name}}
This modifier does not take arguments besides the name of the function that will follow.
Example:
{{#invoke:params|rotating|for_each|[$#: $@]}}
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 ,
rotating ,
all_sorted |
{{#invoke:params|sorting_sequential_values|[criterion]|pipe function name}}
Note: This function sorts sequential parameters based on their values. If you want to sort the way functions iterate across all parameters based on their names, see
all_sorted
.
This function 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 is naturally
, for ordering sequential values in
natural 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|[$#: $@]}}
with_name_matching
Num. of arguments | Ad libitum |
---|---|
Repeatable | Yes |
See also | |
with_name_not_matching ,
with_value_matching ,
with_value_not_matching |
{{#invoke:params|with_name_matching|pattern 1|[plain flag 1]|[or]|[pattern 2]|[plain flag 2]|[or]|[...]|[pattern N]|[plain flag N]|pipe function name}}
Internally this modifier uses Lua's
string.find()
function to find whether parameter names match against given patterns; therefore, unless a plain flag is set, please use the same syntax of
Lua patterns. The plain flag can be either plain
or strict
or omitted. When omitted it is assumed that the target string is a Lua pattern. The difference between plain
and strict
is that the latter also requires that the lengths match (this happens only when the two strings are 100% identical).
To express a
logical OR the or
keyword is available. To express a
logical AND instead, concatenate more invocations of with_name_matching
.
For the sake of argument we will imagine that we are invoking with_name_matching
from within the {{
Infobox artery}} template, and this is being called with the following parameters:
Test cases:
^Image
pattern:
{{#invoke:params|setting|ih/p|{{!}}|{{=}}|with_name_matching|^Image|list}}
^Image
and %d+$
:
{{#invoke:params|setting|ih/p|{{!}}|{{=}}|with_name_matching|^Image|with_name_matching|%d+$|list}}
^Name
or the ^Latin$
pattern:
{{#invoke:params|setting|ih/p|{{!}}|{{=}}|with_name_matching|^Name$|or|^Latin$|list}}
ma
plain string or the me$
pattern:
{{#invoke:params|setting|ih/p|{{!}}|{{=}}|with_name_matching|ma|plain|or|me$|list}}
Using with_name_matching
it is easy to emulate the behaviour of
Module:Enumerate (or similar modules). For instance, the following examples creates a bullet list of all the parameters passed of type |foobar1
, |foobar2
… |foobarN
:
{{#invoke:params|all_sorted|with_name_matching|^foobar%d+$|setting|ih|
* |list_values}}
It is possible to see this example live at {{ ./doc/examples/enumerate}}.
Note: The pattern arguments passed to this function are not trimmed of their leading and trailing spaces. The or
, plain
and strict
keywords, and the with_name_matching
function name itself, however, will be trimmed of their surrounding spaces.
with_name_not_matching
Num. of arguments | Ad libitum |
---|---|
Repeatable | Yes |
See also | |
with_name_matching ,
with_value_matching ,
with_value_not_matching |
{{#invoke:params|with_name_not_matching|pattern 1|[plain flag 1]|[and]|[pattern 2]|[plain flag 2]|[and]|[...]|[pattern N]|[plain flag N]|pipe function name}}
Internally this modifier uses Lua's
string.find()
function to find whether parameter names match against given patterns; therefore, unless a plain flag is set, please use the same syntax of
Lua patterns. The plain flag can be either plain
or strict
or omitted. When omitted it is assumed that the target string is a Lua pattern. The difference between plain
and strict
is that the latter also requires that the lengths match (this happens only when the two strings are 100% identical).
To express a
logical OR the or
keyword is available. To express a
logical AND instead, concatenate more invocations of with_name_not_matching
.
For the sake of argument we will imagine that we are invoking with_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 at
with_name_matching
:
a
pattern:
{{#invoke:params|setting|ih/p|{{!}}|{{=}}|with_name_not_matching|a|list}}
a
plain string and do not match against the l
plain string either:
{{#invoke:params|setting|ih/p|{{!}}|{{=}}|with_name_not_matching|a|plain|with_name_not_matching|l|plain|list}}
a
plain string or the n
plain string:
{{#invoke:params|setting|ih/p|{{!}}|{{=}}|with_name_not_matching|a|plain|or|n|plain|list}}
It is possible to use this function to check for unknown parameters:
{{#ifexpr:{{#invoke:params|with_name_not_matching|hello|strict|with_name_not_matching|wind|strict|count}} > 0
|{{#invoke:Error|error|Error: The only parameters accepted are {{para|hello}} and {{para|wind}}.}}
|Everything is good: do something
}}
You can find this example at {{
./doc/examples/check for unknown parameters}}. E.g., {{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:
Note: The pattern arguments passed to this function are not trimmed of their leading and trailing spaces. The or
, plain
and strict
keywords, and the with_name_not_matching
function 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|pattern 1|[plain flag 1]|[or]|[pattern 2]|[plain flag 2]|[or]|[...]|[pattern N]|[plain flag N]|pipe function name}}
Exactly like
with_name_matching
, but applied to parameter values instead of names.
Internally this modifier uses Lua's
string.find()
function to find whether parameter names match against given patterns; therefore, unless a plain flag is set, please use the same syntax of
Lua patterns. The plain flag can be either plain
or strict
or omitted. When omitted it is assumed that the target string is a Lua pattern. The difference between plain
and strict
is that the latter also requires that the lengths match (this happens only when the two strings are 100% identical).
Example:
{{#invoke:params|with_value_matching|banana|count}}
Note: The pattern arguments passed to this function are not trimmed of their leading and trailing spaces. The or
, plain
and strict
keywords, and the with_value_matching
function 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|pattern 1|[plain flag 1]|[and]|[pattern 2]|[plain flag 2]|[and]|[...]|[pattern N]|[plain flag N]|pipe function name}}
Exactly like
with_name_not_matching
, but applied to parameter values instead of names.
Internally this modifier uses Lua's
string.find()
function to find whether parameter names match against given patterns; therefore, unless a plain flag is set, please use the same syntax of
Lua patterns. The plain flag can be either plain
or strict
or omitted. When omitted it is assumed that the target string is a Lua pattern. The difference between plain
and strict
is that the latter also requires that the lengths match (this happens only when the two strings are 100% identical).
For instance, before calling
list
, 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 function is that of purging all empty incoming parameters before calling another template, especially when this distinguishes between empty and undefined parameters.
{{#invoke:params|with_value_not_matching|^%s*$|concat_and_call|my template}}
Note: The pattern arguments passed to this function are not trimmed of their leading and trailing spaces. The or
, plain
and strict
keywords, and the with_value_not_matching
function 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 placing trimming_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 where trimming_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, placing trimming_values
as the last modifier is usually the best choice.
Placing trimming_values
together with non-sequential
will result in an empty call with no effects, because non-sequential parameters are stripped of their leading and trailing spaces by default.
Using trimming_values
makes this module behave like many Wikipedia modules behave. For example, if we wanted to emulate {{
#invoke:Separated entries|main}}, writing
{{#invoke:params|sequential|squeezing|trimming_values|setting|i|XXXX|list_values}}
will be equivalent to writing,
{{#invoke:separated entries|main|separator=XXXX}}
whereas writing
{{#invoke:params|sequential|squeezing|trimming_values|setting|i/l|XXXX|YYYY|list_values}}
will be equivalent to writing
{{#invoke:separated entries|main|separator=XXXX|conjunction=YYYY}}
The {{ ./doc/trim and call}} example template shows how to call any arbitrary template trimming all parameters beforehand.
mapping_by_calling
Num. of arguments | Ad libitum |
---|---|
Repeatable | Yes |
See also | |
mapping_by_invoking ,
mapping_blindly_by_cal… ,
mapping_blindly_by_inv… ,
renaming_blindly_by_ca… ,
renaming_blindly_by_in… |
{{#invoke:params|mapping_by_calling|template name|[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 another template. The latter will be repeatedly called with at least two parameters: key and value. If the template name is followed by a number, this will be parsed as the amount of additional parameters to pass. 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|NAME|VALUE}}
(where NAME
and VALUE
indicate each different name and value).
On the other hand,
{{#invoke:params|mapping_by_calling|foobar|2|hello|world|setting|i/p|{{!}}|{{=}}|list}}
will do the same, but using the expansion of {{foobar|NAME|VALUE|hello|world}}
.
There are no mechanisms for passing non-sequential or non-numeric additional parameters to the mapping template. A similar function,
mapping_blindly_by_calling
, omits the first parameter (i.e. the parameter's name).
Note: All arguments passed to this modifier except the template name and the number of additional arguments are not trimmed of their leading and trailing spaces. The mapping_by_calling
modifier name itself, however, will be trimmed of its surrounding spaces.
mapping_by_invoking
Num. of arguments | Ad libitum |
---|---|
Repeatable | Yes |
See also | |
mapping_by_calling ,
mapping_blindly_by_cal… ,
mapping_blindly_by_inv… ,
renaming_blindly_by_ca… ,
renaming_blindly_by_in… |
{{#invoke:params|mapping_by_invoking|module name|function name|[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 text returned by a custom module function. The latter will be repeatedly invoked with at least two arguments: key and value. If the function name is followed by a number, this will be parsed as the amount of additional arguments to pass. 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|NAME|VALUE}}
(where NAME
and VALUE
indicate each different name and value).
On the other hand,
{{#invoke:params|mapping_by_invoking|foobar|main|2|hello|world|setting|i/p|{{!}}|{{=}}|list}}
will do the same, but using the expansion of {{#invoke:foobar|main|NAME|VALUE|hello|world}}
.
There are no mechanisms for passing non-sequential or non-numeric additional arguments to the mapping module. A similar function,
mapping_blindly_by_invoking
, omits the first argument (i.e. the parameter's name).
Note: All arguments passed to this modifier except the module name, the function name and the number of additional arguments are not trimmed of their leading and trailing spaces. The mapping_by_invoking
modifier name itself, however, will be trimmed of its surrounding spaces.
mapping_blindly_by_calling
Num. of arguments | Ad libitum |
---|---|
Repeatable | Yes |
See also | |
mapping_by_calling ,
mapping_by_invoking ,
mapping_blindly_by_inv… ,
renaming_blindly_by_ca… ,
renaming_blindly_by_in… |
{{#invoke:params|mapping_blindly_by_calling|template name|[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 another template. The latter will be repeatedly called with at least one parameter: the parameter's value. If the template name is followed by a number, this will be parsed as the amount of additional parameters to pass. For instance, before listing all parameters,
{{#invoke:params|mapping_blindly_by_calling|foobar|setting|i/p|{{!}}|{{=}}|list}}
will replace each value with the expansion of {{foobar|VALUE}}
(where VALUE
indicates each different value).
On the other hand,
{{#invoke:params|mapping_blindly_by_calling|foobar|2|hello|world|setting|i/p|{{!}}|{{=}}|list}}
will do the same, but using the expansion of {{foobar|VALUE|hello|world}}
.
There are no mechanisms for passing non-sequential or non-numeric additional parameters to the mapping template. A similar function,
mapping_by_calling
, passes the parameter's name as well, as first argument.
Note: All arguments passed to this modifier except the template name and the number of additional arguments are not trimmed of their leading and trailing spaces. The mapping_blindly_by_calling
modifier name itself, however, will be trimmed of its surrounding spaces.
mapping_blindly_by_invoking
Num. of arguments | Ad libitum |
---|---|
Repeatable | Yes |
See also | |
mapping_by_calling ,
mapping_by_invoking ,
mapping_blindly_by_cal… ,
renaming_blindly_by_ca… ,
renaming_blindly_by_in… |
{{#invoke:params|mapping_blindly_by_invoking|module name|function name|[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 text returned by a custom module function. The latter will be repeatedly invoked with at least one argument: the parameter's value. If the function name is followed by a number, this will be parsed as the amount of additional arguments to pass. For instance, before listing all parameters,
{{#invoke:params|mapping_blindly_by_invoking|foobar|main|setting|i/p|{{!}}|{{=}}|list}}
will replace each value with the expansion of {{#invoke:foobar|main|VALUE}}
(where VALUE
indicates each different value).
On the other hand,
{{#invoke:params|mapping_blindly_by_invoking|foobar|main|2|hello|world|setting|i/p|{{!}}|{{=}}|list}}
will do the same, but using the expansion of {{#invoke:foobar|main|VALUE|hello|world}}
.
There are no mechanisms for passing non-sequential or non-numeric additional arguments to the mapping module. A similar function,
mapping_by_invoking
, passes the parameter's name as well, as first argument.
Note: All arguments passed to this modifier except the module name, the function name and the number of additional arguments are not trimmed of their leading and trailing spaces. The mapping_blindly_by_invoking
modifier name itself, however, will be trimmed of its surrounding spaces.
renaming_blindly_by_calling
Num. of arguments | Ad libitum |
---|---|
Repeatable | Yes |
See also | |
mapping_by_calling ,
mapping_by_invoking ,
mapping_blindly_by_cal… ,
mapping_blindly_by_inv… ,
renaming_blindly_by_in… |
{{#invoke:params|renaming_blindly_by_calling|template name|[number of additional arguments]|[argument 1]|[argument 2]|[...]|[argument N]|pipe function name}}
This modifier works similarly to
mapping_blindly_by_calling
, but instead of replacing parameters' values it 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.
For instance, the following example uses {{ 2x}} to rename all arguments by doubling their name:
{{#invoke:params|setting|h/i/p/f||][|: ||renaming_blindly_by_calling|2x|list}}
Same, but adding a hyphen in between:
{{#invoke:params|setting|h/i/p/f||][|: ||renaming_blindly_by_calling|2x|1|-|list}}
This function can be particularly useful for sanitizing parameter names (e.g. collapsing several spaces into single spaces, changing the letter case, and so on).
Note: All arguments passed to this modifier except the template name and the number of additional arguments are not trimmed of their leading and trailing spaces. The renaming_blindly_by_calling
modifier name itself, however, will be trimmed of its surrounding spaces.
renaming_blindly_by_invoking
Num. of arguments | Ad libitum |
---|---|
Repeatable | Yes |
See also | |
mapping_by_calling ,
mapping_by_invoking ,
mapping_blindly_by_cal… ,
mapping_blindly_by_inv… ,
renaming_blindly_by_ca… |
{{#invoke:params|renaming_blindly_by_invoking|module name|function name|[number of additional arguments]|[argument 1]|[argument 2]|[...]|[argument N]|pipe function name}}
This modifier works similarly to
mapping_blindly_by_invoking
, but instead of replacing parameters' values it 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.
For instance, the following example uses {{
#invoke:string|
replace}} to rename all arguments 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_blindly_by_invoking|string|replace|4|^arg(%d+)$|%1|1|false|list}}
This function can be particularly useful for sanitizing parameter names (e.g. collapsing several spaces into single spaces, changing the letter case, and so on).
Note: All arguments passed to this modifier except the module name, the function name and the number of additional arguments are not trimmed of their leading and trailing spaces. The mapping_blindly_by_invoking
modifier name itself, however, will be trimmed of its surrounding spaces.
{{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 displayd first (i.e. {{foobar|-8=do|-4=you|9=wanna|11=marry|.=me?}}
).
--- ---
--- LOCAL ENVIRONMENT ---
--- ________________________________ ---
--- ---
--[[ Abstract utilities ]]--
----------------------------
-- Helper function for `string.gsub()` (for managing zero-padded numbers)
function zero_padded(str)
return ("%03d%s"):format(#str, str)
end
-- Helper function for `table.sort()` (for natural sorting)
function natural_sort(var1, var2)
return tostring(var1):gsub("%d+", zero_padded) <
tostring(var2):gsub("%d+", zero_padded)
end
-- Return a copy or a reference to a table
local function copy_or_ref_table(src, refonly)
if refonly then return src end
newtab = {}
for key, val in pairs(src) do newtabkey = val end
return newtab
end
-- Remove numerical elements from a table, shifting everything to the left
function remove_numerical_keys(tbl, idx, len)
local cache = {}
local tmp = idx + len - 1
for key, val in pairs(tbl) do
if type(key) == 'number' and key >= idx then
if key > tmp then cachekey - len = val end
tblkey = nil
end
end
for key, val in pairs(cache) do tblkey = val end
end
-- Make a reduced copy of a table (shifting in both directions if necessary)
function copy_table_reduced(tbl, idx, len)
local ret = {}
local tmp = idx + len - 1
if idx > 0 then
for key, val in pairs(tbl) do
if type(key) ~= 'number' or key < idx then
retkey = val
elseif key > tmp then retkey - len = val end
end
elseif tmp > 0 then
local nshift = 1 - idx
for key, val in pairs(tbl) do
if type(key) ~= 'number' then retkey = val
elseif key > tmp then retkey - tmp = val
elseif key < idx then retkey + nshift = val end
end
else
for key, val in pairs(tbl) do
if type(key) ~= 'number' or key > tmp then
retkey = val
elseif key < idx then retkey + len = val end
end
end
return ret
end
--[[ Module's private environment ]]--
--------------------------------------
-- Special user-given keywords (functions and modifiers MUST avoid these names)
local mkeywords = {
'or' = 0,
--['pattern'] = 1, -- Simply uncommenting enables the option
'plain' = 2,
'strict' = 3
}
-- Sort functions (functions and modifiers MUST avoid these names)
local sortfunctions = {
--['alphabetically'] = false, -- Simply uncommenting enables the option
'naturally' = natural_sort
}
-- Memory slots
local memoryslots = {
i = 'itersep',
l = 'lastsep',
p = 'pairsep',
h = 'header',
f = 'footer',
n = 'ifngiven'
}
-- Directive that can only be invoked as first arguments
local firstposonly = {
new = 'modifier',
self = 'function',
}
-- Maximum number of numerical 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)
local maxfill = 1024
-- The private table of functions
local library = {}
-- Create a new context
local function context_new(frame)
local ctx = {}
ctx.luaname = 'Module:Params' --[[ or `frame:getTitle()` ]]--
ctx.iterfunc = pairs
ctx.frame = frame:getParent()
return ctx
end
-- Prepare the context
local function context_init(frame, funcname, refpipe, refparams)
local ctx = context_new(frame)
ctx.pipe = copy_or_ref_table(frame.args, refpipe)
ctx.params = copy_or_ref_table(ctx.frame.args, refparams)
return funcname(ctx)
end
-- Move to the next action within the user-given list
local function context_iterate(ctx, n_forward)
local nextfn
if ctx.pipen_forward ~= nil then
nextfn = ctx.pipen_forward]:match'^%s*(.*%S)'
end
if nextfn == nil then
error(ctx.luaname .. ': You must specify a function to call', 0)
end
if librarynextfn == nil then
if firstposonlynextfn == nil then
error(ctx.luaname .. ': The function ‘' .. nextfn ..
'’ does not exist', 0)
else
error(ctx.luaname .. ': The ‘' .. nextfn .. '’ ' ..
firstposonlynextfn ..
' can only be invoked in first position', 0)
end
end
remove_numerical_keys(ctx.pipe, 1, n_forward)
return librarynextfn](ctx)
end
-- Concatenate the numerical keys from the table of parameters to the numerical
-- keys from the table of options; non-numerical keys from the table of options
-- will prevail over colliding non-numerical keys from the table of parameters
local function concat_params(ctx)
local shift = table.maxn(ctx.pipe)
local newargs = {}
if ctx.subset == 1 then
-- We need only the sequence
for key, val in ipairs(ctx.params) do
newargskey + shift = val
end
else
if ctx.subset == -1 then
for key, val in ipairs(ctx.params) do
ctx.paramskey = nil
end
end
for key, val in pairs(ctx.params) do
if type(key) == 'number' then
newargskey + shift = val
else
newargskey = val
end
end
end
for key, val in pairs(ctx.pipe) do newargskey = val end
return newargs
end
-- Flush the parameters by calling a custom function for each value (after this
-- function has been invoked `ctx.params` will no longer be usable)
local function flush_params(ctx, fn)
local tbl = ctx.params
if ctx.subset == 1 then
for key, val in ipairs(tbl) do fn(key, val) end
return
end
if ctx.subset == -1 then
for key, val in ipairs(tbl) do tblkey = nil end
end
if ctx.dosort then
local nums = {}
local words = {}
local nlen = 0
local wlen = 0
for key, val in pairs(tbl) do
if type(key) == 'number' then
nlen = nlen + 1
numsnlen = key
else
wlen = wlen + 1
wordswlen = key
end
end
table.sort(nums)
table.sort(words, natural_sort)
for idx = 1, nlen do fn(numsidx], tblnumsidx]]) end
for idx = 1, wlen do fn(wordsidx], tblwordsidx]]) end
return
end
if ctx.subset ~= -1 then
for key, val in ipairs(tbl) do
fn(key, val)
tblkey = nil
end
end
for key, val in pairs(tbl) do fn(key, val) end
end
-- Parse the arguments of the `with_*_matching` class of modifiers
local function parse_match_args(opts, ptns, fname)
local state = 0
local cnt = 1
local keyw
local nptns = 0
for _, val in ipairs(opts) do
if state == 0 then
nptns = nptns + 1
ptnsnptns = { val, false, false }
state = -1
else
keyw = val:match'^%s*(.*%S)'
if keyw == nil or mkeywordskeyw == nil or (
state > 0 and mkeywordskeyw > 0
) then break
else
state = mkeywordskeyw
if state > 1 then ptnsnptns][2 = true end
if state == 3 then ptnsnptns][3 = true end
end
end
cnt = cnt + 1
end
if state == 0 then error(ctx.luaname .. ', ‘' .. fname .. '’: No pattern was given', 0) end
return cnt
end
--[[ Library's modifiers ]]--
-----------------------------
-- See iface.sequential()
library.sequential = function(ctx)
if ctx.subset == -1 then error(ctx.luaname .. ': The two directives ‘non-sequential’ and ‘sequential’ are in contradiction with each other', 0) end
if ctx.dosort then error(ctx.luaname .. ': The ‘all_sorted’ directive is redundant when followed by ‘sequential’', 0) end
ctx.iterfunc = ipairs
ctx.subset = 1
return context_iterate(ctx, 1)
end
-- See iface['non-sequential']()
library'non-sequential' = function(ctx)
if ctx.subset == 1 then error(ctx.luaname .. ': The two directives ‘sequential’ and ‘non-sequential’ are in contradiction with each other', 0) end
ctx.iterfunc = pairs
ctx.subset = -1
return context_iterate(ctx, 1)
end
-- See iface.all_sorted()
library.all_sorted = function(ctx)
if ctx.subset == 1 then error(ctx.luaname .. ': The ‘all_sorted’ directive is redundant after ‘sequential’', 0) end
ctx.dosort = true
return context_iterate(ctx, 1)
end
-- See iface.setting()
library.setting = function(ctx)
local opts = ctx.pipe
local cmd
if opts1 ~= nil then
cmd = opts1]:gsub('%s+', ''):gsub('/+', '/'):match'^/*(.*[^/])'
end
if cmd == nil then error(ctx.luaname .. ', ‘setting’: No directive was given', 0) end
local sep = string.byte('/')
local argc = 2
local dest = {}
local vname
local chr
for idx = 1, #cmd do
chr = cmd:byte(idx)
if chr == sep then
for key, val in ipairs(dest) do
ctxval = optsargc
destkey = nil
end
argc = argc + 1
else
vname = memoryslotsstring.char(chr)]
if vname == nil then error(ctx.luaname .. ', ‘setting’: Unknown slot "' ..
string.char(chr) .. '"', 0) end
table.insert(dest, vname)
end
end
for key, val in ipairs(dest) do ctxval = optsargc end
return context_iterate(ctx, argc + 1)
end
-- See iface.squeezing()
library.squeezing = function(ctx)
local tbl = ctx.params
local store = {}
local indices = {}
local newlen = 0
for key, val in pairs(tbl) do
if type(key) == 'number' then
newlen = newlen + 1
indicesnewlen = key
storekey = val
tblkey = nil
end
end
table.sort(indices)
for idx = 1, newlen do tblidx = storeindicesidx]] end
return context_iterate(ctx, 1)
end
-- See iface.filling_the_gaps()
library.filling_the_gaps = function(ctx)
local tbl = ctx.params
local nmin = 1
local nmax = nil
local nnums = -1
local tmp = {}
for key, val in pairs(tbl) do
if type(key) == 'number' then
if nmax == nil then
if key < nmin then nmin = key end
nmax = key
elseif key > nmax then nmax = key
elseif key < nmin then nmin = key end
nnums = nnums + 1
tmpkey = val
end
end
if nmax ~= nil and nmax - nmin > nnums then
if maxfill + nmin + nnums < nmax then error(ctx.luaname .. ', ‘filling_the_gaps’: It is possible to fill at most ' .. tostring(maxfill) .. ' parameters', 0) end
for idx = nmin, nmax, 1 do tblidx = '' end
for key, val in pairs(tmp) do tblkey = val end
end
return context_iterate(ctx, 1)
end
-- See iface.clearing()
library.clearing = function(ctx)
local tbl = ctx.params
local numericals = {}
for key, val in pairs(tbl) do
if type(key) == 'number' then
numericalskey = val
tblkey = nil
end
end
for key, val in ipairs(numericals) do tblkey = val end
return context_iterate(ctx, 1)
end
-- See iface.cutting()
library.cutting = function(ctx)
local lcut = tonumber(ctx.pipe1])
if lcut == nil then error(ctx.luaname .. ', ‘cutting’: Left cut must be a number', 0) end
local rcut = tonumber(ctx.pipe2])
if rcut == nil then error(ctx.luaname .. ', ‘cutting’: Right cut must be a number', 0) end
local tbl = ctx.params
local len = #tbl
if lcut < 0 then lcut = len + lcut end
if rcut < 0 then rcut = len + rcut end
local tot = lcut + rcut
if tot > 0 then
local cache = {}
if tot >= len then
for key in ipairs(tbl) do tblkey = nil end
tot = len
else
for idx = len - rcut + 1, len, 1 do tblidx = nil end
for idx = 1, lcut, 1 do tblidx = nil end
end
for key, val in pairs(tbl) do
if type(key) == 'number' and key > 0 then
if key > len then
cachekey - tot = val
else
cachekey - lcut = val
end
tblkey = nil
end
end
for key, val in pairs(cache) do tblkey = val end
end
return context_iterate(ctx, 3)
end
-- See iface.cropping()
library.cropping = function(ctx)
local lcut = tonumber(ctx.pipe1])
if lcut == nil then error(ctx.luaname .. ', ‘cropping’: Left crop must be a number', 0) end
local rcut = tonumber(ctx.pipe2])
if rcut == nil then error(ctx.luaname .. ', ‘cropping’: Right crop must be a number', 0) end
local tbl = ctx.params
local nmin
local nmax
for key in pairs(tbl) do
if type(key) == 'number' then
if nmin == nil then
nmin = key
nmax = key
elseif key > nmax then nmax = key
elseif key < nmin then nmin = key end
end
end
if nmin ~= nil then
local len = nmax - nmin + 1
if lcut < 0 then lcut = len + lcut end
if rcut < 0 then rcut = len + rcut end
if lcut + rcut - len > -1 then
for key in pairs(tbl) do
if type(key) == 'number' then tblkey = nil end
end
elseif lcut + rcut > 0 then
for idx = nmax - rcut + 1, nmax, 1 do tblidx = nil end
for idx = nmin, nmin + lcut - 1, 1 do tblidx = nil end
local lshift = nmin + lcut - 1
if lshift > 0 then
for idx = lshift + 1, nmax, 1 do
tblidx - lshift = tblidx
tblidx = nil
end
end
end
end
return context_iterate(ctx, 3)
end
-- See iface.purging()
library.purging = function(ctx)
local first = tonumber(ctx.pipe1])
if first == nil then error(ctx.luaname .. ', ‘purging’: Start offset must be a number', 0) end
local size = tonumber(ctx.pipe2])
if size == nil then error(ctx.luaname .. ', ‘purging’: Length must be a number', 0) end
local tbl = ctx.params
if size < 1 then
size = size + table.maxn(tbl)
if first > size then return context_iterate(ctx, 3) end
size = size - first + 1
end
ctx.params = copy_table_reduced(tbl, first, size)
return context_iterate(ctx, 3)
end
-- See iface.backpurging()
library.backpurging = function(ctx)
local last = tonumber(ctx.pipe1])
if last == nil then error(ctx.luaname .. ', ‘backpurging’: Start offset must be a number', 0) end
local size = tonumber(ctx.pipe2])
if size == nil then error(ctx.luaname .. ', ‘backpurging’: Length must be a number', 0) end
local first
local tbl = ctx.params
if size > 0 then
first = last - size + 1
else
for key in pairs(tbl) do
if type(key) == 'number' and (first == nil or
key < first) then first = key end
end
if first == nil then return context_iterate(ctx, 3) end
first = first - size
if last < first then return context_iterate(ctx, 3) end
size = last - first + 1
end
ctx.params = copy_table_reduced(ctx.params, first, size)
return context_iterate(ctx, 3)
end
-- See iface.rotating()
library.rotating = function(ctx)
local tbl = ctx.params
local numericals = {}
local nmax = 0
for key, val in pairs(tbl) do
if type(key) == 'number' then
numericalskey = val
tblkey = nil
if key > nmax then nmax = key end
end
end
for key, val in pairs(numericals) do tblnmax - key + 1 = val end
return context_iterate(ctx, 1)
end
-- See iface.pivoting()
--[[
library.pivoting = function(ctx)
local tbl = ctx.params
local shift = #tbl + 1
if shift < 2 then return library.rotating(ctx) end
local numericals = {}
for key, val in pairs(tbl) do
if type(key) == 'number' then
numericals[key] = val
tbl[key] = nil
end
end
for key, val in pairs(numericals) do tbl[shift - key] = val end
return context_iterate(ctx, 1)
end
]]--
-- See iface.mirroring()
--[[
library.mirroring = function(ctx)
local tbl = ctx.params
local numericals = {}
local nmax
local nmin
for key, val in pairs(tbl) do
if type(key) == 'number' then
numericals[key] = val
tbl[key] = nil
if nmax == nil then
nmax = key
nmin = key
elseif key > nmax then nmax = key
elseif key < nmin then nmin = key end
end
end
for key, val in pairs(numericals) do tbl[nmax + nmin - key] = val end
return context_iterate(ctx, 1)
end
]]--
-- See iface.swapping()
--[[
library.swapping = function(ctx)
local tbl = ctx.params
local cache = {}
local nsize = 0
local tmp
for key in pairs(tbl) do
if type(key) == 'number' then
nsize = nsize + 1
cache[nsize] = key
end
end
table.sort(cache)
for idx = math.floor(nsize / 2), 1, -1 do
tmp = tbl[cache[idx] ]
tbl[cache[idx] ] = tbl[cache[nsize - idx + 1] ]
tbl[cache[nsize - idx + 1] ] = tmp
end
return context_iterate(ctx, 1)
end
]]--
-- See iface.sorting_sequential_values()
library.sorting_sequential_values = function(ctx)
local sortfn
if ctx.pipe1 ~= nil then sortfn = sortfunctionsctx.pipe1]] end
if sortfn then table.sort(ctx.params, sortfn)
else table.sort(ctx.params) end -- i.e. either `false` or `nil`
if sortfn == nil then return context_iterate(ctx, 1) end
return context_iterate(ctx, 2)
end
-- See iface.with_name_matching()
library.with_name_matching = function(ctx)
local tbl = ctx.params
local patterns = {}
local argc = parse_match_args(ctx.pipe, patterns, 'with_name_matching')
local nomatch
for key in pairs(tbl) do
nomatch = true
for _, ptn in ipairs(patterns) do
if not ptn3 then
if string.find(key, ptn1], 1, ptn2]) then
nomatch = false
break
end
elseif key == ptn1 then
nomatch = false
break
end
end
if nomatch then tblkey = nil end
end
return context_iterate(ctx, argc)
end
-- See iface.with_name_not_matching()
library.with_name_not_matching = function(ctx)
local tbl = ctx.params
local patterns = {}
local argc = parse_match_args(ctx.pipe, patterns,
'with_name_not_matching')
local yesmatch
for key in pairs(tbl) do
yesmatch = true
for _, ptn in ipairs(patterns) do
if not ptn3 then
if not string.find(key, ptn1], 1, ptn2]) then
yesmatch = false
break
end
elseif key ~= ptn1 then
yesmatch = false
break
end
end
if yesmatch then tblkey = nil end
end
return context_iterate(ctx, argc)
end
-- See iface.with_value_matching()
library.with_value_matching = function(ctx)
local tbl = ctx.params
local patterns = {}
local argc = parse_match_args(ctx.pipe, patterns,
'with_value_matching')
local nomatch
for key, val in pairs(tbl) do
nomatch = true
for _, ptn in ipairs(patterns) do
if not ptn3 then
if string.find(val, ptn1], 1, ptn2]) then
nomatch = false
break
end
elseif val == ptn1 then
nomatch = false
break
end
end
if nomatch then tblkey = nil end
end
return context_iterate(ctx, argc)
end
-- See iface.with_value_not_matching()
library.with_value_not_matching = function(ctx)
local tbl = ctx.params
local patterns = {}
local argc = parse_match_args(ctx.pipe, patterns,
'with_value_not_matching')
local yesmatch
for key, val in pairs(tbl) do
yesmatch = true
for _, ptn in ipairs(patterns) do
if not ptn3 then
if not string.find(val, ptn1], 1, ptn2]) then
yesmatch = false
break
end
elseif val ~= ptn1 then
yesmatch = false
break
end
end
if yesmatch then tblkey = nil end
end
return context_iterate(ctx, argc)
end
-- See iface.trimming_values()
library.trimming_values = function(ctx)
local tbl = ctx.params
for key, val in pairs(tbl) do tblkey = val:match'^%s*(.-)%s*$' end
return context_iterate(ctx, 1)
end
-- See iface.mapping_by_calling()
library.mapping_by_calling = function(ctx)
local opts = ctx.pipe
local tname
if opts1 ~= nil then tname = opts1]:match'^%s*(.*%S)' end
if tname == nil then error(ctx.luaname .. ', ‘mapping_by_calling’: No template name was provided', 0) end
local nargs
local margs = {}
local tmp = tonumber(opts2])
if tmp == nil then nargs = 1
elseif tmp < 1 then nargs = 2
else
nargs = tmp + 2
for idx = 3, nargs do margsidx = optsidx end
end
local model = { title = tname, args = margs }
local tbl = ctx.params
for key, val in pairs(tbl) do
margs1 = key
margs2 = val
tblkey = ctx.frame:expandTemplate(model)
end
return context_iterate(ctx, nargs + 1)
end
-- See iface.mapping_by_invoking()
library.mapping_by_invoking = function(ctx)
local opts = ctx.pipe
local mname
local fname
if opts1 ~= nil then mname = opts1]:match'^%s*(.*%S)' end
if mname == nil then error(ctx.luaname .. ', ‘mapping_by_invoking’: No module name was provided', 0) end
if opts2 ~= nil then fname = opts2]:match'^%s*(.*%S)' end
if fname == nil then error(ctx.luaname .. ', ‘mapping_by_invoking’: No function name was provided', 0) end
local nargs
local margs = {}
local tmp = tonumber(opts3])
if tmp == nil then nargs = 2
elseif tmp < 1 then nargs = 3
else
nargs = tmp + 3
for idx = 4, nargs do margsidx - 1 = optsidx end
end
local model = { title = 'Module:' .. mname, args = margs }
local mfunc = require(model.title)[fname
local tbl = ctx.params
for key, val in pairs(tbl) do
margs1 = key
margs2 = val
tblkey = mfunc(ctx.frame:newChild(model))
end
return context_iterate(ctx, nargs + 1)
end
-- See iface.mapping_blindly_by_calling()
library.mapping_blindly_by_calling = function(ctx)
local opts = ctx.pipe
local tname
if opts1 ~= nil then tname = opts1]:match'^%s*(.*%S)' end
if tname == nil then error(ctx.luaname .. ', ‘mapping_blindly_by_calling’: No template name was provided', 0) end
local nargs
local margs = {}
local tmp = tonumber(opts2])
if tmp == nil then nargs = 1
elseif tmp < 1 then nargs = 2
else
nargs = tmp + 2
for idx = 3, nargs do margsidx - 1 = optsidx end
end
local model = { title = tname, args = margs }
local tbl = ctx.params
for key, val in pairs(tbl) do
margs1 = val
tblkey = ctx.frame:expandTemplate(model)
end
return context_iterate(ctx, nargs + 1)
end
-- See iface.mapping_blindly_by_invoking()
library.mapping_blindly_by_invoking = function(ctx)
local opts = ctx.pipe
local mname
local fname
if opts1 ~= nil then mname = opts1]:match'^%s*(.*%S)' end
if mname == nil then error(ctx.luaname .. ', ‘mapping_blindly_by_invoking’: No module name was provided', 0) end
if opts2 ~= nil then fname = opts2]:match'^%s*(.*%S)' end
if fname == nil then error(ctx.luaname .. ', ‘mapping_blindly_by_invoking’: No function name was provided', 0) end
local nargs
local margs = {}
local tmp = tonumber(opts3])
if tmp == nil then nargs = 2
elseif tmp < 1 then nargs = 3
else
nargs = tmp + 3
for idx = 4, nargs do margsidx - 2 = optsidx end
end
local model = { title = 'Module:' .. mname, args = margs }
local mfunc = require(model.title)[fname
local tbl = ctx.params
for key, val in pairs(tbl) do
margs1 = val
tblkey = mfunc(ctx.frame:newChild(model))
end
return context_iterate(ctx, nargs + 1)
end
-- See iface.renaming_blindly_by_calling()
library.renaming_blindly_by_calling = function(ctx)
local opts = ctx.pipe
local tname
if opts1 ~= nil then tname = opts1]:match'^%s*(.*%S)' end
if tname == nil then error(ctx.luaname .. ', ‘renaming_blindly_by_calling’: No template name was provided', 0) end
local nargs
local margs = {}
local tmp = tonumber(opts2])
if tmp == nil then nargs = 1
elseif tmp < 1 then nargs = 2
else
nargs = tmp + 2
for idx = 3, nargs do margsidx - 1 = optsidx end
end
local model = { title = tname, args = margs }
local cache = {}
local tbl = ctx.params
for key, val in pairs(tbl) do
margs1 = key
tmp = ctx.frame:expandTemplate(model):match'^%s*(.-)%s*$'
tmp = tonumber(tmp) or tmp
if key ~= tmp then
cachetmp = val
tblkey = nil
end
end
for key, val in pairs(cache) do tblkey = val end
return context_iterate(ctx, nargs + 1)
end
-- See iface.renaming_blindly_by_invoking()
library.renaming_blindly_by_invoking = function(ctx)
local opts = ctx.pipe
local mname
local fname
if opts1 ~= nil then mname = opts1]:match'^%s*(.*%S)' end
if mname == nil then error(ctx.luaname .. ', ‘renaming_blindly_by_invoking’: No module name was provided', 0) end
if opts2 ~= nil then fname = opts2]:match'^%s*(.*%S)' end
if fname == nil then error(ctx.luaname .. ', ‘renaming_blindly_by_invoking’: No function name was provided', 0) end
local nargs
local margs = {}
local tmp = tonumber(opts3])
if tmp == nil then nargs = 2
elseif tmp < 1 then nargs = 3
else
nargs = tmp + 3
for idx = 4, nargs do margsidx - 2 = optsidx end
end
local model = { title = 'Module:' .. mname, args = margs }
local mfunc = require(model.title)[fname
local cache = {}
local tbl = ctx.params
for key, val in pairs(tbl) do
margs1 = key
tmp = mfunc(ctx.frame:newChild(model)):match'^%s*(.-)%s*$'
tmp = tonumber(tmp) or tmp
if key ~= tmp then
cachetmp = val
tblkey = nil
end
end
for key, val in pairs(cache) do tblkey = val end
return context_iterate(ctx, nargs + 1)
end
--[[ Library's functions ]]--
-----------------------------
-- See iface.count()
library.count = function(ctx)
local count = 0
for _ in ctx.iterfunc(ctx.params) do count = count + 1 end
if ctx.subset == -1 then count = count - #ctx.params end
return count
end
-- See iface.concat_and_call()
library.concat_and_call = function(ctx)
local opts = ctx.pipe
local tname
if opts1 ~= nil then tname = opts1]:match'^%s*(.*%S)' end
if tname == nil then error(ctx.luaname .. ', ‘concat_and_call’: No template name was provided', 0) end
remove_numerical_keys(opts, 1, 1)
return ctx.frame:expandTemplate{
title = tname,
args = concat_params(ctx)
}
end
-- See iface.concat_and_invoke()
library.concat_and_invoke = function(ctx)
local opts = ctx.pipe
local mname
local fname
if opts1 ~= nil then mname = opts1]:match'^%s*(.*%S)' end
if mname == nil then error(ctx.luaname .. ', ‘concat_and_invoke’: No module name was provided', 0) end
if opts2 ~= nil then fname = opts2]:match'^%s*(.*%S)' end
if fname == nil then error(ctx.luaname .. ', ‘concat_and_invoke’: No function name was provided', 0) end
remove_numerical_keys(opts, 1, 2)
return require('Module:' .. mname)[fname](ctx.frame:newChild{
title = 'Module:' .. fname,
args = concat_params(ctx)
})
end
-- See iface.concat_and_magic()
library.concat_and_magic = function(ctx)
local opts = ctx.pipe
local magic
if opts1 ~= nil then magic = opts1]:match'^%s*(.*%S)' end
if magic == nil then error(ctx.luaname .. ', ‘concat_and_magic’: No parser function was provided', 0) end
remove_numerical_keys(opts, 1, 1)
return ctx.frame:callParserFunction(magic, concat_params(ctx))
end
-- See iface.value_of()
library.value_of = function(ctx)
local opts = ctx.pipe
local keystr
if opts1 ~= nil then keystr = opts1]:match'^%s*(.*%S)' end
if keystr == nil then error(ctx.luaname .. ', ‘value_of’: No parameter name was provided', 0) end
local keynum = tonumber(keystr)
local len = #ctx.params
if (
ctx.subset == -1 and keynum ~= nil and len >= keynum
) or (
ctx.subset == 1 and (keynum == nil or len < keynum)
) then return (ctx.ifngiven or '') end
local val = ctx.paramskeynum or keystr
if val == nil then return (ctx.ifngiven or '') end
return (ctx.header or '') .. val .. (ctx.footer or '')
end
-- See iface.list()
library.list = function(ctx)
local kvs = ctx.pairsep or ''
local pps = ctx.itersep or ''
local ret = {}
local nss = 0
flush_params(
ctx,
function(key, val)
retnss + 1 = pps
retnss + 2 = key
retnss + 3 = kvs
retnss + 4 = val
nss = nss + 4
end
)
if nss > 0 then
if nss > 4 and ctx.lastsep ~= nil then
retnss - 3 = ctx.lastsep
end
ret1 = ctx.header or ''
if ctx.footer ~= nil then retnss + 1 = ctx.footer end
return table.concat(ret)
end
return ctx.ifngiven or ''
end
-- See iface.list_values()
library.list_values = function(ctx)
local pps = ctx.itersep or ''
local ret = {}
local nss = 0
flush_params(
ctx,
function(key, val)
retnss + 1 = pps
retnss + 2 = val
nss = nss + 2
end
)
if nss > 0 then
if nss > 2 and ctx.lastsep ~= nil then
retnss - 1 = ctx.lastsep
end
ret1 = ctx.header or ''
if ctx.footer ~= nil then retnss + 1 = ctx.footer end
return table.concat(ret)
end
return ctx.ifngiven or ''
end
-- See iface.for_each()
library.for_each = function(ctx)
local txt = ctx.pipe1 or ''
local pps = ctx.itersep or ''
local ret = {}
local nss = 0
flush_params(
ctx,
function(key, val)
retnss + 1 = pps
retnss + 2 = txt:gsub('%$#', key):gsub('%$@', val)
nss = nss + 2
end
)
if nss > 0 then
if nss > 2 and ctx.lastsep ~= nil then
retnss - 1 = ctx.lastsep
end
ret1 = ctx.header or ''
if ctx.footer ~= nil then retnss + 1 = ctx.footer end
return table.concat(ret)
end
return ctx.ifngiven or ''
end
-- See iface.call_for_each()
library.call_for_each = function(ctx)
local opts = ctx.pipe
local tname
if opts1 ~= nil then tname = opts1]:match'^%s*(.*%S)' end
if tname == nil then error(ctx.luaname .. ', ‘call_for_each’: No template name was provided', 0) end
local model = { title = tname, args = opts }
local ccs = ctx.itersep or ''
local ret = {}
local nss = 0
table.insert(opts, 1, true)
flush_params(
ctx,
function(key, val)
opts1 = key
opts2 = val
retnss + 1 = ccs
retnss + 2 = ctx.frame:expandTemplate(model)
nss = nss + 2
end
)
if nss > 0 then
if nss > 2 and ctx.lastsep ~= nil then
retnss - 1 = ctx.lastsep
end
ret1 = ctx.header or ''
if ctx.footer ~= nil then retnss + 1 = ctx.footer end
return table.concat(ret)
end
return ctx.ifngiven or ''
end
-- See iface.invoke_for_each()
library.invoke_for_each = function(ctx)
local opts = ctx.pipe
local mname
local fname
if opts1 ~= nil then mname = opts1]:match'^%s*(.*%S)' end
if mname == nil then error(ctx.luaname .. ', ‘invoke_for_each’: No module name was provided', 0) end
if opts2 ~= nil then fname = opts2]:match'^%s*(.*%S)' end
if fname == nil then error(ctx.luaname .. ', ‘invoke_for_each’: No function name was provided', 0) end
local model = { title = 'Module:' .. mname, args = opts }
local mfunc = require(model.title)[fname
local ccs = ctx.itersep or ''
local ret = {}
local nss = 0
flush_params(
ctx,
function(key, val)
opts1 = key
opts2 = val
retnss + 1 = ccs
retnss + 2 = mfunc(ctx.frame:newChild(model))
nss = nss + 2
end
)
if nss > 0 then
if nss > 2 and ctx.lastsep ~= nil then
retnss - 1 = ctx.lastsep
end
ret1 = ctx.header or ''
if ctx.footer ~= nil then retnss + 1 = ctx.footer end
return table.concat(ret)
end
return ctx.ifngiven or ''
end
-- See iface.magic_for_each()
library.magic_for_each = function(ctx)
local opts = ctx.pipe
local magic
if opts1 ~= nil then magic = opts1]:match'^%s*(.*%S)' end
if magic == nil then error(ctx.luaname .. ', ‘magic_for_each’: No parser function was provided', 0) end
local ccs = ctx.itersep or ''
local ret = {}
local nss = 0
table.insert(opts, 1, true)
flush_params(
ctx,
function(key, val)
opts1 = key
opts2 = val
retnss + 1 = ccs
retnss + 2 = ctx.frame:callParserFunction(magic,
opts)
nss = nss + 2
end
)
if nss > 0 then
if nss > 2 and ctx.lastsep ~= nil then
retnss - 1 = ctx.lastsep
end
ret1 = ctx.header or ''
if ctx.footer ~= nil then retnss + 1 = ctx.footer end
return table.concat(ret)
end
return ctx.ifngiven or ''
end
-- See iface.call_for_each_value()
library.call_for_each_value = function(ctx)
local opts = ctx.pipe
local tname
if opts1 ~= nil then tname = opts1]:match'^%s*(.*%S)' end
if tname == nil then error(ctx.luaname .. ', ‘call_for_each_value’: No template name was provided', 0) end
local model = { title = tname, args = opts }
local ccs = ctx.itersep or ''
local ret = {}
local nss = 0
flush_params(
ctx,
function(key, val)
opts1 = val
retnss + 1 = ccs
retnss + 2 = ctx.frame:expandTemplate(model)
nss = nss + 2
end
)
if nss > 0 then
if nss > 2 and ctx.lastsep ~= nil then
retnss - 1 = ctx.lastsep
end
ret1 = ctx.header or ''
if ctx.footer ~= nil then retnss + 1 = ctx.footer end
return table.concat(ret)
end
return ctx.ifngiven or ''
end
-- See iface.invoke_for_each_value()
library.invoke_for_each_value = function(ctx)
local opts = ctx.pipe
local mname
local fname
if opts1 ~= nil then mname = opts1]:match'^%s*(.*%S)' end
if mname == nil then error(ctx.luaname .. ', ‘invoke_for_each_value’: No module name was provided', 0) end
if opts2 ~= nil then fname = opts2]:match'^%s*(.*%S)' end
if fname == nil then error(ctx.luaname .. ', ‘invoke_for_each_value’: No function name was provided', 0) end
local model = { title = 'Module:' .. mname, args = opts }
local mfunc = require(model.title)[fname
local ccs = ctx.itersep or ''
local ret = {}
local nss = 0
remove_numerical_keys(opts, 1, 1)
flush_params(
ctx,
function(key, val)
opts1 = val
retnss + 1 = ccs
retnss + 2 = mfunc(ctx.frame:newChild(model))
nss = nss + 2
end
)
if nss > 0 then
if nss > 2 and ctx.lastsep ~= nil then
retnss - 1 = ctx.lastsep
end
ret1 = ctx.header or ''
if ctx.footer ~= nil then retnss + 1 = ctx.footer end
return table.concat(ret)
end
return ctx.ifngiven or ''
end
-- See iface.magic_for_each_value()
library.magic_for_each_value = function(ctx)
local opts = ctx.pipe
local magic
if opts1 ~= nil then magic = opts1]:match'^%s*(.*%S)' end
if magic == nil then error(ctx.luaname .. ', ‘magic_for_each_value’: No parser function was provided', 0) end
local ccs = ctx.itersep or ''
local ret = {}
local nss = 0
flush_params(
ctx,
function(key, val)
opts1 = val
retnss + 1 = ccs
retnss + 2 = ctx.frame:callParserFunction(magic,
opts)
nss = nss + 2
end
)
if nss > 0 then
if nss > 2 and ctx.lastsep ~= nil then
retnss - 1 = ctx.lastsep
end
ret1 = ctx.header or ''
if ctx.footer ~= nil then retnss + 1 = ctx.footer end
return table.concat(ret)
end
return ctx.ifngiven or ''
end
-- See iface.call_for_each_group()
library.call_for_each_group = function(ctx)
-- NOTE: `ctx.pipe` and `ctx.params` might be the original metatables!
local opts = ctx.pipe
local tmp
if opts1 ~= nil then tmp = opts1]:match'^%s*(.*%S)' end
if tmp == nil then error(ctx.luaname .. ', ‘call_for_each_group’: No template name was provided', 0) end
local model = { title = tmp }
local ccs = ctx.itersep or ''
local nss = 0
local prefix
local gid
local groups = {}
local ret = {}
opts = {}
for key, val in pairs(ctx.pipe) do
if type(key) == 'number' then optskey - 1 = val
else optskey = val end
end
ctx.pipe = opts
for key, val in pairs(ctx.params) do
prefix, gid = tostring(key):match'^%s*(.-)%s*(%-?%d*)%s*$'
gid = tonumber(gid) or ''
if groupsgid == nil then groupsgid = {} end
tmp = tonumber(prefix)
if tmp ~= nil then
if tmp < 1 then prefix = tmp - 1 else prefix = tmp end
end
groupsgid][prefix = val
end
ctx.params = groups
flush_params(
ctx,
function(gid, group)
for key, val in pairs(opts) do groupkey = val end
group0 = gid
model.args = group
retnss + 1 = ccs
retnss + 2 = ctx.frame:expandTemplate(model)
nss = nss + 2
end
)
if nss > 0 then
if nss > 2 and ctx.lastsep ~= nil then
retnss - 1 = ctx.lastsep
end
ret1 = ctx.header or ''
if ctx.footer ~= nil then retnss + 1 = ctx.footer end
return table.concat(ret)
end
return ctx.ifngiven or ''
end
--- ---
--- PUBLIC ENVIRONMENT ---
--- ________________________________ ---
--- ---
-- The public table of functions
local iface = {}
--[[ Modifiers ]]--
-------------------
-- Syntax: #invoke:params|sequential|pipe to
iface.sequential = function(frame)
return context_init(frame, library.sequential, false, false)
end
-- Syntax: #invoke:params|non-sequential|pipe to
iface'non-sequential' = function(frame)
return context_init(frame, library'non-sequential'], false, false)
end
-- Syntax: #invoke:params|sort|pipe to
iface.all_sorted = function(frame)
return context_init(frame, library.all_sorted, false, false)
end
-- Syntax: #invoke:params|setting|directives|...|pipe to
iface.setting = function(frame)
return context_init(frame, library.setting, false, false)
end
-- Syntax: #invoke:params|squeezing|pipe to
iface.squeezing = function(frame)
return context_init(frame, library.squeezing, false, false)
end
-- Syntax: #invoke:params|filling_the_gaps|pipe to
iface.filling_the_gaps = function(frame)
return context_init(frame, library.filling_the_gaps, false, false)
end
-- Syntax: #invoke:params|clearing|pipe to
iface.clearing = function(frame)
return context_init(frame, library.clearing, false, false)
end
-- Syntax: #invoke:params|cutting|left cut|right cut|pipe to
iface.cutting = function(frame)
return context_init(frame, library.cutting, false, false)
end
-- Syntax: #invoke:params|cropping|left crop|right crop|pipe to
iface.cropping = function(frame)
return context_init(frame, library.cropping, false, false)
end
-- Syntax: #invoke:params|purging|start offset|length|pipe to
iface.purging = function(frame)
return context_init(frame, library.purging, false, false)
end
-- Syntax: #invoke:params|backpurging|start offset|length|pipe to
iface.backpurging = function(frame)
return context_init(frame, library.backpurging, false, false)
end
-- Syntax: #invoke:params|rotating|pipe to
iface.rotating = function(frame)
return context_init(frame, library.rotating, false, false)
end
-- Syntax: #invoke:params|pivoting|pipe to
--[[
iface.pivoting = function(frame)
return context_init(frame, library.pivoting, false, false)
end
]]
-- Syntax: #invoke:params|mirroring|pipe to
--[[
iface.mirroring = function(frame)
return context_init(frame, library.mirroring, false, false)
end
]]
-- Syntax: #invoke:params|swapping|pipe to
--[[
iface.swapping = function(frame)
return context_init(frame, library.swapping, false, false)
end
]]--
-- Syntax: #invoke:params|sorting_sequential_values|[criterion]|pipe to
iface.sorting_sequential_values = function(frame)
return context_init(frame, library.sorting_sequential_values, false, false)
end
-- Syntax: #invoke:params|with_name_matching|pattern 1|[plain flag 1]|[or]
-- |[pattern 2]|[plain flag 2]|[or]|[...]|[pattern N]|[plain flag
-- N]|pipe to
iface.with_name_matching = function(frame)
return context_init(frame, library.with_name_matching, false, false)
end
-- Syntax: #invoke:params|with_name_not_matching|pattern 1|[plain flag 1]
-- |[and]|[pattern 2]|[plain flag 2]|[and]|[...]|[pattern N]|[plain
-- flag N]|pipe to
iface.with_name_not_matching = function(frame)
return context_init(frame, library.with_name_not_matching, false,
false)
end
-- Syntax: #invoke:params|with_value_matching|pattern 1|[plain flag 1]|[or]
-- |[pattern 2]|[plain flag 2]|[or]|[...]|[pattern N]|[plain flag
-- N]|pipe to
iface.with_value_matching = function(frame)
return context_init(frame, library.with_value_matching, false, false)
end
-- Syntax: #invoke:params|with_value_not_matching|pattern 1|[plain flag 1]
-- |[and]|[pattern 2]|[plain flag 2]|[and]|[...]|[pattern N]|[plain
-- flag N]|pipe to
iface.with_value_not_matching = function(frame)
return context_init(frame, library.with_value_not_matching, false,
false)
end
-- Syntax: #invoke:params|trimming_values|pipe to
iface.trimming_values = function(frame)
return context_init(frame, library.trimming_values, false, false)
end
-- Syntax: #invoke:params|mapping_by_calling|template name|[number of
-- additional arguments]|[argument 1]|[argument 2]|[...]|[argument
-- N]|pipe to
iface.mapping_by_calling = function(frame)
return context_init(frame, library.mapping_by_calling, false, false)
end
-- Syntax: #invoke:params|mapping_by_invoking|module name|function
-- name|[number of additional arguments]|[argument 1]|[argument
-- 2]|[...]|[argument N]|pipe to
iface.mapping_by_invoking = function(frame)
return context_init(frame, library.mapping_by_invoking, false, false)
end
-- Syntax: #invoke:params|mapping_blindly_by_calling|template
-- name|[number of additional arguments]|[argument 1]|[argument
-- 2]|[...]|[argument N]|pipe to
iface.mapping_blindly_by_calling = function(frame)
return context_init(frame, library.mapping_blindly_by_calling, false,
false)
end
-- Syntax: #invoke:params|mapping_blindly_by_invoking|module
-- name|function name|[number of additional arguments]|[argument
-- 1]|[argument 2]|[...]|[argument N]|pipe to
iface.mapping_blindly_by_invoking = function(frame)
return context_init(frame, library.mapping_blindly_by_invoking, false,
false)
end
-- Syntax: #invoke:params|renaming_blindly_by_calling|template
-- name|[number of additional arguments]|[argument 1]|[argument
-- 2]|[...]|[argument N]|pipe to
iface.renaming_blindly_by_calling = function(frame)
return context_init(frame, library.renaming_blindly_by_calling, false,
false)
end
-- Syntax: #invoke:params|renaming_blindly_by_invoking|module
-- name|function name|[number of additional arguments]|[argument
-- 1]|[argument 2]|[...]|[argument N]|pipe to
iface.renaming_blindly_by_invoking = function(frame)
return context_init(frame, library.renaming_blindly_by_invoking, false,
false)
end
--[[ First-position-only modifiers ]]--
---------------------------------------
-- Syntax: #invoke:params|new|pipe to
--[[
iface.new = function(frame)
local ctx = context_new(frame)
ctx.pipe = copy_or_ref_table(frame.args, false)
ctx.params = {}
return context_iterate(ctx, 1)
end
]]--
--[[ Functions ]]--
-------------------
-- Syntax: #invoke:params|count
iface.count = function(frame)
return context_init(frame, library.count, true, true)
end
-- Syntax: #invoke:args|concat_and_call|template name|[prepend 1]|[prepend 2]
-- |[...]|[item n]|[named item 1=value 1]|[...]|[named item n=value
-- n]|[...]
iface.concat_and_call = function(frame)
return context_init(frame, library.concat_and_call, false, true)
end
-- 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]|[...]
iface.concat_and_invoke = function(frame)
return context_init(frame, library.concat_and_invoke, false, true)
end
-- Syntax: #invoke:args|concat_and_magic|parser function|[prepend 1]|[prepend
-- 2]|[...]|[item n]|[named item 1=value 1]|[...]|[named item n=
-- value n]|[...]
iface.concat_and_magic = function(frame)
return context_init(frame, library.concat_and_magic, false, true)
end
-- Syntax: #invoke:params|value_of|parameter name
iface.value_of = function(frame)
return context_init(frame, library.value_of, true, true)
end
-- Syntax: #invoke:params|list
iface.list = function(frame)
return context_init(frame, library.list, true, false)
end
-- Syntax: #invoke:params|list_values
iface.list_values = function(frame)
return context_init(frame, library.list_values, true, false)
end
-- Syntax: #invoke:params|for_each|wikitext
iface.for_each = function(frame)
return context_init(frame, library.for_each, true, false)
end
-- Syntax: #invoke:params|call_for_each|template name|[append 1]|[append 2]
-- |[...]|[append n]|[named param 1=value 1]|[...]|[named param
-- n=value n]|[...]
iface.call_for_each = function(frame)
return context_init(frame, library.call_for_each, false, false)
end
-- 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]|[...]
iface.invoke_for_each = function(frame)
return context_init(frame, library.invoke_for_each, false, false)
end
-- Syntax: #invoke:params|magic_for_each|parser function|[append 1]|[append 2]
-- |[...]|[append n]|[named param 1=value 1]|[...]|[named param
-- n=value n]|[...]
iface.magic_for_each = function(frame)
return context_init(frame, library.magic_for_each, false, false)
end
-- 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]|[...]
iface.call_for_each_value = function(frame)
return context_init(frame, library.call_for_each_value, false, false)
end
-- 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]|[...]
iface.invoke_for_each_value = function(frame)
return context_init(frame, library.invoke_for_each_value, false, false)
end
-- 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]|[...]
iface.magic_for_each_value = function(frame)
return context_init(frame, library.magic_for_each_value, false, false)
end
-- 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]|[...]
iface.call_for_each_group = function(frame)
return context_init(frame, library.call_for_each_group, true, true)
end
--[[ First-position-only functions ]]--
---------------------------------------
-- Syntax: #invoke:params|self
iface.self = function(frame)
return frame:getParent():getTitle()
end
return iface
This module is rated as ready for general use. It has reached a mature form and is thought to be relatively bug-free and ready for use wherever appropriate. It is ready to mention on help pages and other Wikipedia resources as an option for new users to learn. To reduce server load and bad output, it should be improved by sandbox testing rather than repeated trial-and-error editing. |
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 to
variadic templates, to which it offers the possibility to count, list, map and propagate the parameters received without knowing their number in advance.
The module offers elegant shortcuts to non variadic templates as well. Outside templates it has virtually no applications; hence, if you plan to make experiments, make sure to do them from within a template, or you will not be able to see much (you can use {{ Template sandbox}} for that). Under ./testcases you can find helper templates that can be specifically used for testing the module's capabilities in flexible ways (see in particular the {{ ./testcases/tmulti}} template).
Note: In case your template uses this module, please add {{
lua
Among the possibilities that the module offers there is that of performing a series of actions after novel arguments have been concatenated to templates' incoming parameters. As this makes it necessary to keep the argument slots clean from interference, instead of named arguments in order to specify options this module uses piping functions (i.e. functions that expect to be piped instead of returning to the caller), or modifiers. This creates a syntax similar to the following example:
{{#invoke:params|[modifier]|[...]|[modifier]|[...]|function|[...]}}
For instance, as the name suggests, the
list
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 the
setting
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 arguments,
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 of
definition lists,
{{#invoke:params|setting|h/p/i/f|<dl><dt>|</dt><dd>|</dd><dt>|</dd></dl>|list}}
thus yielding:
By placing the
with_name_matching
modifier before the
list
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 to concatenate infinite modifiers. And so, in order to get the accurate result that we want to obtain we could write:
{{#invoke:params|non-sequential|with_name_matching|^B|with_name_matching|n$|with_value_matching|feline|setting|h/p/i/f|<dl><dt>|</dt><dd>|</dd><dt>|</dd></dl>|list}}
The two modifiers
sequential
and
non-sequential
refer to a technical jargon used in wikitext: given a parameter list, the subgroup of sequential parameters is constituted by the largest group of consecutive numerical parameters starting from
Here follows the list of functions. You might want to see also § Modifiers.
self
Num. of arguments | 0 |
---|---|
Not affected by | Any modifier |
See also | |
{{
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 named Page X
contained only a transclusion of a template named {{foobar}}
, and the latter contained the following wikitext,
{{#invoke:params|self}}
{{FULLPAGENAME}}
if we visited Template:Foobar
we would see,
Template:Foobar Template:Foobar
whereas if we visited Page X
we would see:
Template:Foobar Page 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.
If Page X
transcluded {{foobar 2}}
and the latter were a redirect to {{foobar}}
, we would still see
Template:Foobar Page X
A typical use case of this function is that of providing stable links for editing transcluded templates. E.g.:
{{|{{#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 ,
setting ,
sorting_sequential_val… ,
mapping_by_calling ,
mapping_by_invoking ,
mapping_blindly_by_cal… ,
mapping_blindly_by_inv… |
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 arguments,
{{#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 |
See also | |
concat_and_invoke ,
concat_and_magic |
{{#invoke:params|concat_and_call|template name|[prepend 1]|[prepend 2]|[...]|[prepend n]|[named item 1=value 1]|[...]|[named item n=value n]|[...]}}
For example, if our {{example template}}
had the following code,
{{#invoke:params|concat_and_call|foobar|elbow|earth|room|7=classy|hello=not today}}
and were called with,
the following call to the {{foobar}}
template would be performed:
By using the
cutting
modifier it is possible to impose numerical 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 with hello world
:
{{#invoke:params|cutting|3|0|concat_and_call|my template|{{{1|}}}|{{{2|}}}|hello world}}
If no other argument besides the template name are provided this function simply echoes the current parameters to another template.
Note: All arguments passed to this function except the template name are not trimmed of their leading and trailing spaces. The concat_and_call
function name itself, however, will be trimmed of its surrounding spaces.
concat_and_invoke
Num. of arguments | Ad libitum |
---|---|
Not affected by |
all_sorted |
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 like
concat_and_call
, but invokes a module instead of calling a template.
Note: All arguments passed to this function except the module name and the function name are not trimmed of their leading and trailing spaces. The concat_and_invoke
function name itself, however, will be trimmed of its surrounding spaces.
concat_and_magic
Num. of arguments | Ad libitum |
---|---|
Not affected by |
all_sorted |
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 like
concat_and_call
, but calls a
parser function instead of a template.
Note: All arguments passed to this function except the magic word are not trimmed of their leading and trailing spaces. The concat_and_magic
function name itself, however, will be trimmed of its surrounding spaces.
value_of
Num. of arguments | 1 |
---|---|
Relevant runtime variables | h , f , n |
Not affected by |
all_sorted |
See also | |
list_values |
{{#invoke:params|value_of|parameter name}}
Without modifiers this function is similar to writing {{{parameter name|}}}
. With modifiers, however, it allows to reach 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 the
setting
modifier – the strings assigned to the key-value pair delimiter (p
), the iteration delimiter (i
) and the last iteration delimiter (l
) will be ignored.
For instance, the {{ If then show}} template could be rewritten as
{{#invoke:params|with_value_not_matching|^%s*$|setting|h/f/n|{{{3|}}}|{{{4|}}}|{{{2|}}}|value_of|1}}
Simplifying, the following wikitext expands to the first parameter that is not empty:
{{#invoke:params|with_value_not_matching||strict|squeezing|value_of|1}}
Whereas the following wikitext expands to the first parameter that is not blank (i.e. neither empty nor containing only whitespaces)
{{#invoke:params|with_value_not_matching|^%s*$|squeezing|value_of|1}}
list
Num. of arguments | Ad libitum |
---|---|
Sortable | Yes |
Relevant runtime variables | h , p , i , l , f , n |
See also | |
list_values |
{{#invoke:params|list}}
This function does not take arguments.
If the
setting
modifier was not placed earlier, this function will not add delimiters, but will return an indistinct blob of text in which keys and values are sticked to each other. A header (h
), a key-value pair delimiter (p
), an iteration delimiter (i
), a last iteration delimiter (l
), a footer (f
), and a fallback text (n
) can be declared via
setting
.
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 | Ad libitum |
---|---|
Sortable | Yes |
Often preceeded by |
sequential |
Relevant runtime variables | h , i , l , f , n |
See also | |
list ,
value_of , {{
#invoke:separated entries}} |
{{#invoke:params|list_values}}
This function does not take arguments.
The
sequential
modifier often accompanies this function. If the
setting
modifier was not placed earlier, this function will not add delimiters, but will return an indistinct blob of text in which values are sticked to each other. A header (h
), an iteration delimiter (i
), a last iteration delimiter (l
), a footer (f
), and a fallback text (n
) can be declared via
setting
– the string assigned to the key-value pair delimiter (p
) will be ignored.
For example, the following code
{{#invoke:params|setting|h/i/p/f/n|'''Parameters passed:''' |); | (|)|'''No parameters were passed'''|list_values}}
will generate an output similar to the following.
call_for_each
Num. of arguments | Ad libitum |
---|---|
Sortable | Yes |
Relevant runtime variables | h , i , l , f , n |
See also | |
call_for_each_value ,
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]|[...] }}
All unnamed arguments following the template name will be placed after the key-value pair. Named arguments will be passed verbatim. A header (h
), an iteration delimiter (i
), a last iteration delimiter (l
), a footer (f
), and a fallback text (n
) can be declared via the
setting
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 expanded after 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 the template name are not trimmed of their leading and trailing spaces. The call_for_each
function name itself, however, will be trimmed of its surrounding spaces.
invoke_for_each
Num. of arguments | Ad libitum |
---|---|
Sortable | Yes |
Relevant runtime variables | h , i , l , f , n |
See also | |
invoke_for_each_value ,
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 like
call_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 expanded after 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 the module name and the function name are not trimmed of their leading and trailing spaces. The invoke_for_each
function name itself, however, will be trimmed of its surrounding spaces.
magic_for_each
Num. of arguments | Ad libitum |
---|---|
Sortable | Yes |
Relevant runtime variables | h , i , l , f , n |
See also | |
magic_for_each_value ,
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 like
call_for_each
, but calls a
parser function instead of a template.
Note: All arguments passed to this function except the magic word are not trimmed of their leading and trailing spaces. The magic_for_each
function 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 |
Relevant runtime variables | h , i , l , f , n |
See also | |
call_for_each ,
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]|[...]}}
The
sequential
modifier often accompanies this function. All unnamed arguments following the template name will be appended after the value parameter. Named arguments will be passed verbatim. A header (h
), an iteration delimiter (i
), a last iteration delimiter (l
), a footer (f
), and a fallback text (n
) can be declared via the
setting
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 expanded after 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 the template name are not trimmed of their leading and trailing spaces. The call_for_each_value
function 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 |
Relevant runtime variables | h , i , l , f , n |
See also | |
call_for_each_value ,
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 like
call_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 expanded after 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 the module name and the function name are not trimmed of their leading and trailing spaces. The invoke_for_each_value
function 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 |
Relevant runtime variables | h , i , l , f , n |
See also | |
call_for_each_value ,
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 like
call_for_each_value
, but calls a
parser 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 with QUERY
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 pages with preloaded text and parameters.
Note: All arguments passed to this function except the magic word are not trimmed of their leading and trailing spaces. The magic_for_each_value
function name itself, however, will be trimmed of its surrounding spaces.
call_for_each_group
Num. of arguments | Ad libitum |
---|---|
Often preceeded by |
all_sorted |
Sortable | Yes |
Relevant runtime variables | h , i , l , f , n |
See also | |
call_for_each ,
call_for_each_value , {{
#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]|[...] }}
The custom template will be repeatedly called with the numerical id of the group (i.e. the numerical suffix) as argument zero (i.e. {{{0}}}
). This will be an empty string for the group of incoming parameters that do not have a numerical suffix. A hyphen before the numerical suffix will be interpreted as a minus sign (and therefore the group id will be treated as a negative number). Numerical 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 numerical 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 is 0
or a negative number it will be decreased by one unit in order to leave the parameter zero undisturbed (so 0
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 the template 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. Numerical argument names below 1
will be decreased by one unit (i.e. ...|call_for_each_group|0=Hello world|...
will become |-1=Hello world
in the callback template – see above).
A header (h
), an iteration delimiter (i
), a last iteration delimiter (l
), a footer (f
), and a fallback text (n
) can be declared via the
setting
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 and
TableTools.affixNums
.
For example, if a template named {{foobar}}
contained the following code,
{{#invoke:params|all_sorted|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
| 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
}}{{example template
| 0 =
| 1 = hello
| 2 = world
| = ultricies
| foo = bar
| other = elit
| sunscreen = vestibulum
}}
The modifiers
sequential
,
non-sequential
and
all_sorted
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 the with_*_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 numerical suffix are not empty strings). The
all_sorted
modifier often accompanies this function.
Warning In writing templates there is often the habit of signaling
multilevel substitutions using the {{{|safesubst:}}}
notation. This is a dangerous practice, because {{{|safesubst:}}}
means “write the parameter with an empty name, otherwise write safesubst:
”. Due to the fact that call_for_each_group
can pass parameters with an empty name, a callback template should never use {{{|safesubst:}}}
to notate multilevel substitutions, but should use instead safesubst:<noinclude />
. Not following this advice can lead to bugs that are hard to debug.
At {{ ./doc/examples/list of authors}} you can find an example of how to use this function to list authors the same way {{ Cite book}} does. For instance, writing
{{module:params/doc/examples/list of authors
| last1 = Playfair
| first1 = I. S. O.
| author-link1 = Ian Stanley Ord Playfair
| last2 = Stitt
| first2 = G. M. S.
| last3 = Molony
| first3 = C. J. C.
| last4 = Toomer
| first4 = S. E.
}}
will generate
Playfair, I. S. O.; Stitt, G. M. S.; Molony, C. J. C. & Toomer, S. E.
Note: All arguments passed to this function except the template name are not trimmed of their leading and trailing spaces. The call_for_each_group
function name itself, however, will be trimmed of its surrounding spaces.
for_each
Num. of arguments | 1 |
---|---|
Sortable | Yes |
Relevant runtime variables | h , i , l , f , n |
See also | |
list ,
list_values , {{
#invoke:for nowiki}} , {{
for nowiki}} |
$#
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 an expand_for_each
function). If you need wikitext expansion, use
concat_and_call
to propagate the incoming parameters altogether to the {{
for nowiki}} template. Example:
{{#invoke:params|sequential|concat_and_call|for nowiki|[separator]|<nowiki>{{{i}}} is {{urlencode:{{{1}}}|QUERY}}</nowiki>}}
Note: The argument passed to this function is not trimmed of its leading and trailing spaces. The for_each
function name itself, however, will be trimmed of its surrounding spaces.
The following are modifiers, i.e. functions that expect to be piped instead of returning to the caller. Each of them can be followed by either another modifier or a non-piping function. The actions that modifiers do are done sequentially, in the same order chosen during the invocation of this module. Some modifiers, however, after signaling their presence to the modifiers that might follow, add their action to the queue of actions that will be done last (e.g.
sequential
,
non-sequential
,
all_sorted
).
sequential
Num. of arguments | 0 |
---|---|
Repeatable | No |
Conflicts with |
non-sequential ,
all_sorted |
See also | |
non-sequential ,
all_sorted ,
squeezing ,
filling_the_gaps ,
clearing |
{{#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.
Using sequential
together with
non-sequential
will generate an error.
Note: Like
non-sequential
, the sequential
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 |
{{#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.
Using non-sequential
together with
sequential
will generate an error.
Note: Like
sequential
, the non-sequential
modifier permanently marks a query, and no matter what transformations will follow (see
squeezing
) the parameters' “sequence” will not be shown.
all_sorted
Num. of arguments | 0 |
---|---|
Repeatable | No |
Conflicts with |
sequential |
Has no effects on |
count ,
value_of ,
concat_and_call ,
concat_and_invoke ,
concat_and_magic |
See also | |
Natural sort order,
sequential ,
sorting_sequential_values |
{{#invoke:params|all_sorted|pipe function name}}
Note: This function sorts the way functions iterate across all parameters based on their names. If you want to sort sequential parameters based on their values, see
sorting_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. The all_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 the
squeezing
modifier can be used.
[1]
The all_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: The all_sorted
modifier cannot be used with functions that propagate several parameters together in a single call, like
concat_and_call
,
concat_and_invoke
, and
concat_and_magic
, because during a call the order of arguments is always lost. For the same reason, it is not possible to guess the order of named parameters a template was transcluded with.
setting
Num. of arguments | 2–7 (variable) | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Repeatable | Yes | ||||||||||||
Memory slots | |||||||||||||
|
{{#invoke:params|setting|directives|...|pipe function name}}
This modifier allows to set some internal variables that will be used by functions. It takes a variable number of arguments, relying on the first argument to understand how many other arguments to read. A few examples will introduce it better than words:
{{#invoke:params|setting|i|{{!}}|list_values}}
|
, then list all values{{#invoke:params|setting|ih|{{!}}|list_values}}
|
, then list all values{{#invoke:params|setting|ih/p|{{!}}|{{=}}|list}}
|
, set key-value pair delimiter to =
, then list all parameters{{#invoke:params|setting|ih/p/n|{{!}}|{{=}}|No parameters were passed|list}}
|
, set key-value pair delimiter to =
, set fallback text to No 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 when l is not given, or three or more parameters when l 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 defaults to i .
|
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 the directives arguments are discarded. Therefore writing {{#invoke:params|setting|ih/p|...}}
is equivalent to writing
{{#invoke:params|setting| i
h / p |...}}
In theory, instead of assigning different slots at once (i.e. {{...|setting|ih/p|{{!}}|{{=}}|...}}
), it is possible to write separate invocations of setting
for each variable, as in {{...|setting|ih|{{!}}|setting|p|{{=}}...}}
. This method however will be slightly less efficient.
Sometimes it might be necessary to make the values assigned depend on conditional expressions. For instance, the following imaginary {{Foobar see also}}
template uses the
#ifexpr
parser function to properly show the “and” conjunction and possibly an
Oxford comma when more than two page names are provided:
{{Hatnote|{{{altphrase|Foobar see also}}}: {{#if:{{{1|}}}
|{{#invoke:params|sequential|squeezing|setting|i/l|, |{{#ifexpr:{{#invoke:params|sequential|squeezing|count}} > 2|,}} and |trimming_values|for_each|[[$@]]}}
|{{Error|{{tl|Foobar see also}} requires at least one page name}}
}}}}
You can find this example at {{
./doc/examples/Oxford comma}}. E.g., {{module:params/doc/examples/Oxford comma|Latin|English|German|Italian}}
will generate
Note: The setting
modifier will be trimmed of its surrounding spaces. The directives argument will be stripped of all space characters, including internal spaces. All the other arguments passed to this modifier will be parsed verbatim (i.e. leading and trailing spaces will not be removed).
squeezing
Num. of arguments | 0 |
---|---|
Repeatable | Yes |
See also | |
filling_the_gaps ,
sequential ,
clearing |
{{#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.
The following three concatenations will lead to the same result of discarding all parameters with numerical names:
{{...|non-sequential|squeezing|...}}
{{...|squeezing|non-sequential|...}}
{{...|with_name_not_matching|^%-?%d+$|...}}
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 numerical parameters are lower than 1, the gap between 1 and the maximum numerical parameter will not be filled. The following table provides some examples.
Before calling filling_the_gaps
|
After calling filling_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 function.
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.
Unlike
sequential
– which affects only the way parameters are shown – this modifier actually removes all non-sequential numerical parameters, albeit leaves non-numerical parameters intact.
Example:
{{#invoke:params|clearing|setting|i/p|<br />|: |list}}
If you want to remove also non-numerical parameters, add the
with_name_matching
modifier:
{{#invoke:params|clearing|with_name_matching|^%d+$|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 ,
rotating ,
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 left on 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 of sequential 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 numerical parameters will be shifted accordingly.
In some cases it might be necessary to concatenate more than one invocation of the cutting
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, because
non-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 ,
rotating ,
sorting_sequential_values |
{{#invoke:params|cropping|left crop|right crop|pipe function name}}
This function is very similar to
cutting
, but instead of removing arguments from the extremities of the parameters' sequence, arguments will be removed counting from the first and the last numerical 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 left on 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}}
invokes the
cutting
function with 2
and 1
as arguments, as in the example above, the following parameters will be left:
If instead the template invokes the
cropping
function with 2
and 1
as arguments, the following parameters will 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 lowest numerical parameters available, the behavior will be the same as if the sum had been equal to the number of numerical parameters available, both when this is a positive value and when it is a negative value (with opposite results). When sequential parameters are present among the discarded parameters, all the remaining numerical 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 ,
rotating ,
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 lies on the right side. If the second argument contains zero or a negative number its absolute value indicates what must be left at the end of the right side of the list of numerical parameters – i.e. {{#invoke:params|purging|5|0|list}}
indicates that every numerical argument whose numerical name is greater than 4
must be removed.
Example:
{{#invoke:params|purging|2|1|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 ,
rotating ,
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 lies on the left side. If the second argument contains zero or a negative number its absolute value indicates what must be left at the end of the left side of the list of numerical parameters – i.e. {{#invoke:params|purging|5|0|list}}
indicates that every numerical argument whose numerical name is less than 6
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 numerical names, then lists the rest:
{{#invoke:params|backpurging|0|0|for_each|[$#: $@]}}
rotating
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|rotating|pipe function name}}
This modifier does not take arguments besides the name of the function that will follow.
Example:
{{#invoke:params|rotating|for_each|[$#: $@]}}
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 ,
rotating ,
all_sorted |
{{#invoke:params|sorting_sequential_values|[criterion]|pipe function name}}
Note: This function sorts sequential parameters based on their values. If you want to sort the way functions iterate across all parameters based on their names, see
all_sorted
.
This function 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 is naturally
, for ordering sequential values in
natural 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|[$#: $@]}}
with_name_matching
Num. of arguments | Ad libitum |
---|---|
Repeatable | Yes |
See also | |
with_name_not_matching ,
with_value_matching ,
with_value_not_matching |
{{#invoke:params|with_name_matching|pattern 1|[plain flag 1]|[or]|[pattern 2]|[plain flag 2]|[or]|[...]|[pattern N]|[plain flag N]|pipe function name}}
Internally this modifier uses Lua's
string.find()
function to find whether parameter names match against given patterns; therefore, unless a plain flag is set, please use the same syntax of
Lua patterns. The plain flag can be either plain
or strict
or omitted. When omitted it is assumed that the target string is a Lua pattern. The difference between plain
and strict
is that the latter also requires that the lengths match (this happens only when the two strings are 100% identical).
To express a
logical OR the or
keyword is available. To express a
logical AND instead, concatenate more invocations of with_name_matching
.
For the sake of argument we will imagine that we are invoking with_name_matching
from within the {{
Infobox artery}} template, and this is being called with the following parameters:
Test cases:
^Image
pattern:
{{#invoke:params|setting|ih/p|{{!}}|{{=}}|with_name_matching|^Image|list}}
^Image
and %d+$
:
{{#invoke:params|setting|ih/p|{{!}}|{{=}}|with_name_matching|^Image|with_name_matching|%d+$|list}}
^Name
or the ^Latin$
pattern:
{{#invoke:params|setting|ih/p|{{!}}|{{=}}|with_name_matching|^Name$|or|^Latin$|list}}
ma
plain string or the me$
pattern:
{{#invoke:params|setting|ih/p|{{!}}|{{=}}|with_name_matching|ma|plain|or|me$|list}}
Using with_name_matching
it is easy to emulate the behaviour of
Module:Enumerate (or similar modules). For instance, the following examples creates a bullet list of all the parameters passed of type |foobar1
, |foobar2
… |foobarN
:
{{#invoke:params|all_sorted|with_name_matching|^foobar%d+$|setting|ih|
* |list_values}}
It is possible to see this example live at {{ ./doc/examples/enumerate}}.
Note: The pattern arguments passed to this function are not trimmed of their leading and trailing spaces. The or
, plain
and strict
keywords, and the with_name_matching
function name itself, however, will be trimmed of their surrounding spaces.
with_name_not_matching
Num. of arguments | Ad libitum |
---|---|
Repeatable | Yes |
See also | |
with_name_matching ,
with_value_matching ,
with_value_not_matching |
{{#invoke:params|with_name_not_matching|pattern 1|[plain flag 1]|[and]|[pattern 2]|[plain flag 2]|[and]|[...]|[pattern N]|[plain flag N]|pipe function name}}
Internally this modifier uses Lua's
string.find()
function to find whether parameter names match against given patterns; therefore, unless a plain flag is set, please use the same syntax of
Lua patterns. The plain flag can be either plain
or strict
or omitted. When omitted it is assumed that the target string is a Lua pattern. The difference between plain
and strict
is that the latter also requires that the lengths match (this happens only when the two strings are 100% identical).
To express a
logical OR the or
keyword is available. To express a
logical AND instead, concatenate more invocations of with_name_not_matching
.
For the sake of argument we will imagine that we are invoking with_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 at
with_name_matching
:
a
pattern:
{{#invoke:params|setting|ih/p|{{!}}|{{=}}|with_name_not_matching|a|list}}
a
plain string and do not match against the l
plain string either:
{{#invoke:params|setting|ih/p|{{!}}|{{=}}|with_name_not_matching|a|plain|with_name_not_matching|l|plain|list}}
a
plain string or the n
plain string:
{{#invoke:params|setting|ih/p|{{!}}|{{=}}|with_name_not_matching|a|plain|or|n|plain|list}}
It is possible to use this function to check for unknown parameters:
{{#ifexpr:{{#invoke:params|with_name_not_matching|hello|strict|with_name_not_matching|wind|strict|count}} > 0
|{{#invoke:Error|error|Error: The only parameters accepted are {{para|hello}} and {{para|wind}}.}}
|Everything is good: do something
}}
You can find this example at {{
./doc/examples/check for unknown parameters}}. E.g., {{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:
Note: The pattern arguments passed to this function are not trimmed of their leading and trailing spaces. The or
, plain
and strict
keywords, and the with_name_not_matching
function 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|pattern 1|[plain flag 1]|[or]|[pattern 2]|[plain flag 2]|[or]|[...]|[pattern N]|[plain flag N]|pipe function name}}
Exactly like
with_name_matching
, but applied to parameter values instead of names.
Internally this modifier uses Lua's
string.find()
function to find whether parameter names match against given patterns; therefore, unless a plain flag is set, please use the same syntax of
Lua patterns. The plain flag can be either plain
or strict
or omitted. When omitted it is assumed that the target string is a Lua pattern. The difference between plain
and strict
is that the latter also requires that the lengths match (this happens only when the two strings are 100% identical).
Example:
{{#invoke:params|with_value_matching|banana|count}}
Note: The pattern arguments passed to this function are not trimmed of their leading and trailing spaces. The or
, plain
and strict
keywords, and the with_value_matching
function 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|pattern 1|[plain flag 1]|[and]|[pattern 2]|[plain flag 2]|[and]|[...]|[pattern N]|[plain flag N]|pipe function name}}
Exactly like
with_name_not_matching
, but applied to parameter values instead of names.
Internally this modifier uses Lua's
string.find()
function to find whether parameter names match against given patterns; therefore, unless a plain flag is set, please use the same syntax of
Lua patterns. The plain flag can be either plain
or strict
or omitted. When omitted it is assumed that the target string is a Lua pattern. The difference between plain
and strict
is that the latter also requires that the lengths match (this happens only when the two strings are 100% identical).
For instance, before calling
list
, 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 function is that of purging all empty incoming parameters before calling another template, especially when this distinguishes between empty and undefined parameters.
{{#invoke:params|with_value_not_matching|^%s*$|concat_and_call|my template}}
Note: The pattern arguments passed to this function are not trimmed of their leading and trailing spaces. The or
, plain
and strict
keywords, and the with_value_not_matching
function 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 placing trimming_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 where trimming_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, placing trimming_values
as the last modifier is usually the best choice.
Placing trimming_values
together with non-sequential
will result in an empty call with no effects, because non-sequential parameters are stripped of their leading and trailing spaces by default.
Using trimming_values
makes this module behave like many Wikipedia modules behave. For example, if we wanted to emulate {{
#invoke:Separated entries|main}}, writing
{{#invoke:params|sequential|squeezing|trimming_values|setting|i|XXXX|list_values}}
will be equivalent to writing,
{{#invoke:separated entries|main|separator=XXXX}}
whereas writing
{{#invoke:params|sequential|squeezing|trimming_values|setting|i/l|XXXX|YYYY|list_values}}
will be equivalent to writing
{{#invoke:separated entries|main|separator=XXXX|conjunction=YYYY}}
The {{ ./doc/trim and call}} example template shows how to call any arbitrary template trimming all parameters beforehand.
mapping_by_calling
Num. of arguments | Ad libitum |
---|---|
Repeatable | Yes |
See also | |
mapping_by_invoking ,
mapping_blindly_by_cal… ,
mapping_blindly_by_inv… ,
renaming_blindly_by_ca… ,
renaming_blindly_by_in… |
{{#invoke:params|mapping_by_calling|template name|[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 another template. The latter will be repeatedly called with at least two parameters: key and value. If the template name is followed by a number, this will be parsed as the amount of additional parameters to pass. 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|NAME|VALUE}}
(where NAME
and VALUE
indicate each different name and value).
On the other hand,
{{#invoke:params|mapping_by_calling|foobar|2|hello|world|setting|i/p|{{!}}|{{=}}|list}}
will do the same, but using the expansion of {{foobar|NAME|VALUE|hello|world}}
.
There are no mechanisms for passing non-sequential or non-numeric additional parameters to the mapping template. A similar function,
mapping_blindly_by_calling
, omits the first parameter (i.e. the parameter's name).
Note: All arguments passed to this modifier except the template name and the number of additional arguments are not trimmed of their leading and trailing spaces. The mapping_by_calling
modifier name itself, however, will be trimmed of its surrounding spaces.
mapping_by_invoking
Num. of arguments | Ad libitum |
---|---|
Repeatable | Yes |
See also | |
mapping_by_calling ,
mapping_blindly_by_cal… ,
mapping_blindly_by_inv… ,
renaming_blindly_by_ca… ,
renaming_blindly_by_in… |
{{#invoke:params|mapping_by_invoking|module name|function name|[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 text returned by a custom module function. The latter will be repeatedly invoked with at least two arguments: key and value. If the function name is followed by a number, this will be parsed as the amount of additional arguments to pass. 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|NAME|VALUE}}
(where NAME
and VALUE
indicate each different name and value).
On the other hand,
{{#invoke:params|mapping_by_invoking|foobar|main|2|hello|world|setting|i/p|{{!}}|{{=}}|list}}
will do the same, but using the expansion of {{#invoke:foobar|main|NAME|VALUE|hello|world}}
.
There are no mechanisms for passing non-sequential or non-numeric additional arguments to the mapping module. A similar function,
mapping_blindly_by_invoking
, omits the first argument (i.e. the parameter's name).
Note: All arguments passed to this modifier except the module name, the function name and the number of additional arguments are not trimmed of their leading and trailing spaces. The mapping_by_invoking
modifier name itself, however, will be trimmed of its surrounding spaces.
mapping_blindly_by_calling
Num. of arguments | Ad libitum |
---|---|
Repeatable | Yes |
See also | |
mapping_by_calling ,
mapping_by_invoking ,
mapping_blindly_by_inv… ,
renaming_blindly_by_ca… ,
renaming_blindly_by_in… |
{{#invoke:params|mapping_blindly_by_calling|template name|[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 another template. The latter will be repeatedly called with at least one parameter: the parameter's value. If the template name is followed by a number, this will be parsed as the amount of additional parameters to pass. For instance, before listing all parameters,
{{#invoke:params|mapping_blindly_by_calling|foobar|setting|i/p|{{!}}|{{=}}|list}}
will replace each value with the expansion of {{foobar|VALUE}}
(where VALUE
indicates each different value).
On the other hand,
{{#invoke:params|mapping_blindly_by_calling|foobar|2|hello|world|setting|i/p|{{!}}|{{=}}|list}}
will do the same, but using the expansion of {{foobar|VALUE|hello|world}}
.
There are no mechanisms for passing non-sequential or non-numeric additional parameters to the mapping template. A similar function,
mapping_by_calling
, passes the parameter's name as well, as first argument.
Note: All arguments passed to this modifier except the template name and the number of additional arguments are not trimmed of their leading and trailing spaces. The mapping_blindly_by_calling
modifier name itself, however, will be trimmed of its surrounding spaces.
mapping_blindly_by_invoking
Num. of arguments | Ad libitum |
---|---|
Repeatable | Yes |
See also | |
mapping_by_calling ,
mapping_by_invoking ,
mapping_blindly_by_cal… ,
renaming_blindly_by_ca… ,
renaming_blindly_by_in… |
{{#invoke:params|mapping_blindly_by_invoking|module name|function name|[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 text returned by a custom module function. The latter will be repeatedly invoked with at least one argument: the parameter's value. If the function name is followed by a number, this will be parsed as the amount of additional arguments to pass. For instance, before listing all parameters,
{{#invoke:params|mapping_blindly_by_invoking|foobar|main|setting|i/p|{{!}}|{{=}}|list}}
will replace each value with the expansion of {{#invoke:foobar|main|VALUE}}
(where VALUE
indicates each different value).
On the other hand,
{{#invoke:params|mapping_blindly_by_invoking|foobar|main|2|hello|world|setting|i/p|{{!}}|{{=}}|list}}
will do the same, but using the expansion of {{#invoke:foobar|main|VALUE|hello|world}}
.
There are no mechanisms for passing non-sequential or non-numeric additional arguments to the mapping module. A similar function,
mapping_by_invoking
, passes the parameter's name as well, as first argument.
Note: All arguments passed to this modifier except the module name, the function name and the number of additional arguments are not trimmed of their leading and trailing spaces. The mapping_blindly_by_invoking
modifier name itself, however, will be trimmed of its surrounding spaces.
renaming_blindly_by_calling
Num. of arguments | Ad libitum |
---|---|
Repeatable | Yes |
See also | |
mapping_by_calling ,
mapping_by_invoking ,
mapping_blindly_by_cal… ,
mapping_blindly_by_inv… ,
renaming_blindly_by_in… |
{{#invoke:params|renaming_blindly_by_calling|template name|[number of additional arguments]|[argument 1]|[argument 2]|[...]|[argument N]|pipe function name}}
This modifier works similarly to
mapping_blindly_by_calling
, but instead of replacing parameters' values it 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.
For instance, the following example uses {{ 2x}} to rename all arguments by doubling their name:
{{#invoke:params|setting|h/i/p/f||][|: ||renaming_blindly_by_calling|2x|list}}
Same, but adding a hyphen in between:
{{#invoke:params|setting|h/i/p/f||][|: ||renaming_blindly_by_calling|2x|1|-|list}}
This function can be particularly useful for sanitizing parameter names (e.g. collapsing several spaces into single spaces, changing the letter case, and so on).
Note: All arguments passed to this modifier except the template name and the number of additional arguments are not trimmed of their leading and trailing spaces. The renaming_blindly_by_calling
modifier name itself, however, will be trimmed of its surrounding spaces.
renaming_blindly_by_invoking
Num. of arguments | Ad libitum |
---|---|
Repeatable | Yes |
See also | |
mapping_by_calling ,
mapping_by_invoking ,
mapping_blindly_by_cal… ,
mapping_blindly_by_inv… ,
renaming_blindly_by_ca… |
{{#invoke:params|renaming_blindly_by_invoking|module name|function name|[number of additional arguments]|[argument 1]|[argument 2]|[...]|[argument N]|pipe function name}}
This modifier works similarly to
mapping_blindly_by_invoking
, but instead of replacing parameters' values it 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.
For instance, the following example uses {{
#invoke:string|
replace}} to rename all arguments 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_blindly_by_invoking|string|replace|4|^arg(%d+)$|%1|1|false|list}}
This function can be particularly useful for sanitizing parameter names (e.g. collapsing several spaces into single spaces, changing the letter case, and so on).
Note: All arguments passed to this modifier except the module name, the function name and the number of additional arguments are not trimmed of their leading and trailing spaces. The mapping_blindly_by_invoking
modifier name itself, however, will be trimmed of its surrounding spaces.
{{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 displayd first (i.e. {{foobar|-8=do|-4=you|9=wanna|11=marry|.=me?}}
).
--- ---
--- LOCAL ENVIRONMENT ---
--- ________________________________ ---
--- ---
--[[ Abstract utilities ]]--
----------------------------
-- Helper function for `string.gsub()` (for managing zero-padded numbers)
function zero_padded(str)
return ("%03d%s"):format(#str, str)
end
-- Helper function for `table.sort()` (for natural sorting)
function natural_sort(var1, var2)
return tostring(var1):gsub("%d+", zero_padded) <
tostring(var2):gsub("%d+", zero_padded)
end
-- Return a copy or a reference to a table
local function copy_or_ref_table(src, refonly)
if refonly then return src end
newtab = {}
for key, val in pairs(src) do newtabkey = val end
return newtab
end
-- Remove numerical elements from a table, shifting everything to the left
function remove_numerical_keys(tbl, idx, len)
local cache = {}
local tmp = idx + len - 1
for key, val in pairs(tbl) do
if type(key) == 'number' and key >= idx then
if key > tmp then cachekey - len = val end
tblkey = nil
end
end
for key, val in pairs(cache) do tblkey = val end
end
-- Make a reduced copy of a table (shifting in both directions if necessary)
function copy_table_reduced(tbl, idx, len)
local ret = {}
local tmp = idx + len - 1
if idx > 0 then
for key, val in pairs(tbl) do
if type(key) ~= 'number' or key < idx then
retkey = val
elseif key > tmp then retkey - len = val end
end
elseif tmp > 0 then
local nshift = 1 - idx
for key, val in pairs(tbl) do
if type(key) ~= 'number' then retkey = val
elseif key > tmp then retkey - tmp = val
elseif key < idx then retkey + nshift = val end
end
else
for key, val in pairs(tbl) do
if type(key) ~= 'number' or key > tmp then
retkey = val
elseif key < idx then retkey + len = val end
end
end
return ret
end
--[[ Module's private environment ]]--
--------------------------------------
-- Special user-given keywords (functions and modifiers MUST avoid these names)
local mkeywords = {
'or' = 0,
--['pattern'] = 1, -- Simply uncommenting enables the option
'plain' = 2,
'strict' = 3
}
-- Sort functions (functions and modifiers MUST avoid these names)
local sortfunctions = {
--['alphabetically'] = false, -- Simply uncommenting enables the option
'naturally' = natural_sort
}
-- Memory slots
local memoryslots = {
i = 'itersep',
l = 'lastsep',
p = 'pairsep',
h = 'header',
f = 'footer',
n = 'ifngiven'
}
-- Directive that can only be invoked as first arguments
local firstposonly = {
new = 'modifier',
self = 'function',
}
-- Maximum number of numerical 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)
local maxfill = 1024
-- The private table of functions
local library = {}
-- Create a new context
local function context_new(frame)
local ctx = {}
ctx.luaname = 'Module:Params' --[[ or `frame:getTitle()` ]]--
ctx.iterfunc = pairs
ctx.frame = frame:getParent()
return ctx
end
-- Prepare the context
local function context_init(frame, funcname, refpipe, refparams)
local ctx = context_new(frame)
ctx.pipe = copy_or_ref_table(frame.args, refpipe)
ctx.params = copy_or_ref_table(ctx.frame.args, refparams)
return funcname(ctx)
end
-- Move to the next action within the user-given list
local function context_iterate(ctx, n_forward)
local nextfn
if ctx.pipen_forward ~= nil then
nextfn = ctx.pipen_forward]:match'^%s*(.*%S)'
end
if nextfn == nil then
error(ctx.luaname .. ': You must specify a function to call', 0)
end
if librarynextfn == nil then
if firstposonlynextfn == nil then
error(ctx.luaname .. ': The function ‘' .. nextfn ..
'’ does not exist', 0)
else
error(ctx.luaname .. ': The ‘' .. nextfn .. '’ ' ..
firstposonlynextfn ..
' can only be invoked in first position', 0)
end
end
remove_numerical_keys(ctx.pipe, 1, n_forward)
return librarynextfn](ctx)
end
-- Concatenate the numerical keys from the table of parameters to the numerical
-- keys from the table of options; non-numerical keys from the table of options
-- will prevail over colliding non-numerical keys from the table of parameters
local function concat_params(ctx)
local shift = table.maxn(ctx.pipe)
local newargs = {}
if ctx.subset == 1 then
-- We need only the sequence
for key, val in ipairs(ctx.params) do
newargskey + shift = val
end
else
if ctx.subset == -1 then
for key, val in ipairs(ctx.params) do
ctx.paramskey = nil
end
end
for key, val in pairs(ctx.params) do
if type(key) == 'number' then
newargskey + shift = val
else
newargskey = val
end
end
end
for key, val in pairs(ctx.pipe) do newargskey = val end
return newargs
end
-- Flush the parameters by calling a custom function for each value (after this
-- function has been invoked `ctx.params` will no longer be usable)
local function flush_params(ctx, fn)
local tbl = ctx.params
if ctx.subset == 1 then
for key, val in ipairs(tbl) do fn(key, val) end
return
end
if ctx.subset == -1 then
for key, val in ipairs(tbl) do tblkey = nil end
end
if ctx.dosort then
local nums = {}
local words = {}
local nlen = 0
local wlen = 0
for key, val in pairs(tbl) do
if type(key) == 'number' then
nlen = nlen + 1
numsnlen = key
else
wlen = wlen + 1
wordswlen = key
end
end
table.sort(nums)
table.sort(words, natural_sort)
for idx = 1, nlen do fn(numsidx], tblnumsidx]]) end
for idx = 1, wlen do fn(wordsidx], tblwordsidx]]) end
return
end
if ctx.subset ~= -1 then
for key, val in ipairs(tbl) do
fn(key, val)
tblkey = nil
end
end
for key, val in pairs(tbl) do fn(key, val) end
end
-- Parse the arguments of the `with_*_matching` class of modifiers
local function parse_match_args(opts, ptns, fname)
local state = 0
local cnt = 1
local keyw
local nptns = 0
for _, val in ipairs(opts) do
if state == 0 then
nptns = nptns + 1
ptnsnptns = { val, false, false }
state = -1
else
keyw = val:match'^%s*(.*%S)'
if keyw == nil or mkeywordskeyw == nil or (
state > 0 and mkeywordskeyw > 0
) then break
else
state = mkeywordskeyw
if state > 1 then ptnsnptns][2 = true end
if state == 3 then ptnsnptns][3 = true end
end
end
cnt = cnt + 1
end
if state == 0 then error(ctx.luaname .. ', ‘' .. fname .. '’: No pattern was given', 0) end
return cnt
end
--[[ Library's modifiers ]]--
-----------------------------
-- See iface.sequential()
library.sequential = function(ctx)
if ctx.subset == -1 then error(ctx.luaname .. ': The two directives ‘non-sequential’ and ‘sequential’ are in contradiction with each other', 0) end
if ctx.dosort then error(ctx.luaname .. ': The ‘all_sorted’ directive is redundant when followed by ‘sequential’', 0) end
ctx.iterfunc = ipairs
ctx.subset = 1
return context_iterate(ctx, 1)
end
-- See iface['non-sequential']()
library'non-sequential' = function(ctx)
if ctx.subset == 1 then error(ctx.luaname .. ': The two directives ‘sequential’ and ‘non-sequential’ are in contradiction with each other', 0) end
ctx.iterfunc = pairs
ctx.subset = -1
return context_iterate(ctx, 1)
end
-- See iface.all_sorted()
library.all_sorted = function(ctx)
if ctx.subset == 1 then error(ctx.luaname .. ': The ‘all_sorted’ directive is redundant after ‘sequential’', 0) end
ctx.dosort = true
return context_iterate(ctx, 1)
end
-- See iface.setting()
library.setting = function(ctx)
local opts = ctx.pipe
local cmd
if opts1 ~= nil then
cmd = opts1]:gsub('%s+', ''):gsub('/+', '/'):match'^/*(.*[^/])'
end
if cmd == nil then error(ctx.luaname .. ', ‘setting’: No directive was given', 0) end
local sep = string.byte('/')
local argc = 2
local dest = {}
local vname
local chr
for idx = 1, #cmd do
chr = cmd:byte(idx)
if chr == sep then
for key, val in ipairs(dest) do
ctxval = optsargc
destkey = nil
end
argc = argc + 1
else
vname = memoryslotsstring.char(chr)]
if vname == nil then error(ctx.luaname .. ', ‘setting’: Unknown slot "' ..
string.char(chr) .. '"', 0) end
table.insert(dest, vname)
end
end
for key, val in ipairs(dest) do ctxval = optsargc end
return context_iterate(ctx, argc + 1)
end
-- See iface.squeezing()
library.squeezing = function(ctx)
local tbl = ctx.params
local store = {}
local indices = {}
local newlen = 0
for key, val in pairs(tbl) do
if type(key) == 'number' then
newlen = newlen + 1
indicesnewlen = key
storekey = val
tblkey = nil
end
end
table.sort(indices)
for idx = 1, newlen do tblidx = storeindicesidx]] end
return context_iterate(ctx, 1)
end
-- See iface.filling_the_gaps()
library.filling_the_gaps = function(ctx)
local tbl = ctx.params
local nmin = 1
local nmax = nil
local nnums = -1
local tmp = {}
for key, val in pairs(tbl) do
if type(key) == 'number' then
if nmax == nil then
if key < nmin then nmin = key end
nmax = key
elseif key > nmax then nmax = key
elseif key < nmin then nmin = key end
nnums = nnums + 1
tmpkey = val
end
end
if nmax ~= nil and nmax - nmin > nnums then
if maxfill + nmin + nnums < nmax then error(ctx.luaname .. ', ‘filling_the_gaps’: It is possible to fill at most ' .. tostring(maxfill) .. ' parameters', 0) end
for idx = nmin, nmax, 1 do tblidx = '' end
for key, val in pairs(tmp) do tblkey = val end
end
return context_iterate(ctx, 1)
end
-- See iface.clearing()
library.clearing = function(ctx)
local tbl = ctx.params
local numericals = {}
for key, val in pairs(tbl) do
if type(key) == 'number' then
numericalskey = val
tblkey = nil
end
end
for key, val in ipairs(numericals) do tblkey = val end
return context_iterate(ctx, 1)
end
-- See iface.cutting()
library.cutting = function(ctx)
local lcut = tonumber(ctx.pipe1])
if lcut == nil then error(ctx.luaname .. ', ‘cutting’: Left cut must be a number', 0) end
local rcut = tonumber(ctx.pipe2])
if rcut == nil then error(ctx.luaname .. ', ‘cutting’: Right cut must be a number', 0) end
local tbl = ctx.params
local len = #tbl
if lcut < 0 then lcut = len + lcut end
if rcut < 0 then rcut = len + rcut end
local tot = lcut + rcut
if tot > 0 then
local cache = {}
if tot >= len then
for key in ipairs(tbl) do tblkey = nil end
tot = len
else
for idx = len - rcut + 1, len, 1 do tblidx = nil end
for idx = 1, lcut, 1 do tblidx = nil end
end
for key, val in pairs(tbl) do
if type(key) == 'number' and key > 0 then
if key > len then
cachekey - tot = val
else
cachekey - lcut = val
end
tblkey = nil
end
end
for key, val in pairs(cache) do tblkey = val end
end
return context_iterate(ctx, 3)
end
-- See iface.cropping()
library.cropping = function(ctx)
local lcut = tonumber(ctx.pipe1])
if lcut == nil then error(ctx.luaname .. ', ‘cropping’: Left crop must be a number', 0) end
local rcut = tonumber(ctx.pipe2])
if rcut == nil then error(ctx.luaname .. ', ‘cropping’: Right crop must be a number', 0) end
local tbl = ctx.params
local nmin
local nmax
for key in pairs(tbl) do
if type(key) == 'number' then
if nmin == nil then
nmin = key
nmax = key
elseif key > nmax then nmax = key
elseif key < nmin then nmin = key end
end
end
if nmin ~= nil then
local len = nmax - nmin + 1
if lcut < 0 then lcut = len + lcut end
if rcut < 0 then rcut = len + rcut end
if lcut + rcut - len > -1 then
for key in pairs(tbl) do
if type(key) == 'number' then tblkey = nil end
end
elseif lcut + rcut > 0 then
for idx = nmax - rcut + 1, nmax, 1 do tblidx = nil end
for idx = nmin, nmin + lcut - 1, 1 do tblidx = nil end
local lshift = nmin + lcut - 1
if lshift > 0 then
for idx = lshift + 1, nmax, 1 do
tblidx - lshift = tblidx
tblidx = nil
end
end
end
end
return context_iterate(ctx, 3)
end
-- See iface.purging()
library.purging = function(ctx)
local first = tonumber(ctx.pipe1])
if first == nil then error(ctx.luaname .. ', ‘purging’: Start offset must be a number', 0) end
local size = tonumber(ctx.pipe2])
if size == nil then error(ctx.luaname .. ', ‘purging’: Length must be a number', 0) end
local tbl = ctx.params
if size < 1 then
size = size + table.maxn(tbl)
if first > size then return context_iterate(ctx, 3) end
size = size - first + 1
end
ctx.params = copy_table_reduced(tbl, first, size)
return context_iterate(ctx, 3)
end
-- See iface.backpurging()
library.backpurging = function(ctx)
local last = tonumber(ctx.pipe1])
if last == nil then error(ctx.luaname .. ', ‘backpurging’: Start offset must be a number', 0) end
local size = tonumber(ctx.pipe2])
if size == nil then error(ctx.luaname .. ', ‘backpurging’: Length must be a number', 0) end
local first
local tbl = ctx.params
if size > 0 then
first = last - size + 1
else
for key in pairs(tbl) do
if type(key) == 'number' and (first == nil or
key < first) then first = key end
end
if first == nil then return context_iterate(ctx, 3) end
first = first - size
if last < first then return context_iterate(ctx, 3) end
size = last - first + 1
end
ctx.params = copy_table_reduced(ctx.params, first, size)
return context_iterate(ctx, 3)
end
-- See iface.rotating()
library.rotating = function(ctx)
local tbl = ctx.params
local numericals = {}
local nmax = 0
for key, val in pairs(tbl) do
if type(key) == 'number' then
numericalskey = val
tblkey = nil
if key > nmax then nmax = key end
end
end
for key, val in pairs(numericals) do tblnmax - key + 1 = val end
return context_iterate(ctx, 1)
end
-- See iface.pivoting()
--[[
library.pivoting = function(ctx)
local tbl = ctx.params
local shift = #tbl + 1
if shift < 2 then return library.rotating(ctx) end
local numericals = {}
for key, val in pairs(tbl) do
if type(key) == 'number' then
numericals[key] = val
tbl[key] = nil
end
end
for key, val in pairs(numericals) do tbl[shift - key] = val end
return context_iterate(ctx, 1)
end
]]--
-- See iface.mirroring()
--[[
library.mirroring = function(ctx)
local tbl = ctx.params
local numericals = {}
local nmax
local nmin
for key, val in pairs(tbl) do
if type(key) == 'number' then
numericals[key] = val
tbl[key] = nil
if nmax == nil then
nmax = key
nmin = key
elseif key > nmax then nmax = key
elseif key < nmin then nmin = key end
end
end
for key, val in pairs(numericals) do tbl[nmax + nmin - key] = val end
return context_iterate(ctx, 1)
end
]]--
-- See iface.swapping()
--[[
library.swapping = function(ctx)
local tbl = ctx.params
local cache = {}
local nsize = 0
local tmp
for key in pairs(tbl) do
if type(key) == 'number' then
nsize = nsize + 1
cache[nsize] = key
end
end
table.sort(cache)
for idx = math.floor(nsize / 2), 1, -1 do
tmp = tbl[cache[idx] ]
tbl[cache[idx] ] = tbl[cache[nsize - idx + 1] ]
tbl[cache[nsize - idx + 1] ] = tmp
end
return context_iterate(ctx, 1)
end
]]--
-- See iface.sorting_sequential_values()
library.sorting_sequential_values = function(ctx)
local sortfn
if ctx.pipe1 ~= nil then sortfn = sortfunctionsctx.pipe1]] end
if sortfn then table.sort(ctx.params, sortfn)
else table.sort(ctx.params) end -- i.e. either `false` or `nil`
if sortfn == nil then return context_iterate(ctx, 1) end
return context_iterate(ctx, 2)
end
-- See iface.with_name_matching()
library.with_name_matching = function(ctx)
local tbl = ctx.params
local patterns = {}
local argc = parse_match_args(ctx.pipe, patterns, 'with_name_matching')
local nomatch
for key in pairs(tbl) do
nomatch = true
for _, ptn in ipairs(patterns) do
if not ptn3 then
if string.find(key, ptn1], 1, ptn2]) then
nomatch = false
break
end
elseif key == ptn1 then
nomatch = false
break
end
end
if nomatch then tblkey = nil end
end
return context_iterate(ctx, argc)
end
-- See iface.with_name_not_matching()
library.with_name_not_matching = function(ctx)
local tbl = ctx.params
local patterns = {}
local argc = parse_match_args(ctx.pipe, patterns,
'with_name_not_matching')
local yesmatch
for key in pairs(tbl) do
yesmatch = true
for _, ptn in ipairs(patterns) do
if not ptn3 then
if not string.find(key, ptn1], 1, ptn2]) then
yesmatch = false
break
end
elseif key ~= ptn1 then
yesmatch = false
break
end
end
if yesmatch then tblkey = nil end
end
return context_iterate(ctx, argc)
end
-- See iface.with_value_matching()
library.with_value_matching = function(ctx)
local tbl = ctx.params
local patterns = {}
local argc = parse_match_args(ctx.pipe, patterns,
'with_value_matching')
local nomatch
for key, val in pairs(tbl) do
nomatch = true
for _, ptn in ipairs(patterns) do
if not ptn3 then
if string.find(val, ptn1], 1, ptn2]) then
nomatch = false
break
end
elseif val == ptn1 then
nomatch = false
break
end
end
if nomatch then tblkey = nil end
end
return context_iterate(ctx, argc)
end
-- See iface.with_value_not_matching()
library.with_value_not_matching = function(ctx)
local tbl = ctx.params
local patterns = {}
local argc = parse_match_args(ctx.pipe, patterns,
'with_value_not_matching')
local yesmatch
for key, val in pairs(tbl) do
yesmatch = true
for _, ptn in ipairs(patterns) do
if not ptn3 then
if not string.find(val, ptn1], 1, ptn2]) then
yesmatch = false
break
end
elseif val ~= ptn1 then
yesmatch = false
break
end
end
if yesmatch then tblkey = nil end
end
return context_iterate(ctx, argc)
end
-- See iface.trimming_values()
library.trimming_values = function(ctx)
local tbl = ctx.params
for key, val in pairs(tbl) do tblkey = val:match'^%s*(.-)%s*$' end
return context_iterate(ctx, 1)
end
-- See iface.mapping_by_calling()
library.mapping_by_calling = function(ctx)
local opts = ctx.pipe
local tname
if opts1 ~= nil then tname = opts1]:match'^%s*(.*%S)' end
if tname == nil then error(ctx.luaname .. ', ‘mapping_by_calling’: No template name was provided', 0) end
local nargs
local margs = {}
local tmp = tonumber(opts2])
if tmp == nil then nargs = 1
elseif tmp < 1 then nargs = 2
else
nargs = tmp + 2
for idx = 3, nargs do margsidx = optsidx end
end
local model = { title = tname, args = margs }
local tbl = ctx.params
for key, val in pairs(tbl) do
margs1 = key
margs2 = val
tblkey = ctx.frame:expandTemplate(model)
end
return context_iterate(ctx, nargs + 1)
end
-- See iface.mapping_by_invoking()
library.mapping_by_invoking = function(ctx)
local opts = ctx.pipe
local mname
local fname
if opts1 ~= nil then mname = opts1]:match'^%s*(.*%S)' end
if mname == nil then error(ctx.luaname .. ', ‘mapping_by_invoking’: No module name was provided', 0) end
if opts2 ~= nil then fname = opts2]:match'^%s*(.*%S)' end
if fname == nil then error(ctx.luaname .. ', ‘mapping_by_invoking’: No function name was provided', 0) end
local nargs
local margs = {}
local tmp = tonumber(opts3])
if tmp == nil then nargs = 2
elseif tmp < 1 then nargs = 3
else
nargs = tmp + 3
for idx = 4, nargs do margsidx - 1 = optsidx end
end
local model = { title = 'Module:' .. mname, args = margs }
local mfunc = require(model.title)[fname
local tbl = ctx.params
for key, val in pairs(tbl) do
margs1 = key
margs2 = val
tblkey = mfunc(ctx.frame:newChild(model))
end
return context_iterate(ctx, nargs + 1)
end
-- See iface.mapping_blindly_by_calling()
library.mapping_blindly_by_calling = function(ctx)
local opts = ctx.pipe
local tname
if opts1 ~= nil then tname = opts1]:match'^%s*(.*%S)' end
if tname == nil then error(ctx.luaname .. ', ‘mapping_blindly_by_calling’: No template name was provided', 0) end
local nargs
local margs = {}
local tmp = tonumber(opts2])
if tmp == nil then nargs = 1
elseif tmp < 1 then nargs = 2
else
nargs = tmp + 2
for idx = 3, nargs do margsidx - 1 = optsidx end
end
local model = { title = tname, args = margs }
local tbl = ctx.params
for key, val in pairs(tbl) do
margs1 = val
tblkey = ctx.frame:expandTemplate(model)
end
return context_iterate(ctx, nargs + 1)
end
-- See iface.mapping_blindly_by_invoking()
library.mapping_blindly_by_invoking = function(ctx)
local opts = ctx.pipe
local mname
local fname
if opts1 ~= nil then mname = opts1]:match'^%s*(.*%S)' end
if mname == nil then error(ctx.luaname .. ', ‘mapping_blindly_by_invoking’: No module name was provided', 0) end
if opts2 ~= nil then fname = opts2]:match'^%s*(.*%S)' end
if fname == nil then error(ctx.luaname .. ', ‘mapping_blindly_by_invoking’: No function name was provided', 0) end
local nargs
local margs = {}
local tmp = tonumber(opts3])
if tmp == nil then nargs = 2
elseif tmp < 1 then nargs = 3
else
nargs = tmp + 3
for idx = 4, nargs do margsidx - 2 = optsidx end
end
local model = { title = 'Module:' .. mname, args = margs }
local mfunc = require(model.title)[fname
local tbl = ctx.params
for key, val in pairs(tbl) do
margs1 = val
tblkey = mfunc(ctx.frame:newChild(model))
end
return context_iterate(ctx, nargs + 1)
end
-- See iface.renaming_blindly_by_calling()
library.renaming_blindly_by_calling = function(ctx)
local opts = ctx.pipe
local tname
if opts1 ~= nil then tname = opts1]:match'^%s*(.*%S)' end
if tname == nil then error(ctx.luaname .. ', ‘renaming_blindly_by_calling’: No template name was provided', 0) end
local nargs
local margs = {}
local tmp = tonumber(opts2])
if tmp == nil then nargs = 1
elseif tmp < 1 then nargs = 2
else
nargs = tmp + 2
for idx = 3, nargs do margsidx - 1 = optsidx end
end
local model = { title = tname, args = margs }
local cache = {}
local tbl = ctx.params
for key, val in pairs(tbl) do
margs1 = key
tmp = ctx.frame:expandTemplate(model):match'^%s*(.-)%s*$'
tmp = tonumber(tmp) or tmp
if key ~= tmp then
cachetmp = val
tblkey = nil
end
end
for key, val in pairs(cache) do tblkey = val end
return context_iterate(ctx, nargs + 1)
end
-- See iface.renaming_blindly_by_invoking()
library.renaming_blindly_by_invoking = function(ctx)
local opts = ctx.pipe
local mname
local fname
if opts1 ~= nil then mname = opts1]:match'^%s*(.*%S)' end
if mname == nil then error(ctx.luaname .. ', ‘renaming_blindly_by_invoking’: No module name was provided', 0) end
if opts2 ~= nil then fname = opts2]:match'^%s*(.*%S)' end
if fname == nil then error(ctx.luaname .. ', ‘renaming_blindly_by_invoking’: No function name was provided', 0) end
local nargs
local margs = {}
local tmp = tonumber(opts3])
if tmp == nil then nargs = 2
elseif tmp < 1 then nargs = 3
else
nargs = tmp + 3
for idx = 4, nargs do margsidx - 2 = optsidx end
end
local model = { title = 'Module:' .. mname, args = margs }
local mfunc = require(model.title)[fname
local cache = {}
local tbl = ctx.params
for key, val in pairs(tbl) do
margs1 = key
tmp = mfunc(ctx.frame:newChild(model)):match'^%s*(.-)%s*$'
tmp = tonumber(tmp) or tmp
if key ~= tmp then
cachetmp = val
tblkey = nil
end
end
for key, val in pairs(cache) do tblkey = val end
return context_iterate(ctx, nargs + 1)
end
--[[ Library's functions ]]--
-----------------------------
-- See iface.count()
library.count = function(ctx)
local count = 0
for _ in ctx.iterfunc(ctx.params) do count = count + 1 end
if ctx.subset == -1 then count = count - #ctx.params end
return count
end
-- See iface.concat_and_call()
library.concat_and_call = function(ctx)
local opts = ctx.pipe
local tname
if opts1 ~= nil then tname = opts1]:match'^%s*(.*%S)' end
if tname == nil then error(ctx.luaname .. ', ‘concat_and_call’: No template name was provided', 0) end
remove_numerical_keys(opts, 1, 1)
return ctx.frame:expandTemplate{
title = tname,
args = concat_params(ctx)
}
end
-- See iface.concat_and_invoke()
library.concat_and_invoke = function(ctx)
local opts = ctx.pipe
local mname
local fname
if opts1 ~= nil then mname = opts1]:match'^%s*(.*%S)' end
if mname == nil then error(ctx.luaname .. ', ‘concat_and_invoke’: No module name was provided', 0) end
if opts2 ~= nil then fname = opts2]:match'^%s*(.*%S)' end
if fname == nil then error(ctx.luaname .. ', ‘concat_and_invoke’: No function name was provided', 0) end
remove_numerical_keys(opts, 1, 2)
return require('Module:' .. mname)[fname](ctx.frame:newChild{
title = 'Module:' .. fname,
args = concat_params(ctx)
})
end
-- See iface.concat_and_magic()
library.concat_and_magic = function(ctx)
local opts = ctx.pipe
local magic
if opts1 ~= nil then magic = opts1]:match'^%s*(.*%S)' end
if magic == nil then error(ctx.luaname .. ', ‘concat_and_magic’: No parser function was provided', 0) end
remove_numerical_keys(opts, 1, 1)
return ctx.frame:callParserFunction(magic, concat_params(ctx))
end
-- See iface.value_of()
library.value_of = function(ctx)
local opts = ctx.pipe
local keystr
if opts1 ~= nil then keystr = opts1]:match'^%s*(.*%S)' end
if keystr == nil then error(ctx.luaname .. ', ‘value_of’: No parameter name was provided', 0) end
local keynum = tonumber(keystr)
local len = #ctx.params
if (
ctx.subset == -1 and keynum ~= nil and len >= keynum
) or (
ctx.subset == 1 and (keynum == nil or len < keynum)
) then return (ctx.ifngiven or '') end
local val = ctx.paramskeynum or keystr
if val == nil then return (ctx.ifngiven or '') end
return (ctx.header or '') .. val .. (ctx.footer or '')
end
-- See iface.list()
library.list = function(ctx)
local kvs = ctx.pairsep or ''
local pps = ctx.itersep or ''
local ret = {}
local nss = 0
flush_params(
ctx,
function(key, val)
retnss + 1 = pps
retnss + 2 = key
retnss + 3 = kvs
retnss + 4 = val
nss = nss + 4
end
)
if nss > 0 then
if nss > 4 and ctx.lastsep ~= nil then
retnss - 3 = ctx.lastsep
end
ret1 = ctx.header or ''
if ctx.footer ~= nil then retnss + 1 = ctx.footer end
return table.concat(ret)
end
return ctx.ifngiven or ''
end
-- See iface.list_values()
library.list_values = function(ctx)
local pps = ctx.itersep or ''
local ret = {}
local nss = 0
flush_params(
ctx,
function(key, val)
retnss + 1 = pps
retnss + 2 = val
nss = nss + 2
end
)
if nss > 0 then
if nss > 2 and ctx.lastsep ~= nil then
retnss - 1 = ctx.lastsep
end
ret1 = ctx.header or ''
if ctx.footer ~= nil then retnss + 1 = ctx.footer end
return table.concat(ret)
end
return ctx.ifngiven or ''
end
-- See iface.for_each()
library.for_each = function(ctx)
local txt = ctx.pipe1 or ''
local pps = ctx.itersep or ''
local ret = {}
local nss = 0
flush_params(
ctx,
function(key, val)
retnss + 1 = pps
retnss + 2 = txt:gsub('%$#', key):gsub('%$@', val)
nss = nss + 2
end
)
if nss > 0 then
if nss > 2 and ctx.lastsep ~= nil then
retnss - 1 = ctx.lastsep
end
ret1 = ctx.header or ''
if ctx.footer ~= nil then retnss + 1 = ctx.footer end
return table.concat(ret)
end
return ctx.ifngiven or ''
end
-- See iface.call_for_each()
library.call_for_each = function(ctx)
local opts = ctx.pipe
local tname
if opts1 ~= nil then tname = opts1]:match'^%s*(.*%S)' end
if tname == nil then error(ctx.luaname .. ', ‘call_for_each’: No template name was provided', 0) end
local model = { title = tname, args = opts }
local ccs = ctx.itersep or ''
local ret = {}
local nss = 0
table.insert(opts, 1, true)
flush_params(
ctx,
function(key, val)
opts1 = key
opts2 = val
retnss + 1 = ccs
retnss + 2 = ctx.frame:expandTemplate(model)
nss = nss + 2
end
)
if nss > 0 then
if nss > 2 and ctx.lastsep ~= nil then
retnss - 1 = ctx.lastsep
end
ret1 = ctx.header or ''
if ctx.footer ~= nil then retnss + 1 = ctx.footer end
return table.concat(ret)
end
return ctx.ifngiven or ''
end
-- See iface.invoke_for_each()
library.invoke_for_each = function(ctx)
local opts = ctx.pipe
local mname
local fname
if opts1 ~= nil then mname = opts1]:match'^%s*(.*%S)' end
if mname == nil then error(ctx.luaname .. ', ‘invoke_for_each’: No module name was provided', 0) end
if opts2 ~= nil then fname = opts2]:match'^%s*(.*%S)' end
if fname == nil then error(ctx.luaname .. ', ‘invoke_for_each’: No function name was provided', 0) end
local model = { title = 'Module:' .. mname, args = opts }
local mfunc = require(model.title)[fname
local ccs = ctx.itersep or ''
local ret = {}
local nss = 0
flush_params(
ctx,
function(key, val)
opts1 = key
opts2 = val
retnss + 1 = ccs
retnss + 2 = mfunc(ctx.frame:newChild(model))
nss = nss + 2
end
)
if nss > 0 then
if nss > 2 and ctx.lastsep ~= nil then
retnss - 1 = ctx.lastsep
end
ret1 = ctx.header or ''
if ctx.footer ~= nil then retnss + 1 = ctx.footer end
return table.concat(ret)
end
return ctx.ifngiven or ''
end
-- See iface.magic_for_each()
library.magic_for_each = function(ctx)
local opts = ctx.pipe
local magic
if opts1 ~= nil then magic = opts1]:match'^%s*(.*%S)' end
if magic == nil then error(ctx.luaname .. ', ‘magic_for_each’: No parser function was provided', 0) end
local ccs = ctx.itersep or ''
local ret = {}
local nss = 0
table.insert(opts, 1, true)
flush_params(
ctx,
function(key, val)
opts1 = key
opts2 = val
retnss + 1 = ccs
retnss + 2 = ctx.frame:callParserFunction(magic,
opts)
nss = nss + 2
end
)
if nss > 0 then
if nss > 2 and ctx.lastsep ~= nil then
retnss - 1 = ctx.lastsep
end
ret1 = ctx.header or ''
if ctx.footer ~= nil then retnss + 1 = ctx.footer end
return table.concat(ret)
end
return ctx.ifngiven or ''
end
-- See iface.call_for_each_value()
library.call_for_each_value = function(ctx)
local opts = ctx.pipe
local tname
if opts1 ~= nil then tname = opts1]:match'^%s*(.*%S)' end
if tname == nil then error(ctx.luaname .. ', ‘call_for_each_value’: No template name was provided', 0) end
local model = { title = tname, args = opts }
local ccs = ctx.itersep or ''
local ret = {}
local nss = 0
flush_params(
ctx,
function(key, val)
opts1 = val
retnss + 1 = ccs
retnss + 2 = ctx.frame:expandTemplate(model)
nss = nss + 2
end
)
if nss > 0 then
if nss > 2 and ctx.lastsep ~= nil then
retnss - 1 = ctx.lastsep
end
ret1 = ctx.header or ''
if ctx.footer ~= nil then retnss + 1 = ctx.footer end
return table.concat(ret)
end
return ctx.ifngiven or ''
end
-- See iface.invoke_for_each_value()
library.invoke_for_each_value = function(ctx)
local opts = ctx.pipe
local mname
local fname
if opts1 ~= nil then mname = opts1]:match'^%s*(.*%S)' end
if mname == nil then error(ctx.luaname .. ', ‘invoke_for_each_value’: No module name was provided', 0) end
if opts2 ~= nil then fname = opts2]:match'^%s*(.*%S)' end
if fname == nil then error(ctx.luaname .. ', ‘invoke_for_each_value’: No function name was provided', 0) end
local model = { title = 'Module:' .. mname, args = opts }
local mfunc = require(model.title)[fname
local ccs = ctx.itersep or ''
local ret = {}
local nss = 0
remove_numerical_keys(opts, 1, 1)
flush_params(
ctx,
function(key, val)
opts1 = val
retnss + 1 = ccs
retnss + 2 = mfunc(ctx.frame:newChild(model))
nss = nss + 2
end
)
if nss > 0 then
if nss > 2 and ctx.lastsep ~= nil then
retnss - 1 = ctx.lastsep
end
ret1 = ctx.header or ''
if ctx.footer ~= nil then retnss + 1 = ctx.footer end
return table.concat(ret)
end
return ctx.ifngiven or ''
end
-- See iface.magic_for_each_value()
library.magic_for_each_value = function(ctx)
local opts = ctx.pipe
local magic
if opts1 ~= nil then magic = opts1]:match'^%s*(.*%S)' end
if magic == nil then error(ctx.luaname .. ', ‘magic_for_each_value’: No parser function was provided', 0) end
local ccs = ctx.itersep or ''
local ret = {}
local nss = 0
flush_params(
ctx,
function(key, val)
opts1 = val
retnss + 1 = ccs
retnss + 2 = ctx.frame:callParserFunction(magic,
opts)
nss = nss + 2
end
)
if nss > 0 then
if nss > 2 and ctx.lastsep ~= nil then
retnss - 1 = ctx.lastsep
end
ret1 = ctx.header or ''
if ctx.footer ~= nil then retnss + 1 = ctx.footer end
return table.concat(ret)
end
return ctx.ifngiven or ''
end
-- See iface.call_for_each_group()
library.call_for_each_group = function(ctx)
-- NOTE: `ctx.pipe` and `ctx.params` might be the original metatables!
local opts = ctx.pipe
local tmp
if opts1 ~= nil then tmp = opts1]:match'^%s*(.*%S)' end
if tmp == nil then error(ctx.luaname .. ', ‘call_for_each_group’: No template name was provided', 0) end
local model = { title = tmp }
local ccs = ctx.itersep or ''
local nss = 0
local prefix
local gid
local groups = {}
local ret = {}
opts = {}
for key, val in pairs(ctx.pipe) do
if type(key) == 'number' then optskey - 1 = val
else optskey = val end
end
ctx.pipe = opts
for key, val in pairs(ctx.params) do
prefix, gid = tostring(key):match'^%s*(.-)%s*(%-?%d*)%s*$'
gid = tonumber(gid) or ''
if groupsgid == nil then groupsgid = {} end
tmp = tonumber(prefix)
if tmp ~= nil then
if tmp < 1 then prefix = tmp - 1 else prefix = tmp end
end
groupsgid][prefix = val
end
ctx.params = groups
flush_params(
ctx,
function(gid, group)
for key, val in pairs(opts) do groupkey = val end
group0 = gid
model.args = group
retnss + 1 = ccs
retnss + 2 = ctx.frame:expandTemplate(model)
nss = nss + 2
end
)
if nss > 0 then
if nss > 2 and ctx.lastsep ~= nil then
retnss - 1 = ctx.lastsep
end
ret1 = ctx.header or ''
if ctx.footer ~= nil then retnss + 1 = ctx.footer end
return table.concat(ret)
end
return ctx.ifngiven or ''
end
--- ---
--- PUBLIC ENVIRONMENT ---
--- ________________________________ ---
--- ---
-- The public table of functions
local iface = {}
--[[ Modifiers ]]--
-------------------
-- Syntax: #invoke:params|sequential|pipe to
iface.sequential = function(frame)
return context_init(frame, library.sequential, false, false)
end
-- Syntax: #invoke:params|non-sequential|pipe to
iface'non-sequential' = function(frame)
return context_init(frame, library'non-sequential'], false, false)
end
-- Syntax: #invoke:params|sort|pipe to
iface.all_sorted = function(frame)
return context_init(frame, library.all_sorted, false, false)
end
-- Syntax: #invoke:params|setting|directives|...|pipe to
iface.setting = function(frame)
return context_init(frame, library.setting, false, false)
end
-- Syntax: #invoke:params|squeezing|pipe to
iface.squeezing = function(frame)
return context_init(frame, library.squeezing, false, false)
end
-- Syntax: #invoke:params|filling_the_gaps|pipe to
iface.filling_the_gaps = function(frame)
return context_init(frame, library.filling_the_gaps, false, false)
end
-- Syntax: #invoke:params|clearing|pipe to
iface.clearing = function(frame)
return context_init(frame, library.clearing, false, false)
end
-- Syntax: #invoke:params|cutting|left cut|right cut|pipe to
iface.cutting = function(frame)
return context_init(frame, library.cutting, false, false)
end
-- Syntax: #invoke:params|cropping|left crop|right crop|pipe to
iface.cropping = function(frame)
return context_init(frame, library.cropping, false, false)
end
-- Syntax: #invoke:params|purging|start offset|length|pipe to
iface.purging = function(frame)
return context_init(frame, library.purging, false, false)
end
-- Syntax: #invoke:params|backpurging|start offset|length|pipe to
iface.backpurging = function(frame)
return context_init(frame, library.backpurging, false, false)
end
-- Syntax: #invoke:params|rotating|pipe to
iface.rotating = function(frame)
return context_init(frame, library.rotating, false, false)
end
-- Syntax: #invoke:params|pivoting|pipe to
--[[
iface.pivoting = function(frame)
return context_init(frame, library.pivoting, false, false)
end
]]
-- Syntax: #invoke:params|mirroring|pipe to
--[[
iface.mirroring = function(frame)
return context_init(frame, library.mirroring, false, false)
end
]]
-- Syntax: #invoke:params|swapping|pipe to
--[[
iface.swapping = function(frame)
return context_init(frame, library.swapping, false, false)
end
]]--
-- Syntax: #invoke:params|sorting_sequential_values|[criterion]|pipe to
iface.sorting_sequential_values = function(frame)
return context_init(frame, library.sorting_sequential_values, false, false)
end
-- Syntax: #invoke:params|with_name_matching|pattern 1|[plain flag 1]|[or]
-- |[pattern 2]|[plain flag 2]|[or]|[...]|[pattern N]|[plain flag
-- N]|pipe to
iface.with_name_matching = function(frame)
return context_init(frame, library.with_name_matching, false, false)
end
-- Syntax: #invoke:params|with_name_not_matching|pattern 1|[plain flag 1]
-- |[and]|[pattern 2]|[plain flag 2]|[and]|[...]|[pattern N]|[plain
-- flag N]|pipe to
iface.with_name_not_matching = function(frame)
return context_init(frame, library.with_name_not_matching, false,
false)
end
-- Syntax: #invoke:params|with_value_matching|pattern 1|[plain flag 1]|[or]
-- |[pattern 2]|[plain flag 2]|[or]|[...]|[pattern N]|[plain flag
-- N]|pipe to
iface.with_value_matching = function(frame)
return context_init(frame, library.with_value_matching, false, false)
end
-- Syntax: #invoke:params|with_value_not_matching|pattern 1|[plain flag 1]
-- |[and]|[pattern 2]|[plain flag 2]|[and]|[...]|[pattern N]|[plain
-- flag N]|pipe to
iface.with_value_not_matching = function(frame)
return context_init(frame, library.with_value_not_matching, false,
false)
end
-- Syntax: #invoke:params|trimming_values|pipe to
iface.trimming_values = function(frame)
return context_init(frame, library.trimming_values, false, false)
end
-- Syntax: #invoke:params|mapping_by_calling|template name|[number of
-- additional arguments]|[argument 1]|[argument 2]|[...]|[argument
-- N]|pipe to
iface.mapping_by_calling = function(frame)
return context_init(frame, library.mapping_by_calling, false, false)
end
-- Syntax: #invoke:params|mapping_by_invoking|module name|function
-- name|[number of additional arguments]|[argument 1]|[argument
-- 2]|[...]|[argument N]|pipe to
iface.mapping_by_invoking = function(frame)
return context_init(frame, library.mapping_by_invoking, false, false)
end
-- Syntax: #invoke:params|mapping_blindly_by_calling|template
-- name|[number of additional arguments]|[argument 1]|[argument
-- 2]|[...]|[argument N]|pipe to
iface.mapping_blindly_by_calling = function(frame)
return context_init(frame, library.mapping_blindly_by_calling, false,
false)
end
-- Syntax: #invoke:params|mapping_blindly_by_invoking|module
-- name|function name|[number of additional arguments]|[argument
-- 1]|[argument 2]|[...]|[argument N]|pipe to
iface.mapping_blindly_by_invoking = function(frame)
return context_init(frame, library.mapping_blindly_by_invoking, false,
false)
end
-- Syntax: #invoke:params|renaming_blindly_by_calling|template
-- name|[number of additional arguments]|[argument 1]|[argument
-- 2]|[...]|[argument N]|pipe to
iface.renaming_blindly_by_calling = function(frame)
return context_init(frame, library.renaming_blindly_by_calling, false,
false)
end
-- Syntax: #invoke:params|renaming_blindly_by_invoking|module
-- name|function name|[number of additional arguments]|[argument
-- 1]|[argument 2]|[...]|[argument N]|pipe to
iface.renaming_blindly_by_invoking = function(frame)
return context_init(frame, library.renaming_blindly_by_invoking, false,
false)
end
--[[ First-position-only modifiers ]]--
---------------------------------------
-- Syntax: #invoke:params|new|pipe to
--[[
iface.new = function(frame)
local ctx = context_new(frame)
ctx.pipe = copy_or_ref_table(frame.args, false)
ctx.params = {}
return context_iterate(ctx, 1)
end
]]--
--[[ Functions ]]--
-------------------
-- Syntax: #invoke:params|count
iface.count = function(frame)
return context_init(frame, library.count, true, true)
end
-- Syntax: #invoke:args|concat_and_call|template name|[prepend 1]|[prepend 2]
-- |[...]|[item n]|[named item 1=value 1]|[...]|[named item n=value
-- n]|[...]
iface.concat_and_call = function(frame)
return context_init(frame, library.concat_and_call, false, true)
end
-- 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]|[...]
iface.concat_and_invoke = function(frame)
return context_init(frame, library.concat_and_invoke, false, true)
end
-- Syntax: #invoke:args|concat_and_magic|parser function|[prepend 1]|[prepend
-- 2]|[...]|[item n]|[named item 1=value 1]|[...]|[named item n=
-- value n]|[...]
iface.concat_and_magic = function(frame)
return context_init(frame, library.concat_and_magic, false, true)
end
-- Syntax: #invoke:params|value_of|parameter name
iface.value_of = function(frame)
return context_init(frame, library.value_of, true, true)
end
-- Syntax: #invoke:params|list
iface.list = function(frame)
return context_init(frame, library.list, true, false)
end
-- Syntax: #invoke:params|list_values
iface.list_values = function(frame)
return context_init(frame, library.list_values, true, false)
end
-- Syntax: #invoke:params|for_each|wikitext
iface.for_each = function(frame)
return context_init(frame, library.for_each, true, false)
end
-- Syntax: #invoke:params|call_for_each|template name|[append 1]|[append 2]
-- |[...]|[append n]|[named param 1=value 1]|[...]|[named param
-- n=value n]|[...]
iface.call_for_each = function(frame)
return context_init(frame, library.call_for_each, false, false)
end
-- 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]|[...]
iface.invoke_for_each = function(frame)
return context_init(frame, library.invoke_for_each, false, false)
end
-- Syntax: #invoke:params|magic_for_each|parser function|[append 1]|[append 2]
-- |[...]|[append n]|[named param 1=value 1]|[...]|[named param
-- n=value n]|[...]
iface.magic_for_each = function(frame)
return context_init(frame, library.magic_for_each, false, false)
end
-- 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]|[...]
iface.call_for_each_value = function(frame)
return context_init(frame, library.call_for_each_value, false, false)
end
-- 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]|[...]
iface.invoke_for_each_value = function(frame)
return context_init(frame, library.invoke_for_each_value, false, false)
end
-- 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]|[...]
iface.magic_for_each_value = function(frame)
return context_init(frame, library.magic_for_each_value, false, false)
end
-- 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]|[...]
iface.call_for_each_group = function(frame)
return context_init(frame, library.call_for_each_group, true, true)
end
--[[ First-position-only functions ]]--
---------------------------------------
-- Syntax: #invoke:params|self
iface.self = function(frame)
return frame:getParent():getTitle()
end
return iface