Selasa, 22 September 2026
23:55 WIB
TERKINI
Regional Solo Safari Bantah Larang Hijab, Akui Ada Kesalahan Komunikasi Berita Banjir Bandang Landa Kompleks Pemkab Solok, Peralatan Kantor Hanyut dan Warga Mengungsi Berita Mengungkap Jaringan Video Asusila "A Day in My Life": Dua Pelaku Raup Jutaan Rupiah Berita Nusron Wahid Mundur dari Golkar, Serahkan Detail ke Bahlil Lahadalia Wawancara Tragedi 1965: Oka Rusmini Soroti Perampasan Hak Hidup Perempuan Prelude Dua Mantan Menteri Keuangan: Riwayat Berbeda di Kursi Kasir Negara Politik Kepala BGN Gencar Beriklan di Medsos, Benahi Citra Program Makan Bergizi Gratis Bisnis Jerat Pungli Ancam UMKM Indonesia: Kisah Bolosego dan Solusi Mendesak Hukum & Kriminal Empat Eks Pejabat LPEI Divonis 6 Tahun Penjara dalam Skandal Korupsi Pembiayaan Ekspor Hukum & Kriminal Mantan Bupati Sidoarjo Gus Muhdlor Bebas Bersyarat Usai Dua Tahun Dipenjara Regional Solo Safari Bantah Larang Hijab, Akui Ada Kesalahan Komunikasi Berita Banjir Bandang Landa Kompleks Pemkab Solok, Peralatan Kantor Hanyut dan Warga Mengungsi Berita Mengungkap Jaringan Video Asusila "A Day in My Life": Dua Pelaku Raup Jutaan Rupiah Berita Nusron Wahid Mundur dari Golkar, Serahkan Detail ke Bahlil Lahadalia Wawancara Tragedi 1965: Oka Rusmini Soroti Perampasan Hak Hidup Perempuan Prelude Dua Mantan Menteri Keuangan: Riwayat Berbeda di Kursi Kasir Negara Politik Kepala BGN Gencar Beriklan di Medsos, Benahi Citra Program Makan Bergizi Gratis Bisnis Jerat Pungli Ancam UMKM Indonesia: Kisah Bolosego dan Solusi Mendesak Hukum & Kriminal Empat Eks Pejabat LPEI Divonis 6 Tahun Penjara dalam Skandal Korupsi Pembiayaan Ekspor Hukum & Kriminal Mantan Bupati Sidoarjo Gus Muhdlor Bebas Bersyarat Usai Dua Tahun Dipenjara

Modul:Params

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_key_list_sorted(tbl,sort_fn)
localnums,words,nn,nw={},{},0,0
forkey,valinpairs(tbl)do
iftype(key)=='number'then
nn=nn+1
nums[nn]=key
else
nw=nw+1
words[nw]=key
end
end
table.sort(nums)
table.sort(words,sort_fn)
returnnums,words,nn,nw
end
-- Parse a parameter name string and return it as a string or a number
localfunctionget_parameter_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_parameter_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.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
localrefpipe={
call_for_each_group=true,
--coins = true,
count=true,
evaluating=true,
for_each=true,
list=true,
list_values=true,
list_maybe_with_names=true,
value_of=true
}
-- 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,
--renaming_to_values = true,
shifting=true,
splicing=true,
--swapping_names_and_values = 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)
localmain_frame=child_frame:getParent()
return{
frame=main_frame,
opipe=child_frame.args,
oparams=main_frame.args,
firstposonly=static_iface,
iterfunc=pairs,
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,n_forward)
localnextfn
ifctx.pipe[n_forward]~=nilthen
nextfn=ctx.pipe[n_forward]:match'^%s*(.*%S)'
end
ifnextfn==nilthenerror(modulename..
': You must specify a function to call',0)end
iflibrary[nextfn]==nilthen
ifctx.firstposonly[nextfn]==nilthenerror(modulename..
': The function ‘'..nextfn..'’ does not exist',0)
elseerror(modulename..': The ‘'..nextfn..
'’ directive can only appear in first position',0)
end
end
remove_numeric_keys(ctx.pipe,1,n_forward)
returnlibrary[nextfn]
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,start_from)
localcmd
ifopts[start_from]==nilthenreturnstart_from-1end
cmd=opts[start_from]:gsub('%s+',''):gsub('/+','/')
:match'^/*(.*[^/])'
ifcmd==nilthenreturnstart_fromend
localvname,chr
localamap,sep,argc={},string.byte('/'),start_from+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)
ifraw_arg==nilthenreturnnil,1,falseend
localtrarg=raw_arg:match'^%s*(.-)%s*$'
iftrarg=='without_sorting'thenreturnnil,2,false,trargend
localtmp=sortfunctions[trarg]
iftmp==nilthenreturnnil,1,false,trargend
returntmpornil,2,true,trarg
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_parameter_name(src[pin+1])
mem[tmp1],tbl[tmp1],pin=nil,src[pin+2],pin+3
--[[
		elseif tmp1 == 'expose' then
			tmp1 = get_parameter_name(src[pin + 1])
			tmp2 = params[tmp1]
			mem[tmp1], tbl[tmp1], pin = tmp2, tmp2, pin + 2
]]--
elseiftmp1=='use'andsrc[pin+2]~=nilthen
tmp1=get_parameter_name(src[pin+2])
tmp2=params[tmp1]
mem[tmp1],tbl[get_parameter_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,n_skip,default_style,params)
localstyle,shf
localtmp=src[n_skip+1]
iftmp~=nilthenstyle=mapping_styles[tmp:match'^%s*(.-)%s*$']end
ifstyle==nilthenstyle,shf=default_style,n_skip-1
elseshf=n_skipend
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
localdest,argc,tnew,mem=load_child_opts(src,style[2]+shf,
n_exist,params)
tmp=style[1]
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,whoami)
ifopts[1]==nilthenerror(modulename..
', ‘'..whoami..'’: No pattern string was given',0)end
ifopts[2]==nilthenerror(modulename..
', ‘'..whoami..'’: No replacement string was given',0)end
localptn,repl,nmax,argc=opts[1],opts[2],tonumber(opts[3]),3
ifnmax~=nilor(opts[3]or''):match'^%s*$'~=nilthenargc=4end
localflg=opts[argc]
ifflg~=nilthenflg=mkeywords[flg:match'^%s*(.-)%s*$']end
ifflg==0thenflg=nilelseifflg~=nilthenargc=argc+1end
returnptn,repl,nmax,flg,argc,(nmax~=nilandnmax<1)or
(flg==3andptn==repl)
end
-- Parse the arguments of the `with_*_matching` class of modifiers
localfunctionload_pattern_args(opts,whoami)
localkeyw
localptns,state,nptns,cnt={},0,0,1
for_,valinipairs(opts)do
ifstate==0then
nptns,state=nptns+1,-1
ptns[nptns]={val,false,false}
else
keyw=val:match'^%s*(.*%S)'
ifkeyw==nilormkeywords[keyw]==nilor(
state>0andmkeywords[keyw]>0
)thenbreak
else
state=mkeywords[keyw]
ifstate>1thenptns[nptns][2]=trueend
ifstate==3thenptns[nptns][3]=trueend
end
end
cnt=cnt+1
end
ifstate==0thenerror(modulename..', ‘'..whoami..
'’: No pattern was given',0)end
returnptns,nptns,cnt
end
-- Load the optional arguments of the `parsing`, `reinterpreting` and
-- `evaluating` modifiers
localfunctionload_parse_opts(opts,start_from,isp,psp)
localtmp
localoptslots,noptslots,argc,trimn,trimu,iplain,pplain=
{true,true,true},3,start_from,true,false,true,true
repeat
noptslots,tmp=noptslots-1,opts[argc]
iftmp==nilthenbreakend
tmp=tmp:match'^%s*(.-)%s*$'
ifoptslots[1]~=nilandtrim_parse_opts[tmp]~=nilthen
tmp=trim_parse_opts[tmp]
trimn,trimu,optslots[1]=tmp[1],tmp[2],nil
elseifoptslots[2]~=nilandisep_parse_opts[tmp]~=nilthen
argc=argc+1
iplain,isp,optslots[2]=isep_parse_opts[tmp],
opts[argc],nil
elseifoptslots[3]~=nilandpsep_parse_opts[tmp]~=nilthen
argc=argc+1
pplain,psp,optslots[3]=psep_parse_opts[tmp],
opts[argc],nil
elsebreakend
argc=argc+1
untilnoptslots<1
returnisp,iplain,psp,pplain,trimn,trimu,argc
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''
else
prefix,gid='',key
end
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)
localidx,s_pos,skel,canvas=1,1,{},{}
locale_pos=string.find(target,'%$[@#]',1,false)
whilee_pos~=nildo
canvas[idx]=target:sub(s_pos,e_pos-1)
skel[idx+1]=target:sub(e_pos,e_pos+1)=='$@'
idx=idx+2
s_pos=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
returnidx
end
spos1,spos2=str:find(psp,1,ppl)
ifspos1==nilthen
key=idx
iftruthenval=str:match'^%s*(.-)%s*$'
elseval=strend
idx=idx+1
else
key=get_parameter_name(str:sub(1,spos1-1))
val=str:sub(spos2+1)
iftrnthenval=val:match'^%s*(.-)%s*$'end
end
tbl[key]=val
returnidx
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
returnidx
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_parameter_name(val:sub(1,spos1-1))
val=val:sub(spos2+1)
iftrnthenval=val:match'^%s*(.-)%s*$'end
end
tbl[key]=val
untilpos2==nil
returnidx
end
-- Heavy lifting for `snapshotting` and `remembering`
localfunctionmake_child(ctx,src,whoami)
locallen=tonumber(ctx.pipe[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=ctx.pipe
ifctx.pipe[1]==nilthenerror(modulename..
', ‘'..whoami..'’: No parameter name was provided',0)end
localargc
localtbl,vars=ctx.params,{}
localsortfn,varsarg0,do_sort,tmp=load_sort_opt(opts[2])
ifvarsarg0==2thentmp=opts[3]andopts[3]:match'^%s*(.-)%s*$'end
iftmp=='with_flushed_glue'then
varsarg0=varsarg0+1
argc=set_strings_from_opts(vars,opts,varsarg0+1)
set_strings_from_substack(ctx,vars,whoami)
else
iftmp=='without_flushed_glue'thenvarsarg0=varsarg0+1end
argc=set_strings_from_opts(vars,opts,varsarg0+1)
end
ifargc<varsarg0thenerror(modulename..
', ‘'..whoami..'’: No setting directive was given',0)end
ifnext(tbl)==nilthen
ifvars.ifngiven~=nilthenctx.params=
{[get_parameter_name(ctx.pipe[1])]=vars.ifngiven}
elseiftbl==ctx.oparamsthenctx.params={}end
returnargc
end
localcache,len
ifdo_sortthen
localwords
cache,words,len,tmp=get_key_list_sorted(tbl,sortfn)
foridx=1,tmpdocache[len+idx]=words[idx]end
len=len+tmp
else
len,cache=0,{}
forkeyinpairs(tbl)do
len=len+1
cache[len]=key
end
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_parameter_name(ctx.pipe[1])]=table.concat(pmap)}
returnargc
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)
localretval,tbl,nmax={},ctx.params,table.maxn(ctx.pipe)
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(ctx.pipe)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)
localtbl=ctx.params
ifctx.subset==1then
forkey,valinipairs(tbl)dofn(key,val)end
return
end
ifctx.subset==-1then
forkey,valinipairs(tbl)dotbl[key]=nilend
end
ifctx.sorttype>0then
localnums,words,nn,nw=get_key_list_sorted(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~=-1then
forkey,valinipairs(tbl)do
fn(key,val)
tbl[key]=nil
end
end
forkey,valinpairs(tbl)dofn(key,val)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
forkey,valinipairs(ctx.params)dofn_seq(key,val)end
return
end
ifctx.subset==-1then
flush_params(ctx,fn_oth)
return
end
localtbl=ctx.params
ifctx.sorttype>0then
localnums,words,nn,nw=get_key_list_sorted(tbl,natural_sort)
localsequence={}
forkey,valinipairs(tbl)dosequence[key]=valend
ifctx.sorttype==2then
foridx=1,nwdofn_oth(words[idx],tbl[words[idx]])end
end
foridx=1,nndo
ifsequence[nums[idx]]thenfn_seq(nums[idx],sequence[nums[idx]])
elsefn_oth(nums[idx],tbl[nums[idx]])end
end
ifctx.sorttype~=2then
foridx=1,nwdofn_oth(words[idx],tbl[words[idx]])end
end
return
end
forkey,valinipairs(tbl)do
fn_seq(key,val)
tbl[key]=nil
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,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,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,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,1)
end
-- Syntax:  #invoke:params|setting|directives|...|pipe to
library.setting=function(ctx)
localargc=set_strings_from_opts(ctx,ctx.pipe,1)
ifargc<2thenerror(modulename..
', ‘setting’: No directive was given',0)end
returncontext_iterate(ctx,argc+1)
end
-- Syntax:  #invoke:params|scoring|new parameter name|[container]|pipe to
library.scoring=function(ctx)
ifctx.pipe[1]==nilthenerror(modulename..
', ‘scoring’: No parameter name was provided',0)end
localtmp
localretval,opts=0,ctx.pipe
for_inpairs(ctx.params)doretval=retval+1end
ifopts[2]~=nilthentmp=opts[2]:match'^%s*(.*%S)'end
iftmp=='in_substack'then
new_substack(ctx)[get_parameter_name(opts[1])]=tostring(retval)
returncontext_iterate(ctx,3)
end
ctx.params[get_parameter_name(opts[1])]=tostring(retval)
returncontext_iterate(ctx,tmp=='here'and3or2)
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,1)
end
-- Syntax:  #invoke:params|filling_the_gaps|pipe to
library.filling_the_gaps=function(ctx)
localnewval,tbl,tmp,nmin,nmax,nnums=
ctx.pipe[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,nmax,1dotbl[idx]=newvalend
forkey,valinpairs(tmp)dotbl[key]=valend
end
returncontext_iterate(ctx,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,1)
end
-- Syntax:  #invoke:params|cutting|left cut|right cut|pipe to
library.cutting=function(ctx)
locallcut=tonumber(ctx.pipe[1])
iflcut==nilormath.floor(lcut)~=lcutthenerror(modulename..
', ‘cutting’: Left cut must be an integer number',0)end
localrcut=tonumber(ctx.pipe[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,len,1dotbl[idx]=nilend
foridx=1,lcut,1dotbl[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,3)
end
-- Syntax:  #invoke:params|cropping|left crop|right crop|pipe to
library.cropping=function(ctx)
locallcut=tonumber(ctx.pipe[1])
iflcut==nilormath.floor(lcut)~=lcutthenerror(modulename..
', ‘cropping’: Left crop must be an integer number',0)end
localrcut=tonumber(ctx.pipe[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,nmax,1do
tbl[idx-lshift],tbl[idx]=
tbl[idx],nil
end
end
end
end
returncontext_iterate(ctx,3)
end
-- Syntax:  #invoke:params|purging|start offset|length|pipe to
library.purging=function(ctx)
localidx=tonumber(ctx.pipe[1])
ifidx==nilormath.floor(idx)~=idxthenerror(modulename..
', ‘purging’: Start offset must be an integer number',0)end
locallen=tonumber(ctx.pipe[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,3)end
len=len-idx+1
end
ctx.params=copy_table_reduced(tbl,idx,len)
returncontext_iterate(ctx,3)
end
-- Syntax:  #invoke:params|backpurging|start offset|length|pipe to
library.backpurging=function(ctx)
locallast=tonumber(ctx.pipe[1])
iflast==nilormath.floor(last)~=lastthenerror(modulename..
', ‘backpurging’: Start offset must be an integer number',0)end
locallen=tonumber(ctx.pipe[2])
iflen==nilormath.floor(len)~=lenthenerror(modulename..
', ‘backpurging’: Length must be an integer number',0)end
localidx
localtbl=ctx.params
iflen>0then
idx=last-len+1
else
forkeyinpairs(tbl)do
iftype(key)=='number'and(idx==nilor
key<idx)thenidx=keyend
end
ifidx==nilthenreturncontext_iterate(ctx,3)end
idx=idx-len
iflast<idxthenreturncontext_iterate(ctx,3)end
len=last-idx+1
end
ctx.params=copy_table_reduced(ctx.params,idx,len)
returncontext_iterate(ctx,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[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,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,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 numerics = {}
	for key, val in pairs(tbl) do
		if type(key) == 'number' then
			numerics[key] = val
			tbl[key] = nil
		end
	end
	for key, val in pairs(numerics) do tbl[shift - key] = val end
	return context_iterate(ctx, 1)
end
]]--
-- Syntax:  #invoke:params|mirroring_numeric_names|pipe to
--[[
library.mirroring_numeric_names = function (ctx)
	local nmax, nmin
	local tbl, numerics = ctx.params, {}
	for key, val in pairs(tbl) do
		if type(key) == 'number' then
			numerics[key] = val
			tbl[key] = 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(numerics) do tbl[nmax + nmin - key] = val end
	return context_iterate(ctx, 1)
end
]]--
-- Syntax:  #invoke:params|swapping_numeric_names|pipe to
--[[
library.swapping_numeric_names = function (ctx)
	local tmp
	local tbl, cache, nsize = ctx.params, {}, 0
	for key in pairs(tbl) do
		if type(key) == 'number' then
			nsize = nsize + 1
			cache[nsize] = key
		end
	end
	table.sort(cache)
	for idx = math.floor(nsize / 2), 1, -1 do
		tmp = tbl[cache[idx] ]
		tbl[cache[idx] ] = tbl[cache[nsize - idx + 1] ]
		tbl[cache[nsize - idx + 1] ] = tmp
	end
	return context_iterate(ctx, 1)
end
]]--
-- Syntax:  #invoke:params|sorting_sequential_values|[criterion]|pipe to
library.sorting_sequential_values=function(ctx)
localsortfn
ifctx.pipe[1]~=nilthen
sortfn=sortfunctions[ctx.pipe[1]:match'^%s*(.-)%s*$']
end
ifsortfnthentable.sort(ctx.params,sortfn)
elsetable.sort(ctx.params)end-- i.e. either `false` or `nil`
ifsortfn==nilthenreturncontext_iterate(ctx,1)end
returncontext_iterate(ctx,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
localopts,tbl=ctx.pipe,ctx.params
localtmp1=opts[1]
iftmp1~=nilthen
tmp2=tonumber(tmp1)
iftmp2==nilormath.floor(tmp2)~=tmp2then
pos,argc,tmp2=tonumber(opts[2]),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,3,0end
elsepos,argc,refp=tonumber(opts[2]),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-pos+1
forkey=pos,pos+insn-1dotbl[key]=opts[key+tmp1]end
returncontext_iterate(ctx,argc+insn+1)
end
-- Syntax:  #invoke:params|imposing|name|value|pipe to
library.imposing=function(ctx)
ifctx.pipe[1]==nilthenerror(modulename..
', ‘imposing’: Missing parameter name to impose',0)end
ctx.params[get_parameter_name(ctx.pipe[1])]=ctx.pipe[2]
returncontext_iterate(ctx,3)
end
-- Syntax:  #invoke:params|providing|name|value|pipe to
library.providing=function(ctx)
ifctx.pipe[1]==nilthenerror(modulename..
', ‘providing’: Missing parameter name to provide',0)end
localkey=get_parameter_name(ctx.pipe[1])
ifctx.params[key]==nilthenctx.params[key]=ctx.pipe[2]end
returncontext_iterate(ctx,3)
end
-- Syntax:  #invoke:params|reassigning|source|destination|[mode]|pipe to
library.reassigning=function(ctx)
localopts,tbl=ctx.pipe,ctx.params
ifopts[1]==nilthenerror(modulename..
', ‘reassigning’: Missing source parameter',0)end
ifopts[2]==nilthenerror(modulename..
', ‘reassigning’: Missing destination parameter',0)end
localmode,argc
localsrc=get_parameter_name(opts[1])
localval=tbl[src]
ifopts[3]~=nilthenmode=a_modes[opts[3]:match'^%s*(.-)%s*$']end
ifmode==nilthenmode,argc=0,3elseargc=4end
ifval==nilandmode>1thenreturncontext_iterate(ctx,argc)end
localdest=get_parameter_name(opts[2])
localtmp=tbl[dest]==nil
ifmode%2==0or(mode==7andtmp)thentbl[src]=nilend
iftmpormode<4thentbl[dest]=valend
returncontext_iterate(ctx,argc)
end
-- Syntax:  #invoke:params|discarding|name|[how many]|pipe to
library.discarding=function(ctx)
ifctx.pipe[1]==nilthenerror(modulename..
', ‘discarding’: Missing parameter name to discard',0)end
locallen=tonumber(ctx.pipe[2])
iflen==nilthen
ctx.params[get_parameter_name(ctx.pipe[1])]=nil
returncontext_iterate(ctx,2)
end
localkey=tonumber(ctx.pipe[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,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,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,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
localtargets,nptns,argc=load_pattern_args(ctx.pipe,
'with_name_matching')
localtbl,newparams=ctx.params,{}
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)
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)
localtargets,nptns,argc=load_pattern_args(ctx.pipe,
'with_name_not_matching')
localtbl=ctx.params
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)
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)
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=ctx.params
localtargets,nptns,argc=load_pattern_args(ctx.pipe,
'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)
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=ctx.params
localtargets,nptns,argc=load_pattern_args(ctx.pipe,
'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)
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[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,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,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,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,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)
localtname
localopts=ctx.pipe
ifopts[1]~=nilthentname=opts[1]:match'^%s*(.*%S)'end
iftname==nilthenerror(modulename..
', ‘mapping_by_calling’: No template name was provided',0)end
localmargs,argc,looptype,karg,varg,tbl,mem=
load_callback_opts(opts,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)
localmname,fname
localopts=ctx.pipe
ifopts[1]~=nilthenmname=opts[1]:match'^%s*(.*%S)'end
ifmname==nilthenerror(modulename..
', ‘mapping_by_invoking’: No module name was provided',0)end
ifopts[2]~=nilthenfname=opts[2]:match'^%s*(.*%S)'end
iffname==nilthenerror(modulename..
', ‘mapping_by_invoking’: No function name was provided',0)end
localmargs,argc,looptype,karg,varg,tbl,mem=
load_callback_opts(opts,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)
localmagic
localopts=ctx.pipe
ifopts[1]~=nilthenmagic=opts[1]:match'^%s*(.*%S)'end
ifmagic==nilthenerror(modulename..
', ‘mapping_by_magic’: No parser function was provided',0)end
localmargs,argc,looptype,karg,varg,tbl,mem=
load_callback_opts(opts,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=
load_replace_args(ctx.pipe,'mapping_by_replacing')
ifdiethenreturncontext_iterate(ctx,argc)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)
end
-- Syntax:  #invoke:params|mapping_by_mixing|mixing string|pipe to
library.mapping_by_mixing=function(ctx)
ifctx.pipe[1]==nilthenerror(modulename..
', ‘mapping_by_mixing’: No mixing string was provided',0)end
localtbl,mix=ctx.params,ctx.pipe[1]
ifmix=='$#'then
forkeyinpairs(tbl)dotbl[key]=tostring(key)end
returncontext_iterate(ctx,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,2)
end
-- Syntax:  #invoke:params|mapping_to_names|pipe to
--[[
library.mapping_to_names = function (ctx)
	local tbl = ctx.params
	for key in pairs(tbl) do tbl[key] = tostring(key) end
	return context_iterate(ctx, 1)
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,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,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,do_sort=load_sort_opt(ctx.pipe[1])
ifdo_sortthen
localwords,wl
cache,words,len,wl=get_key_list_sorted(tbl,sortfn)
foridx=1,lendocache[idx]=tbl[cache[idx]]end
foridx=1,wldocache[len+idx]=tbl[words[idx]]end
else
len,cache=0,{}
for_,valinpairs(tbl)do
len=len+1
cache[len]=val
end
end
ctx.params=cache
returncontext_iterate(ctx,argc)
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)
localtname
localopts=ctx.pipe
ifopts[1]~=nilthentname=opts[1]:match'^%s*(.*%S)'end
iftname==nilthenerror(modulename..
', ‘renaming_by_calling’: No template name was provided',0)end
localrargs,argc,looptype,karg,varg,tbl,mem=
load_callback_opts(opts,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)
localmname,fname
localopts=ctx.pipe
ifopts[1]~=nilthenmname=opts[1]:match'^%s*(.*%S)'end
ifmname==nilthenerror(modulename..
', ‘renaming_by_invoking’: No module name was provided',0)end
ifopts[2]~=nilthenfname=opts[2]:match'^%s*(.*%S)'end
iffname==nilthenerror(modulename..
', ‘renaming_by_invoking’: No function name was provided',0)end
localrargs,argc,looptype,karg,varg,tbl,mem=
load_callback_opts(opts,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=ctx.pipe
localmagic
ifopts[1]~=nilthenmagic=opts[1]:match'^%s*(.*%S)'end
ifmagic==nilthenerror(modulename..
', ‘renaming_by_magic’: No parser function was provided',0)end
localrargs,argc,looptype,karg,varg,tbl,mem=
load_callback_opts(opts,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=
load_replace_args(ctx.pipe,'renaming_by_replacing')
ifdiethenreturncontext_iterate(ctx,argc)end
localtbl=ctx.params
ifflg==3then
ptn=get_parameter_name(ptn)
localval=tbl[ptn]
ifval~=nilthen
tbl[ptn],tbl[get_parameter_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)
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
ifctx.pipe[1]==nilthenerror(modulename..
', ‘renaming_by_mixing’: No mixing string was provided',0)end
localmix=ctx.pipe[1]:match'^%s*(.-)%s*$'
localcache={}
ifmix=='$@'then
for_,valinpairs(ctx.params)do
cache[get_parameter_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_parameter_name(table.concat(canvas))]=val
end
end
ctx.params=cache
returncontext_iterate(ctx,2)
end
-- Syntax:  #invoke:params|renaming_to_values|pipe to
--[[
library.renaming_to_values = function (ctx)
	-- NOTE: `ctx.params` might be the original metatable! As a modifier,
	-- this function MUST create a copy of it before returning
	local cache = {}
	for _, val in pairs(ctx.params) do cache[val] = val end
	ctx.params = cache
	return context_iterate(ctx, 1)
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
localtmp,argc,tbl,mem=load_child_opts(ctx.pipe,2,0,ctx.params)
localgargs={}
forkey,valinpairs(tmp)do
iftype(key)=='number'andkey<1thengargs[key-1]=val
elsegargs[key]=valend
end
tmp=ctx.pipe[1]
iftmp~=nilthentmp=tmp:match'^%s*(.*%S)'end
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=ctx.pipe
ifopts[1]==nilthenerror(modulename..
', ‘parsing’: No string to parse was provided',0)end
localisep,iplain,psep,pplain,trimnamed,trimunnamed,argc=
load_parse_opts(opts,2,'|','=')
parse_parameter_string(ctx.params,opts[1],isep,iplain,psep,pplain,
trimnamed,trimunnamed)
returncontext_iterate(ctx,argc)
end
-- Syntax:  #invoke:params|reinterpreting|parameter to reinterpret|[trim
--            flag]|[iteration delimiter setter]|[...]|[key-value delimiter
--            setter]|[...]|pipe to
library.reinterpreting=function(ctx)
localopts=ctx.pipe
ifopts[1]==nilthenerror(modulename..
', ‘reinterpreting’: No parameter to reinterpret was provided',0)end
localisep,iplain,psep,pplain,trimnamed,trimunnamed,argc=
load_parse_opts(opts,2,'|','=')
localtbl,tmp=ctx.params,get_parameter_name(opts[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)
end
-- Syntax:  #invoke:params|evaluating|string to parse|[trim flag]|[iteration
--            delimiter setter]|[...]|[key-value delimiter setter]|[...]|pipe to
library.evaluating=function(ctx)
-- NOTE: `ctx.pipe` might be the original metatable! As a modifier,
-- this function MUST create a copy of it before returning
localopts=ctx.pipe
ifopts[1]==nilthenerror(modulename..
', ‘evaluating’: No string to parse was provided',0)end
localisep,iplain,psep,pplain,trimnamed,trimunnamed,argc=
load_parse_opts(opts,2,'!',':')
ifopts[1]:match'^%s*(.*%S)'==nilthen
ctx.pipe=copy_or_ref_table(opts,opts~=ctx.opipe)
returncontext_iterate(ctx,argc)
end
localnew_opts,cache={},{}
localshift=parse_parameter_string(cache,opts[1],isep,iplain,
psep,pplain,trimnamed,trimunnamed)-argc
forkey,valinpairs(opts)do
iftype(key)~='number'orkey<1thennew_opts[key]=val
elseifkey>=argcthennew_opts[key+shift]=valend
end
forkey,valinpairs(cache)donew_opts[key]=valend
ctx.pipe=new_opts
returncontext_iterate(ctx,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
ifctx.pipe[1]==nilthenerror(modulename..
', ‘mixing_names_and_values’: No mixing string was provided for parameter names',0)end
ifctx.pipe[2]==nilthenerror(modulename..
', ‘mixing_names_and_values’: No mixing string was provided for parameter values',0)end
localtmp
localmix_k=ctx.pipe[1]:match'^%s*(.-)%s*$'
localcache,mix_v={},ctx.pipe[2]
ifmix_k=='$@'andmix_v=='$@'then
for_,valinpairs(ctx.params)do
cache[get_parameter_name(val)]=val
end
elseifmix_k=='$@'andmix_v=='$#'then
forkey,valinpairs(ctx.params)do
cache[get_parameter_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]=valelsecnv_k[idx]=tmpend
end
foridx=2,n_parts_v,2do
ifskel_v[idx]thencnv_v[idx]=valelsecnv_v[idx]=tmpend
end
cache[get_parameter_name(table.concat(cnv_k))]=
table.concat(cnv_v)
end
end
ctx.params=cache
returncontext_iterate(ctx,3)
end
-- Syntax:  #invoke:params|swapping_names_and_values|pipe to
--[[
library.swapping_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
	local cache = {}
	for key, val in pairs(ctx.params) do cache[val] = key end
	ctx.params = cache
	return context_iterate(ctx, 1)
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'
)+1)
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'
)+1)
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
localtname=ctx.pipe[1]
iftname~=nilthentname=tname:match'^%s*(.*%S)'
elseerror(modulename..
', ‘combining_by_calling’: No template name was provided',0)end
ifctx.pipe[2]==nilthenerror(modulename..
', ‘combining_by_calling’: No parameter name was provided',0)end
ctx.params={
[get_parameter_name(ctx.pipe[2])]=ctx.frame:expandTemplate{
title=tname,
args=ctx.params
}
}
returncontext_iterate(ctx,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
localmname=ctx.pipe[1]
ifmname~=nilthenmname=mname:match'^%s*(.*%S)'
elseerror(modulename..
', ‘combining_by_invoking’: No module name was provided',0)end
localfname=ctx.pipe[2]
iffname~=nilthenfname=fname:match'^%s*(.*%S)'
elseerror(modulename..
', ‘combining_by_invoking’: No function name was provided',0)end
ifctx.pipe[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_parameter_name(ctx.pipe[3])]=
tostring(mfunc(ctx.frame:newChild(model)))
}
returncontext_iterate(ctx,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
localmagic=ctx.pipe[1]
ifmagic~=nilthenmagic=magic:match'^%s*(.*%S)'
elseerror(modulename..
', ‘combining_by_magic’: No parser function was provided',0)end
ifctx.pipe[2]==nilthenerror(modulename..
', ‘combining_by_magic’: No parameter name was provided',0)end
ctx.params={
[get_parameter_name(ctx.pipe[2])]=
ctx.frame:callParserFunction(magic,ctx.params)
}
returncontext_iterate(ctx,3)
end
-- Syntax:  #invoke:params|snapshotting|[maximum number]|pipe to
library.snapshotting=function(ctx)
returncontext_iterate(ctx,make_child(ctx,ctx.params,'snapshotting'))
end
-- Syntax:  #invoke:params|remembering|[maximum number]|pipe to
library.remembering=function(ctx)
returncontext_iterate(ctx,make_child(ctx,ctx.oparams,'remembering'))
end
-- Syntax:  #invoke:params|entering_substack|[new]|pipe to
library.entering_substack=function(ctx)
localtbl,ncurrparent=ctx.params,ctx.n_parents+1
ifctx.parents==nilthenctx.parents={tbl}
elsectx.parents[ncurrparent]=tblend
ctx.n_parents=ncurrparent
ifctx.pipe[1]~=nilandctx.pipe[1]:match'^%s*new%s*$'then
ctx.params={}
returncontext_iterate(ctx,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,1)
end
-- Syntax:  #invoke:params|pulling|parameter name|pipe to
library.pulling=function(ctx)
localopts=ctx.pipe
ifopts[1]==nilthenerror(modulename..
', ‘pulling’: No parameter to pull was provided',0)end
localtmp=ctx.n_parents
localparent=tmp<1andctx.oparamsorctx.parents[tmp]
tmp=get_parameter_name(opts[1])
ifparent[tmp]~=nilthenctx.params[tmp]=parent[tmp]end
returncontext_iterate(ctx,2)
end
-- Syntax:  #invoke:params|recalling|parameter name|pipe to
library.recalling=function(ctx)
localopts=ctx.pipe
ifopts[1]==nilthenerror(modulename..
', ‘recalling’: No parameter to recall was provided',0)end
localarg=get_parameter_name(opts[1])
ifctx.oparams[arg]~=nilthenctx.params[arg]=ctx.oparams[arg]end
returncontext_iterate(ctx,2)
end
-- Syntax:  #invoke:params|finding|parameter name|pipe to
--[[
library.finding = function (ctx)
	local opts = ctx.pipe
	if opts[1] == nil then error(modulename ..
		', ‘finding’: No parameter to find was provided', 0) end
	local arg = get_parameter_name(opts[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, 2)
		end
	end
	if ctx.oparams[arg] ~= nil then ctx.params[arg] = ctx.oparams[arg] end
	return context_iterate(ctx, 2)
end
]]--
-- Syntax:  #invoke:params|picking|number of parameters to pick|pipe to
--[[
library.picking = function (ctx)
	local len = tonumber(ctx.pipe[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, 2)
end
]]--
-- Syntax:  #invoke:params|detaching_substack|pipe to
library.detaching_substack=function(ctx)
localncurrparent=ctx.n_parents
ifncurrparent<1thenerror(modulename..
', ‘detaching_substack’: No substack has been created',0)end
localparent=ctx.parents[ncurrparent]
forkeyinpairs(ctx.params)doparent[key]=nilend
returncontext_iterate(ctx,1)
end
-- Syntax:  #invoke:params|dropping_substack|pipe to
library.dropping_substack=function(ctx)
localncurrparent=ctx.n_parents
ifncurrparent<1thenerror(modulename..
', ‘dropping_substack’: No substack has been created',0)end
ctx.params,ctx.parents[ncurrparent],ctx.n_parents=
ctx.parents[ncurrparent],nil,ncurrparent-1
returncontext_iterate(ctx,1)
end
-- Syntax:  #invoke:params|leaving_substack|pipe to
library.leaving_substack=function(ctx)
localncurrparent=ctx.n_parents
ifncurrparent<1thenerror(modulename..
', ‘leaving_substack’: No substack has 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,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,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,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,1)
end
--[[ Functions ]]--
-----------------------------
-- Syntax:  #invoke:params|count
library.count=function(ctx)
-- NOTE: `ctx.pipe` and `ctx.params` might be the original metatables!
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!
localtname
localopts=ctx.pipe
ifopts[1]~=nilthentname=opts[1]:match'^%s*(.*%S)'end
iftname==nilthenerror(modulename..
', ‘concat_and_call’: No template name was provided',0)end
remove_numeric_keys(opts,1,1)
ctx.text=ctx.frame:expandTemplate{
title=tname,
args=concat_params(ctx)
}
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!
localmname,fname
localopts=ctx.pipe
ifopts[1]~=nilthenmname=opts[1]:match'^%s*(.*%S)'end
ifmname==nilthenerror(modulename..
', ‘concat_and_invoke’: No module name was provided',0)end
ifopts[2]~=nilthenfname=opts[2]:match'^%s*(.*%S)'end
iffname==nilthenerror(modulename..
', ‘concat_and_invoke’: No function name was provided',0)end
remove_numeric_keys(opts,1,2)
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)
})
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!
localmagic
localopts=ctx.pipe
ifopts[1]~=nilthenmagic=opts[1]:match'^%s*(.*%S)'end
ifmagic==nilthenerror(modulename..
', ‘concat_and_magic’: No parser function was provided',0)end
remove_numeric_keys(opts,1,1)
ctx.text=ctx.frame:callParserFunction(magic,concat_params(ctx))
returnfalse
end
-- Syntax:  #invoke:params|value_of|parameter name
library.value_of=function(ctx)
-- NOTE: `ctx.pipe` and `ctx.params` might be the original metatables!
localopts=ctx.pipe
ifopts[1]==nilthenerror(modulename..
', ‘value_of’: No parameter name was provided',0)end
localval
localkey=opts[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)
-- NOTE: `ctx.pipe` might be the original metatable!
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: `ctx.pipe` might be the original metatable!
-- 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)
-- NOTE: `ctx.pipe` might be the original metatable!
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|coins|[first coin = value 1]|[second coin = value
--            2]|[...]|[last coin = value N]
--[[
library.coins = function (ctx)
	-- NOTE: `ctx.pipe` might be the original metatable!
	local opts, tbl = ctx.pipe, ctx.params
	for key, val in pairs(tbl) do tbl[key] = opts[get_parameter_name(val)] end
	return library.list_values(ctx)
end
]]--
-- Syntax:  #invoke:params|unique_coins|[first coin = value 1]|[second coin =
--            value 2]|[...]|[last coin = value N]
--[[
library.unique_coins = function (ctx)
	local tmp
	local opts, tbl = ctx.pipe, ctx.params
	for key, val in pairs(tbl) do
		tmp = get_parameter_name(val)
		tbl[key], opts[tmp] = opts[tmp], nil
	end
	return library.list_values(ctx)
end
]]
-- Syntax:  #invoke:params|for_each|wikitext
library.for_each=function(ctx)
-- NOTE: `ctx.pipe` might be the original metatable!
localret,nss,pps,txt={},0,ctx.itersepor'',ctx.pipe[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)
localtname
localopts=ctx.pipe
ifopts[1]~=nilthentname=opts[1]:match'^%s*(.*%S)'end
iftname==nilthenerror(modulename..
', ‘call_for_each’: No template name was provided',0)end
localmodel={title=tname,args=opts}
localret,nss,ccs={},0,ctx.itersepor''
table.insert(opts,1,true)
flush_params(ctx,function(key,val)
opts[1],opts[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)
localmname,fname
localopts=ctx.pipe
ifopts[1]~=nilthenmname=opts[1]:match'^%s*(.*%S)'end
ifmname==nilthenerror(modulename..
', ‘invoke_for_each’: No module name was provided',0)end
ifopts[2]~=nilthenfname=opts[2]:match'^%s*(.*%S)'end
iffname==nilthenerror(modulename..
', ‘invoke_for_each’: No function name was provided',0)end
localmodel={title='Module:'..mname,args=opts}
localmfunc=require(model.title)[fname]
localret,nss,ccs={},0,ctx.itersepor''
flush_params(ctx,function(key,val)
opts[1],opts[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)
localmagic
localopts=ctx.pipe
ifopts[1]~=nilthenmagic=opts[1]:match'^%s*(.*%S)'end
ifmagic==nilthenerror(modulename..
', ‘magic_for_each’: No parser function was provided',0)end
localret,nss,ccs={},0,ctx.itersepor''
table.insert(opts,1,true)
flush_params(ctx,function(key,val)
opts[1],opts[2],ret[nss+1],nss=key,val,ccs,nss+2
ret[nss]=ctx.frame:callParserFunction(magic,opts)
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)
localtname
localopts=ctx.pipe
ifopts[1]~=nilthentname=opts[1]:match'^%s*(.*%S)'end
iftname==nilthenerror(modulename..
', ‘call_for_each_value’: No template name was provided',0)end
localmodel={title=tname,args=opts}
localret,nss,ccs={},0,ctx.itersepor''
flush_params(ctx,function(key,val)
opts[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=ctx.pipe
localmname,fname
ifopts[1]~=nilthenmname=opts[1]:match'^%s*(.*%S)'end
ifmname==nilthenerror(modulename..
', ‘invoke_for_each_value’: No module name was provided',0)end
ifopts[2]~=nilthenfname=opts[2]:match'^%s*(.*%S)'end
iffname==nilthenerror(modulename..
', ‘invoke_for_each_value’: No function name was provided',0)end
localmodel={title='Module:'..mname,args=opts}
localmfunc=require(model.title)[fname]
localret,nss,ccs={},0,ctx.itersepor''
remove_numeric_keys(opts,1,1)
flush_params(ctx,function(key,val)
opts[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=ctx.pipe
localmagic
ifopts[1]~=nilthenmagic=opts[1]:match'^%s*(.*%S)'end
ifmagic==nilthenerror(modulename..
', ‘magic_for_each_value’: No parser function was provided',0)end
localret,nss,ccs={},0,ctx.itersepor''
flush_params(ctx,function(key,val)
opts[1],ret[nss+1],nss=val,ccs,nss+2
ret[nss]=ctx.frame:callParserFunction(magic,opts)
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.pipe` and `ctx.params` might be the original metatables!
localtmp
ifctx.pipe[1]~=nilthentmp=ctx.pipe[1]:match'^%s*(.*%S)'end
iftmp==nilthenerror(modulename..
', ‘call_for_each_group’: No template name was provided',0)end
localmodel={title=tmp}
localopts,ret,nss,ccs={},{},0,ctx.itersepor''
forkey,valinpairs(ctx.pipe)do
iftype(key)=='number'thenopts[key-1]=val
elseopts[key]=valend
end
ctx.pipe=opts
ctx.params=make_groups(ctx.params)
flush_params(ctx,function(gid,group)
forkey,valinpairs(opts)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)
ctx.pipe=copy_or_ref_table(ctx.opipe,false)
ctx.params={}
main_loop(ctx,context_iterate(ctx,1))
returnctx.text
end
--[[ First-position-only functions ]]--
---------------------------------------
-- Syntax:  #invoke:params|self
static_iface.self=function(frame)
returnframe: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)
ctx.pipe=copy_or_ref_table(ctx.opipe,refpipe[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