Sətir 1: |
Sətir 1: |
− | local M={} | + | local p={} |
− | ---------------------------------------------------------
| + | |
− | -- Функции для работы с параметрами вызвавшего шаблона -- | + | -- Вызывает внутренний шаблон с аргументами объемлющего шаблона |
− | ---------------------------------------------------------
| + | function p.call(frame) |
− | function M.uni(f)-- Унификация имён параметров; псевдонимы. | + | local template = frame.args[1] |
− | local tf, cs=f:getParent(), {};
| + | local args = frame:getParent().args |
− | local findcs=function(a) cs[a]=f.args[a] end;
| + | return frame:expandTemplate{ title=template, args=args } |
− | (f.args['|фиксрег'] or f.args['|fixreg'] or ''):gmatch(' *([^%n]+) *', findcs);
| |
− | -- {{!}}фиксрег = список разделённых новыми строками аргументов, регистр которых не менять
| |
− | local args,am={};
| |
− | for a,v in pairs(tf.args) do
| |
− | am = a:lower():gsub('[_ ]+',' ');
| |
− | args[ cs[a] and a or ( f.args[am] or am ) ] = v
| |
− | end
| |
− | return tf:expandTemplate{title=f.args[1]; args=args} | |
| end | | end |
| | | |
− | M['forall'] = function(f)-- Итератор по аргументам вызывающего шаблона.
| + | -- Общая реализация для forall и call |
− | -- f.args[1] — имя вызываемого шаблона.
| + | local function forallImpl(args, separator, conjunction, func) |
− | local tf,ac,res,tln,sep,gl=f:getParent(),{},{},f.args[1]:match('^%s*([^#]-)%s*#(.*)$'),tonumber(f.args[2]) or 1;
| + | -- нумерованные ключи из args |
− | if not tln then tln,sep=f.args[1]:match('^%s*(.-)%s*$'),'' end
| + | local keys = {} |
− | for p,k in pairs(f.args) do if type(p)=='string' then ac[p]=k end end
| + | -- перебор в произвольном порядке, даже для нумерованных ключей |
− | local ans,i,ablk={},1;
| + | for key, value in pairs(args) do |
− | while tf.args[i] do
| + | if type(key) == 'number' and value and value ~= '' then |
− | if gl==1 then
| + | table.insert(keys, key) |
− | ans[i] = tf:expandTemplate{ title=tln; args={tf.args[i], unpack(ac)} }
| + | end |
− | else
| + | end |
− | ablk={}; for j = 0, gl-1 do ablk[j] = tf.args[i*gl+j] end;
| + | table.sort(keys) |
− | for k,v in pairs(ac) do ablk[k]=v end;
| + | |
− | ans[i] = tf:expandTemplate{ title=tln; args=ablk }
| + | local results = {} |
− | end
| + | for _, key in ipairs(keys) do |
− | i = i+1
| + | local value = func(args[key]) |
− | end
| + | table.insert(results, value) |
− | return table.concat(ans,sep)
| + | end |
| + | |
| + | return mw.text.listToText(results, separator, conjunction) |
| end | | end |
| | | |
− | function M.escapeparams(f)-- Нормализация | + | -- Вызывает внутренний шаблон, передавая ему нумерованные параметры объемлющего шаблона по-одному |
− | -- (обезопасивание) значений параметров. | + | function p.forall(frame) |
− | local i,ac,acn=0,{},{};
| + | local template = frame.args[1] |
− | local function repl(s)
| + | local separator = frame.args.separator or '' |
− | return s:gsub('{{','{{Х'):gsub('}}',"{{ЪЪ}}"):gsub('{{Х','{{ХХ}}')--: --замена фигурных скобок
| + | local conjunction = frame.args.conjunction or separator |
− | :gsub('=','{{=}}'):gsub('|','{{!}}')
| + | local args = frame:getParent().args |
− | end
| + | local func = function(value) |
− | for k,v in pairs(f:getParent().args) do
| + | return frame:expandTemplate{ title = template, args = {value} } -- или другой frame? |
− | if type(k)=='number' then ac[k]=repl(v); i=i+1
| + | end |
− | else acn[repl(k)]=repl(v)end
| + | return forallImpl(args, separator, conjunction, func) |
− | end
| |
− | if i ~= #ac-1 then --нумерованные параметры не сплошные
| |
− | for k,v in pairs(ac) do
| |
− | if k>i then acn[tostring(k)] = v; ac[k]=nil end-- удалять в pairs можно
| |
− | end
| |
− | end
| |
− | for k,v in pairs(acn) do
| |
− | table.insert(ac, table.concat(f.args[2] or "\n ", k, f.args[3] or ' = ', v, f.args[4] or '') )
| |
− | end
| |
− | return table.concat(ac,'|')
| |
| end | | end |
| | | |
− | function M.npc(f)-- Итератор по именованно-нумерованным параметрам.
| + | -- Берёт нумерованные аргументы объемлющего шаблона и склеивает их в единую строку |
− | local tf, ac, ns = f:getParent(), {}, {};
| + | function p.join(frame) |
− | for k,v in pairs(tf.args) do
| + | local separator = frame.args[1] or '' |
− | local b,n = string.match(k,"^(.-)%s*(%d*)$");
| + | local conjunction = frame.args[2] or separator |
− | n = tonumber(n);
| + | local args = frame:getParent().args |
− | if n then
| + | local func = function(value) |
− | if f.args[b] then
| + | return value |
− | if not ac[n] then
| + | end |
− | ac[n] = mw.clone(f.args)
| + | return forallImpl(args, separator, conjunction, func) |
− | setmetatable( ac[n], nil ) -- metatable ломает expandTemplate
| |
− | table.insert(ns,n)
| |
− | end
| |
− | ac[n][b] = v
| |
− | end--if f.args[b]
| |
− | end--if n
| |
− | end--for
| |
− | table.sort(ns);
| |
− | local tmod = #f.args-1
| |
− | for n,i in ipairs(ns) do
| |
− | ns[n]=tf:expandTemplate{ title=f.args[n % tmod+1]; args=ac[i] }
| |
− | end
| |
− | return table.concat(ns)
| |
| end | | end |
| | | |
− | function M.call(f)-- Просто вызывает шаблон с аргументами вызывающего.
| + | -- Служебная функция: удаляет дубликаты из отсортированного массива с нумерованными индексами |
− | return f:getParent():expandTemplate{ title=f.args[1]; args=f:getParent().args }
| + | local function deleteDuplicates(args) |
| + | local res = {} |
| + | for key, value in pairs(args) do |
| + | if args[key+1] ~= value then |
| + | table.insert(res, value) |
| + | end |
| + | end |
| + | return res |
| end | | end |
| | | |
− | function M.join(f)-- Версия forall с разделителем вместо шаблона. | + | -- Вызывает внутренний шаблон несколько раз, передавая в него блоки аргументов объемлющего шаблона |
− | -- f.args[1] — разделитель.
| + | function p.npc(frame) |
− | local t, tf, i = {}, f:getParent(), tonumber(f.args.from) or 1
| + | local args = frame:getParent().args |
− | local k,j,m = tonumber(f.args.to),i,f.args[3]
| + | local templateFrame = frame:getParent() |
− | while k and i<=k or tf.args[i] do
| + | local template = frame.args[1] |
− | if (
| + | |
− | ({
| + | -- определение, блоки аргументов с какими номерами нужны: |
− | ['_']=function(s)return s~=''end;
| + | -- если в объемлющем шаблоне есть "параметр12" и в вызове модуля есть "параметр", то вызывается 12-й блок |
− | ['s']=function(s)return not tostring(s):match("^%s*$")end
| + | local nums = {} |
− | })[m] or function() return true end
| + | for key, _ in pairs(args) do |
− | )(tf.args[i]) then
| + | local main, num = string.match(key, '^(.-)%s*(%d*)$') |
− | t[j]=tf.args[i];
| + | num = tonumber(num) |
− | j=j+1
| + | -- учитывать "параметр12", только если задано "параметр" |
− | end;
| + | if num and frame.args[main] then |
− | i=i+1
| + | table.insert(nums, num) |
− | end
| + | end |
− | return mw.text.listToText(t,f.args[1],f.args[2] or f.args[1]) | + | end |
| + | table.sort(nums) |
| + | nums = deleteDuplicates(nums) |
| + | |
| + | -- проходить по нужным номерам блоков по возрастанию и однократно |
| + | -- подставлять в шаблон: |
| + | -- 1. общие аргументы данного модуля |
| + | -- 2. аргументы объемлющего шаблона вида "параметр12" как "параметр" в 12-й блок |
| + | local results = {} |
| + | for _, blockNum in ipairs(nums) do |
| + | -- общие аргументы модуля, которые передаются в каждый блок |
| + | local blockArgs = mw.clone(frame.args) |
| + | -- metatable ломает expandTemplate |
| + | setmetatable(blockArgs, nil) |
| + | |
| + | for key, value in pairs(args) do |
| + | local main, num = string.match(key, '^(.-)%s*(%d*)$') |
| + | num = tonumber(num) |
| + | -- передавать "параметр12" как "параметр" в 12-й блок, только если есть "параметр" в вызове модуля |
| + | if blockNum == num and frame.args[main] then |
| + | blockArgs[main] = value |
| + | end |
| + | end |
| + | |
| + | local blockText = templateFrame:expandTemplate{ title=template; args=blockArgs } |
| + | table.insert(results, blockText) |
| + | end |
| + | |
| + | return table.concat(results) |
| end | | end |
− | -------------------------------------------------------
| + | |
− | -- Функции для работы с параметрами шаблона в invoke -- | + | -- Действует аналогично forall по числовой переменной, изменяющейся (по умолчанию, от 1) до f.args[2]. |
− | -------------------------------------------------------
| + | function p.cycle(f) |
− | --[[
| + | local tf,ac,op=f:getParent(), {}, f.args.output or 'inline'; |
− | function M.split(f)-- Разрезает строку f.args[3]
| + | local sep=''; |
− | -- указанным в f.args[2](?) разделителем
| + | if op == 'newline' then |
− | -- и передаёт куски шаблону f.args[1].
| + | sep='\n'; |
− | local tf, ac, oldi, i, e =f:getParent(), {}, 1, f.args[3]:find(f.args[1],1,true) | |
− | -- «f.args[1]» в строке выше — точно не ошибка? --Incnis Mrsi | |
− | while i do | |
− | table.insert( ac, f.args[3]:sub(oldi, i-1) ); oldi=e+1
| |
| end | | end |
− | table.insert( ac, f.args[3]:sub(oldi, #f.args[3]-1) )
| |
− | return f:getParent():expandTemplate{ title=f.args[1]; args=ac }
| |
− | end
| |
− | ]]
| |
− |
| |
− | function M.cycle(f)-- Действует аналогично forall по числовой переменной,
| |
− | -- изменяющейся (по умолчанию, от 1) до f.args[2].
| |
− | local tf,ac=f:getParent(),{};
| |
| for p,k in pairs(f.args) do | | for p,k in pairs(f.args) do |
| if type(p)=='number' then | | if type(p)=='number' then |
Sətir 132: |
Sətir 126: |
| f.args[2]:match('%.%.%s*(%S.*)%s*$') or f.args[2] or ''; | | f.args[2]:match('%.%.%s*(%S.*)%s*$') or f.args[2] or ''; |
| fh=tonumber(fh) or fh:match('^%s*(.-)%s*$'); | | fh=tonumber(fh) or fh:match('^%s*(.-)%s*$'); |
| + | s=tonumber(s); |
| local acr={}; | | local acr={}; |
− | if not tonumber(s) then error('Начало цикла «'..s..'» — не число') end | + | if not s then error('Начало цикла «'..s..'» — не число') end |
− | local function dc() | + | local function dc(order) |
− | local r=tf:expandTemplate{ title=f.args[1]; args={s,unpack(ac)} }
| + | local r=tf:expandTemplate{ title=f.args[1]; args={s,unpack(ac)} } |
− | s=s+1;
| + | if order == 'desc' then |
− | if r~='' then table.insert(acr,r); return r end
| + | s=s-1; |
| + | else |
| + | s=s+1; |
| + | end |
| + | if r~='' then table.insert(acr,r); return r end |
| end | | end |
− | if type(fh)=='number' then | + | if type(fh)=='number' then |
− | while s<fh do dc() end
| + | if fh > s then |
| + | while s<=fh do dc('asc') end |
| + | else |
| + | while s>=fh do dc('desc') end |
| + | end |
| elseif fh~='' then | | elseif fh~='' then |
− | while tf:expandTemplate{ title=fh; args={s,unpack(ac)} } do dc() end | + | while tf:expandTemplate{ title=fh; args={s,unpack(ac)} } do dc('asc') end |
| else | | else |
− | while dc() do end | + | while dc('asc') do end |
| end | | end |
− | return table.concat(acr) | + | return table.concat(acr, sep) |
| end | | end |
− | --[[Функция не пашет как можно ждать — пробелы отсекаются после передачи параметров в expandTemplate
| + | |
− | function M.pass(f)-- Передаёт шаблону параметры без подрезки.
| + | return p |
− | local ac,i={},1;
| |
− | while f.args[2*i] do ac[ tonumber(f.args[2*i]) or f.args[2*i] ] = f.args[2*i+1]; i=i+1 end;
| |
− | return f:getParent():expandTemplate{ title=f.args[1]; args=ac }
| |
− | end
| |
− | ]]
| |
− | return M | |