Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

Documentation for this module may be created at Module:Loops/doc

local p = {};
local getArgs = require("Module:Arguments").getArgs;

-- Note to dev wiki editors: this function is copied from Module:Example.
-- Changes to this function should be synced with the source.
local function unescape(text)
	if not text:match("UNIQ") then
		return text;
	end
	local unescaped = mw.text.unstripNoWiki(text);
	local text, count = string.gsub(unescaped, "&lt;", "<");
	text, count = string.gsub(text, "&gt;", ">");
	text, count = string.gsub(text, "<//nowiki>", "</nowiki>");
	return text;
end

-- This feature is experimental and therefore undocumented.
local function sentenceJoin(lst, delimiter, beforeLast)
	if not delimiter then
		delimiter = ", ";
		if not beforeLast then
			beforeLast = "and";
		end
	elseif not beforeLast then
		beforeLast = delimiter;
	end
	local count = #lst;
	if count == 0 then
		return "";
	elseif count == 1 then
		return lst[1];
	elseif count == 2 then
		return string.format("%s %s %s", lst[1], beforeLast, lst[2]);
	else
		local last = lst[count];
		lst[count] = nil;
		return string.format("%s %s %s",
			table.concat(lst, delimiter),
			beforeLast,
			last
		);
	end
end

-- This feature is experimental and therefore undocumented.
function formatConcat(result, args)
	local outputFormat = args['format'] or nil;
	if not outputFormat then
		return table.concat(result, "");
	end
	if outputFormat == "concat" then
		return sentenceJoin(result, args['delimiter'], args['final-delimiter']);
	end
end

function p.loop(frame)
	local args = getArgs(frame);
	local variableName = args[1];
	local startingValue = tonumber(args[2]) or 1;
	local loopNum = tonumber(args[3]) or 0;
	local markup = unescape(args[4]);
	local result = {};
	for i = startingValue, startingValue + loopNum - 1 do
		local s = markup:gsub(variableName, tostring(i));
		table.insert(result, s);
	end
	return frame:getParent():preprocess(formatConcat(result, args));
end

function p.fornumargs(frame)
	local args = getArgs(frame, { removeBlanks = false });
	local keyName = args['key'] or "DNE";
	local valueName = args['value'] or "DNE";
	local markup = unescape(args['pattern']);
	
	local keys = {};
	for k, v in pairs(args) do
		if type(k) == "number" then
			table.insert(keys, k);
		end
	end
	table.sort(keys);
	
	local result = {};
	for _, key in ipairs(keys) do
		local value = args[key];
		local s = markup:gsub(keyName, key):gsub(valueName, value);
		table.insert(result, s);
	end
	return frame:getParent():preprocess(formatConcat(result, args));
end

function p.forargs(frame)
	local args = getArgs(frame, { removeBlanks = false });
	local prefix = args[1] or "";
	local keyName = args[2] or "DNE";
	local valueName = args[3] or "DNE";
	local markup = unescape(args[4]);
	for i = 1, 4 do
		table.remove(args, i);
	end
	
	local keys = {};
	for k, v in pairs(args) do
		if type(k) == "string" then
			i, j = k:find(prefix);
			if i ~= nil and i == 1 then
				table.insert(keys, k:sub(j + 1));
			end
		end
	end
	table.sort(keys);
	
	local result = {};
	for _, key in ipairs(keys) do
		local value = args[prefix .. key];
		local s = markup:gsub(keyName, key):gsub(valueName, value);
		table.insert(result, s);
	end
	return frame:getParent():preprocess(formatConcat(result, args));
end

return p;