Module:Iteration
This module contains the functions for different templates, solving their iteration problem
- The Wikipedia template coding does not support the repetitive processing of a parameter set,
- which leads often to a very primitive and long chain of parameter checks in the kind of <syntaxhighlight lang="text"> {{#if:{{{1|}}} | perform an action with parameter 1 }} {{#if:{{{2|}}} | perform an action with parameter 2 }} {{#if:{{{3|}}} | perform an action with parameter 3 }} {{#if:{{{4|}}} | perform an action with parameter 4 }} ••• ••• {{#if:{{{33|}}} perform an action with parameter 33 }}</syntaxhighlight>
with the disadvantage that such a construct will fail as soon as there comes a 34nd parm.
I always thought that with Lua and its for loops this iterations should be possible, somehow.
After long searching without any success and without an idea how to perform it, I asked at several forums
and got finally from User:Trappist the monk the helping hint to solve it with a control structure like<syntaxhighlight lang="text">
local out = {}
for i, v in ipairs (args) do
table.insert (out, frame:expandTemplate{ title = title, args = v })
end
return table.concat (out)</syntaxhighlight>
The functions contained therein are from very simple, just one parameter to pass,
to more complicated ones, where e.g. a pair of parameters needs kind of a flip-flop switch
when always a tuple of e.g. an item and its correlated text needs to be passed.
When there are tuples, triples etc., the table.insert occurs, when the last element is processed;
this performs problems when the last group is incomplete – it should be finished with empty values
to trigger the table.insert. The check with table.maxn seems not to work correctly ?
This problem is solved differently, for the function "attribs" with a primitive workaround.
File list templates
The three "Ifim " templates avoid to display the file itself as an 'other version'.
There are currently five templates creating file lists with the function:filelist
- Other versions a vertical list (without initial)
- Filelist a horizontal list (without initial)
- Derivative versions a vertical list
- Derived from a vertical list
- File a horizontal list
All these templates support also the "gallery" option.
Other file lists
The function:svglang creates a list of just file_names and language_codes, for
Much more is created by the function:ownbased for the template
which will handle in the majority of cases just one file, but can serve an unlimited number.
This list can be controlled by the user to be displayed either horizontally or vertically.
The template works, whether there is a user assigned for a file, or one filename follows another.
-- This module contains the functions for different templates, solving their iteration problems.
local p = {}
-- for Template:Ifim
function p.ifim1 (frame)
local args = mw.getCurrentFrame(): getParent().args;
local otab = {};
local p1 = args.p1 or "";
local p2 = args.p2 or "";
local p3 = args.p3 or "";
local p4 = args.p4 or "";
local p5 = args.p5 or "";
local fn = args.fn or "";
for _, v in ipairs(args) do
table.insert(otab, frame:expandTemplate{ title = "Ifim1", args = { v, p1, p2, p3, p4, p5, n= fn } });
end
return table.concat (otab)
end -- function ifim
-- for Template:Ifimc
function p.ifim2 (frame)
local args = mw.getCurrentFrame(): getParent().args;
local otab = {};
local p1 = args.p1 or "";
local p2 = args.p2 or "";
local p3 = args.p3 or "";
local p4 = args.p4 or "";
for _, v in ipairs(args) do
table.insert(otab, frame:expandTemplate{ title = "Ifim2", args = { v, p1, p2, p3, p4, v } });
end
return table.concat (otab)
end -- function ifim2
-- for Template:Ifimt (param pairs)
function p.ifimt (frame)
local args = mw.getCurrentFrame(): getParent().args;
local otab = {};
local v1 = "";
local p1 = args.p1 or "";
local p2 = args.p2 or "";
local p3 = args.p3 or "";
local p4 = args.p4 or "";
for _, v in ipairs(args) do
if v1 == "" then
v1 = mw.text.trim( v );
else
table.insert(otab, frame:expandTemplate{ title = "Ifim2", args = { v1, p1, p2, p3, p4, v } });
v1 = "";
end
end
if v1 ~= "" then
table.insert(otab, frame:expandTemplate{ title = "Ifim2", args = { v1, p1, p2, p3, p4, "" } }); -- last elem
end
return table.concat (otab)
end -- function ifimt
-------------------------------------------------------
-- helper function for: ownbased, and filelist
local function samefile ( fnam, numb, frst )
local name = mw.text.trim( fnam ) or ""
if mw.ustring.sub(name, 1, 1) == "."
then
local nsnr = tonumber( mw.title.getCurrentTitle().namespace );
local page = mw.title.getCurrentTitle().text;
local part = "Example" -- default name
if nsnr == 6 or nsnr == 7
then local parts = mw.text.split(page , '.', true)
local upTo = #parts - 1 -- copied from Module:File
part = table.concat(parts, '.', 1, math.max(upTo, 1))
end
if name == "." then name = part .. ".png";
elseif name == ".p" then name = part .. ".png";
elseif name == ".j" then name = part .. ".jpg";
elseif name == ".g" then name = part .. ".gif";
elseif name == ".s" then name = part .. ".svg";
else name = part .. name;
end
elseif name == ""
then
local nsnr = tonumber( mw.title.getCurrentTitle().namespace );
local page = mw.title.getCurrentTitle().text;
if tonumber( numb ) == 1
then name = "Example.svg";
if nsnr == 6 or nsnr == 7
then name = page;
end
else name = mw.text.trim( frst );
if name == ""
or mw.ustring.sub(name, 1, 1) == "."
then name = "Example.svg";
if nsnr == 6 or nsnr == 7
then name = page;
end
end
end
end
return name
end -- function samefile
-------------------------------------------------------
-- for Template:Own based (horizontal - but vertical when "b1=")
function p.ownbased (frame)
-- local lpar = parm -- local parms
-- local gpar = frame.args -- global parms
local ppar = mw.getCurrentFrame(): getParent().args;
local btab = {};
local dtab = {};
local htab = {};
local itab = {};
local ltab = {};
local ntab = {};
local otab = {};
local qtab = {};
local rtab = {};
local Ctab = {};
local by0 = ppar.b or ppar.by or ppar.u or ppar.user or "";
local dis = ppar.d or ppar.dis or ppar.display or "";
local hil = ppar.h or ppar.hilite or "";
local lng = ppar.i or ppar.lang or "";
local wik = ppar.l or ppar.wiki or "";
local nam = ppar.n or ppar.name or "";
local opt = ppar.o or ppar.opt or ppar.option or "";
local pr4 = ppar.par4 or ppar.qpar or "";
local pr5 = ppar.par5 or ppar.rpar or "";
local max = 0;
local cor = 0;
local x = 0; -- running index, can be ~= i
local fst = 0; -- first occurrence
local plus = "";
for i, v in ipairs(ppar) do
if v == "+" then
plus = "+";
elseif v == "-" then
if plus == "" then plus = "-" end
else
x = x + 1;
if fst == 0 then fst = x end;
btab [x] = ppar ["b" .. tostring( x )] or ppar ["by" .. tostring( x )] or ppar ["u" .. tostring( x )] or "-";
dtab [x] = ppar ["d" .. tostring( x )] or "-";
htab [x] = ppar ["h" .. tostring( x )] or "-";
itab [x] = ppar ["i" .. tostring( x )] or "-";
ltab [x] = ppar ["l" .. tostring( x )] or "-";
ntab [x] = ppar ["n" .. tostring( x )] or "-";
otab [x] = ppar ["o" .. tostring( x )] or "-";
qtab [x] = ppar ["q" .. tostring( x )] or "-";
rtab [x] = ppar ["r" .. tostring( x )] or "-";
end
max = x;
if v == "x"
or v == "X"
or v == "×" then
cor = cor + 1;
end
end -- for
x = 0;
if fst > 0 then
local mnm = mw.text.trim ( ppar [fst] );
end
for _, v in ipairs(ppar) do
if v ~= "+" and v ~= "-" then
x = x + 1;
local by = by0; if btab[x] ~= "-" then by = btab[x] end
local ds = dis; if dtab[x] ~= "-" then ds = dtab[x] end
local hl = hil; if htab[x] ~= "-" then hl = htab[x] end
local il = wik; if ltab[x] ~= "-" then il = ltab[x] end
local lg = lng; if itab[x] ~= "-" then lg = itab[x] end
local nm = ""; if ntab[x] ~= "-" then nm = ntab[x] end
local op = opt; if otab[x] ~= "-" then op = otab[x] end
local p4 = pr4; if qtab[x] ~= "-" then p4 = qtab[x] end
local p5 = pr5; if rtab[x] ~= "-" then p5 = rtab[x] end
local px = "";
local vv = mw.text.trim ( v );
vv = samefile ( vv, x, mnm );
if x == 1 then mnm = vv; end
if vv ~= "" and vv ~= "×" then
if ppar.b1 == nil then -- parameter missing
px = "";
if x == 1 then
px = " "
elseif x == max then
table.insert(Ctab, frame:expandTemplate{ title = "Conj-and" });
else
table.insert(Ctab, frame:expandTemplate{ title = "Comma" });
end
else -- ppar.b1 is defined (with value, or empty)
px = "<br><span style=color:#69F>✦ </span>"; -- «list» item
end
-- ds = mw.text.trim(ds);
if mw.ustring.sub(ds, -2) == "px" then
ds = mw.ustring.sub(ds, 1, mw.ustring.len(ds) -2);
end
if nm == "" and x == 1 then nm = nam end
if hl ~= "" then
if nm == "" then nm = vv end
nm = "<" .. hl .. ">" .. nm .. "</" .. hl .. ">"
end
-- if il ~= "" then ds = "" end -- ? (discrepancy)
if vv == "x" then ds = "" end -- this should be the last "file"
table.insert(Ctab, frame:expandTemplate{ title = "F", args = {vv, nm, ds, op, p4, p5, plus, l= il, lang= lg, p= px, by= by} });
end
end
end -- for
if max - cor > 3 then
table.insert(Ctab, frame:expandTemplate{ title = "Igen/cat", args = {"Own-based with more than 3 files|" .. max} });
end
return table.concat (Ctab);
end -- function ownbased
-- horizontal file list for: Template:SVG lang, Template:Lang gallery and others
function p.svglang (frame)
local dirp = frame.args-- global parms
local titl = dirp [1] or "Source thumb" -- SVG lang; "Lang gallery thumb";
local args = mw.getCurrentFrame(): getParent().args;
local otab = {};
local file = args.file or "";
for _, v in ipairs(args) do
table.insert(otab, frame:expandTemplate{ title = titl, args = { file, mw.text.trim(v) } });
end
return table.concat (otab)
end -- function svglang
-- horizontal file list for: Template:Filelist; Template:File
-- vertical file list for: Template:Other versions; Template:Derived from, Template:Derivative versions
function p.filelist (frame)
-- local locp = frame -- 1 local parm
local dirp = frame.args-- global parms
local args = mw.getCurrentFrame(): getParent().args;
local ctab = {};
local ntab = {};
local dtab = {};
local otab = {};
local qtab = {};
local rtab = {};
local vtab = {};
local ktab = {};
local itab = {};
local xtab = {};
local btab = {};
local mnum = 0;
local dir = dirp[1] or "none"
local nam = args.n or args.name or "";
local dis = args.d or args.dis or args.display or "";
local opt = args.o or args.opt or args.option or "";
local pr4 = args.par4 or args.qpar or "";
local pr5 = args.par5 or args.rpar or "";
local pr6 = args.par6 or args.vpar or "";
local by0 = args.user or args.by or "";
local wik = args.w or args.k or args.wiki or args.sisterproject or "";
local int = args.i or args.int or args.ind or args.inter or "";
local pfx = args.p or args.x or args.pfx or args.prefix or ""; -- 'list' item {{Comma}}
if mw.ustring.sub(dis, -2) == 'px' then
dis = mw.ustring.sub(dis, 1, mw.ustring.len(dis) -2)
end
if dir == "vert" and pfx == "" then
pfx = "<br><span style=color:#69F>✦ </span>"; -- 'list' item
end
for i, v in ipairs(args) do
ntab [i] = args ["n" .. tostring( i )] or args ["l" .. tostring( i )] or "-";
dtab [i] = args ["d" .. tostring( i )] or "-";
otab [i] = args ["o" .. tostring( i )] or "-";
qtab [i] = args ["q" .. tostring( i )] or "-";
rtab [i] = args ["r" .. tostring( i )] or "-";
vtab [i] = args ["v" .. tostring( i )] or "-";
ktab [i] = args ["k" .. tostring( i )] or "-";
itab [i] = args ["i" .. tostring( i )] or "-";
xtab [i] = args ["x" .. tostring( i )] or "-";
btab [i] = args ["b" .. tostring( i )] or args ["by" .. tostring( i )] or "-";
mnum = i;
end
for i, v in ipairs(args) do
local nm = nam; if ntab[i] ~= "-" then nm = ntab[i] end
local ds = dis; if dtab[i] ~= "-" then ds = dtab[i] end
local op = opt; if otab[i] ~= "-" then op = otab[i] end
local p4 = pr4; if qtab[i] ~= "-" then p4 = qtab[i] end
local p5 = pr5; if rtab[i] ~= "-" then p5 = rtab[i] end
local p6 = pr6; if vtab[i] ~= "-" then p6 = vtab[i] end
local pk = wik; if ktab[i] ~= "-" then pk = ktab[i] end
local pi = int; if itab[i] ~= "-" then pi = itab[i] end
local px = pfx; if xtab[i] ~= "-" then px = xtab[i] end
local by = by0; if btab[i] ~= "-" then by = btab[i] end
local vv = v;
vv = samefile ( vv, i, args [1] )
if vv ~= "" then
if dir == "hori" then
px = "";
if i == 1 then
px = " "
elseif i == mnum then
table.insert(ctab, frame:expandTemplate{ title = "Conj-and" });
else
table.insert(ctab, frame:expandTemplate{ title = "Comma" });
end
else -- elseif dir == "vert" then
if i == 1 then
px = " "
end
end
table.insert(ctab, frame:expandTemplate{ title = "F", args = {vv, nm, ds, op, p4, p5, p6, l= pk, lang= pi, p= px, by= by} });
end
end
return table.concat (ctab)
end -- function filelist
-- for Template:Attribs (param pairs; but also for single oarams)
function p.attribs (frame)
local args = mw.getCurrentFrame(): getParent().args;
local otab = {};
local ftab = {};
local ptab = {};
local rtab = {}
local fnum = 0;
local rnum = 0;
local hnum = 0;
local tp = args.type or "SVG"; -- needs check
local un = args.by or args.U or args.u or "";
local tt = args.t or args.to or "";
local f = args.f or args.from or tt;
local p = args.p or args.part or "";
local vx = "";
local ux = "";
local ft = "";
for i, v in ipairs(args) do
fnum = fnum + 1; -- input parm number
if fnum % 2 == 0 then -- even: should be a username
local enam = mw.text.trim ( v );
local snam = mw.ustring.lower ( mw.ustring.sub ( enam, -4 ) );
if snam == ".svg"
or snam == ".png"
or snam == ".jpg" -- a rough check: is_extension ?
or snam == ".gif"
or snam == ".pdf"
or snam == ".tif" then -- no - it's the next filename
table.insert(rtab, "" ); -- empty username inbetween
rnum = rnum + 1;
fnum = fnum + 1; -- make it odd
end
end
if fnum % 2 == 1 then -- odd (now): is a filename
hnum = fnum + 1
hnum = hnum / 2
ftab [hnum] = args ["f" .. tostring( hnum )] or ".";
ptab [hnum] = args ["p" .. tostring( hnum )] or ".";
end
-- table.maxnum (args) does not work
-- therefore the "rtab" workaround
table.insert(rtab, args[i]); -- = enam
rnum = rnum + 1
end
-- plus one item when odd number
if rnum % 2 == 1 then
table.insert( rtab, "" ); -- empty user name, to get a pair
end
--
for i, v in ipairs(rtab) do
if vx == "" then -- the 2nd 'v' can be empty
vx = mw.text.trim( v );
else
ux = mw.text.trim( v );
if ux == "" then ux = un end; -- does not work otherwise (?)
hnum = i + 0
hnum = hnum / 2
if ftab[hnum] == "." then
ft = f;
else
ft = ftab[hnum]
end
if ptab[hnum] == "." then
pt = p;
else
pt = ptab[hnum]
end
table.insert(otab, frame:expandTemplate{ title = "Attrib", args = {vx, ux, "-", tp, "", ux, tt, ft, pt } });
vx = "";
end
end
return table.concat (otab)
end -- function attribs
--
-- for Template:userlist (horizontal - but vertical when dir=I/O/U/V)
function p.userlist (frame)
-- local lpar = parm -- local parms
local gpar = frame.args -- global parms (par/P,dir/V)
local ppar = mw.getCurrentFrame(): getParent().args;
local ctab = {};
local htab = {};
local ltab = {};
local ntab = {};
local otab = {};
local ptab = {};
local ttab = {};
--@ local rtab = {};
--@ local qtab = {};
local wtab = {};
local Xtab = {};
local cas = ppar.c or ppar.case or "";
local hil = ppar.h or ppar.hilite or "";
local lnk = ppar.l or ppar.link or "";
local nam = ppar.n or ppar.name or "";
local opt = ppar.o or ppar.opt or ppar.option or "";
local pag = ppar.p or ppar.page or "";
--@ local pr4 = ppar.q or ppar.qpar or ppar.par4 or "";
--@ local pr5 = ppar.r or ppar.rpar or ppar.par5 or "";
local trl = ppar.t or ppar.i18n or ppar.translate or "";
local wik = ppar.w or ppar.wiki or ppar.lang or "";
local max = 0;
local cor = 0;
local x = 0; -- running index, can be ~= i
local y = 0; -- running index, can be ~= i
local odd = 0;
local out = 0;
local plus = ""; -- opt
local prim = ""
local prfx = ":"
local pend = ""
if gpar.dir == "O" then -- ordered list
prim = "<ol>";
prfx = "<li>";
pend = "</ol>";
end
if gpar.dir == "U" then -- unordered list
prim = "<ul>";
prfx = "<li>";
pend = "</ul>";
end
if gpar.dir == "V" then -- vertical list
prim = " ";
prfx = "<br><span style=color:#69F>✦ </span>";
end
for _, v in ipairs(ppar) do
v = mw.text.trim ( v );
if v == "+" then
plus = "+";
elseif v == "-" then
if plus == "" then plus = "-" end
else
y = y + 1;
if gpar.par == "P" -- pairs of (user, name)
and y % 2 == 0 then -- 1=user, 0=name
x = x;
else
x = x + 1;
ctab [x] = ppar ["c" .. tostring( x )] or "-";
htab [x] = ppar ["h" .. tostring( x )] or "-";
ltab [x] = ppar ["l" .. tostring( x )] or "-";
ntab [x] = ppar ["n" .. tostring( x )] or "-";
otab [x] = ppar ["o" .. tostring( x )] or "/";
ptab [x] = ppar ["p" .. tostring( x )] or "-";
--@ rtab [x] = ppar ["r" .. tostring( x )] or "-";
--@ qtab [x] = ppar ["q" .. tostring( x )] or "-";
ttab [x] = ppar ["t" .. tostring( x )] or "-";
wtab [x] = ppar ["w" .. tostring( x )] or "-";
end
end
max = x;
end -- for
odd = y % 2; -- 1 when last one not paired
if plus > "" and opt == "" then
opt = plus; -- discrepancy ? opt has priority
end
x = 0;
y = 0;
local vv = "";
for _, v in ipairs(ppar) do
v = mw.text.trim ( v );
if v ~= "+" and v ~= "-" then
y = y + 1;
if gpar.par == "P" -- pairs of (user, name)
and y % 2 == 1 -- 1=user, 0=name
and odd == 0 then -- last one paired
vv = v; -- userid
else
x = x + 1;
local cs = cas; if ctab[x] ~= "-" then cs = ctab[x] end
local hl = hil; if htab[x] ~= "-" then hl = htab[x] end
local lk = lnk; if ltab[x] ~= "-" then lk = ltab[x] end
local nm = nam; if ntab[x] ~= "-" then nm = ntab[x] end
local op = opt; if otab[x] ~= "/" then op = otab[x] end
local pg = pag; if ptab[x] ~= "-" then pg = ptab[x] end
--@ local p4 = pr4; if rtab[x] ~= "-" then p4 = rtab[x] end
--@ local p5 = pr5; if qtab[x] ~= "-" then p5 = qtab[x] end
local tr = trl; if ttab[x] ~= "-" then tr = ttab[x] end
local wk = wik; if wtab[x] ~= "-" then wk = wtab[x] end
if gpar.par == "P" then -- y%2 = 0 (name)
if odd == 1 then -- no: last user:
vv = v; -- user
else
nm = v; -- name
end
else
vv = v;
end
if hl ~= "" then
if nm == "" then nm = vv; end
nm = "<" .. hl .. ">" .. nm .. "</" .. hl .. ">";
end
local p1 = ""; -- prefix
local p2 = ""; -- postfix
if pg == "t" or pg == "wt" or pg == "tw" then p1 = " talk"; end
if pg == "w" or pg == "wt" or pg == "tw" then p2 = "~commonswiki"; end
-- {{Uc}} --> [[Special:Contributions/userid]]
if vv ~= "" and vv ~= "×" then
if gpar.dir == "I"
or gpar.dir == "O"
or gpar.dir == "U"
or gpar.dir == "V" then -- vertical list
if out == 0 then
table.insert(Xtab, frame:expandTemplate{ title = "=", args = { prim } });
end
table.insert(Xtab, frame:expandTemplate{ title = "=", args = { prfx } });
out = out + 1;
else --
if x == 1 then
x = 1 -- ??? horizontal list initializing (text)
elseif x == max then
table.insert(Xtab, frame:expandTemplate{ title = "Conj-and" });
else
table.insert(Xtab, frame:expandTemplate{ title = "Comma" });
end
end
table.insert(Xtab, frame:expandTemplate{ title = "U/main", args = { vv, nm, wk, op, link=lk, par1=p1, par2=p2, case=cs, i18n=tr} });
end
end
end
end -- for
if out > 0 and pend > " " then
table.insert(Xtab, frame:expandTemplate{ title = "=", args = { pend } });
end
return table.concat (Xtab);
end -- function userlist
--
-- for Template:Legend-table (param pairs)
function p.legendt (frame)
local args = mw.getCurrentFrame(): getParent().args;
local otab = {};
local lg = args.lang or "";
local v1 = ""
-- same problem when not a last pair
for _, v in ipairs(args) do
if v1 == "" then
v1 = v;
else
table.insert(otab, frame:expandTemplate{ title = "Legend", args = { lang = lg, v1, v } });
v1 = "";
end
end
if v1 ~= "" then
table.insert(otab, frame:expandTemplate{ title = "Legend", args = { lang = lg, v1, "" } }); -- last elem
end
return table.concat (otab)
end -- function legendt
-- for Template:ColorString (Igen/cbox - param pairs)
function p.colorbox (frame)
local args = mw.getCurrentFrame(): getParent().args;
local otab = {};
local lg = args.lang or "{{PAGELANGUAGE}}"; --
local v1 = ""
local p2 = ""
for i, v in ipairs(args) do
if i <= 2 then
p2 = v;
else
if v1 == "" then
v1 = mw.text.trim( v );
else
table.insert(otab, frame:expandTemplate{ title = "Igen/cbox", args = { v1, v, p2, lang = lg } });
v1 = "";
end
end
end
if v1 ~= "" then
table.insert(otab, frame:expandTemplate{ title = "Igen/cbox", args = { v1, "", p2, lang = lg } }); -- last elem
end
return table.concat (otab)
end -- function colorbox
-- Template:Tle
function p.tleparm (frame)
-- local lprm = frame -- local parms
-- local gprm = frame.args-- global parms
local pprm = mw.getCurrentFrame(): getParent().args;
local par1 = "";
local par3 = pprm.f or ""; -- form feed
local par4 = pprm.style or ""; -- style for value
local par5 = pprm.style2 or ""; -- style for param
local numb = pprm.number or "";
local ctab = {}
numb = mw.text.trim( numb );
for i, v in ipairs(pprm) do
par1 = pprm ["p" .. tostring( i )] or "";
if par1 == "" and numb ~= "" then
par1 = tostring( i )
end
if mw.text.trim(v) == "" then v = " " end
table.insert( ctab, frame:expandTemplate{ title = "Tle/parm", args = { par1, v, par3, par4, par5} } );
end
return table.concat (ctab)
end -- function tleparm
return p;