Module:Loops
Lua module implementing features similar to mw:Extension:Loops, specifically with functionality to parse lists, since the AE Wiki mainly utilizes the extension for that purpose.
Usage[edit source]
{{#invoke:Loops|function_name}}
Functions[edit source]
parseList
[edit source]
Parses a string list using a given delimiter (defaults to %s if not given). The value is then passed into the specified template or formatted according to a given string format pattern.
Transitioning from Extension:Loops[edit source]
This is documentation on how to transition from using Extension:Loops to Module:Loops to parse lists.
Extension:Loops Syntax
{{#vardefine:count|0}} {{#while: | {{#if: {{#explode:<list>|<delimiter>|{{#var:count}}}} | true }} | <!-- do something --> }}
The key variables here are <list> and <delimiter>. These can simply be specified in the module invoke like so:
{{#invoke: |list=<list> |delimiter=<delimiter> ... }}
The rest of the invoke depends on how complex the "do something"/block statement portion is, you can choose to either use a string format (simple output) or template format (more complex output).
- If your block statement is simple formatting, then use string format output.
- Because of the order the parser runs statements, some Wikitext may not be compatible with string format. Thus it's recommended for more complex Wikitext use template format instead.
- If you use
{{#explode:<list>|<delimiter>|{{#var:count}}}}
inside your block statement, replace it with a replace string of choice. This should be a unique string pattern, as you don't want to erroneously replace other parts of the format string.
- If your block statement is more complex, consider moving it into a template which you can then specify with the module invoke.
- If you use
{{#explode:<list>|<delimiter>|{{#var:count}}}}
inside your block statement, replace it with{{{1|}}}
. - If you use your index/counter variable in your template code, you can replace it with
{{#var:count}}
.
- If you use
See the parseList examples for sample usages.
Usage[edit source]
- Template format
{{#invoke:Loops|parseList |list= |delimiter= |template= |template!<arg>= //optional }}
- String format
{{#invoke:Loops|parseList |list= |delimiter= |format= |replaceString= }}
Examples[edit source]
- Template format
{{#invoke:Loops|parseList |list=Marius "Dream of Thebes",Marius "Dream of Thebes",Marius "Dream of Thebes" |delimiter=, |template=Card icon |template!size=50px |template!text=500 }}
- String format example #1
{{#invoke:Loops|parseList |list=git,gem,fp |delimiter=, |format=|format=<nowiki/> * Test $1 |replaceString=$1 }}
- Test git
- Test gem
- Test fp
- String format example #2
{| class="wikitable" ! Test {{#invoke:Loops|parseList |list=git,gem,fp |delimiter=, |format=<tr><td>$1 in a cell</td></tr> |replaceString=$1 }} |}
Test |
---|
git in a cell |
gem in a cell |
fp in a cell |
numElements
[edit source]
Returns the number of elements in a string list given a delimiter (defaults to %s if not given).
Usage[edit source]
{{#invoke:Loops|numElements |list= |delimiter= }}
Example[edit source]
{{#invoke:Loops|numElements |list=this,list,has,5,elements |delimiter=, }}
5
loop
[edit source]
Duplicates the mw:Extension:Loop##loop function. Output can either be a given template or string format.
Usage[edit source]
{{#invoke:Loops|loop |startValue= |numLoops= |template= |template!<arg>= //optional }}
- String format
{{#invoke:Loops|parseList |startValue= |numLoops= |format= |replaceString= //optional }}
Example[edit source]
- Template format
{{#invoke:Loops|loop |startValue=3 |numLoops=5 |template=Text |template!style=border: 1px solid black; }}
Lua error: expandTemplate: template "Text" does not exist.
- String format
{{#invoke:Loops|loop |startValue=8 |numLoops=3 |format=<nowiki/> * Test $1 |replaceString=$1 }}
- Test 8
- Test 9
- Test 10
-- This module was created for the Another Eden Miraheze Wiki to replace
-- Extension:Loops. For most Loops usage cases, we were parsing lists, so
-- most of the module currently focuses on that.
--
-- @module loops
-- @author [[User:Elaeagnifolia]]
-- Dependencies
VariablesLua = mw.ext.VariablesLua
local loops = {};
--- Returns an error message
-- @param {string} message
-- @return {string}
local function userError(message)
return '<strong class="error">' .. message .. '</strong>';
end
--- Splits a string list based on the given delimiter.
-- @param {string} list
-- @param {string} delimiter
-- @return {table}
local function explode(list, delimiter)
-- Default the delimiter to space if not given
if delimiter == nil then
delimiter = "%s"
end
t = {}
for str in string.gmatch(list, "([^" .. delimiter .. "]+)") do
table.insert(t, str)
end
return t
end
--- Returns the number of elements in a string list split by a given delimiter
--
-- Usage:
-- {{#invoke:Loops|numElements
-- |list=
-- |delimiter=
-- }}
--
-- @param {Frame} frame
-- @return {integer}
function loops.numElements(frame)
-- Instantiate variables
local list, delimiter;
local frameArgs = frame.args;
-- Grab the frame arguments
list = frameArgs.list;
delimiter = frameArgs.delimiter;
local listElements = explode(list, delimiter);
return #listElements;
end
--- Iterates the list based on a given delimiter and parses the value through
--- either a template or a specified format string. Similar to exploding and
--- iterating a list with #while.
--
-- See Module:Loops/doc for additional usage examples.
--
-- @param {Frame} frame
-- @return {table} result
function loops.parseList(frame)
local list, delimiter, template, format, replaceString;
local frameArgs = frame.args;
local templateArgs = {};
local templateArgPrefix = 'template!';
-- Grab the frame arguments
list = frameArgs.list;
delimiter = frameArgs.delimiter;
template = frameArgs.template;
format = frameArgs.format;
replaceString = frameArgs.replaceString;
-- Validate the frame arguments
if list == nil then
return userError('list argument has not been specified');
end
if template == nil and format == nil then
return userError('template or format argument has not been specified');
end
if template ~= nil and format ~= nil then
return userError('template and format arguments cannot be used together');
end
if format ~= nil and replaceString == nil then
return userError('replaceString argument must be specified with format');
end
-- For delimiter, default to %s if one hasn't been specified
if delimiter == nil then
delimiter = '%s';
end
-- Get the additional arguments that will be sent to the template
for key, value in pairs(frameArgs) do
if string.find(key, templateArgPrefix) ~= nil then
local _, endIndex = string.find(key, templateArgPrefix);
templateArgs[string.sub(key, endIndex+1)] = value
end
end
local result = {}
local count = 0;
local listElements = explode(list, delimiter)
-- Loop through the exploded list and send value to specified template
for key, value in pairs(listElements) do
-- Increment loop counter
count = count + 1;
-- Keep a count of how many loops in {{#var:count}}
-- This var can be used in the given template if needed
VariablesLua.vardefine('count', count);
-- If template argument was specified, format by expanding template
if template ~= nil then
-- Add the list element value to the template arguments
-- The value must be {{{1}}} in the given template
table.insert(templateArgs, 1, value);
-- Pass the arguments to the template and expand template
result[#result+1] = frame:expandTemplate{title = template, args = templateArgs };
end
-- Format based on the given string
if format ~= nil then
result[#result+1] = format:gsub(replaceString, value);
end
end
return table.concat(result);
end
--- Duplicates functionality of Extension:Loop's #loop. Takes a
--- start value to increment a specified loop amount. Will also
--- output either a given template or string each loop.
--
-- See Module:Loops/doc for additional usage examples.
--
-- @param {Frame} frame
-- @return {table} result
function loops.loop(frame)
local startValue, numLoops, template, format, replaceString;
local frameArgs = frame.args;
local templateArgs = {};
local templateArgPrefix = 'template!';
-- Grab the frame arguments
startValue = frameArgs.startValue;
numLoops = frameArgs.numLoops;
template = frameArgs.template;
format = frameArgs.format;
replaceString = frameArgs.replaceString;
-- Validate the frame arguments
if startValue == nil then
return userError('startValue argument has not been specified');
elseif tonumber(startValue) == nil then
return userError('startValue must be a valid number');
end
if numLoops == nil then
return userError('numLoops argument has not been specified');
elseif tonumber(numLoops) == nil then
return userError('numLoops must be a valid number');
end
if template == nil and format == nil then
return userError('template or format argument has not been specified');
end
if template ~= nil and format ~= nil then
return userError('template and format arguments cannot be used together');
end
-- Get the additional arguments that will be sent to the template
for key, value in pairs(frameArgs) do
if string.find(key, templateArgPrefix) ~= nil then
local _, endIndex = string.find(key, templateArgPrefix);
templateArgs[string.sub(key, endIndex+1)] = value
end
end
local result = {}
local count = 0;
for i=1,tonumber(numLoops) do
-- Increment loop counter
count = count + 1;
-- Keep a count of how many loops in {{#var:count}}
-- This var can be used in the given template if needed
VariablesLua.vardefine('count', count);
-- Also increment startValue and store it in a var to be used in templates
VariablesLua.vardefine('startValue', startValue);
-- If template argument was specified, format by expanding template
if template ~= nil then
-- Add the list element value to the template arguments
-- The value must be {{{1}}} in the given template
table.insert(templateArgs, 1, startValue);
-- Pass the arguments to the template and expand template
result[#result+1] = frame:expandTemplate{title = template, args = templateArgs };
end
-- Format based on the given string
if format ~= nil then
result[#result+1] = format:gsub(replaceString, startValue);
end
-- Increment startValue
startValue = startValue + 1;
end
return table.concat(result);
end
function loops.varLoop(frame)
local list, delimiter, valueDelimiter;
local frameArgs = frame.args;
list = frameArgs.list;
delimiter = frameArgs.delimiter;
valueDelimiter = frameArgs.valueDelimiter;
local result = {}
local listElements = explode(list, delimiter);
for key, value in pairs(listElements) do
result[#result+1] = value .. '///';
--VariablesLua.vardefine(
-- value:sub(1, value:find(valueDelimiter)-1),
-- value:sub(value:find(valueDelimiter)+1)
--);
end
return table.concat(result);
--return '';
end
return loops;