Sabtu, 07 November 2026
07:04 WIB
TERKINI
Bandar Lampung Agenda Strategis Pemprov Lampung 6 November 2026: Revitalisasi Stadion Jadi Prioritas Bandar Lampung Harga Beras di Pasar Pasir Gintung Bandar Lampung Merangkak Naik, Stok Aman Bandar Lampung Disdag Bandar Lampung Jamin Pasokan Beras Aman hingga Akhir 2026 Insight Komitmen Pembangunan Negeri, PTBA Sabet Penghargaan Kepatuhan PNBP ESDM 2026 Pemprov Lampung Gubernur Mirza Canangkan Mulang Maya Jadi Magnet Wisata Budaya Unggulan Lampung Tuba Barat Mewujudkan Haji: Pemkab Tubaba dan BSI Ajak Masyarakat Menabung Sejak Dini Lampung Timur Bupati Ela Dekatkan Diri dengan Siswa, Pastikan Kualitas Pendidikan dan Gizi di Lampung Timur Tuba Barat Kemitraan Strategis Pemkab Tubaba dan Kejari: Wujudkan Tata Kelola Pemerintahan Akuntabel Bandar Lampung Mantan Ketua DPRD Lampung Bersaksi dalam Sidang Arinal Djunaidi Bandar Lampung Senator Bustami Zainudin dan Staf DPD Lampung Ikuti Program Cek Kesehatan Gratis Bandar Lampung Agenda Strategis Pemprov Lampung 6 November 2026: Revitalisasi Stadion Jadi Prioritas Bandar Lampung Harga Beras di Pasar Pasir Gintung Bandar Lampung Merangkak Naik, Stok Aman Bandar Lampung Disdag Bandar Lampung Jamin Pasokan Beras Aman hingga Akhir 2026 Insight Komitmen Pembangunan Negeri, PTBA Sabet Penghargaan Kepatuhan PNBP ESDM 2026 Pemprov Lampung Gubernur Mirza Canangkan Mulang Maya Jadi Magnet Wisata Budaya Unggulan Lampung Tuba Barat Mewujudkan Haji: Pemkab Tubaba dan BSI Ajak Masyarakat Menabung Sejak Dini Lampung Timur Bupati Ela Dekatkan Diri dengan Siswa, Pastikan Kualitas Pendidikan dan Gizi di Lampung Timur Tuba Barat Kemitraan Strategis Pemkab Tubaba dan Kejari: Wujudkan Tata Kelola Pemerintahan Akuntabel Bandar Lampung Mantan Ketua DPRD Lampung Bersaksi dalam Sidang Arinal Djunaidi Bandar Lampung Senator Bustami Zainudin dan Staf DPD Lampung Ikuti Program Cek Kesehatan Gratis

Modul:Params

Bagikan:
Dokumentasi modulbuatsegarkan
Anda dapat membuat halaman dokumentasi untuk buat pada modul Scribunto ini.
Penyunting dapat melakukan uji coba pada halaman bak pasir (buat | cermin) dan kasus uji (buat) modul ini.
Subhalaman modul ini.
require[[strict]]
---                                        ---
---     PRIVATE ENVIRONMENT                ---
---    ________________________________    ---
---                                        ---
--[[ Abstract utilities ]]--
----------------------------
-- Helper function for `string.gsub()` (for managing zero-padded numbers)
localfunctionzero_padded(str)
return('%03d%s'):format(#str,str)
end
-- Helper function for `table.sort()` (for natural sorting)
localfunctionnatural_sort(var1,var2)
returnvar1:gsub('%d+',zero_padded)<var2:gsub('%d+',zero_padded)
end
-- Return a copy or a reference to a table
localfunctioncopy_or_ref_table(src,refonly)
ifrefonlythenreturnsrcend
localnewtab={}
forkey,valinpairs(src)donewtab[key]=valend
returnnewtab
end
-- Copy at most N items (of all kinds) from `src` to `dest` and return `dest`
localfunctioncopy_table_maxn(dest,src,len)
localidx=1
forkey,valinpairs(src)do
dest[key],idx=val,idx+1
ifidx>lenthenbreakend
end
returndest
end
-- Remove some numeric elements from a table, shifting everything to the left
localfunctionremove_numeric_keys(tbl,idx,len)
localcache,tmp={},idx+len-1
forkey,valinpairs(tbl)do
iftype(key)=='number'andkey>=idxthen
ifkey>tmpthencache[key-len]=valend
tbl[key]=nil
end
end
forkey,valinpairs(cache)dotbl[key]=valend
end
-- Make a reduced copy of a table (shifting in both directions if necessary)
localfunctioncopy_table_reduced(tbl,idx,len)
localret,tmp={},idx+len-1
ifidx>0then
forkey,valinpairs(tbl)do
iftype(key)~='number'orkey<idxthen
ret[key]=val
elseifkey>tmpthenret[key-len]=valend
end
elseiftmp>0then
localnshift=1-idx
forkey,valinpairs(tbl)do
iftype(key)~='number'thenret[key]=val
elseifkey>tmpthenret[key-tmp]=val
elseifkey<idxthenret[key+nshift]=valend
end
else
forkey,valinpairs(tbl)do
iftype(key)~='number'orkey>tmpthen
ret[key]=val
elseifkey<idxthenret[key+len]=valend
end
end
returnret
end
-- Make an expanded copy of a table (shifting in both directions if necessary)
localfunctioncopy_table_expanded(tbl,idx,len)
localret,tmp={},idx+len-1
ifidx>0then
forkey,valinpairs(tbl)do
iftype(key)~='number'orkey<idxthen
ret[key]=val
elseret[key+len]=valend
end
elseiftmp>0then
localnshift=idx-1
forkey,valinpairs(tbl)do
iftype(key)~='number'thenret[key]=val
elseifkey>0thenret[key+tmp]=val
elseifkey<1thenret[key+nshift]=valend
end
else
forkey,valinpairs(tbl)do
iftype(key)~='number'orkey>tmpthen
ret[key]=val
elseret[key-len]=valend
end
end
returnret
end
-- Given a table, create two new tables containing the sorted list of keys
localfunctionget_sorted_key_list(tbl,sort_fn)
localnums,words,nn,nw={},{},1,1
forkey,valinpairs(tbl)do
iftype(key)=='number'thennums[nn],nn=key,nn+1
elsewords[nw],nw=key,nw+1end
end
table.sort(nums)
table.sort(words,sort_fn)
returnnums,words,nn-1,nw-1
end
-- Parse a parameter name string and return it as a string or a number
localfunctionget_param_name(par_str)
localret=par_str:match'^%s*(.-)%s*$'
ifret~='0'andret:find'^%-?[1-9]%d*$'==nilthenreturnretend
returntonumber(ret)
end
-- Move a key from a table to another, but only if under a different name and
-- always parsing numeric strings as numbers
localfunctionsteal_if_renamed(val,src,skey,dest,dkey)
localrealkey=get_param_name(dkey)
ifskey~=realkeythendest[realkey],src[skey]=val,nilend
end
--[[ Public strings ]]--
------------------------
-- Special match keywords (functions and modifiers MUST avoid these names)
localmkeywords={
['or']=0,
pattern=1,
plain=2,
strict=3
}
-- Sort functions (functions and modifiers MUST avoid these names)
localsortfunctions={
alphabetically=false,
naturally=natural_sort
}
-- Callback styles for the `mapping_*` and `renaming_*` class of modifiers
-- (functions and modifiers MUST avoid these names)
--[[
Meanings of the columns:
  col[1] = Loop type (0-3)
  col[2] = Number of module arguments that the style requires (1-3)
  col[3] = Minimum number of sequential parameters passed to the callback
  col[4] = Name of the callback parameter where to place each parameter name
  col[5] = Name of the callback parameter where to place each parameter value
  col[6] = Argument in the modifier's invocation that will override `col[4]`
  col[7] = Argument in the modifier's invocation that will override `col[5]`
A value of `-1` indicates that no meaningful value is stored (i.e. `nil`)
]]--
localmapping_styles={
names_and_values={3,2,2,1,2,-1,-1},
values_and_names={3,2,2,2,1,-1,-1},
values_only={1,2,1,-1,1,-1,-1},
names_only={2,2,1,1,-1,-1,-1},
names_and_values_as={3,4,0,-1,-1,2,3},
names_only_as={2,3,0,-1,-1,2,-1},
values_only_as={1,3,0,-1,-1,-1,2},
blindly={0,2,0,-1,-1,-1,-1}
}
-- Memory slots (functions and modifiers MUST avoid these names)
localmemoryslots={
h='header',
f='footer',
i='itersep',
l='lastsep',
n='ifngiven',
p='pairsep',
s='oxfordsep'
}
-- Possible trimming modes for the `parsing` modifier
localtrim_parse_opts={
trim_none={false,false},
trim_positional={false,true},
trim_named={true,false},
trim_all={true,true}
}
-- Possible string modes for the iteration separator in the `parsing` and
-- `reinterpreting` modifiers
localisep_parse_opts={
splitter_pattern=false,
splitter_string=true
}
-- Possible string modes for the key-value separator in the `parsing` and
-- `reinterpreting` modifiers
localpsep_parse_opts={
setter_pattern=false,
setter_string=true
}
-- Possible position references for the `splicing` modifier
localposition_references={
add_nothing=0,
add_smallest_number=1,
add_last_of_sequence=2,
add_largest_number=3
}
-- Possible modes for the `reassigning` modifier
locala_modes={
transfer=0,
clone=1,
rename=2,
copy=3,
sacrifice=4,
provide=5,
spare=7
}
-- Functions and modifiers MUST avoid these names too: `here`, `in_substack`,
-- `let`, `expose`, `use`, `with_flushed_glue`, `without_flushed_glue`
-- `without_sorting`
--[[ Private constants ]]--
---------------------------
-- Hard-coded name of the module (to avoid going through `frame:getTitle()`)
localmodulename='Module:Params'
-- The functions listed here declare that they don't need the
-- `frame:getParent().args` metatable to be copied into a regular table; if 
-- they are modifiers they also guarantee that they will make their own
-- (modified) copy available
localrefparams={
call_for_each_group=true,
combining=true,
combining_by_calling=true,
combining_values=true,
concat_and_call=true,
concat_and_invoke=true,
concat_and_magic=true,
count=true,
grouping_by_calling=true,
mixing_names_and_values=true,
keeping_at_most=true,
renaming_by_mixing=true,
renaming_to_sequence=true,
renaming_to_uppercase=true,
renaming_to_lowercase=true,
shifting=true,
splicing=true,
value_of=true,
with_name_matching=true
}
-- Maximum number of numeric 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)
localmaxfill=1024
-- The private table of functions
locallibrary={}
-- Functions and modifiers that can only be invoked in first position
localstatic_iface={}
--[[ Private functions ]]--
---------------------------
-- Create a new context
localfunctioncontext_new(child_frame,first_fn_name)
localmain_frame,tpipe=child_frame:getParent(),{first_fn_name}
forkey,valinpairs(child_frame.args)do
iftype(key)=='number'andkey>0thentpipe[key+1]=val
elsetpipe[key]=valend
end
return{
frame=main_frame,
pipe=tpipe,
oparams=main_frame.args,
firstposonly=static_iface,
iterfunc=pairs,
fnpos=1,
sorttype=0,
n_parents=0,
n_children=0,
n_available=maxfill
}
end
-- Move to the next action within the user-given list
localfunctioncontext_iterate(ctx,next_fn_pos,trimmed_fname)
localfname=trimmed_fnameorctx.pipe[next_fn_pos]and
ctx.pipe[next_fn_pos]:match'^%s*(.*%S)'
iffname==nilthenerror(modulename..
': You must specify a function to call',0)end
iflibrary[fname]==nilthen
ifctx.firstposonly[fname]==nilthenerror(modulename..
': The function ‘'..fname..'’ does not exist',0)
elseerror(modulename..': The ‘'..fname..
'’ directive can only appear in first position',0)
end
end
ctx.fnpos=next_fn_pos
returnlibrary[fname]
end
-- Main loop
localfunctionmain_loop(ctx,start_with)
localfn=start_with
repeatfn=fn(ctx)untilnotfn
ifctx.n_parents>0thenerror(modulename..
': One or more ‘merging_substack’ directives are missing',0)end
ifctx.n_children>0thenerror(modulename..
', For some of the snapshots either the ‘flushing’ directive is missing or a group has not been properly closed with ‘merging_substack’',0)end
end
-- Load a `setting`-like directive string into the `dest` table
localfunctionset_strings_from_opts(dest,opts,offs)
localcmd
ifopts[offs]==nilthenreturnoffs-1end
cmd=opts[offs]:gsub('%s+',''):gsub('/+','/'):match'^/*(.*[^/])'
ifcmd==nilthenreturnoffsend
localvname,chr
localamap,sep,argc={},string.byte('/'),offs+1
foridx=1,#cmddo
chr=cmd:byte(idx)
ifchr==septhen
forkey,valinipairs(amap)do
dest[val],amap[key]=opts[argc],nil
end
argc=argc+1
else
vname=memoryslots[string.char(chr)]
ifvname==nilthenerror(modulename..
', ‘setting’: Unknown slot ‘'..string.char(chr)..'’',0)end
table.insert(amap,vname)
end
end
forkey,valinipairs(amap)dodest[val]=opts[argc]end
returnargc
end
-- Add a new stack of parameters to `ctx.children`
localfunctionnew_substack(ctx)
localcurrsnap,newparams=ctx.n_children+1,{}
ifctx.children==nilthenctx.children={newparams}
elsectx.children[currsnap]=newparamsend
ctx.n_children=currsnap
returnnewparams
end
-- Parse a raw argument containing a `sortfunctions` directive, or
-- `'without_sorting'`, or `nil`
localfunctionload_sort_opt(raw_arg)
localtrarg
ifraw_arg~=nilthentrarg=raw_arg:match'^%s*(.*%S)'end
iftrarg==nilthenreturnnil,1,false,nilend
iftrarg=='without_sorting'thenreturnnil,2,false,nilend
localtmp=sortfunctions[trarg]
iftmp==nilthenreturnnil,1,false,trargend
returntmpornil,2,true,nil
end
-- Parse optional user arguments of type `...|[let/use]|[...]|[let/use]|[...]|
-- [number of additional parameters]|[parameter 1]|[parameter 2]|[...]`
localfunctionload_child_opts(src,start_from,append_after,params)
localtnamed,tmp1,tmp2
localpin,tbl,mem=start_from,{},{}
whilesrc[pin]~=nilandsrc[pin+1]~=nildo
tmp1=src[pin]:match'^%s*(.*%S)'
iftmp1=='let'andsrc[pin+2]~=nilthen
tmp1=get_param_name(src[pin+1])
tbl[tmp1],pin=src[pin+2],pin+3
--[[
		elseif tmp1 == 'expose' then
			tmp1 = get_param_name(src[pin + 1])
			tmp2 = params[tmp1]
			mem[tmp1], tbl[tmp1], pin = tmp2, tmp2, pin + 2
]]--
elseiftmp1=='use'andsrc[pin+2]~=nilthen
tmp1=get_param_name(src[pin+2])
tmp2=params[tmp1]
mem[tmp1],tbl[get_param_name(src[pin+1])],pin=
tmp2,tmp2,pin+3
elsebreakend
end
localtnew=copy_or_ref_table(params,next(mem)==nil)
forkeyinpairs(mem)dotnew[key]=nilend
ifpin~=start_fromthentnamed,tbl=tbl,{}end
tmp1=tonumber(src[pin])
iftmp1~=nilandmath.floor(tmp1)==tmp1then
iftmp1<0thentmp1=-1end
tmp2=append_after-pin
foridx=pin+1,pin+tmp1dotbl[idx+tmp2]=src[idx]end
pin=pin+tmp1+1
end
iftnamed~=nilthen
forkey,valinpairs(tnamed)dotbl[key]=valend
end
returntbl,pin,tnew,mem
end
-- Load the optional arguments of some of the `mapping_*` and `renaming_*`
-- class of modifiers
localfunctionload_callback_opts(src,start_from,default_style,params)
localstyle,shf
localtmp=src[start_from+1]
iftmp~=nilthenstyle=mapping_styles[tmp:match'^%s*(.-)%s*$']end
ifstyle==nilthenstyle,shf=default_style,start_from-1
elseshf=start_fromend
localn_exist,karg,varg=style[3],style[4],style[5]
tmp=style[6]
iftmp>-1then
karg=src[tmp+shf]:match'^%s*(.-)%s*$'
ifkarg=='0'orkarg:find'^%-?[1-9]%d*$'~=nilthen
karg=tonumber(karg)
n_exist=math.max(n_exist,karg)
end
end
tmp=style[7]
iftmp>-1then
varg=src[tmp+shf]:match'^%s*(.-)%s*$'
ifvarg=='0'orvarg:find'^%-?[1-9]%d*$'~=nilthen
varg=tonumber(varg)
n_exist=math.max(n_exist,varg)
end
end
tmp=style[1]
localdest,argc,tnew,mem=load_child_opts(src,style[2]+shf,
n_exist,params)
if(tmp==3ortmp==2)anddest[karg]~=nilthen
tmp=tmp-2end
if(tmp==3ortmp==1)anddest[varg]~=nilthen
tmp=tmp-1end
returndest,argc,tmp,karg,varg,tnew,mem
end
-- Parse the arguments of some of the `mapping_*` and `renaming_*` class of
-- modifiers
localfunctionload_replace_args(opts,offs,whoami)
ifopts[offs+1]==nilthenerror(modulename..
', ‘'..whoami..'’: No pattern string was given',0)end
ifopts[offs+2]==nilthenerror(modulename..
', ‘'..whoami..'’: No replacement string was given',0)end
localtn,flg
localptn,repl,nmax,argc=
opts[offs+1],opts[offs+2],tonumber(opts[offs+3]),3
ifnmax~=nilthenargc=4
elseifopts[offs+3]~=nilthen
tn=opts[offs+3]:match'^%s*(.*%S)'
iftn==nilthenargc=4end
end
iftn==nilandopts[offs+argc]~=nilthen
tn=opts[offs+argc]:match'^%s*(.*%S)'
end
iftn~=nilthen
flg=mkeywords[tn]
ifflg~=nilthentn=nilend
end
ifflg==0thenflg=nilelseifflg~=nilthenargc=argc+1end
returnptn,repl,nmax,flg,offs+argc,(nmax~=nilandnmax<1)or
(flg==3andptn==repl),tn
end
-- Parse the arguments of the `with_*_matching` class of modifiers
localfunctionload_pattern_args(opts,offs,whoami)
localtn,kwid
localptns,arg,state,nptns,idx={},opts[offs+1],0,0,offs+2
whilearg~=nildo
ifstate==0then
nptns,state=nptns+1,-1
ptns[nptns]={arg,false,false}
else
tn=arg:match'^%s*(.*%S)'
kwid=tnandmkeywords[tn]
ifkwid==nilor(state>0andkwid>0)thenbreak
else
state=kwid
ifstate>1thenptns[nptns][2]=trueend
ifstate==3thenptns[nptns][3]=trueend
end
end
arg,idx=opts[idx],idx+1
end
ifstate==0thenerror(modulename..
', ‘'..whoami..'’: No pattern was given',0)end
returnptns,nptns,idx-1,kwid==nilandtnornil
end
-- Load the optional arguments of the `parsing`, `reinterpreting` and
-- `evaluating` modifiers
localfunctionload_parse_opts(opts,offs,isp,psp)
localtn,tmp
localoptslots,noptslots,argc,trimn,trimu,iplain,pplain=
{true,true,true},3,offs,true,false,true,true
repeat
noptslots,tmp=noptslots-1,opts[argc]
tn=tmpandtmp:match'^%s*(.*%S)'
iftn==nilthenbreakend
ifoptslots[1]~=nilandtrim_parse_opts[tn]~=nilthen
tmp=trim_parse_opts[tn]
trimn,trimu,optslots[1]=tmp[1],tmp[2],nil
elseifoptslots[2]~=nilandisep_parse_opts[tn]~=nilthen
argc=argc+1
iplain,isp,optslots[2]=isep_parse_opts[tn],
opts[argc],nil
elseifoptslots[3]~=nilandpsep_parse_opts[tn]~=nilthen
argc=argc+1
pplain,psp,optslots[3]=psep_parse_opts[tn],
opts[argc],nil
elsebreakend
argc,tn=argc+1,nil
untilnoptslots<1
returnisp,iplain,psp,pplain,trimn,trimu,argc,tn
end
-- Map parameters' values using a custom callback and a referenced table
localvalue_maps={
[0]=function(tbl,margs,karg,varg,fn)
forkeyinpairs(tbl)dotbl[key]=fn()end
end,
[1]=function(tbl,margs,karg,varg,fn)
forkey,valinpairs(tbl)do
margs[varg]=val
tbl[key]=fn()
end
end,
[2]=function(tbl,margs,karg,varg,fn)
forkeyinpairs(tbl)do
margs[karg]=key
tbl[key]=fn()
end
end,
[3]=function(tbl,margs,karg,varg,fn)
forkey,valinpairs(tbl)do
margs[karg],margs[varg]=key,val
tbl[key]=fn()
end
end
}
-- Private table for `map_names()`
localname_thieves={
[0]=function(cache,tbl,rargs,karg,varg,fn)
forkey,valinpairs(tbl)do
steal_if_renamed(val,tbl,key,cache,fn())
end
end,
[1]=function(cache,tbl,rargs,karg,varg,fn)
forkey,valinpairs(tbl)do
rargs[varg]=val
steal_if_renamed(val,tbl,key,cache,fn())
end
end,
[2]=function(cache,tbl,rargs,karg,varg,fn)
forkey,valinpairs(tbl)do
rargs[karg]=key
steal_if_renamed(val,tbl,key,cache,fn())
end
end,
[3]=function(cache,tbl,rargs,karg,varg,fn)
forkey,valinpairs(tbl)do
rargs[karg],rargs[varg]=key,val
steal_if_renamed(val,tbl,key,cache,fn())
end
end
}
-- Map parameters' names using a custom callback and a referenced table
localfunctionmap_names(tbl,rargs,karg,varg,looptype,fn)
localcache={}
name_thieves[looptype](cache,tbl,rargs,karg,varg,fn)
forkey,valinpairs(cache)dotbl[key]=valend
end
-- Return a new table that contains `src` regrouped according to the numeric
-- suffixes in its keys
localfunctionmake_groups(src)
-- NOTE: `src` might be the original metatable!
localprefix,gid
localgroups={}
forkey,valinpairs(src)do
-- `key` must only be a string or a number...
iftype(key)=='string'then
prefix,gid=key:match'^%s*(.-)%s*(%-?%d*)%s*$'
gid=tonumber(gid)or''
elseprefix,gid='',keyend
ifgroups[gid]==nilthengroups[gid]={}end
ifprefix=='0'orprefix:find'^%-?[1-9]%d*$'~=nilthen
prefix=tonumber(prefix)
ifprefix<1thenprefix=prefix-1end
end
groups[gid][prefix]=val
end
returngroups
end
-- Split into parts a string containing the `$#` and `$@` placeholders and
-- return the information as a skeleton table, a canvas table and a length
localfunctionparse_placeholder_string(target)
localskel,canvas,idx,s_pos,e_pos=
{},{},1,1,string.find(target,'%$[@#]',1,false)
whilee_pos~=nildo
canvas[idx],skel[idx+1]=
target:sub(s_pos,e_pos-1),
target:sub(e_pos,e_pos+1)=='$@'
idx,s_pos=idx+2,e_pos+2
e_pos=string.find(target,'%$[@#]',s_pos,false)
end
if(s_pos>target:len())thenidx=idx-1
elsecanvas[idx]=target:sub(s_pos)end
returnskel,canvas,idx
end
-- Populate a table by parsing a parameter string (heavy lifting for `parsing`,
-- `reinterpreting` and `evaluating`)
localfunctionparse_parameter_string(tbl,str,isp,ipl,psp,ppl,trn,tru)
localkey,val,spos1,spos2,pos1,pos2
localpos3,idx,lenplone=0,1,#str+1
ifisp==nilorisp==''then
ifpsp==nilorpsp==''then
iftruthentbl[idx]=str:match'^%s*(.-)%s*$'
elsetbl[idx]=strend
return
end
spos1,spos2=str:find(psp,1,ppl)
ifspos1==nilthen
key=idx
iftruthenval=str:match'^%s*(.-)%s*$'
elseval=strend
else
key=get_param_name(str:sub(1,spos1-1))
val=str:sub(spos2+1)
iftrnthenval=val:match'^%s*(.-)%s*$'end
end
tbl[key]=val
return
end
ifpsp==nilorpsp==''then
repeat
pos1=pos3+1
pos2,pos3=str:find(isp,pos1,ipl)
val=str:sub(pos1,(pos2orlenplone)-1)
iftruthenval=val:match'^%s*(.-)%s*$'end
tbl[idx],idx=val,idx+1
untilpos2==nil
return
end
repeat
pos1=pos3+1
pos2,pos3=str:find(isp,pos1,ipl)
val=str:sub(pos1,(pos2orlenplone)-1)
spos1,spos2=val:find(psp,1,ppl)
ifspos1==nilthen
key=idx
iftruthenval=val:match'^%s*(.-)%s*$'end
idx=idx+1
else
key=get_param_name(val:sub(1,spos1-1))
val=val:sub(spos2+1)
iftrnthenval=val:match'^%s*(.-)%s*$'end
end
tbl[key]=val
untilpos2==nil
return
end
-- Heavy lifting for `snapshotting` and `remembering`
localfunctionmake_child(ctx,src,whoami)
locallen=tonumber(ctx.pipe[ctx.fnpos+1])
iflen==nilorlen==0then
localstack=new_substack(ctx)
forkey,valinpairs(src)dostack[key]=valend
returnlen==niland1or2
end
iflen<0ormath.floor(len)~=lenthenerror(modulename..', ‘'..
whoami..'’: The number of parameters to copy must be an integer greater than zero',0)end
copy_table_maxn(new_substack(ctx),src,len)
return2
end
-- Heavy lifting for `setting_by_flushing`, `combining` and `combining_values`
localfunctionset_strings_from_substack(ctx,dest,whoami)
ifctx.n_children<1thenerror(modulename..
', ‘'..whoami..'’: There are no substacks to flush',0)end
localcurrsnap=ctx.n_children
localstack=ctx.children[currsnap]
forkey,valinpairs(memoryslots)do
ifstack[key]~=nilthendest[val]=stack[key]end
end
ctx.children[currsnap],ctx.n_children=nil,currsnap-1
end
-- Heavy lifting for `combining` and `combining_values`
localfunctioncombine_parameters(ctx,keyval_fn,whoami)
-- NOTE: `ctx.params` might be the original metatable! This function
-- MUST create a copy of it before returning
localopts,offs=ctx.pipe,ctx.fnpos
ifopts[offs+1]==nilthenerror(modulename..
', ‘'..whoami..'’: No parameter name was provided',0)end
localargc
localtbl,vars=ctx.params,{}
localsortfn,ivar0,dosort,tmp=load_sort_opt(opts[offs+2])
ifivar0==2then
tmp=opts[offs+3]~=nilandopts[offs+3]:match'^%s*(.*%S)'
end
ivar0=ivar0+offs
iftmp=='with_flushed_glue'then
ivar0=ivar0+1
argc=set_strings_from_opts(vars,opts,ivar0+1)
set_strings_from_substack(ctx,vars,whoami)
else
iftmp=='without_flushed_glue'thenivar0=ivar0+1end
argc=set_strings_from_opts(vars,opts,ivar0+1)
end
ifargc<ivar0thenerror(modulename..
', ‘'..whoami..'’: No setting directive was given',0)end
ifnext(tbl)==nilthen
ifvars.ifngiven~=nilthenctx.params=
{[get_param_name(opts[offs+1])]=vars.ifngiven}
elseiftbl==ctx.oparamsthenctx.params={}end
returnargc+1
end
localcache,len
ifdosortthen
localwords
cache,words,len,tmp=get_sorted_key_list(tbl,sortfn)
foridx=1,tmpdocache[len+idx]=words[idx]end
len=len+tmp
else
cache,len={},1
forkeyinpairs(tbl)docache[len],len=key,len+1end
len=len-1
end
localpmap,nss,kvs,pps=
{},0,vars.pairsepor'',vars.itersepor''
foridx=1,lendo
tmp,pmap[nss+1]=cache[idx],pps
pmap[nss+2]=keyval_fn(tmp,tbl[tmp],kvs)
nss=nss+2
end
tmp=vars.oxfordseporvars.lastsep
iftmp~=nilandnss>4thenpmap[nss-1]=tmp
elseifnss>2andvars.lastsep~=nilthen
pmap[nss-1]=vars.lastsep
end
pmap[1]=vars.headeror''
ifvars.footer~=nilthenpmap[nss+1]=vars.footerend
ctx.params={[get_param_name(opts[offs+1])]=table.concat(pmap)}
returnargc+1
end
-- Concatenate the numeric keys from the table of parameters to the numeric
-- keys from the table of options; non-numeric keys from the table of options
-- will prevail over colliding non-numeric keys from the table of parameters
localfunctionconcat_params(ctx,offs)
localtbl,retval,cache,nmax=ctx.params,{},{},0
forkey,valinpairs(ctx.pipe)do
iftype(key)=='number'then
ifkey<1thencache[key]=val
elseifkey>offsthencache[key-offs]=valend
ifkey>nmaxthennmax=keyend
elsecache[key]=valend
end
nmax=nmax-offs
ifctx.subset==1then
-- We need only the sequence
forkey,valinipairs(tbl)doretval[key+nmax]=valend
else
ifctx.subset==-1then
forkeyinipairs(tbl)dotbl[key]=nilend
end
forkey,valinpairs(tbl)do
iftype(key)=='number'andkey>0then
retval[key+nmax]=val
elseretval[key]=valend
end
end
forkey,valinpairs(cache)doretval[key]=valend
returnretval
end
-- Flush the parameters by calling a custom function for each value (after this
-- function has been invoked `ctx.params` will be no longer usable)
localfunctionflush_params(ctx,fn)
localtmp
localtbl=ctx.params
ifctx.subset==-1then
forkey,valinipairs(tbl)dotbl[key]=nilend
elseifctx.subset==1then
ifctx.pins==nilthen
forkey,valinipairs(tbl)dofn(key,val)end
return
end
tmp={}
forkey,valinipairs(tbl)dotmp[key]=valend
tbl=tmp
end
ifctx.pins~=nilthen
localmarker=ctx.sorttype<1andctx.subset~=-1ornil
foridx=1,#ctx.pinsdo
tmp=ctx.pins[idx]
iftbl[tmp]~=nilthen
fn(tmp,tbl[tmp])
tbl[tmp]=marker
end
end
ifctx.subset==1then
forkey,valinipairs(tbl)do
ifval~=truethenfn(key,val)end
end
return
end
end
ifctx.sorttype>0then
localnums,words,nn,nw=
get_sorted_key_list(tbl,natural_sort)
ifctx.sorttype==2then
foridx=1,nwdofn(words[idx],tbl[words[idx]])end
foridx=1,nndofn(nums[idx],tbl[nums[idx]])end
return
end
foridx=1,nndofn(nums[idx],tbl[nums[idx]])end
foridx=1,nwdofn(words[idx],tbl[words[idx]])end
return
end
ifctx.subset==-1orctx.pins==nilthen
forkey,valinipairs(tbl)do
fn(key,val)
tbl[key]=nil
end
forkey,valinpairs(tbl)dofn(key,val)end
return
end
forkey,valinipairs(tbl)do
ifval~=truethenfn(key,val)end
tbl[key]=nil
end
forkey,valinpairs(tbl)do
ifval~=truethenfn(key,val)end
end
end
-- Flush the parameters by calling one of two custom functions for each value
-- (after this function has been invoked `ctx.params` will be no longer usable)
localfunctionmixed_flush_params(ctx,fn_seq,fn_oth)
ifctx.subset==1then
flush_params(ctx,fn_seq)
return
end
ifctx.subset==-1then
flush_params(ctx,fn_oth)
return
end
localtbl=ctx.params
ifctx.pins==nilandctx.sorttype<1then
forkey,valinipairs(tbl)do
fn_seq(key,val)
tbl[key]=nil
end
forkey,valinpairs(tbl)dofn_oth(key,val)end
return
end
localtseq={}
forkey,valinipairs(tbl)dotseq[key]=valend
ifctx.pins~=nilthen
localtmp
localmarker=ctx.sorttype<1ornil
foridx=1,#ctx.pinsdo
tmp=ctx.pins[idx]
iftseq[tmp]~=nilthen
fn_seq(tmp,tbl[tmp])
tbl[tmp],tseq[tmp]=nil,marker
elseiftbl[tmp]~=nilthen
fn_oth(tmp,tbl[tmp])
tbl[tmp]=nil
end
end
end
ifctx.sorttype>0then
localnums,words,nn,nw=
get_sorted_key_list(tbl,natural_sort)
ifctx.sorttype==2then
foridx=1,nwdo
fn_oth(words[idx],tbl[words[idx]])
end
end
foridx=1,nndo
iftseq[nums[idx]]~=nilthen
fn_seq(nums[idx],tseq[nums[idx]])
elsefn_oth(nums[idx],tbl[nums[idx]])end
end
ifctx.sorttype~=2then
foridx=1,nwdo
fn_oth(words[idx],tbl[words[idx]])
end
end
return
end
forkey,valinipairs(tseq)do
ifval~=truethen
fn_seq(key,val)
tbl[key]=nil
end
end
forkey,valinpairs(tbl)dofn_oth(key,val)end
end
-- Finalize and return a concatenated list
localfunctionfinalize_and_return_concatenated_list(ctx,lst,len,modsize)
iflen>0then
localtmp=ctx.oxfordseporctx.lastsep
iftmp~=nilandlen>modsize*2then
lst[len-modsize+1]=tmp
elseiflen>modsizeandctx.lastsep~=nilthen
lst[len-modsize+1]=ctx.lastsep
end
lst[1]=ctx.headeror''
ifctx.footer~=nilthenlst[len+1]=ctx.footerend
ctx.text=table.concat(lst)
elsectx.text=ctx.ifngivenor''end
end
---                                        ---
---     PUBLIC ENVIRONMENT                 ---
---    ________________________________    ---
---                                        ---
--[[ Modifiers ]]--
-------------------
-- Syntax:  #invoke:params|sequential|pipe to
library.sequential=function(ctx)
ifctx.subset==1thenerror(modulename..
': The ‘sequential’ directive has been provided more than once',0)end
ifctx.subset==-1thenerror(modulename..
': The two directives ‘non-sequential’ and ‘sequential’ are in contradiction with each other',0)end
ifctx.sorttype>0thenerror(modulename..
': The ‘all_sorted’ and ‘reassorted’ directives are redundant when followed by ‘sequential’',0)end
ctx.iterfunc,ctx.subset=ipairs,1
returncontext_iterate(ctx,ctx.fnpos+1)
end
-- Syntax:  #invoke:params|non-sequential|pipe to
library['non-sequential']=function(ctx)
ifctx.subset==-1thenerror(modulename..
': The ‘non-sequential’ directive has been provided more than once',0)end
ifctx.subset==1thenerror(modulename..
': The two directives ‘sequential’ and ‘non-sequential’ are in contradiction with each other',0)end
ctx.iterfunc,ctx.subset=pairs,-1
returncontext_iterate(ctx,ctx.fnpos+1)
end
-- Syntax:  #invoke:params|all_sorted|pipe to
library.all_sorted=function(ctx)
ifctx.sorttype==1thenerror(modulename..
': The ‘all_sorted’ directive has been provided more than once',0)end
ifctx.subset==1thenerror(modulename..
': The ‘all_sorted’ directive is redundant after ‘sequential’',0)end
ifctx.sorttype==2thenerror(modulename..
': The two directives ‘reassorted’ and ‘sequential’ are in contradiction with each other',0)end
ctx.sorttype=1
returncontext_iterate(ctx,ctx.fnpos+1)
end
-- Syntax:  #invoke:params|reassorted|pipe to
library.reassorted=function(ctx)
ifctx.sorttype==2thenerror(modulename..
': The ‘reassorted’ directive has been provided more than once',0)end
ifctx.subset==1thenerror(modulename..
': The ‘reassorted’ directive is redundant after ‘sequential’',0)end
ifctx.sorttype==1thenerror(modulename..
': The two directives ‘sequential’ and ‘reassorted’ are in contradiction with each other',0)end
ctx.sorttype=2
returncontext_iterate(ctx,ctx.fnpos+1)
end
-- Syntax:  #invoke:params|pinned_until|sentinel|[parameter name 1]|[parameter
--            name 2]|...|parameter name N|sentinel|pipe to
library.pinned_until=function(ctx)
localopts,offs=ctx.pipe,ctx.fnpos
ifopts[offs+1]==nilthenerror(modulename..
', ‘pinned_until’: No sentinel was provided',0)end
localtmp,bucket,curr,ncurr
localsntl,idx=opts[offs+1]:match'^%s*(.-)%s*$',2
ifctx.pin_bucket==nilthen
bucket,curr,ncurr={},{},0
ctx.pin_bucket,ctx.pins=bucket,curr
elsebucket,curr,ncurr=ctx.pin_bucket,ctx.pins,ctx.npinsend
whileopts[offs+idx]~=nildo
tmp=opts[offs+idx]:match'^%s*(.-)%s*$'
iftmp==sntlthen
ifidx==2thenerror(modulename..
', ‘pinned_until’: No parameters to pin were provided',0)end
ctx.npins=ncurr+idx-2
returncontext_iterate(ctx,offs+idx+1)
end
iftmp=='0'ortmp:find'^%-?[1-9]%d*$'~=nilthen
tmp=tonumber(tmp)
end
ifbucket[tmp]thenerror(modulename..
', ‘pinned_until’: Duplicate pinned parameter ‘'..tostring(tmp)..'’',0)end
curr[ncurr+idx-1],bucket[tmp],idx=tmp,true,idx+1
end
error(modulename..', ‘pinned_until’: Missing sentinel in position #'..tostring(idx),0)
end
-- Syntax:  #invoke:params|setting|directives|...|pipe to
library.setting=function(ctx)
localnew_offs=set_strings_from_opts(ctx,ctx.pipe,ctx.fnpos+1)
ifnew_offs-ctx.fnpos<2thenerror(modulename..
', ‘setting’: No directive was given',0)end
returncontext_iterate(ctx,new_offs+1)
end
-- Syntax:  #invoke:params|scoring|new parameter name|[container]|pipe to
library.scoring=function(ctx)
localopts,offs,retval=ctx.pipe,ctx.fnpos,0
ifopts[offs+1]==nilthenerror(modulename..
', ‘scoring’: No parameter name was provided',0)end
for_inpairs(ctx.params)doretval=retval+1end
localtn=opts[offs+2]andopts[offs+2]:match'^%s*(.*%S)'
iftn=='in_substack'then
new_substack(ctx)[get_param_name(opts[offs+1])]=
tostring(retval)
returncontext_iterate(ctx,offs+3)
end
ctx.params[get_param_name(opts[offs+1])]=tostring(retval)
returntn=='here'andcontext_iterate(ctx,offs+3)or
context_iterate(ctx,offs+2,tn)
end
-- Syntax:  #invoke:params|squeezing|pipe to
library.squeezing=function(ctx)
localstore,indices,tbl,newlen={},{},ctx.params,0
forkey,valinpairs(tbl)do
iftype(key)=='number'then
newlen=newlen+1
indices[newlen],store[key],tbl[key]=key,val,nil
end
end
table.sort(indices)
foridx=1,newlendotbl[idx]=store[indices[idx]]end
returncontext_iterate(ctx,ctx.fnpos+1)
end
-- Syntax:  #invoke:params|filling_the_gaps|pipe to
library.filling_the_gaps=function(ctx)
localnewval,tbl,tmp,nmin,nmax,nnums=
ctx.pipe[ctx.fnpos+1],ctx.params,{},1,nil,-1
ifnewval==nilthenerror(modulename..
', ‘filling_the_gaps’: No value was provided',0)end
forkey,valinpairs(tbl)do
iftype(key)=='number'then
ifnmax==nilthen
ifkey<nminthennmin=keyend
nmax=key
elseifkey>nmaxthennmax=key
elseifkey<nminthennmin=keyend
tmp[key],nnums=val,nnums+1
end
end
ifnmax~=nilandnmax-nmin>nnumsthen
ctx.n_available=ctx.n_available+nmin+nnums-nmax
ifctx.n_available<0thenerror(modulename..
', ‘filling_the_gaps’: It is possible to fill at most '..tostring(maxfill)..' parameters',0)end
foridx=nmin,nmaxdotbl[idx]=newvalend
forkey,valinpairs(tmp)dotbl[key]=valend
end
returncontext_iterate(ctx,ctx.fnpos+2)
end
-- Syntax:  #invoke:params|clearing|pipe to
library.clearing=function(ctx)
localtbl,numerics=ctx.params,{}
forkey,valinpairs(tbl)do
iftype(key)=='number'then
numerics[key],tbl[key]=val,nil
end
end
forkey,valinipairs(numerics)dotbl[key]=valend
returncontext_iterate(ctx,ctx.fnpos+1)
end
-- Syntax:  #invoke:params|cutting|left cut|right cut|pipe to
library.cutting=function(ctx)
localopts,offs=ctx.pipe,ctx.fnpos
locallcut=tonumber(opts[offs+1])
iflcut==nilormath.floor(lcut)~=lcutthenerror(modulename..
', ‘cutting’: Left cut must be an integer number',0)end
localrcut=tonumber(opts[offs+2])
ifrcut==nilormath.floor(rcut)~=rcutthenerror(modulename..
', ‘cutting’: Right cut must be an integer number',0)end
localtbl=ctx.params
locallen=#tbl
iflcut<0thenlcut=len+lcutend
ifrcut<0thenrcut=len+rcutend
localtot=lcut+rcut
iftot>0then
localcache={}
iftot>=lenthen
forkeyinipairs(tbl)dotbl[key]=nilend
tot=len
else
foridx=len-rcut+1,lendotbl[idx]=nilend
foridx=1,lcutdotbl[idx]=nilend
end
forkey,valinpairs(tbl)do
iftype(key)=='number'andkey>0then
ifkey>lenthencache[key-tot]=val
elsecache[key-lcut]=valend
tbl[key]=nil
end
end
forkey,valinpairs(cache)dotbl[key]=valend
end
returncontext_iterate(ctx,offs+3)
end
-- Syntax:  #invoke:params|cropping|left crop|right crop|pipe to
library.cropping=function(ctx)
localopts,offs=ctx.pipe,ctx.fnpos
locallcut=tonumber(opts[offs+1])
iflcut==nilormath.floor(lcut)~=lcutthenerror(modulename..
', ‘cropping’: Left crop must be an integer number',0)end
localrcut=tonumber(opts[offs+2])
ifrcut==nilormath.floor(rcut)~=rcutthenerror(modulename..
', ‘cropping’: Right crop must be an integer number',0)end
localtbl=ctx.params
localnmin,nmax
forkeyinpairs(tbl)do
iftype(key)=='number'then
ifnmin==nilthennmin,nmax=key,key
elseifkey>nmaxthennmax=key
elseifkey<nminthennmin=keyend
end
end
ifnmin~=nilthen
locallen=nmax-nmin+1
iflcut<0thenlcut=len+lcutend
ifrcut<0thenrcut=len+rcutend
iflcut+rcut-len>-1then
forkeyinpairs(tbl)do
iftype(key)=='number'thentbl[key]=nilend
end
elseiflcut+rcut>0then
foridx=nmax-rcut+1,nmaxdotbl[idx]=nilend
foridx=nmin,nmin+lcut-1dotbl[idx]=nilend
locallshift=nmin+lcut-1
iflshift>0then
foridx=lshift+1,nmaxdo
tbl[idx-lshift],tbl[idx]=
tbl[idx],nil
end
end
end
end
returncontext_iterate(ctx,offs+3)
end
-- Syntax:  #invoke:params|purging|start offset|length|pipe to
library.purging=function(ctx)
localopts,offs=ctx.pipe,ctx.fnpos
localidx=tonumber(opts[offs+1])
ifidx==nilormath.floor(idx)~=idxthenerror(modulename..
', ‘purging’: Start offset must be an integer number',0)end
locallen=tonumber(opts[offs+2])
iflen==nilormath.floor(len)~=lenthenerror(modulename..
', ‘purging’: Length must be an integer number',0)end
localtbl=ctx.params
iflen<1then
len=len+table.maxn(tbl)
ifidx>lenthenreturncontext_iterate(ctx,offs+3)end
len=len-idx+1
end
ctx.params=copy_table_reduced(tbl,idx,len)
returncontext_iterate(ctx,offs+3)
end
-- Syntax:  #invoke:params|backpurging|start offset|length|pipe to
library.backpurging=function(ctx)
localopts,offs=ctx.pipe,ctx.fnpos
locallast=tonumber(opts[offs+1])
iflast==nilormath.floor(last)~=lastthenerror(modulename..
', ‘backpurging’: Start offset must be an integer number',0)end
locallen=tonumber(opts[offs+2])
iflen==nilormath.floor(len)~=lenthenerror(modulename..
', ‘backpurging’: Length must be an integer number',0)end
localidx
localtbl=ctx.params
iflen>0thenidx=last-len+1
else
forkeyinpairs(tbl)do
iftype(key)=='number'and(idx==nilor
key<idx)thenidx=keyend
end
ifidx==nilthenreturncontext_iterate(ctx,offs+3)end
idx=idx-len
iflast<idxthenreturncontext_iterate(ctx,offs+3)end
len=last-idx+1
end
ctx.params=copy_table_reduced(ctx.params,idx,len)
returncontext_iterate(ctx,offs+3)
end
-- Syntax:  #invoke:params|shifting|addend|pipe to
library.shifting=function(ctx)
-- NOTE: `ctx.params` might be the original metatable! As a modifier,
-- this function MUST create a copy of it before returning
localnshift=tonumber(ctx.pipe[ctx.fnpos+1])
ifnshift==nilornshift==0ormath.floor(nshift)~=nshiftthen
error(modulename..', ‘shifting’: A non-zero integer number must be provided',0)end
localtbl={}
forkey,valinpairs(ctx.params)do
iftype(key)=='number'thentbl[key+nshift]=val
elsetbl[key]=valend
end
ctx.params=tbl
returncontext_iterate(ctx,ctx.fnpos+2)
end
-- Syntax:  #invoke:params|reversing_numeric_names|pipe to
library.reversing_numeric_names=function(ctx)
localtbl,numerics,nmax=ctx.params,{},0
forkey,valinpairs(tbl)do
iftype(key)=='number'then
numerics[key],tbl[key]=val,nil
ifkey>nmaxthennmax=keyend
end
end
forkey,valinpairs(numerics)dotbl[nmax-key+1]=valend
returncontext_iterate(ctx,ctx.fnpos+1)
end
-- Syntax:  #invoke:params|pivoting_numeric_names|pipe to
--[[
library.pivoting_numeric_names = function (ctx)
	local tbl = ctx.params
	local shift = #tbl + 1
	if shift < 2 then return library.reversing_numeric_names(ctx) end
	local tmp = {}
	for key, val in pairs(tbl) do
		if type(key) == 'number' then tmp[key], tbl[key] = val, nil end
	end
	for key, val in pairs(tmp) do tbl[shift - key] = val end
	return context_iterate(ctx, ctx.fnpos + 1)
end
]]--
-- Syntax:  #invoke:params|mirroring_numeric_names|pipe to
--[[
library.mirroring_numeric_names = function (ctx)
	local nmax, nmin
	local tbl, tmp = ctx.params, {}
	for key, val in pairs(tbl) do
		if type(key) == 'number' then
			tmp[key], tbl[key] = val, nil
			if nmax == nil then nmin, nmax = key, key
			elseif key > nmax then nmax = key
			elseif key < nmin then nmin = key end
		end
	end
	for key, val in pairs(tmp) do tbl[nmax + nmin - key] = val end
	return context_iterate(ctx, ctx.fnpos + 1)
end
]]--
-- Syntax:  #invoke:params|swapping_numeric_names|pipe to
--[[
library.swapping_numeric_names = function (ctx)
	local tmp
	local tbl, cache, nsize = ctx.params, {}, 1
	for key in pairs(tbl) do
		if type(key) == 'number' then
			cache[nsize], nsize = key, nsize + 1
		end
	end
	table.sort(cache)
	for idx = math.floor((nsize - 1) / 2), 1, -1 do
		tmp = tbl[cache[idx] ]
		tbl[cache[idx] ] = tbl[cache[nsize - idx] ]
		tbl[cache[nsize - idx] ] = tmp
	end
	return context_iterate(ctx, ctx.fnpos + 1)
end
]]--
-- Syntax:  #invoke:params|sorting_sequential_values|[criterion]|pipe to
library.sorting_sequential_values=function(ctx)
localsortfn
localopts,offs=ctx.pipe,ctx.fnpos
localtn=opts[offs+1]andopts[offs+1]:match'^%s*(.*%S)'
iftn~=nilthensortfn=sortfunctions[tn]end
ifsortfnthentable.sort(ctx.params,sortfn)
elsetable.sort(ctx.params)end-- i.e. either `false` or `nil`
ifsortfn==nilthenreturncontext_iterate(ctx,offs+1,tn)end
returncontext_iterate(ctx,offs+2)
end
-- Syntax:  #invoke:params|splicing|[add to position]|position|increment|
--            [number of elements to write]|...|pipe to
library.splicing=function(ctx)
-- NOTE: `ctx.params` might be the original metatable! As a modifier,
-- this function MUST create a copy of it before returning
localtmp2,argc,pos,refp
localtbl,opts,offs=ctx.params,ctx.pipe,ctx.fnpos
localtmp1=opts[offs+1]
iftmp1~=nilthen
tmp2=tonumber(tmp1)
iftmp2==nilormath.floor(tmp2)~=tmp2then
pos,argc,tmp2=tonumber(opts[offs+2]),offs+4,
tmp1:match'^%s*(.*%S)'
iftmp2~=nilthen
refp=position_references[tmp2]
ifrefp==nilthenerror(modulename..
', ‘splicing’: ‘'..tostring(tmp2)..'’ is not a valid first argument',0)end
elserefp=0end
elsepos,argc,refp=tmp2,offs+3,0end
elsepos,argc,refp=tonumber(opts[offs+2]),offs+4,0end
ifpos==nilormath.floor(pos)~=posthenerror(modulename..
', ‘splicing’: The position must be an integer number',0)end
locallen=tonumber(opts[argc-1])
iflen==nilormath.floor(len)~=lenthenerror(modulename..
', ‘splicing’: The increment must be an integer number',0)end
localinsn=tonumber(opts[argc])
iflen==0and(insn==nilorinsn<1)thenerror(modulename..
', ‘splicing’: When the increment is zero the number of elements to write cannot be zero',0)end
ifrefp==2then
for_inipairs(tbl)dopos=pos+1end
refp=0
end
tmp1,tmp2=nil,nil
ifrefp~=0orlen~=0then
forkey,valinpairs(tbl)do
iftype(key)=='number'then
iftmp1==nilthentmp1,tmp2=key,key
elseifkey<tmp1thentmp1=key
elseifkey>tmp2thentmp2=keyend
end
end
end
iftmp2==nilthenlen=0
elseifrefp==3thenpos=pos+tmp2
elseifrefp==1thenpos=pos+tmp1end
iflen>0andpos+len>tmp1andpos<=tmp2then
tbl=copy_table_expanded(tbl,pos,len)
elseiflen<0andpos-len>tmp1andpos<=tmp2then
tbl=copy_table_reduced(tbl,pos,-len)
elsetbl=copy_or_ref_table(tbl,tbl~=ctx.oparams)end
ctx.params=tbl
ifinsn==nilorinsn<0ormath.floor(insn)~=insnthen
returncontext_iterate(ctx,argc)
end
tmp1=argc-offs-pos+1
forkey=pos,pos+insn-1dotbl[key]=opts[offs+key+tmp1]end
returncontext_iterate(ctx,argc+insn+1)
end
-- Syntax:  #invoke:params|imposing|name|value|pipe to
library.imposing=function(ctx)
localopts,offs=ctx.pipe,ctx.fnpos
ifopts[offs+1]==nilthenerror(modulename..
', ‘imposing’: Missing parameter name to impose',0)end
ctx.params[get_param_name(opts[offs+1])]=opts[offs+2]
returncontext_iterate(ctx,offs+3)
end
-- Syntax:  #invoke:params|providing|name|value|pipe to
library.providing=function(ctx)
localopts,offs=ctx.pipe,ctx.fnpos
ifopts[offs+1]==nilthenerror(modulename..
', ‘providing’: Missing parameter name to provide',0)end
localkey=get_param_name(opts[offs+1])
ifctx.params[key]==nilthenctx.params[key]=opts[offs+2]end
returncontext_iterate(ctx,offs+3)
end
-- Syntax:  #invoke:params|reassigning|source|destination|[mode]|pipe to
library.reassigning=function(ctx)
localtbl,opts,offs=ctx.params,ctx.pipe,ctx.fnpos
ifopts[offs+1]==nilthenerror(modulename..
', ‘reassigning’: Missing source parameter',0)end
ifopts[offs+2]==nilthenerror(modulename..
', ‘reassigning’: Missing destination parameter',0)end
localmode,argc
localsrc,tn=get_param_name(opts[offs+1]),
opts[offs+3]~=nilandopts[offs+3]:match'^%s*(.*%S)'
localval=tbl[src]
iftn~=nilthenmode=a_modes[tn]end
ifmode==nilthenmode,argc=0,offs+3
elseargc,tn=offs+4,nilend
ifval==nilandmode>1then
returncontext_iterate(ctx,argc,tn)
end
localdest=get_param_name(opts[offs+2])
localtmp=tbl[dest]==nil
ifmode%2==0or(mode==7andtmp)thentbl[src]=nilend
iftmpormode<4thentbl[dest]=valend
returncontext_iterate(ctx,argc,tn)
end
-- Syntax:  #invoke:params|discarding|name|[how many]|pipe to
library.discarding=function(ctx)
localopts,offs=ctx.pipe,ctx.fnpos
ifopts[offs+1]==nilthenerror(modulename..
', ‘discarding’: Missing parameter name to discard',0)end
locallen=tonumber(opts[offs+2])
iflen==nilthen
ctx.params[get_param_name(opts[offs+1])]=nil
returncontext_iterate(ctx,offs+2)
end
localkey=tonumber(opts[offs+1])
ifkey==nilormath.floor(key)~=keythenerror(modulename..
', ‘discarding’: A range was provided, but the initial parameter name is not an integer number',0)end
iflen<1ormath.floor(len)~=lenthenerror(modulename..
', ‘discarding’: A range can only be an integer number greater than zero',0)end
foridx=key,key+len-1doctx.params[idx]=nilend
returncontext_iterate(ctx,offs+3)
end
-- Syntax:  #invoke:params|excluding_non-numeric_names|pipe to
library['excluding_non-numeric_names']=function(ctx)
localtmp=ctx.params
forkey,valinpairs(tmp)do
iftype(key)~='number'thentmp[key]=nilend
end
returncontext_iterate(ctx,ctx.fnpos+1)
end
-- Syntax:  #invoke:params|excluding_numeric_names|pipe to
library.excluding_numeric_names=function(ctx)
localtmp=ctx.params
forkey,valinpairs(tmp)do
iftype(key)=='number'thentmp[key]=nilend
end
returncontext_iterate(ctx,ctx.fnpos+1)
end
-- Syntax:  #invoke:params|with_name_matching|target 1|[plain flag 1]|[or]|
--            [target 2]|[plain flag 2]|[or]|[...]|[target N]|[plain flag
--            N]|pipe to
library.with_name_matching=function(ctx)
-- NOTE: `ctx.params` might be the original metatable! As a modifier,
-- this function MUST create a copy of it before returning
localtmp,ptn
localtbl,newparams,opts,offs=ctx.params,{},ctx.pipe,ctx.fnpos
localtargets,nptns,argc,tn=load_pattern_args(opts,offs,
'with_name_matching')
foridx=1,nptnsdo
ptn=targets[idx]
ifptn[3]then
tmp=ptn[1]
iftmp=='0'ortmp:find'^%-?[1-9]%d*$'~=nilthen
tmp=tonumber(tmp)
end
newparams[tmp]=tbl[tmp]
else
forkey,valinpairs(tbl)do
iftostring(key):find(ptn[1],1,ptn[2])then
newparams[key]=val
end
end
end
end
ctx.params=newparams
returncontext_iterate(ctx,argc,tn)
end
-- Syntax:  #invoke:params|with_name_not_matching|target 1|[plain flag 1]|
--            [and]|[target 2]|[plain flag 2]|[and]|[...]|[target N]|[plain
--            flag N]|pipe to
library.with_name_not_matching=function(ctx)
localtbl,opts,offs=ctx.params,ctx.pipe,ctx.fnpos
localtargets,nptns,argc,tn=load_pattern_args(opts,offs,
'with_name_not_matching')
ifnptns==1andtargets[1][3]then
localtmp=targets[1][1]
iftmp=='0'ortmp:find'^%-?[1-9]%d*$'~=nilthen
tbl[tonumber(tmp)]=nil
elsetbl[tmp]=nilend
returncontext_iterate(ctx,argc,tn)
end
localyesmatch,ptn
forkeyinpairs(tbl)do
yesmatch=true
foridx=1,nptnsdo
ptn=targets[idx]
ifptn[3]then
iftostring(key)~=ptn[1]then
yesmatch=false
break
end
elseifnottostring(key):find(ptn[1],1,ptn[2])then
yesmatch=false
break
end
end
ifyesmatchthentbl[key]=nilend
end
returncontext_iterate(ctx,argc,tn)
end
-- Syntax:  #invoke:params|with_value_matching|target 1|[plain flag 1]|[or]|
--            [target 2]|[plain flag 2]|[or]|[...]|[target N]|[plain flag
--            N]|pipe to
library.with_value_matching=function(ctx)
localnomatch,ptn
localtbl,opts,offs=ctx.params,ctx.pipe,ctx.fnpos
localtargets,nptns,argc,tn=load_pattern_args(opts,offs,
'with_value_matching')
forkey,valinpairs(tbl)do
nomatch=true
foridx=1,nptnsdo
ptn=targets[idx]
ifptn[3]then
ifval==ptn[1]then
nomatch=false
break
end
elseifval:find(ptn[1],1,ptn[2])then
nomatch=false
break
end
end
ifnomatchthentbl[key]=nilend
end
returncontext_iterate(ctx,argc,tn)
end
-- Syntax:  #invoke:params|with_value_not_matching|target 1|[plain flag 1]|
--            [and]|[target 2]|[plain flag 2]|[and]|[...]|[target N]|[plain
--            flag N]|pipe to
library.with_value_not_matching=function(ctx)
localyesmatch,ptn
localtbl,opts,offs=ctx.params,ctx.pipe,ctx.fnpos
localtargets,nptns,argc,tn=load_pattern_args(opts,offs,
'with_value_not_matching')
forkey,valinpairs(tbl)do
yesmatch=true
foridx=1,nptnsdo
ptn=targets[idx]
ifptn[3]then
ifval~=ptn[1]then
yesmatch=false
break
end
elseifnotval:find(ptn[1],1,ptn[2])then
yesmatch=false
break
end
end
ifyesmatchthentbl[key]=nilend
end
returncontext_iterate(ctx,argc,tn)
end
-- Syntax:  #invoke:params|keeping_at_most|number of parameters to pick|pipe to
library.keeping_at_most=function(ctx)
-- NOTE: `ctx.params` might be the original metatable! As a modifier,
-- this function MUST create a copy of it before returning
locallen=tonumber(ctx.pipe[ctx.fnpos+1])
iflen==nilorlen<1ormath.floor(len)~=lenthenerror(modulename..
', ‘keeping_at_most’: The number of parameters to keep must be an integer greater than zero',0)end
ctx.params=copy_table_maxn({},ctx.params,len)
returncontext_iterate(ctx,ctx.fnpos+2)
end
-- Syntax:  #invoke:params|trimming_values|pipe to
library.trimming_values=function(ctx)
localtbl=ctx.params
forkey,valinpairs(tbl)dotbl[key]=val:match'^%s*(.-)%s*$'end
returncontext_iterate(ctx,ctx.fnpos+1)
end
-- Syntax:  #invoke:params|mapping_to_lowercase|pipe to
library.mapping_to_lowercase=function(ctx)
localtbl=ctx.params
forkey,valinpairs(tbl)dotbl[key]=val:lower()end
returncontext_iterate(ctx,ctx.fnpos+1)
end
-- Syntax:  #invoke:params|mapping_to_uppercase|pipe to
library.mapping_to_uppercase=function(ctx)
localtbl=ctx.params
forkey,valinpairs(tbl)dotbl[key]=val:upper()end
returncontext_iterate(ctx,ctx.fnpos+1)
end
-- Syntax:  #invoke:params|mapping_by_calling|template name|[call
--            style]|[let/use]|[...]|[let/use]|[...]|[number of additional
--            parameters]|[parameter 1]|[parameter 2]|[...]|[parameter N]|pipe to
library.mapping_by_calling=function(ctx)
localopts,offs=ctx.pipe,ctx.fnpos
localtname=opts[offs+1]andopts[offs+1]:match'^%s*(.*%S)'
iftname==nilthenerror(modulename..
', ‘mapping_by_calling’: No template name was provided',0)end
localmargs,argc,looptype,karg,varg,tbl,mem=
load_callback_opts(opts,offs+1,mapping_styles.values_only,
ctx.params)
localmodel={title=tname,args=margs}
value_maps[looptype](tbl,margs,karg,varg,function()
returnctx.frame:expandTemplate(model)
end)
forkey,valinpairs(mem)dotbl[key]=valend
ctx.params=tbl
returncontext_iterate(ctx,argc)
end
-- Syntax:  #invoke:params|mapping_by_invoking|module name|function name|[call
--            style]|[let/use]|[...]|[let/use]|[...]|[number of additional
--            arguments]|[argument 1]|[argument 2]|[...]|[argument N]|pipe to
library.mapping_by_invoking=function(ctx)
localopts,offs=ctx.pipe,ctx.fnpos
localmname=opts[offs+1]andopts[offs+1]:match'^%s*(.*%S)'
ifmname==nilthenerror(modulename..
', ‘mapping_by_invoking’: No module name was provided',0)end
localfname=opts[offs+2]andopts[offs+2]:match'^%s*(.*%S)'
iffname==nilthenerror(modulename..
', ‘mapping_by_invoking’: No function name was provided',0)end
localmargs,argc,looptype,karg,varg,tbl,mem=
load_callback_opts(opts,offs+2,mapping_styles.values_only,
ctx.params)
localmodel={title='Module:'..mname,args=margs}
localmfunc=require(model.title)[fname]
ifmfunc==nilthenerror(modulename..
', ‘mapping_by_invoking’: The function ‘'..fname..'’ does not exist',0)end
value_maps[looptype](tbl,margs,karg,varg,function()
returntostring(mfunc(ctx.frame:newChild(model)))
end)
forkey,valinpairs(mem)dotbl[key]=valend
ctx.params=tbl
returncontext_iterate(ctx,argc)
end
-- Syntax:  #invoke:params|mapping_by_magic|parser function|[call
--            style]|[let/use]|[...]|[let/use]|[...]|[number of additional
--            arguments]|[argument 1]|[argument 2]|[...]|[argument N]|pipe to
library.mapping_by_magic=function(ctx)
localopts,offs=ctx.pipe,ctx.fnpos
localmagic=opts[offs+1]andopts[offs+1]:match'^%s*(.*%S)'
ifmagic==nilthenerror(modulename..
', ‘mapping_by_magic’: No parser function was provided',0)end
localmargs,argc,looptype,karg,varg,tbl,mem=
load_callback_opts(opts,offs+1,mapping_styles.values_only,
ctx.params)
value_maps[looptype](tbl,margs,karg,varg,function()
returnctx.frame:callParserFunction(magic,margs)
end)
forkey,valinpairs(mem)dotbl[key]=valend
ctx.params=tbl
returncontext_iterate(ctx,argc)
end
-- Syntax:  #invoke:params|mapping_by_replacing|target|replace|[count]|[plain
--            flag]|pipe to
library.mapping_by_replacing=function(ctx)
localptn,repl,nmax,flg,argc,die,tn=
load_replace_args(ctx.pipe,ctx.fnpos,'mapping_by_replacing')
ifdiethenreturncontext_iterate(ctx,argc,tn)end
localtbl=ctx.params
ifflg==3then
forkey,valinpairs(tbl)do
ifval==ptnthentbl[key]=replend
end
else
ifflg==2then
-- Copied from Module:String's `str._escapePattern()`
ptn=ptn:gsub('[%(%)%.%%%+%-%*%?%[%^%$%]]','%%%0')
end
forkey,valinpairs(tbl)do
tbl[key]=val:gsub(ptn,repl,nmax)
end
end
returncontext_iterate(ctx,argc,tn)
end
-- Syntax:  #invoke:params|mapping_by_mixing|mixing string|pipe to
library.mapping_by_mixing=function(ctx)
localopts,offs=ctx.pipe,ctx.fnpos
ifopts[offs+1]==nilthenerror(modulename..
', ‘mapping_by_mixing’: No mixing string was provided',0)end
localtbl,mix=ctx.params,opts[offs+1]
ifmix=='$#'then
forkeyinpairs(tbl)dotbl[key]=tostring(key)end
returncontext_iterate(ctx,offs+2)
end
localskel,cnv,n_parts=parse_placeholder_string(mix)
forkey,valinpairs(tbl)do
foridx=2,n_parts,2do
ifskel[idx]thencnv[idx]=val
elsecnv[idx]=tostring(key)end
end
tbl[key]=table.concat(cnv)
end
returncontext_iterate(ctx,offs+2)
end
-- Syntax:  #invoke:params|renaming_to_lowercase|pipe to
library.renaming_to_lowercase=function(ctx)
-- NOTE: `ctx.params` might be the original metatable! As a modifier,
-- this function MUST create a copy of it before returning
localcache={}
forkey,valinpairs(ctx.params)do
iftype(key)=='string'thencache[key:lower()]=valelse
cache[key]=valend
end
ctx.params=cache
returncontext_iterate(ctx,ctx.fnpos+1)
end
-- Syntax:  #invoke:params|renaming_to_uppercase|pipe to
library.renaming_to_uppercase=function(ctx)
-- NOTE: `ctx.params` might be the original metatable! As a modifier,
-- this function MUST create a copy of it before returning
localcache={}
forkey,valinpairs(ctx.params)do
iftype(key)=='string'thencache[key:upper()]=valelse
cache[key]=valend
end
ctx.params=cache
returncontext_iterate(ctx,ctx.fnpos+1)
end
-- Syntax:  #invoke:params|renaming_to_sequence|[sort order]|pipe to
library.renaming_to_sequence=function(ctx)
-- NOTE: `ctx.params` might be the original metatable! As a modifier,
-- this function MUST create a copy of it before returning
localcache,len
localtbl=ctx.params
localsortfn,argc,dosort,tn=load_sort_opt(ctx.pipe[ctx.fnpos+1])
ifdosortthen
localwords,wl
cache,words,len,wl=get_sorted_key_list(tbl,sortfn)
foridx=1,lendocache[idx]=tbl[cache[idx]]end
foridx=1,wldocache[len+idx]=tbl[words[idx]]end
else
cache,len={},1
for_,valinpairs(tbl)docache[len],len=val,len+1end
end
ctx.params=cache
returncontext_iterate(ctx,ctx.fnpos+argc,tn)
end
-- Syntax:  #invoke:params|renaming_by_calling|template name|[call
--            style]|[let/use]|[...]|[let/use]|[...]|[number of additional
--            parameters]|[parameter 1]|[parameter 2]|[...]|[parameter N]|pipe to
library.renaming_by_calling=function(ctx)
localopts,offs=ctx.pipe,ctx.fnpos
localtname=opts[offs+1]andopts[offs+1]:match'^%s*(.*%S)'
iftname==nilthenerror(modulename..
', ‘renaming_by_calling’: No template name was provided',0)end
localrargs,argc,looptype,karg,varg,tbl,mem=
load_callback_opts(opts,offs+1,mapping_styles.names_only,
ctx.params)
localmodel={title=tname,args=rargs}
map_names(tbl,rargs,karg,varg,looptype,function()
returnctx.frame:expandTemplate(model)
end)
forkey,valinpairs(mem)dotbl[key]=valend
ctx.params=tbl
returncontext_iterate(ctx,argc)
end
-- Syntax:  #invoke:params|renaming_by_invoking|module name|function
--            name|[call style]|[let/use]|[...]|[let/use]|[...]|[number of
--            additional arguments]|[argument 1]|[argument 2]|[...]|[argument
--            N]|pipe to
library.renaming_by_invoking=function(ctx)
localopts,offs=ctx.pipe,ctx.fnpos
localmname=opts[offs+1]andopts[offs+1]:match'^%s*(.*%S)'
ifmname==nilthenerror(modulename..
', ‘renaming_by_invoking’: No module name was provided',0)end
localfname=opts[offs+2]andopts[offs+2]:match'^%s*(.*%S)'
iffname==nilthenerror(modulename..
', ‘renaming_by_invoking’: No function name was provided',0)end
localrargs,argc,looptype,karg,varg,tbl,mem=
load_callback_opts(opts,offs+2,mapping_styles.names_only,
ctx.params)
localmodel={title='Module:'..mname,args=rargs}
localmfunc=require(model.title)[fname]
ifmfunc==nilthenerror(modulename..
', ‘renaming_by_invoking’: The function ‘'..fname..'’ does not exist',0)end
map_names(tbl,rargs,karg,varg,looptype,function()
returntostring(mfunc(ctx.frame:newChild(model)))
end)
forkey,valinpairs(mem)dotbl[key]=valend
ctx.params=tbl
returncontext_iterate(ctx,argc)
end
-- Syntax:  #invoke:params|renaming_by_magic|parser function|[call
--            style]|[let/use]|[...]|[let/use]|[...]|[number of additional
--            arguments]|[argument 1]|[argument 2]|[...]|[argument N]|pipe to
library.renaming_by_magic=function(ctx)
localopts,offs=ctx.pipe,ctx.fnpos
localmagic=opts[offs+1]andopts[offs+1]:match'^%s*(.*%S)'
ifmagic==nilthenerror(modulename..
', ‘renaming_by_magic’: No parser function was provided',0)end
localrargs,argc,looptype,karg,varg,tbl,mem=
load_callback_opts(opts,offs+1,mapping_styles.names_only,
ctx.params)
map_names(tbl,rargs,karg,varg,looptype,function()
returnctx.frame:callParserFunction(magic,rargs)
end)
forkey,valinpairs(mem)dotbl[key]=valend
ctx.params=tbl
returncontext_iterate(ctx,argc)
end
-- Syntax:  #invoke:params|renaming_by_replacing|target|replace|[count]|[plain
--            flag]|pipe to
library.renaming_by_replacing=function(ctx)
localptn,repl,nmax,flg,argc,die,tn=
load_replace_args(ctx.pipe,ctx.fnpos,'renaming_by_replacing')
ifdiethenreturncontext_iterate(ctx,argc,tn)end
localtbl=ctx.params
ifflg==3then
ptn=get_param_name(ptn)
localval=tbl[ptn]
ifval~=nilthen
tbl[ptn],tbl[get_param_name(repl)]=nil,val
end
else
ifflg==2then
-- Copied from Module:String's `str._escapePattern()`
ptn=ptn:gsub('[%(%)%.%%%+%-%*%?%[%^%$%]]','%%%0')
end
localcache={}
forkey,valinpairs(tbl)do
steal_if_renamed(val,tbl,key,cache,
tostring(key):gsub(ptn,repl,nmax))
end
forkey,valinpairs(cache)dotbl[key]=valend
end
returncontext_iterate(ctx,argc,tn)
end
-- Syntax:  #invoke:params|renaming_by_mixing|mixing string|pipe to
library.renaming_by_mixing=function(ctx)
-- NOTE: `ctx.params` might be the original metatable! As a modifier,
-- this function MUST create a copy of it before returning
localmix=ctx.pipe[ctx.fnpos+1]
ifmix==nilthenerror(modulename..
', ‘renaming_by_mixing’: No mixing string was provided',0)end
localcache={}
mix=mix:match'^%s*(.-)%s*$'
ifmix=='$@'then
for_,valinpairs(ctx.params)do
cache[get_param_name(val)]=val
end
else
localskel,canvas,n_parts=parse_placeholder_string(mix)
forkey,valinpairs(ctx.params)do
foridx=2,n_parts,2do
ifskel[idx]thencanvas[idx]=val
elsecanvas[idx]=tostring(key)end
end
cache[get_param_name(table.concat(canvas))]=val
end
end
ctx.params=cache
returncontext_iterate(ctx,ctx.fnpos+2)
end
-- Syntax:  #invoke:params|grouping_by_calling|template
--            name|[let/use]|[...]|[let/use]|[...]|[number of additional
--            arguments]|[argument 1]|[argument 2]|[...]|[argument N]|pipe to
library.grouping_by_calling=function(ctx)
-- NOTE: `ctx.params` might be the original metatable! As a modifier,
-- this function MUST create a copy of it before returning
localopts,offs=ctx.pipe,ctx.fnpos
localtmp,argc,tbl,mem=
load_child_opts(opts,offs+2,0,ctx.params)
localgargs={}
forkey,valinpairs(tmp)do
iftype(key)=='number'andkey<1thengargs[key-1]=val
elsegargs[key]=valend
end
tmp=opts[offs+1]andopts[offs+1]:match'^%s*(.*%S)'
iftmp==nilthenerror(modulename..
', ‘grouping_by_calling’: No template name was provided',0)end
localmodel={title=tmp}
localgroups=make_groups(tbl)
forgid,groupinpairs(groups)do
forkey,valinpairs(gargs)dogroup[key]=valend
group[0],model.args=gid,group
groups[gid]=ctx.frame:expandTemplate(model)
end
forkey,valinpairs(mem)dogroups[key]=valend
ctx.params=groups
returncontext_iterate(ctx,argc)
end
-- Syntax:  #invoke:params|parsing|string to parse|[trim flag]|[iteration
--            delimiter setter]|[...]|[key-value delimiter setter]|[...]|pipe to
library.parsing=function(ctx)
localopts,offs=ctx.pipe,ctx.fnpos
ifopts[offs+1]==nilthenerror(modulename..
', ‘parsing’: No string to parse was provided',0)end
localisep,iplain,psep,pplain,trimnamed,trimunnamed,argc,tn=
load_parse_opts(opts,offs+2,'|','=')
parse_parameter_string(ctx.params,opts[offs+1],isep,iplain,psep,
pplain,trimnamed,trimunnamed)
returncontext_iterate(ctx,argc,tn)
end
-- Syntax:  #invoke:params|reinterpreting|parameter to reinterpret|[trim
--            flag]|[iteration delimiter setter]|[...]|[key-value delimiter
--            setter]|[...]|pipe to
library.reinterpreting=function(ctx)
localopts,offs=ctx.pipe,ctx.fnpos
ifopts[offs+1]==nilthenerror(modulename..
', ‘reinterpreting’: No parameter to reinterpret was provided',0)end
localisep,iplain,psep,pplain,trimnamed,trimunnamed,argc,tn=
load_parse_opts(opts,offs+2,'|','=')
localtbl,tmp=ctx.params,get_param_name(opts[offs+1])
localstr=tbl[tmp]
ifstr~=nilthen
tbl[tmp]=nil
parse_parameter_string(tbl,str,isep,iplain,psep,pplain,
trimnamed,trimunnamed)
end
returncontext_iterate(ctx,argc,tn)
end
-- Syntax:  #invoke:params|evaluating|string to parse|[trim flag]|[iteration
--            delimiter setter]|[...]|[key-value delimiter setter]|[...]|pipe to
library.evaluating=function(ctx)
localopts,offs=ctx.pipe,ctx.fnpos
ifopts[offs+1]==nilthenerror(modulename..
', ‘evaluating’: No string to parse was provided',0)end
localisep,iplain,psep,pplain,trimnamed,trimunnamed,repos,tn=
load_parse_opts(opts,offs+2,'!',':')
ifopts[offs+1]:match'^%s*(.*%S)'==nilthen
remove_numeric_keys(opts,offs,repos-offs)
returncontext_iterate(ctx,offs,tn)
end
localnew_opts,cache={},{}
parse_parameter_string(cache,opts[offs+1],isep,iplain,psep,
pplain,trimnamed,trimunnamed)
localshift=#cache+offs-repos+1
forkey,valinpairs(opts)do
iftype(key)~='number'orkey<offsthennew_opts[key]=val
elseifkey>=reposthennew_opts[key+shift]=valend
end
forkey,valinpairs(cache)do
iftype(key)~='number'orkey<1thennew_opts[key]=val
elsenew_opts[key+offs]=valend
end
ctx.pipe=new_opts
returncontext_iterate(ctx,offs+1)
end
-- Syntax:  #invoke:params|mixing_names_and_values|mixing string|pipe to
library.mixing_names_and_values=function(ctx)
-- NOTE: `ctx.params` might be the original metatable! As a modifier,
-- this function MUST create a copy of it before returning
localopts,offs=ctx.pipe,ctx.fnpos
ifopts[offs+1]==nilthenerror(modulename..
', ‘mixing_names_and_values’: No mixing string was provided for parameter names',0)end
ifopts[offs+2]==nilthenerror(modulename..
', ‘mixing_names_and_values’: No mixing string was provided for parameter values',0)end
localtmp
localcache,mix_k,mix_v=
{},opts[offs+1]:match'^%s*(.-)%s*$',opts[offs+2]
ifmix_k=='$@'andmix_v=='$@'then
for_,valinpairs(ctx.params)do
cache[get_param_name(val)]=val
end
elseifmix_k=='$@'andmix_v=='$#'then
forkey,valinpairs(ctx.params)do
cache[get_param_name(val)]=tostring(key)
end
elseifmix_k=='$#'andmix_v=='$#'then
forkeyinpairs(ctx.params)docache[key]=tostring(key)end
else
localskel_k,cnv_k,n_parts_k=parse_placeholder_string(mix_k)
localskel_v,cnv_v,n_parts_v=parse_placeholder_string(mix_v)
forkey,valinpairs(ctx.params)do
tmp=tostring(key)
foridx=2,n_parts_k,2do
ifskel_k[idx]thencnv_k[idx]=val
elsecnv_k[idx]=tmpend
end
foridx=2,n_parts_v,2do
ifskel_v[idx]thencnv_v[idx]=val
elsecnv_v[idx]=tmpend
end
cache[get_param_name(table.concat(cnv_k))]=
table.concat(cnv_v)
end
end
ctx.params=cache
returncontext_iterate(ctx,offs+3)
end
-- Syntax:  #invoke:params|combining|new parameter name|[sort
--            order]|[with/without flushed glue]|setting directives|...|pipe to
library.combining=function(ctx)
-- NOTE: `ctx.params` might be the original metatable! As a modifier,
-- this function MUST create a copy of it before returning
returncontext_iterate(ctx,combine_parameters(
ctx,
function(key,val,kvs)returnkey..kvs..valend,
'combining'
))
end
-- Syntax:  #invoke:params|combining_values|new parameter name|[sort
--            order]|[with/without flushed glue]|setting directives|...|pipe to
library.combining_values=function(ctx)
-- NOTE: `ctx.params` might be the original metatable! As a modifier,
-- this function MUST create a copy of it before returning
returncontext_iterate(ctx,combine_parameters(
ctx,
function(key,val,kvs)returnvalend,
'combining_values'
))
end
-- Syntax:  #invoke:params|combining_by_calling|template name|new parameter
--            name|pipe to
library.combining_by_calling=function(ctx)
-- NOTE: `ctx.params` might be the original metatable! As a modifier,
-- this function MUST create a copy of it before returning
localopts,offs=ctx.pipe,ctx.fnpos
localtname=opts[offs+1]andopts[offs+1]:match'^%s*(.*%S)'
iftname==nilthenerror(modulename..
', ‘combining_by_calling’: No template name was provided',0)end
ifopts[offs+2]==nilthenerror(modulename..
', ‘combining_by_calling’: No parameter name was provided',0)end
ctx.params={
[get_param_name(opts[offs+2])]=ctx.frame:expandTemplate{
title=tname,
args=ctx.params
}
}
returncontext_iterate(ctx,offs+3)
end
-- Syntax:  #invoke:params|combining_by_invoking|module name|function name|new
--            parameter name|pipe to
library.combining_by_invoking=function(ctx)
-- NOTE: `ctx.params` might be the original metatable! As a modifier,
-- this function MUST create a copy of it before returning
localopts,offs=ctx.pipe,ctx.fnpos
localmname=opts[offs+1]andopts[offs+1]:match'^%s*(.*%S)'
ifmname==nilthenerror(modulename..
', ‘combining_by_invoking’: No module name was provided',0)end
localfname=opts[offs+2]andopts[offs+2]:match'^%s*(.*%S)'
iffname==nilthenerror(modulename..
', ‘combining_by_invoking’: No function name was provided',0)end
ifopts[offs+3]==nilthenerror(modulename..
', ‘combining_by_invoking’: No parameter name was provided',0)end
localmodel={title='Module:'..mname,args=ctx.params}
localmfunc=require(model.title)[fname]
ifmfunc==nilthenerror(modulename..
', ‘mapping_by_invoking’: The function ‘'..fname..'’ does not exist',0)end
ctx.params={
[get_param_name(opts[offs+3])]=
tostring(mfunc(ctx.frame:newChild(model)))
}
returncontext_iterate(ctx,offs+4)
end
-- Syntax:  #invoke:params|combining_by_magic|parser function|new parameter
--            name|pipe to
library.combining_by_magic=function(ctx)
-- NOTE: `ctx.params` might be the original metatable! As a modifier,
-- this function MUST create a copy of it before returning
localopts,offs=ctx.pipe,ctx.fnpos
localmagic=opts[offs+1]andopts[offs+1]:match'^%s*(.*%S)'
ifmagic==nilthenerror(modulename..
', ‘combining_by_magic’: No parser function was provided',0)end
ifopts[offs+2]==nilthenerror(modulename..
', ‘combining_by_magic’: No parameter name was provided',0)end
ctx.params={
[get_param_name(opts[offs+2])]=
ctx.frame:callParserFunction(magic,ctx.params)
}
returncontext_iterate(ctx,offs+3)
end
-- Syntax:  #invoke:params|snapshotting|[maximum number]|pipe to
library.snapshotting=function(ctx)
returncontext_iterate(ctx,ctx.fnpos+
make_child(ctx,ctx.params,'snapshotting'))
end
-- Syntax:  #invoke:params|remembering|[maximum number]|pipe to
library.remembering=function(ctx)
returncontext_iterate(ctx,ctx.fnpos+
make_child(ctx,ctx.oparams,'remembering'))
end
-- Syntax:  #invoke:params|entering_substack|[new]|pipe to
library.entering_substack=function(ctx)
localtbl,opts,offs,ncurrparent=
ctx.params,ctx.pipe,ctx.fnpos,ctx.n_parents+1
localtn=opts[offs+1]andopts[offs+1]:match'^%s*(.*%S)'
ifctx.parents==nilthenctx.parents={tbl}
elsectx.parents[ncurrparent]=tblend
ctx.n_parents=ncurrparent
iftn=='new'then
ctx.params={}
returncontext_iterate(ctx,offs+2)
end
localcurrsnap=ctx.n_children
ifcurrsnap>0then
ctx.params,ctx.children[currsnap],ctx.n_children=
ctx.children[currsnap],nil,currsnap-1
else
localnewparams={}
forkey,valinpairs(tbl)donewparams[key]=valend
ctx.params=newparams
end
returncontext_iterate(ctx,offs+1,tn)
end
-- Syntax:  #invoke:params|pulling|parameter name|pipe to
library.pulling=function(ctx)
localopts,offs=ctx.pipe,ctx.fnpos
ifopts[offs+1]==nilthenerror(modulename..
', ‘pulling’: No parameter to pull was provided',0)end
localtmp=ctx.n_parents
localparent=tmp<1andctx.oparamsorctx.parents[tmp]
tmp=get_param_name(opts[offs+1])
ifparent[tmp]~=nilthenctx.params[tmp]=parent[tmp]end
returncontext_iterate(ctx,ctx.fnpos+2)
end
-- Syntax:  #invoke:params|recalling|parameter name|pipe to
library.recalling=function(ctx)
localopts,offs=ctx.pipe,ctx.fnpos
ifopts[offs+1]==nilthenerror(modulename..
', ‘recalling’: No parameter to recall was provided',0)end
localarg=get_param_name(opts[offs+1])
ifctx.oparams[arg]~=nilthenctx.params[arg]=ctx.oparams[arg]end
returncontext_iterate(ctx,ctx.fnpos+2)
end
-- Syntax:  #invoke:params|finding|parameter name|pipe to
--[[
library.finding = function (ctx)
	local opts, offs = ctx.pipe, ctx.fnpos
	if opts[offs + 1] == nil then error(modulename ..
		', ‘finding’: No parameter to find was provided', 0) end
	local arg = get_param_name(opts[offs + 1])
	local parent
	for idx = ctx.n_parents, 1, -1 do
		parent = ctx.parents[idx]
		if parent[arg] ~= nil then
			ctx.params[arg] = parent[arg]
			return context_iterate(ctx, offs + 2)
		end
	end
	if ctx.oparams[arg] ~= nil then ctx.params[arg] = ctx.oparams[arg] end
	return context_iterate(ctx, offs + 2)
end
]]--
-- Syntax:  #invoke:params|picking|number of parameters to pick|pipe to
--[[
library.picking = function (ctx)
	local len = tonumber(ctx.pipe[ctx.fnpos + 1])
	if len == nil or len < 1 or math.floor(len) ~= len then error(modulename ..
		', ‘picking’: The number of parameters to pick must be an integer greater than zero', 0) end
	if ctx.n_parents < 1 then copy_table_maxn(ctx.params, ctx.oparams, len)
	else copy_table_maxn(ctx.params, ctx.parents[ctx.n_parents], len) end
	return context_iterate(ctx, ctx.fnpos + 2)
end
]]--
-- Syntax:  #invoke:params|detaching_substack|pipe to
library.detaching_substack=function(ctx)
localncurrparent=ctx.n_parents
ifncurrparent<1thenerror(modulename..
', ‘detaching_substack’: No substacks have been created',0)end
localparent=ctx.parents[ncurrparent]
forkeyinpairs(ctx.params)doparent[key]=nilend
returncontext_iterate(ctx,ctx.fnpos+1)
end
-- Syntax:  #invoke:params|dropping_substack|pipe to
library.dropping_substack=function(ctx)
localncurrparent=ctx.n_parents
ifncurrparent<1thenerror(modulename..
', ‘dropping_substack’: No substacks have been created',0)end
ctx.params,ctx.parents[ncurrparent],ctx.n_parents=
ctx.parents[ncurrparent],nil,ncurrparent-1
returncontext_iterate(ctx,ctx.fnpos+1)
end
-- Syntax:  #invoke:params|leaving_substack|pipe to
library.leaving_substack=function(ctx)
localncurrparent=ctx.n_parents
ifncurrparent<1thenerror(modulename..
', ‘leaving_substack’: No substacks have been created',0)end
localcurrsnap=ctx.n_children+1
ifctx.children==nilthenctx.children={ctx.params}
elsectx.children[currsnap]=ctx.paramsend
ctx.params,ctx.parents[ncurrparent],ctx.n_parents,ctx.n_children=
ctx.parents[ncurrparent],nil,ncurrparent-1,currsnap
returncontext_iterate(ctx,ctx.fnpos+1)
end
-- Syntax:  #invoke:params|merging_substack|pipe to
library.merging_substack=function(ctx)
localncurrparent=ctx.n_parents
ifncurrparent<1thenerror(modulename..
', ‘merging_substack’: No substack has been created',0)end
localparent,child=ctx.parents[ncurrparent],ctx.params
ctx.params,ctx.parents[ncurrparent],ctx.n_parents=parent,nil,
ncurrparent-1
forkey,valinpairs(child)doparent[key]=valend
returncontext_iterate(ctx,ctx.fnpos+1)
end
-- Syntax:  #invoke:params|flushing|pipe to
library.flushing=function(ctx)
ifctx.n_children<1thenerror(modulename..
', ‘flushing’: There are no substacks to flush',0)end
localparent,currsnap=ctx.params,ctx.n_children
forkey,valinpairs(ctx.children[currsnap])doparent[key]=valend
ctx.children[currsnap],ctx.n_children=nil,currsnap-1
returncontext_iterate(ctx,ctx.fnpos+1)
end
-- Syntax:  #invoke:params|setting_by_flushing|pipe to
library.setting_by_flushing=function(ctx)
set_strings_from_substack(ctx,ctx,'setting_by_flushing')
returncontext_iterate(ctx,ctx.fnpos+1)
end
--[[ Functions ]]--
-----------------------------
-- Syntax:  #invoke:params|count
library.count=function(ctx)
-- NOTE: `ctx.params` might be the original metatable!
localretval=0
for_inctx.iterfunc(ctx.params)doretval=retval+1end
ifctx.subset==-1thenretval=retval-#ctx.paramsend
ctx.text=retval
returnfalse
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]|[...]
library.concat_and_call=function(ctx)
-- NOTE: `ctx.params` might be the original metatable!
localopts,offs=ctx.pipe,ctx.fnpos
localtname=opts[offs+1]andopts[offs+1]:match'^%s*(.*%S)'
iftname==nilthenerror(modulename..
', ‘concat_and_call’: No template name was provided',0)end
ctx.text=ctx.frame:expandTemplate{
title=tname,
args=concat_params(ctx,offs+1)
}
returnfalse
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]|[...]
library.concat_and_invoke=function(ctx)
-- NOTE: `ctx.params` might be the original metatable!
localopts,offs=ctx.pipe,ctx.fnpos
localmname=opts[offs+1]andopts[offs+1]:match'^%s*(.*%S)'
ifmname==nilthenerror(modulename..
', ‘concat_and_invoke’: No module name was provided',0)end
localfname=opts[offs+2]andopts[offs+2]:match'^%s*(.*%S)'
iffname==nilthenerror(modulename..
', ‘concat_and_invoke’: No function name was provided',0)end
localmfunc=require('Module:'..mname)[fname]
ifmfunc==nilthenerror(modulename..
', ‘concat_and_invoke’: The function ‘'..fname..'’ does not exist',0)end
ctx.text=mfunc(ctx.frame:newChild{
title='Module:'..mname,
args=concat_params(ctx,offs+2)
})
returnfalse
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]|[...]
library.concat_and_magic=function(ctx)
-- NOTE: `ctx.params` might be the original metatable!
localopts,offs=ctx.pipe,ctx.fnpos
localmagic=opts[offs+1]andopts[offs+1]:match'^%s*(.*%S)'
ifmagic==nilthenerror(modulename..
', ‘concat_and_magic’: No parser function was provided',0)end
ctx.text=ctx.frame:callParserFunction(magic,
concat_params(ctx,offs+1))
returnfalse
end
-- Syntax:  #invoke:params|value_of|parameter name
library.value_of=function(ctx)
-- NOTE: `ctx.params` might be the original metatable!
localopts,offs=ctx.pipe,ctx.fnpos
ifopts[offs+1]==nilthenerror(modulename..
', ‘value_of’: No parameter name was provided',0)end
localval
localkey=opts[offs+1]:match'^%s*(.-)%s*$'
ifkey=='0'orkey:find'^%-?[1-9]%d*$'~=nilthen
key=tonumber(key)
val=ctx.params[key]
-- No worries: #ctx.params is unused when the modifier is in
-- first position (and therefore `ctx.params` is a metatable)
ifval~=niland(
ctx.subset~=-1orkey>#ctx.paramsorkey<1
)and(
ctx.subset~=1or(key<=#ctx.paramsandkey>0)
)then
ctx.text=(ctx.headeror'')..val..
(ctx.footeror'')
elsectx.text=ctx.ifngivenor''end
else
val=ctx.params[key]
ifctx.subset~=1andval~=nilthenctx.text=(ctx.header
or'')..val..(ctx.footeror'')
elsectx.text=ctx.ifngivenor''end
end
returnfalse
end
-- Syntax:  #invoke:params|list
library.list=function(ctx)
localret,nss,kvs,pps={},0,ctx.pairsepor'',ctx.itersepor''
flush_params(ctx,function(key,val)
ret[nss+1],ret[nss+2],ret[nss+3],ret[nss+4],nss=
pps,key,kvs,val,nss+4
end)
finalize_and_return_concatenated_list(ctx,ret,nss,4)
returnfalse
end
-- Syntax:  #invoke:params|list_values
library.list_values=function(ctx)
-- NOTE: `library.coins()` and `library.unique_coins()` rely on us
localret,nss,pps={},0,ctx.itersepor''
flush_params(ctx,function(key,val)
ret[nss+1],ret[nss+2],nss=pps,val,nss+2
end)
finalize_and_return_concatenated_list(ctx,ret,nss,2)
returnfalse
end
-- Syntax:  #invoke:params|list_maybe_with_names
library.list_maybe_with_names=function(ctx)
localret,nss,kvs,pps={},0,ctx.pairsepor'',ctx.itersepor''
mixed_flush_params(
ctx,
function(key,val)
ret[nss+1],ret[nss+2],ret[nss+3],
ret[nss+4],nss=pps,'','',val,nss+4
end,
function(key,val)
ret[nss+1],ret[nss+2],ret[nss+3],
ret[nss+4],nss=pps,key,kvs,val,nss+4
end
)
finalize_and_return_concatenated_list(ctx,ret,nss,4)
returnfalse
end
-- Syntax:  #invoke:params|for_each|wikitext
library.for_each=function(ctx)
localret,nss,pps,txt=
{},0,ctx.itersepor'',ctx.pipe[ctx.fnpos+1]or''
localskel,cnv,n_parts=parse_placeholder_string(txt)
flush_params(ctx,function(key,val)
foridx=2,n_parts,2do
ifskel[idx]thencnv[idx]=val
elsecnv[idx]=tostring(key)end
end
ret[nss+1],nss=pps,nss+2
ret[nss]=table.concat(cnv)
end)
finalize_and_return_concatenated_list(ctx,ret,nss,2)
returnfalse
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]|[...]
library.call_for_each=function(ctx)
localopts,offs=ctx.pipe,ctx.fnpos
localtname=opts[offs+1]andopts[offs+1]:match'^%s*(.*%S)'
iftname==nilthenerror(modulename..
', ‘call_for_each’: No template name was provided',0)end
localcargs=copy_table_reduced(opts,1,offs-1)
localmodel,ret,nss,ccs=
{title=tname,args=cargs},{},0,ctx.itersepor''
flush_params(ctx,function(key,val)
cargs[1],cargs[2],ret[nss+1],nss=key,val,ccs,nss+2
ret[nss]=ctx.frame:expandTemplate(model)
end)
finalize_and_return_concatenated_list(ctx,ret,nss,2)
returnfalse
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]|[...]
library.invoke_for_each=function(ctx)
localopts,offs=ctx.pipe,ctx.fnpos
localmname=opts[offs+1]andopts[offs+1]:match'^%s*(.*%S)'
ifmname==nilthenerror(modulename..
', ‘invoke_for_each’: No module name was provided',0)end
localfname=opts[offs+2]andopts[offs+2]:match'^%s*(.*%S)'
iffname==nilthenerror(modulename..
', ‘invoke_for_each’: No function name was provided',0)end
localiargs=copy_table_reduced(ctx.pipe,1,offs)
localmodel={title='Module:'..mname,args=iargs}
localmfunc,ret,nss,ccs=
require(model.title)[fname],{},0,ctx.itersepor''
ifmfunc==nilthenerror(modulename..
', ‘invoke_for_each’: The function ‘'..fname..'’ does not exist',0)end
flush_params(ctx,function(key,val)
iargs[1],iargs[2],ret[nss+1],nss=key,val,ccs,nss+2
ret[nss]=mfunc(ctx.frame:newChild(model))
end)
finalize_and_return_concatenated_list(ctx,ret,nss,2)
returnfalse
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]|[...]
library.magic_for_each=function(ctx)
localopts,offs=ctx.pipe,ctx.fnpos
localmagic=opts[offs+1]andopts[offs+1]:match'^%s*(.*%S)'
ifmagic==nilthenerror(modulename..
', ‘magic_for_each’: No parser function was provided',0)end
localret,nss,ccs,cargs={},0,ctx.itersepor'',
copy_table_reduced(opts,1,offs-1)
flush_params(ctx,function(key,val)
cargs[1],cargs[2],ret[nss+1],nss=key,val,ccs,nss+2
ret[nss]=ctx.frame:callParserFunction(magic,cargs)
end)
finalize_and_return_concatenated_list(ctx,ret,nss,2)
returnfalse
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]|[...]
library.call_for_each_value=function(ctx)
localopts,offs=ctx.pipe,ctx.fnpos
localtname=opts[offs+1]andopts[offs+1]:match'^%s*(.*%S)'
iftname==nilthenerror(modulename..
', ‘call_for_each_value’: No template name was provided',0)end
localcargs=copy_table_reduced(ctx.pipe,1,offs)
localmodel={title=tname,args=cargs}
localret,nss,ccs={},0,ctx.itersepor''
flush_params(ctx,function(key,val)
cargs[1],ret[nss+1],nss=val,ccs,nss+2
ret[nss]=ctx.frame:expandTemplate(model)
end)
finalize_and_return_concatenated_list(ctx,ret,nss,2)
returnfalse
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]|[...]
library.invoke_for_each_value=function(ctx)
localopts,offs=ctx.pipe,ctx.fnpos
localmname=opts[offs+1]andopts[offs+1]:match'^%s*(.*%S)'
ifmname==nilthenerror(modulename..
', ‘invoke_for_each_value’: No module name was provided',0)end
localfname=opts[offs+2]andopts[offs+2]:match'^%s*(.*%S)'
iffname==nilthenerror(modulename..
', ‘invoke_for_each_value’: No function name was provided',0)end
localiargs=copy_table_reduced(ctx.pipe,1,offs+1)
localmodel={title='Module:'..mname,args=iargs}
localmfunc,ret,nss,ccs=
require(model.title)[fname],{},0,ctx.itersepor''
ifmfunc==nilthenerror(modulename..
', ‘invoke_for_each_value’: The function ‘'..fname..'’ does not exist',0)end
flush_params(ctx,function(key,val)
iargs[1],ret[nss+1],nss=val,ccs,nss+2
ret[nss]=mfunc(ctx.frame:newChild(model))
end)
finalize_and_return_concatenated_list(ctx,ret,nss,2)
returnfalse
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]|[...]
library.magic_for_each_value=function(ctx)
localopts,offs=ctx.pipe,ctx.fnpos
localmagic=opts[offs+1]andopts[offs+1]:match'^%s*(.*%S)'
ifmagic==nilthenerror(modulename..
', ‘magic_for_each_value’: No parser function was provided',0)end
localcargs,ret,nss,ccs=
copy_table_reduced(opts,1,offs),{},0,ctx.itersepor''
flush_params(ctx,function(key,val)
cargs[1],ret[nss+1],nss=val,ccs,nss+2
ret[nss]=ctx.frame:callParserFunction(magic,cargs)
end)
finalize_and_return_concatenated_list(ctx,ret,nss,2)
returnfalse
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]|[...]
library.call_for_each_group=function(ctx)
-- NOTE: `ctx.params` might be the original metatable!
localopts,offs=ctx.pipe,ctx.fnpos
localtmp=opts[offs+1]andopts[offs+1]:match'^%s*(.*%S)'
iftmp==nilthenerror(modulename..
', ‘call_for_each_group’: No template name was provided',0)end
localmodel={title=tmp}
localbargs,ret,nss,ccs={},{},0,ctx.itersepor''
forkey,valinpairs(opts)do
iftype(key)~='number'thenbargs[key]=val
elseifkey>offsthenbargs[key-offs-1]=val
elseifkey<1thenbargs[key-1]=valend
end
ctx.params=make_groups(ctx.params)
flush_params(ctx,function(gid,group)
forkey,valinpairs(bargs)dogroup[key]=valend
group[0],model.args,ret[nss+1],nss=gid,group,ccs,
nss+2
ret[nss]=ctx.frame:expandTemplate(model)
end)
finalize_and_return_concatenated_list(ctx,ret,nss,2)
returnfalse
end
--[[ First-position-only modifiers ]]--
---------------------------------------
-- Syntax:  #invoke:params|new|pipe to
static_iface.new=function(child_frame)
localctx=context_new(child_frame,'new')
ctx.params={}
main_loop(ctx,context_iterate(ctx,2))
returnctx.text
end
--[[ First-position-only functions ]]--
---------------------------------------
-- Syntax:  #invoke:params|self
static_iface.self=function(child_frame)
returnchild_frame:getParent():getTitle()
end
--[[ Public metatable of functions ]]--
---------------------------------------
returnsetmetatable({},{
__index=function(_,query)
localfname=query:match'^%s*(.*%S)'
iffname==nilthenerror(modulename..
': You must specify a function to call',0)end
localfunc=static_iface[fname]
iffunc~=nilthenreturnfuncend
func=library[fname]
iffunc==nilthenerror(modulename..
': The function ‘'..fname..'’ does not exist',0)end
returnfunction(child_frame)
localctx=context_new(child_frame,fname)
ctx.params=copy_or_ref_table(ctx.oparams,
refparams[fname])
main_loop(ctx,func)
returnctx.text
end
end
})
Konten disalin dari Wikipedia Bahasa Indonesia (lisensi CC BY-SA) Lihat versi asli di Wikipedia

Rekomendasi Pilihan