Module:Iteration
CodeDiscussionEditHistoryLinksLink count Subpages:DocumentationTestsResultsSandboxLive code All modules
{{=}}
for title = "="
The module uses frequently the template
This module contains the functions for different templates, solving their iteration problem
The MediaWiki 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:
{{#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 }}
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:
local out = {}
for i, v in ipairs (args) do
table.insert (out, frame:expandTemplate{ title = title, args = v })
end
return table.concat (out)
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.
Namespace lists
There are special lists for some namespaces:
- Filelist - for items of the namespace 6 (File:)
- Userlist - for items of the namespace 2 (User:)
- Linklist - for items of the namespace
0(main) — not yet - Templist - for items of the namespace
10(Template:) — not yet - Cat-list - for items of the namespace
14(Category:) — not yet - Mod-list - for items of the namespace
828(Module:) — not yet
Filelist
File list templates
The three templates {{Ifim}}
, {{Ifim1}}
and {{Ifimt}}
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 are autoreferencing, and the support also the |gallery=
option.
Other file lists
The function:svglang
creates a list of just file_names and language_codes, for:
-
{{Svg lang}}
{{Lang gallery}}
{{Multilingual SVG diagrams}}
Much more is created by the function:ownbased
for the template:
{{Own based}}
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.
{{Attribs}}
The template works, whether there is a user assigned for a file, or one filename follows another.
{{Emoji}}
The template displays a line of SVG emojis; Unicode characters/emojis can be displayed with the function emodis
or emotab
.
Variable iterations
A very simple iteration, usable for everything, is performed by function:iterate
- used by e.g.
{{Image extracted}}
,{{Image translated}}
,
More usable is the function:iteration
for transclusions of a template with:
- a number of positional parameters which can change at each transclusion, and
- a number of positional parameters which are the same for all transclusions.
See template {{Iterate}}
.
The function:loop
is used by {{Repeat}}
.
samefile
function
When the name of one of the files is the same as the first one, it is enough to reference it with its extension after a dot, e.g. just ".jpeg". The most standard extensions can be abbreviated, e.g. ".j" will be sufficient for ".jpg" (only for lower case!).
The function incrhx
increments a hexadecimal number (parm 1) by a decimal number (parm 2).
Valid numbers are assumed, no checking occurs!
When parameter 2 is preceded by a minus, the first number is decremented by the second one.
Userlist
- Userlist:
{{Userlist}}
with many formatting parameters
Linklist
Templist
Other iterations
- Langlist:
- Colorbox:
{{ColorString}}
and other color box templates - Legends :
{{Legtab}}
combines single{{Legend}}
s - Tleparms: the metatemplate
{{Tle}}
displays the parameter usage of a template - Navigate:
{{Navcat}}
navigates through color categories - Showname:
{{Showname}}
helper template, for parameter tests - Emodis :
{{Emoji}}
displays (one or many) Unicode characters
- The function
emodis
displays Unicode characters / emojis; it can care for newlines, while - The function
emotab
displays a table of files / emojis.
Code
-- This module contains the functions for different templates, solving their iteration problems.
local max = math.max
local len = string.len
local sub = string.sub
local find = string.find
local format = string.format
local insert = table.insert
local concat = table.concat
local trim = mw.text.trim
local split = mw.text.split
local titleNew = mw.title.new
local char = mw.ustring.char
local NL = char(10)
local lower = mw.ustring.lower
local upper = mw.ustring.upper
local gsub = mw.ustring.gsub
local Usub = mw.ustring.sub
local function Ucfirst(text)
text = trim(text)
return upper(Usub(text, 1, 1)) .. Usub(text, 2)
end
----------------------------------------------------------------------------------------------
-- Template expansion helpers for performance:
-- Saves CPU and time resources on large iterations by minimizing repeated recursive calls to
-- the parser, eliminating many table constructions/deletion/lookups in memory. Also allows
-- reporting CPU/time usage for expansions of costly templates inside recursive calls
-- (otherwise all CPU/time is counted inside Lua, those templates are not counted).
local currentTitle = mw.title.getCurrentTitle()
local currentNs = tonumber(currentTitle.namespace)
local currentPage = currentTitle.text
local frameCurrent = mw.getCurrentFrame()
local expandTemplateCurrent = frameCurrent.expandTemplate
local callParserFunctionCurrent = frameCurrent.callParserFunction
local contentLanguage = mw.language.getContentLanguage()
local langDefault = contentLanguage:getCode()
local langUser = lower(trim(callParserFunctionCurrent(frameCurrent, 'Int', 'Lang')))
local transclude = {}
local function expand(template, args)
transclude.title = template
transclude.args = args or {}
return expandTemplateCurrent(frameCurrent, transclude)
end
local argsOne = {}
local function expand1(title, arg1)
argsOne[1] = arg1
return expand(title, argsOne)
end
local argsLangUser = { lang = langUser }
local argsLangDefault = { lang = langDefault }
local argsLangOther = {}
local function expandWithLang(template, lang)
if type(lang) == 'string' then
lang = trim(lang)
if lang == '' then
lang = nil
else
lang = lower(lang)
end
else
lang = nil
end
if not lang or lang == langUser then
return expand(template, argsLangUser)
elseif lang == langDefault then
return expand(template, argsLangDefault)
else
argsLangOther.lang = lang
return expand(template, argsLangOther)
end
end
local Comma, ConjAnd
local function commaAnd(isLast)
if isLast then
if not ConjAnd then
ConjAnd = expand('Conj-and', argsLangUser)
end
return ConjAnd
else
if not Comma then
Comma = expand('Comma', argsLangUser)
end
return Comma
end
end
----------------------------------------------------------------------------------------------
local p = {}
-- For Template:Ifim.
local argsIfim1 = { -- Parameters for expanding 'Template:Ifim1'.
'', -- [1] = v
'', -- [2] = trim(ppar.p1 or ''),
'', -- [3] = trim(ppar.p2 or ''),
'', -- [4] = trim(ppar.p3 or ''),
'', -- [5] = trim(ppar.p4 or ''),
'', -- [6] = trim(ppar.p5 or ''),
n = '' -- ['n'] = trim(ppar.fn or ''),
}
function p.ifim1(frame)
local ppar = frameCurrent:getParent().args
argsIfim1[2] = trim(ppar.p1 or '')
argsIfim1[3] = trim(ppar.p2 or '')
argsIfim1[4] = trim(ppar.p3 or '')
argsIfim1[5] = trim(ppar.p4 or '')
argsIfim1[6] = trim(ppar.p5 or '')
argsIfim1.n = trim(ppar.fn or '')
local results = {}
for _, v in ipairs(ppar) do
argsIfim1[1] = v
insert(results, expand('Ifim1', argsIfim1))
end
return concat(results)
end -- function ifim
-- For Template:Ifimc.
local argsIfim2 = { -- Parameters for expanding 'Template:Ifim2'.
'', -- [1] = v1
'', -- [2] = trim(ppar.p1 or ''),
'', -- [3] = trim(ppar.p2 or ''),
'', -- [4] = trim(ppar.p3 or ''),
'', -- [5] = trim(ppar.p4 or ''),
'', -- [6] = v
}
function p.ifim2(frame)
local ppar = frameCurrent:getParent().args
argsIfim2[2] = trim(ppar.p1 or '')
argsIfim2[3] = trim(ppar.p2 or '')
argsIfim2[4] = trim(ppar.p3 or '')
argsIfim2[5] = trim(ppar.p4 or '')
local results = {}
for _, v in ipairs(ppar) do
argsIfim2[1] = v
argsIfim2[6] = v
insert(results, expand('Ifim2', argsIfim2))
end
return concat(results)
end -- function ifim2
-- For Template:Ifimt (param pairs).
function p.ifimt(frame)
local ppar = frameCurrent:getParent().args
argsIfim2[2] = trim(ppar.p1 or '')
argsIfim2[3] = trim(ppar.p2 or '')
argsIfim2[4] = trim(ppar.p3 or '')
argsIfim2[5] = trim(ppar.p4 or '')
local v1 = ''
local results = {}
for _, v in ipairs(ppar) do
if v1 == '' then
v1 = v
else
argsIfim2[1] = v1
argsIfim2[6] = v
insert(results, expand('Ifim2', argsIfim2))
v1 = ''
end
end
if v1 ~= '' then
argsIfim2[6] = ''
insert(results, expand('Ifim2', argsIfim2)) -- Last item.
end
return concat(results)
end -- function ifimt
-------------------------------------------------------
-- Helper function for: ownbased, and filelist
local function samefile(filename, num, first)
local filename = trim(filename or '')
if sub(filename, 1, 1) == '.' then
local part = 'Example' -- default filename
if currentNs == 6 or currentNs == 7 then
part = split(currentPage , '.', true)
part = concat(part, '.', 1, math.max(#part - 1, 1))
end
-- Supported short aliases:
if filename == '.' then filename = part .. '.png'
elseif filename == '.p' then filename = part .. '.png'
elseif filename == '.g' then filename = part .. '.gif'
elseif filename == '.j' then filename = part .. '.jpg'
elseif filename == '.s' then filename = part .. '.svg'
-- Exotics:
elseif filename == '.m' then filename = part .. '.mid'
elseif filename == '.o' then filename = part .. '.ogg'
elseif filename == '.t' then filename = part .. '.tif'
elseif filename == '.v' then filename = part .. '.wav'
elseif filename == '.x' then filename = part .. '.xcf'
-- Note: no "short alias" for '.pdf' ('.p' already used for '.png')
-- Note: short aliases for a few longer extensions:
elseif filename == '.d' then filename = part .. '.djvu'
elseif filename == '.w' then filename = part .. '.webp'
else filename = part .. filename
end
elseif filename == '' or filename == '*' then
if tonumber(num) == 1 then
filename = 'Example.svg'
if currentNs == 6 or currentNs == 7 then
filename = currentPage
end
else
filename = trim(first)
if filename == '' or filename == '*' or sub(filename, 1, 1) == '.' then
filename = 'Example.svg'
if currentNs == 6 or currentNs == 7 then
filename = currentPage
end
end
end
end
return filename
end -- function samefile
---++++++++++++++++++++++++++++++++++++++++++++++++++++
-- Simple iterations - without many params.
function p.iterate(frame)
local gpar = frame.args -- global parms
local template = gpar[1] or '' -- template name
local args = { -- Parameters for expanding the given template.
'', -- [1] = v
gpar[2] or '',
gpar[3] or '',
}
local ppar = frameCurrent:getParent().args
local results = {}
for _, v in ipairs(ppar) do
args[1] = v
insert(results, expand(template, args))
end
return concat(results)
end -- function iterate
-- More iterations - for params, param pairs, or n-tuples.
function p.iteration(frame)
local gpar = frame.args -- Global parms.
local vmax = tonumber(gpar.n) or 2 -- Tuple number (default = 2).
local vnum = vmax + 1 -- Additional not-changing params.
local template = '' -- Template name.
local args = {} -- Parameters for expanding the given template.
for i, p in ipairs(gpar) do
p = trim(p)
if i == 1 then
template = p
else
args[vnum] = p
vnum = vnum + 1
end
end
vnum = 1
local ppar = frameCurrent:getParent().args
local results = {} -- output
for _, v in ipairs(ppar) do
args[vnum] = trim(v)
vnum = vnum + 1
if vnum > vmax then
insert(results, expand(template, args))
vnum = 1
end
end
return concat(results)
end -- function iteration
-- For different templates, for general use, e.g. Emoji.
function p.parlst(frame)
local gpar = frame.args -- Global parameters.
local template = trim(gpar.temp or '')
local results = {}
if template ~= '' then -- Slow expansion (e.g. for template = 'Emoji', which will recurse into iterations calling p.emodis)
local ff = trim(gpar.ff or '') -- Inbetween?
if ff ~= '' then
ff = expand1(ff, trim(gpar.pf or ''))
else
ff = nil
end
local nocat = trim(gpar.nocat or '')
local args = { -- Parameters for expanding the given template.
nocat = nocat ~= '' and nocat or nil
}
for k, v in pairs(gpar) do
v = trim(v)
if v ~= '' then args[k] = v end
end
local count = tonumber(args[1] or '') or 0
for i = 1, (count or 1) do -- default: go 1× for nil
if ff then insert(results, ff) end
if count then args[1] = i - 1 end
insert(results, expand(template, args))
end
else -- Template expansion not needed (much faster, without recursed iterations calling p.emodis from a specified template).
local count = tonumber(gpar[1] or '') or 0
local code = tonumber(gpar[2] or '', 16) or 0
local catlink = gpar.catlink or ''
if catlink == '' then
local args = {
'<span title="U+',
'', -- [2] = format('%04X', code + i - 1)
'">',
'', -- [4] = char(code + i - 1)
'</span>',
}
for i = 1, count do
args[2] = format('%04X', code + i - 1)
args[4] = char(code + i - 1)
insert(results, concat(args))
end
elseif catlink == 'U' then
local args = {
'[[:Category:U+',
'', -- [2] = format('%04X', code + i - 1)
'|<span title="U+',
'', -- [4] = format('%04X', code + i - 1)
'">',
'', -- [6] = char(code + i - 1)
'</span>]]',
}
for i = 1, count do
args[2] = format('%04X', code + i - 1)
args[4] = args[2]
args[6] = char(code + i - 1)
insert(results, concat(args))
end
else
local args = {
'[[:Category:',
'', -- [2] = char(code + i - 1)
'|<span title="U+',
'', -- [4] = format('%04X', code + i - 1)
'">',
'', -- [6] = char(code + i - 1)
'</span>]]',
}
for i = 1, count do
args[2] = char(code + i - 1)
args[4] = format('%04X', code + i - 1)
args[6] = args[2]
insert(results, concat(args))
end
end
end
return concat(results)
end -- function parlst
-- Global function for one filename.
function p.filename(frame)
local gpar = frame.args -- Global parameters.
return samefile(trim(gpar[1] or ''), 1)
end -- function filename
-- For Template:Own based (one filename which is '.').
function p.ownbasby(frame)
local gpar = frame.args -- Global parameters.
return expand('F', {
samefile(gpar[1] or '.', 1),
by = trim(gpar[2] or '')
})
end -- function ownbasby
-- For Template:Own based (horizontal - but vertical when "b1=").
function p.ownbased(frame)
local ppar = frameCurrent:getParent().args
local by0 = trim(ppar.b or ppar.by or ppar.u or ppar.user or '')
local dis = trim(ppar.d or ppar.dis or ppar.display or '')
local hil = trim(ppar.h or ppar.hilite or '')
local lng = trim(ppar.i or ppar.lang or '')
local wik = trim(ppar.l or ppar.w or ppar.wiki or '')
local nam = trim(ppar.n or ppar.name or '')
local opt = trim(ppar.o or ppar.opt or ppar.option or '')
local mod = trim(ppar.m or ppar.mod or '')
local pr4 = trim(ppar.par4 or ppar.qpar or '')
local pr5 = trim(ppar.par5 or ppar.rpar or '')
local btab = {}
local dtab = {}
local htab = {}
local itab = {}
local ltab = {}
local ntab = {}
local otab = {}
local qtab = {}
local rtab = {}
local ttab = {}
local utab = {}
local x = 0 -- running index, can be ~= i
local fst = 0 -- first occurrence
local cor = 0
local max = 0
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
local z = tostring(x)
btab[x] = trim(ppar['b' .. z] or ppar['by' .. z] or ppar['u' .. z] or '-')
dtab[x] = trim(ppar['d' .. z] or '-')
htab[x] = trim(ppar['h' .. z] or '-')
itab[x] = trim(ppar['i' .. z] or '-')
ltab[x] = trim(ppar['l' .. z] or ppar['w' .. z] or '-')
ntab[x] = trim(ppar['n' .. z] or '-')
otab[x] = trim(ppar['o' .. z] or '-')
qtab[x] = trim(ppar['q' .. z] or '-')
rtab[x] = trim(ppar['r' .. z] or '-')
ttab[x] = trim(ppar['t' .. z] or '-')
utab[x] = trim(ppar['m' .. z] 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 = trim(ppar[fst])
end
local hls = {
'<',
'', -- [2] = hl
'>',
'', -- [4] = (nm ~= '') and nm or vv
'</',
'', -- [6] = hl
'>',
}
local args = { -- Parameters for expanding 'Template:F'.
'', -- [1] = vv,
'', -- [2] = nm
'', -- [3] = ds
'', -- [4] = op
'', -- [5] = p4
'', -- [6] = p5
plus,
l = '', -- ['l'] = il
lang = '', -- ['lang'] = lg
p = '', -- ['p'] = px
by = '', -- ['by'] = by
u = '', -- ['u'] = um
}
local results = {}
for _, v in ipairs(ppar) do
if v ~= '+' and v ~= '-' then
x = x + 1
local by = btab[x] ~= '-' and btab[x] or by0
local ds = dtab[x] ~= '-' and dtab[x] or dis
local hl = htab[x] ~= '-' and htab[x] or hil
local il = ltab[x] ~= '-' and ltab[x] or wik
local lg = itab[x] ~= '-' and itab[x] or lng
local op = otab[x] ~= '-' and otab[x] or opt
local p4 = qtab[x] ~= '-' and qtab[x] or pr4
local p5 = rtab[x] ~= '-' and rtab[x] or pr5
local um = utab[x] ~= '-' and utab[x] or mod
local nm = ntab[x] ~= '-' and ntab[x] or ''
local tx = ttab[x] ~= '-' and ttab[x] or ''
local vv = trim(v)
if find(vv, '/') == nil then
vv = samefile(vv, x, mnm)
if x == 1 then mnm = vv end
end
if vv ~= '' and vv ~= '×' then
local px = ''
if ppar.b1 == nil then -- parameter missing
if x == 1 then
px = ' '
else
insert(results, commaAnd(x == max))
end
else -- ppar.b1 is defined (with value, or empty)
px = '<br /> <span style=color:#69F>✦ </span>' -- "list" item
end
if sub(ds, -2) == 'px' then
ds = sub(ds, 1, -3)
end
if nm == '' and x == 1 then
nm = nam
end
if hl ~= '' then
hls[2] = hl
hls[4] = (nm ~= '') and nm or vv
hls[6] = hl
nm = concat(hls)
end
-- if il ~= '' then ds = '' end -- ? (discrepancy)
if vv == 'x' then ds = '' end -- this should be the last "file"
if by == '' then -- check for abbreviating '/'
local sby = find(vv, '/')
if sby ~= nil then
by = sub(vv, sby + 1)
vv = sub(vv, 1, sby - 1)
vv = samefile(vv, x, mnm)
if x == 1 then mnm = vv end
end
end
args[1] = vv
args[2] = nm
args[3] = ds
args[4] = op
args[5] = p4
args[6] = p5
args.l = il
args.lang = lg
args.p = px
args.by = by
args.u = um
insert(results, expand('F', args))
if tx ~= '' then
insert(results, expand1('=', tx))
end
end
end
end -- for
if max - cor > 9 then
insert(results, expand1('Igen/cat', 'Own-based with more than 9 files|' .. max))
end
return concat(results)
end -- function ownbased
-- Horizontal file list for: Template:SVG lang, Template:Lang gallery, and others.
function p.svglang(frame)
local gpar = frame.args -- Global parameters.
local template = gpar[1] or 'Source thumb' -- 'SVG lang', 'Lang gallery/thumb'
local ppar = frameCurrent:getParent().args
args = { -- Parameters to expand the given template.
trim(ppar.file or ''),
'', -- [2] = lang
p = trim(ppar.p or ''),
}
local results = {}
for _, v in ipairs(ppar) do
local lang = trim(v)
if lang > ' ' then
args[2] = lang
insert(results, trim(expand(template, args)))
insert(results, NL)
end
end
return concat(results)
end -- function svglang
-- Elements count for: Template:SVG lang, Template:Lang gallery, and others.
function p.elemct (frame)
local ppar = frameCurrent:getParent().args
local count = 0
for _, v in ipairs(ppar) do
if trim(v) ~= '' then
count = count + 1
end
end
return count
end -- function elemct
-- 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 gpar = frame.args -- Global parameters.
local ppar = frameCurrent:getParent().args
local spa = trim(ppar.spa or ppar.s or '-')
local pfx = trim(ppar.x or ppar.pfx or ppar.prefix or '') -- "List" item {{Comma}}
local dir = gpar[1] or 'none'
if dir == 'vert' and pfx == '' then
pfx = '\n* ' -- "list" item
end
local nam = trim(ppar.n or ppar.name or '')
local dis = trim(ppar.d or ppar.z or ppar.dis or ppar.display or '')
if sub(dis, -2) == 'px' then dis = sub(dis, 1, -3) end
local opt = trim(ppar.o or ppar.opt or ppar.option or '')
local pr4 = trim(ppar.par4 or ppar.qpar or '')
local pr5 = trim(ppar.par5 or ppar.rpar or '')
local pr6 = trim(ppar.par6 or ppar.vpar or '')
local wik = trim(ppar.w or ppar.k or ppar.wiki or ppar.sisterproject or '')
local int = trim(ppar.i or ppar.int or ppar.ind or ppar.inter or '')
local pre = trim(ppar.p or ppar.pre or ppar.pretext or '')
local by0 = trim(ppar.user or ppar.by or '')
local mod = trim(ppar.m or ppar.mod or '')
local lnk = trim(ppar.l or ppar.lnk or ppar.link or '')
local con = trim(ppar.conj or ppar.con or ppar.c or '')
con = sub(con, 1, 1)
if ppar.z then
if con == '' then con = 'n' end
if opt == '' then opt = 'Z' end
if pre == '' then pre = ' ' end
end
local vary = trim(ppar.vary or ppar.v or '') -- Variable pattern
local var1 = trim(ppar.var1 or ppar.v1 or '') -- Variable filling space before
local var2 = trim(ppar.var2 or ppar.v2 or '') -- Variable filling space after
local replacement = {
(var1 == 'space') and ' ' or var1,
'', -- [2] = (sp == '+' and ' ' or '')
'', -- [3] = vv
(var2 == 'space') and ' ' or var2,
}
local stab = {}
local xtab = {}
local ntab = {}
local dtab = {}
local otab = {}
local qtab = {}
local rtab = {}
local vtab = {}
local ktab = {}
local itab = {}
local ptab = {}
local btab = {}
local utab = {}
local ltab = {}
local ttab = {}
local loop = {}
local mnum = 0 -- maximum index reached in the previous tables of indexed parameters
for i, v in ipairs(ppar) do
local z = tostring(i)
stab[i] = trim(ppar['s' .. z] or '~')
xtab[i] = trim(ppar['x' .. z] or '-')
ntab[i] = trim(ppar['n' .. z] or ppar['l' .. z] or '-')
dtab[i] = trim(ppar['d' .. z] or '-')
otab[i] = trim(ppar['o' .. z] or '-')
qtab[i] = trim(ppar['q' .. z] or '-')
rtab[i] = trim(ppar['r' .. z] or '-')
vtab[i] = trim(ppar['v' .. z] or '-')
ktab[i] = trim(ppar['k' .. z] or '-')
itab[i] = trim(ppar['i' .. z] or '-')
ptab[i] = trim(ppar['p' .. z] or '-')
btab[i] = trim(ppar['b' .. z] or ppar['by' .. z] or '-')
utab[i] = trim(ppar['m' .. z] or '-')
ltab[i] = trim(ppar['l' .. z] or '-')
ttab[i] = trim(ppar['t' .. z] or '-')
mnum = i
end
local args = { -- Parameters for expanding 'Template:F'.
'', -- [1] = vv
'', -- [2] = nm
'', -- [3] = ds
'', -- [4] = op
'', -- [5] = p4
'', -- [6] = p5
'', -- [7] = p6
l = '', -- ['l'] = pk
lang = '', -- ['lang'] = pi
p = '', -- ['p'] = pr
by = '', -- ['by'] = by
u = '', -- ['u'] = um
link = '', -- ['link'] = (ln ~= '' and ln or nil)
}
local results = {}
local lcnt = 0 -- Loop count.
local i = 1 -- While index.
while ppar[i] ~= nil do -- for i, v in ipairs(ppar) do
local j = 1
local vv = trim(ppar[i])
if vary ~= '' and sub(vv, 1, 1) == '#' and sub(vv, -1) == '#' then -- Loop processing?
loop = split(vv, '#', true--[[plain]])
local llow = tonumber(loop[2]) or -1
local lupp = tonumber(loop[3]) or -1
if llow >= 0 and lupp >= llow then
llow = llow + lcnt
vv = tostring(llow)
lcnt = lcnt + 1
if llow < lupp then
j = 0 -- Iterate this index.
else
lcnt = 0 -- Loop ended.
end
end
end -- End loop processing.
if sub(vv, 1, 1) == '"' and sub(vv, -1) == '"' then -- Text processing?
insert(results, expand1('=', sub(vv, 2, -2)))
elseif vary == '' or i > 1 then
local sp = stab[i] ~= '~' and stab[i] or spa
local px = xtab[i] ~= '-' and xtab[i] or pfx
local nm = ntab[i] ~= '-' and ntab[i] or nam
local ds = dtab[i] ~= '-' and dtab[i] or dis
local op = otab[i] ~= '-' and otab[i] or opt
local p4 = qtab[i] ~= '-' and qtab[i] or pr4
local p5 = rtab[i] ~= '-' and rtab[i] or pr5
local p6 = vtab[i] ~= '-' and vtab[i] or pr6
local pk = ktab[i] ~= '-' and ktab[i] or wik
local pi = itab[i] ~= '-' and itab[i] or int
local pr = ptab[i] ~= '-' and ptab[i] or pre
local by = btab[i] ~= '-' and btab[i] or by0
local um = utab[i] ~= '-' and utab[i] or mod
local ln = ltab[i] ~= '-' and ltab[i] or lnk
local tx = ttab[i] ~= '-' and ttab[i] or ''
if vary ~= '' then
replacement[2] = (sp == '+' and ' ' or '')
replacement[3] = vv
vv = gsub(ppar[1], vary, concat(replacement))
else
vv = samefile(vv, i, ppar[1])
end
if vv ~= '' and vv ~= '×' then
if dir == 'hori' and con ~= 'n' then -- Horizontal list.
px = (i == 1) and ' ' or commaAnd(i == mnum)
else -- elseif dir == 'vert' then -- Vertical list.
px = (i == 1) and ' ' or px
end
if px ~= '' then insert(results, px) end
if by == '' then -- Check for abbreviating '/'.
local sby = find(vv, '/')
if sby ~= nil then
by = sub(vv, sby + 1)
vv = sub(vv, 1, sby - 1)
end
end
args[1] = vv
args[2] = nm
args[3] = ds
args[4] = op
args[5] = p4
args[6] = p5
args[7] = p6
args.l = pk
args.lang = pi
args.p = pr
args.by = by
args.u = um
args.link = (ln ~= '' and ln or nil)
insert(results, expand('F', args))
if tx ~= '' then insert(results, expand1('=', tx)) end
end -- if vary
end -- if vv
i = i + j -- next in do loop
end -- while
return concat(results)
end -- function filelist
-- For Template:Attribs (param pairs; but also for single params).
function p.attribs(frame)
local ppar = frameCurrent:getParent().args
local un = trim(ppar.by or ppar.U or ppar.u or '')
local md = trim(ppar.m or ppar.mod or '')
local tt = trim(ppar.t or ppar.to or '') -- "to" topic.
local f = trim(ppar.f or ppar.from or tt) -- "from".
local p = trim(ppar.p or ppar.part or '')
local args = { -- Parameters for expandnig 'Template:Attrib'.
'', -- [1] = vx
'', -- [2] = ux
'-',
trim(ppar.type or 'SVG'), -- Needs check.
'',
ux, -- [6] = ux
tt,
'', -- [8] = (ftab[hnum] ~= '.') and ftab[hnum] or f
'', -- [9] = (ptab[hnum] ~= '.') and ptab[hnum] or p
m = '', -- ['m'] = (mtab[hnum] ~= '.') and mtab[hnum] or md
s = trim(ppar.s or ppar.style or 's'), -- default
}
local ftab = {} -- "from" topic.
local ptab = {} -- Parts.
local mtab = {} -- Modification.
local rtab = {} -- Working table.
local fnum = 0
local rnum = 0
local hnum = 0
for i, v in ipairs(ppar) do
fnum = fnum + 1 -- Input parm number.
if fnum % 2 == 0 then -- Even: should be a username.
local enam = trim(v)
-- A rough check: is_extension?
local snam = lower(sub(enam, -4))
if snam == '.png'
or snam == '.gif'
or snam == '.jpg'
or snam == '.svg'
-- Exotics:
or snam == '.mid'
or snam == '.ogg'
or snam == '.tif'
or snam == '.wav'
or snam == '.xcf'
or snam == '.pdf' -- Note: no "short alias" in samefile()
-- Note: Longer extensions still not supported (need check):
-- snam == '.djvu'
-- snam == '.webp'
then -- No - it's the next filename.
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) / 2
local z = tostring(hnum)
ftab[hnum] = ppar['f' .. z] or '.'
ptab[hnum] = ppar['p' .. z] or '.'
mtab[hnum] = ppar['m' .. z] or '.'
end
-- table.maxnum(ppar) does not work; therefore the "rtab" workaround.
insert(rtab, ppar[i]) -- = enam
rnum = rnum + 1
end
if rnum % 2 == 1 then -- Plus one item when odd number.
insert(rtab, '') -- Empty user name, to get a pair.
end
local results = {} -- Output.
local vx = ''
for i, v in ipairs(rtab) do
if i % 2 == 1 then -- odd: 1st value in pair is a filename
vx = trim(v) -- this 1st 'v' should not be empty
else -- even: 2nd value in pair is a user name (possibly empty)
local ux = trim(v) -- this 2nd 'v' can be empty
if ux == '' then ux = un end -- Does not work otherwise?
hnum = i / 2
args[1] = vx -- a filename
args[2] = ux -- a username
args[6] = ux -- a username
args[8] = (ftab[hnum] ~= '.') and ftab[hnum] or f
args[9] = (ptab[hnum] ~= '.') and ptab[hnum] or p
args.m = (mtab[hnum] ~= '.') and mtab[hnum] or md
insert(results, expand('Attrib', args))
vx = '' -- reset the filename for the next pairs
end
end
return concat(results)
end -- function attribs
-- Get the user id: the (last) parameter which is prefixed by '/'.
function p.byuser(frame)
local ppar = frameCurrent:getParent().args
local user = ''
for _, value in pairs(ppar) do
if value ~= nil and user == '' and sub(value, 1, 1) == '/' then
user = sub(value, 2) -- remove the '/'
end
-- TODO: Test whether userID exists?
end
return user
end -- function byuser, for template:F
-- for Template:userlist (horizontal - but vertical when dir=I/O/U/D/V).
function p.userlist(frame)
local gpar = frame.args -- global parms (par/P, dir/V)
local ppar = frameCurrent:getParent().args
local mod = ppar.m or ppar.mod or ppar.user or ppar.u or ppar.page or ppar.p or ''
local hil = ppar.h or ppar.hilite or ''
local nam = ppar.n or ppar.name or ''
local wik = ppar.w or ppar.wiki or ppar.lang or ''
local opt = ppar.o or ppar.opt or ppar.option or ''
local lnk = ppar.l or ppar.link or ''
--@ local pr4 = ppar.q or ppar.qpar or ppar.par4 or ''
--@ local pr5 = ppar.r or ppar.rpar or ppar.par5 or ''
local cas = ppar.c or ppar.case or ''
local trl = ppar.t or ppar.i18n or ppar.translate or ''
-- If ever template expansion of prim, prfx, sufx, or pend is needed,
-- this must be done once here (out of the loop below).
local prim, prfx, sufx, pend = '', '', '', ''
if gpar.dir == 'O' then -- Ordered/numbered vertical list.
prim, prfx, sufx, pend = '<ol>', '<li>', '</li>', '</ol>'
elseif gpar.dir == 'U' then -- Unordered/bulleted vertical list.
prim, prfx, sufx, pend = '<ul>', '<li>', '</li>', '</ul>'
elseif gpar.dir == 'D' then -- Simple definition/indented vertical list.
prim, prfx, sufx, pend = '<dl>', '<dt>', '</dt>', '</dl>'
elseif gpar.dir == 'V' then -- Custom vertical list of users.
prim, prfx, sufx, pend = '<dl style="margin:.3em 0">', '<dt><span style="color:#69F">✦ </span>', '</dt>', '</dl>'
else --'I': Inline horizontal list.
-- prim, prfx, sufx, pend: not used; replaced by separators, expanded by commaAnd()
end
local mtab = {} -- u_mod c/t/w/wt (aka utab, mtab, ptab)
local htab = {} -- hilite
local ntab = {} -- 2 display name
local wtab = {} -- 3 interwiki
local otab = {} -- 4 +/- option
local ltab = {} -- link option
--@ local qtab = {}
--@ local rtab = {}
local ctab = {} -- case
local ttab = {} -- translate i18n
local xtab = {} -- postfix text
local x = 0 -- running index, can be ~= i
local y = 0 -- running index, can be ~= i
local plus = '' -- opt
local xmax = 0
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 --[[1=user, 0=name]] then
x = x
else
x = x + 1
local z = tostring(x)
mtab[x] = ppar['m' .. z] or ppar['u' .. z] or ppar['p' .. z] or '-'
htab[x] = ppar['h' .. z] or '-'
ntab[x] = ppar['n' .. z] or '-'
wtab[x] = ppar['w' .. z] or '-'
otab[x] = ppar['o' .. z] or '/'
ltab[x] = ppar['l' .. z] or '-'
--@ qtab[x] = ppar['q' .. z] or '-'
--@ rtab[x] = ppar['r' .. z] or '-'
ctab[x] = ppar['c' .. z] or '-'
ttab[x] = ppar['t' .. z] or '-'
xtab[x] = ppar['x' .. z] or '-'
end
end
xmax = x
end -- for
if plus ~= '' and opt == '' then
opt = plus --[[discrepancy? opt has priority]]
end
local odd = y % 2 --[[1 when last one not paired]]
local p2s = {
'~',
'', -- [2] = (wk ~= '') and wk or 'commons'
'wiki',
}
local hls = {
'<',
'', -- [2] = hl
'>',
'', -- [4] = (nm ~= '') and nm or vv
'</',
'', -- [6] = hl
'>',
}
local args = { -- Parameters for expanding 'Tempplate:U/main'.
'', -- [1] = vv,
'', -- [2] = nm,
'', -- [3] = wk,
'', -- [4] = op,
link = '', -- ['link'] = lk
par1 = '', -- ['par1'] = p1
par2 = '', -- ['par2'] = p2
--@ par4 = '', -- ['par4'] = p4
--@ par5 = '', -- ['par5'] = p5
case = '', -- ['case'] = cs
i18n = '', -- ['i18n'] = tr
}
local results = {}
local out = 0
local vv = ''
x = 0
y = 0
for _, v in ipairs(ppar) do
v = 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 md = (mtab[x] ~= '-') and mtab[x] or mod
local hl = (htab[x] ~= '-') and htab[x] or hil
local nm = (ntab[x] ~= '-') and ntab[x] or nam
local wk = (wtab[x] ~= '-') and wtab[x] or wik
local op = (otab[x] ~= '/') and otab[x] or opt
local lk = (ltab[x] ~= '-') and ltab[x] or lnk
--@ local p4 = (qtab[x] ~= '-') and qtab[x] or pr4
--@ local p5 = (rtab[x] ~= '-') and rtab[x] or pr5
local cs = (ctab[x] ~= '-') and ctab[x] or cas
local tr = (ttab[x] ~= '-') and ttab[x] or trl
local tx = (xtab[x] ~= '-') and xtab[x] or ''
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
hls[2] = hl
hls[4] = (nm ~= '') and nm or vv
hls[6] = hl
nm = concat(hls)
end
if md == 'n' or md == 'no' then
lk = md -- no link
end
local p1 = '' -- prefix
if md == 't' or md == 'wt' or md == 'tw' then
p1 = ' talk'
end
local p2 = '' -- postfix
if md == 'w' or md == 'wt' or md == 'tw' then
p2s[2] = (wk ~= '') and wk or 'commons'
p2 = concat(p2s)
end
if vv ~= '' and vv ~= '×' then
if md == 'c' then vv = 'Special:Contributions/' .. vv end
if gpar.dir == 'I' or gpar.dir == 'O' or gpar.dir == 'U' or gpar.dir == 'V' then
-- Vertical list (uses: prim, prfx, sufx, pend).
if out == 0 then
insert(results, prim) -- expansion of prim not needed
end
insert(results, prfx) -- expansion of prefx not needed
out = out + 1
else -- Horizontal inline list.
if x ~= 1 then
insert(results, commaAnd(x == xmax))
end
end
if sub(vv, 1, 2) == '{{' or sub(vv, 1, 2) == '[[' then
insert(results, expand1('=', vv))
else
args[1] = vv
args[2] = nm
args[3] = wk
args[4] = op
args.link = lk
args.par1 = p1
args.par2 = p2
--@ args.par4 = p4
--@ args.par5 = p5
args.case = cs
args.i18n = tr
insert(results, expand('U/main', args))
end
if tx ~= '' then
insert(results, expand1('=', tx))
end
if sufx ~= '' then
insert(results, sufx) -- expansion of sufx not needed
end
end
end
end
end -- for
if out > 0 and pend ~= '' then
insert(results, pend) -- expansion of pend not needed
end
return concat(results)
end -- function userlist
-- Table for templates: Legend; Legend-line, Legend2, Legend-small... (param pairs)
function p.legendt (frame)
local ppar = frameCurrent:getParent().args
local ttip = trim(ppar.tt or ppar.ttip or ppar.tooltipping or '')
local frmp = frame.args
local template = trim(frmp[1] or 'Legend')
local args = { -- Parameters for expanding the given template.
'', -- [1] = v1
'', -- [2] = v
lang = trim(ppar.lang or ''),
p = trim(frmp[2] or ''),
size = trim(frmp[3] or ''),
css = '', -- ['css'] = '" title="' .. upper(v1)
}
local results = {}
local v1 = ''
for _, v in ipairs(ppar) do
if v1 == '' then
v1 = v
if ttip == 'yes' and v1 ~= '' then -- Tooltip the colors.
-- HACK: terminates the style="..." attribute and opens another attribute
args.css = '" title="' .. Ucfirst(v1)
end
else
args[1] = v1
args[2] = v
insert(results, expand(template, args))
v1 = ''
args.css = ''
end
end
if v1 ~= '' then -- Last item: problem when not a last pair
insert(results, expand(template, args))
end
return concat(results)
end -- function legendt
-- For Template:ColorString (Igen/cbox, param pairs).
local argsColorbox = { -- Parameters for expanding 'Template:Igen/cbox'.
'', -- [1] -- (striped; border)
'', -- [2] -- color value
'', -- [3] -- either code-2 ( BCDLMST-), or color value
0, -- [4] -- count of spaces
'', -- [5] -- ?
'', -- [6] -- 'char' or 'file'
'', -- ['lang'] = ppar.lang or content language,
}
function p.colorbox(frame)
local ppar = frameCurrent:getParent().args
argsColorbox.lang = ppar.lang or mw.getContentLanguage():getCode()
local results = {}
local v1 = ''
for i, v in ipairs(ppar) do
if i <= 2 then
argsColorbox[3] = v -- either code-2 ( BCDLMST-), or color value
elseif v1 == '' then
v1 = v -- (striped; border)
local ct = 0 -- count of spaces
local bp = 0 -- position of first space
for c = 1, len(v1) do
if sub(v1, c, c) == ' ' then
ct = ct + 1 -- space count
if bp == 0 then bp = c end
end
end
local bc = ''
if ct >= 3 then -- 3 = border, 4 = line
bc = sub(v1, bp + 1)
v1 = sub(v1, 1, bp - 1)
end
local cf = ''
if ct == 1 then -- 'char' or 'file'
bc = sub(v1, bp + 1)
v1 = sub(v1, 1, bp - 1)
cf = (sub(bc, -4, -4 ) == '.') and 'file' or 'char'
end
argsColorbox[4] = ct -- count of spaces
argsColorbox[5] = bc
argsColorbox[6] = cf -- 'char' or 'file'
else
argsColorbox[1] = v1
argsColorbox[2] = v
insert(results, expand('Igen/cbox', argsColorbox))
v1 = ''
end
end
if v1 ~= '' then
argsColorbox[1] = v1
argsColorbox[2] = ''
insert(results, expand('Igen/cbox', argsColorbox)) -- last item
end
return concat(results)
end -- function colorbox
--------------------------------------------------------------------------------
-- Returns a parameter list: (replacement of «#» or «~» by «=»: not necessary).
function p.plist(frame)
local ppar = frameCurrent:getParent().args
return concat(ppar, '|') -- return gsub(concat(ppar, '|'), '#', '='), not necessary
end -- function plist
-- Repeats a text string.
function p.loop (frame)
local ppar = frameCurrent:getParent().args
return string.rep(ppar[2] or ' ', tonumber(ppar[1] or 1))
end -- function loop
-- Increment a hex number by a ±decimal value
function p.incrhx(frame)
local gpar = frame.args -- global parms
return format('%X', tonumber(gpar[1], 16) + gpar[2])
end -- function incrhx
-- Display inline a range of characters with their Unicode code point in tool tip, such as emojis for Template:Emoji, with optional
-- line breaks to limit lines to at most 16 characters (breaks after every code point which is the last one in a UCS column):
-- {{#invoke:Iteration|parlst |temp=Emoji |1=(nb of characters) |2=(4- to 6-digits uppercase hexadecimal code point)
-- |3=(border or 0) |4=(padding or 0) |5=(font size in px or -)
-- |6=(styles or -) |(nocat=1)
-- }}
local argsEmodis = {
-- WARNING: partial HTML (see the template using this function)
-- This function can only be used after an UNTERMINATED opening HTML tag,
-- whose LAST attribute MUST BE ' title=' not followed by quotes.
-- This returned value closes the opening HTML tag of the template
-- The calling template will then append itself the closing HTML tag.
'"U+',
'', -- [2] = format('%04X', code)
'">',
'', -- [4] = char(code)
nil -- [5] = optional line break
}
function p.emodis(frame)
local gpar = frame.args -- global parms
local code = tonumber(gpar[1], 16) + gpar[2]
argsEmodis[2] = format('%04X', code)
argsEmodis[4] = char(code)
argsEmodis[5] = gpar[3] == '16' and (code % 16 == 15 and '<br />') or nil
return concat(argsEmodis)
end -- function emodis
-- For Template:Emoji table: {{#invoke:Iteration|emotab|prefix=1F250|par1=... | ... }}
local argsEmotab = { -- Parameters for expanding 'Template:F'.
'', -- [1] = file
'', -- [2] = 'Z'
'', -- [3] = '49'
'', -- [4] = 'b'
'', -- [5] = 'l'
'', -- [6] = ''
link = '*',
}
function p.emotab(frame)
local gpar = frame.args -- global parms
local codp
codp = trim(gpar.par1 or '') --[['Z' ]] argsEmotab[2] = (codp ~= '') and codp or nil
codp = trim(gpar.par2 or '') --[['49']] argsEmotab[3] = (codp ~= '') and codp or nil
codp = trim(gpar.par3 or '') --[['b' ]] argsEmotab[4] = (codp ~= '') and codp or nil
codp = trim(gpar.par4 or '') --[['l' ]] argsEmotab[5] = (codp ~= '') and codp or nil
codp = trim(gpar.par5 or '') --[['' ]] argsEmotab[6] = (codp ~= '') and codp or nil
codp = trim(gpar.codp or '')
local parts = {
'', -- [1] = v
'', -- [2] = ((file == 'Emojio' or file == 'Fxemoj' or file == 'OpenMo') and upper or lower)(codp)
'.svg',
}
local results = {}
for _, v in ipairs(gpar) do
local file = sub(v, 1, 6)
parts[1] = v
parts[2] = ((file == 'Emojio' or file == 'Fxemoj' or file == 'OpenMo') and upper or lower)(codp)
file = concat(parts)
if titleNew(file, 6).exists then
argsEmotab[1] = file
insert(results, expand('F', argsEmotab))
end
end
return concat(results)
end -- function emotab
-- For template: Navcat (via Navcattab).
function p.navcat(frame)
local gpar = frame.args -- global parms
local cats = { -- Categories to generate.
trim(gpar.c1 or ''),
'', -- [2] = ctxt
trim(gpar.c2 or ''),
}
local args = { -- Parameters for expanding 'Template:Navcat'.
'', -- [1] = (ccod = vtab[2] --[[opt.]])
'', -- [2] = concat(cats)
'', -- [3] = (dtxt = Ucfirst(ctxt))
'', -- [4] = (cnam = vtab[3] or ccod or ctxt)
span = trim(gpar.span or ''),
}
local ppar = frameCurrent:getParent().args
local results = {}
for _, v in ipairs(ppar) do
v = trim(v)
if v == '' or v == 'nl' then
insert(results, '<br /> ')
else
local vtab = split(v, '/')
local ctxt = vtab[1] or ' ' --[[requ.]]
local ccod = vtab[2] --[[opt.]]
cats[2] = ctxt
args[1] = ccod
args[2] = concat(cats)
args[3] = Ucfirst(ctxt)
args[4] = vtab[3] or ccod or ctxt
insert(results, expand('Navcat', args))
end
end
return concat(results)
end -- function navcat
-- For Template:Tle.
function p.tleparm(frame)
local ppar = frameCurrent:getParent().args
local parnumber = trim(ppar.number or '')
local parkbd = trim(ppar.kbd or '')
if parkbd ~= '' then
parkbd = {
'<kbd>',
'', -- [2] = par1
'</kbd>',
}
else
parkbd = nil
end
local args = { -- Parameters for expanding 'Template:Tle/parm'.
'', -- [1] = par1
'', -- [2] = v
trim(ppar.f or ''), -- form feed
trim(ppar.style or ''), -- style for parameter value
trim(ppar.style2 or ''), -- style for parameter name
}
local results = {}
for i, v in ipairs(ppar) do
local z = tostring(i)
local par1 = trim(ppar['p' .. z] or '')
if par1 ~= '' and parkbd then
parkbd[2] = par1
par1 = concat(parkbd)
end
if par1 == '' and parnumber ~= '' then
par1 = z
end
if par1 ~= '' then -- keep parameter value as is if positional (and not parnumberd explicitly)
v = trim(v)
if v == '' then v = ' ' --[[Note: ' ' would change the semantics.]] end
end
args[1] = par1
args[2] = v
insert(results, expand('Tle/parm', args))
end
return concat(results)
end -- function tleparm
-- for Template:Variate.
function p.variation(frame)
local ppar = frameCurrent:getParent().args
local sept = ppar.sept or '|' -- separator before
local sample = trim(ppar[1] or '') -- sample string
local pattern = ppar.pttn or '?' -- pattern
local var1 = ppar.var1 or '' -- filling space before
local var2 = ppar.var2 or '' -- filling space after
local sep2 = ppar.sep2 or '' -- separator after
local parts = { -- Replacement parts for gsub().
(var1 == 'space') and ' ' or var1,
'', -- [2] = trim(v)
(var2 == 'space') and ' ' or var2,
}
local results = {}
for i, v in ipairs(ppar) do
if i > 1 then
insert(results, sept)
parts[2] = trim(v)
insert(results, gsub(sample, pattern, concat(parts)))
insert(results, sep2)
end
end
return concat(results)
end
return p