Модуль:Transclude: различия между версиями
Материал из ChronoWiki
Перейти к навигацииПерейти к поиску (По запросу У:Wikisaurus) |
Lirik (обсуждение | вклад) м (1 версия импортирована) |
||
(не показаны 3 промежуточные версии 3 участников) | |||
Строка 1: | Строка 1: | ||
− | local | + | local p={} |
− | + | ||
− | -- | + | -- Вызывает внутренний шаблон с аргументами объемлющего шаблона |
− | + | function p.call(frame) | |
− | function | + | local template = frame.args[1] |
− | + | local args = frame:getParent().args | |
− | + | return frame:expandTemplate{ title=template, args=args } | |
− | + | end | |
− | + | ||
− | + | -- Общая реализация для forall и call | |
− | + | local function forallImpl(args, separator, conjunction, func) | |
− | + | -- нумерованные ключи из args | |
− | + | local keys = {} | |
− | + | -- перебор в произвольном порядке, даже для нумерованных ключей | |
− | + | for key, value in pairs(args) do | |
+ | if type(key) == 'number' and value and value ~= '' then | ||
+ | table.insert(keys, key) | ||
+ | end | ||
+ | end | ||
+ | table.sort(keys) | ||
+ | |||
+ | local results = {} | ||
+ | for _, key in ipairs(keys) do | ||
+ | local value = func(args[key]) | ||
+ | table.insert(results, value) | ||
+ | end | ||
+ | |||
+ | return mw.text.listToText(results, separator, conjunction) | ||
end | end | ||
− | function | + | -- Вызывает внутренний шаблон, передавая ему нумерованные параметры объемлющего шаблона по-одному |
+ | function p.forall(frame) | ||
local template = frame.args[1] | local template = frame.args[1] | ||
local separator = frame.args.separator or '' | local separator = frame.args.separator or '' | ||
local conjunction = frame.args.conjunction or separator | local conjunction = frame.args.conjunction or separator | ||
− | + | local args = frame:getParent().args | |
− | local | + | local func = function(value) |
− | + | return frame:expandTemplate{ title = template, args = {value} } -- или другой frame? | |
− | |||
− | |||
− | |||
end | end | ||
− | return | + | return forallImpl(args, separator, conjunction, func) |
end | end | ||
− | function | + | -- Берёт нумерованные аргументы объемлющего шаблона и склеивает их в единую строку |
− | + | function p.join(frame) | |
− | + | local separator = frame.args[1] or '' | |
− | + | local conjunction = frame.args[2] or separator | |
− | + | local args = frame:getParent().args | |
− | + | local func = function(value) | |
− | + | return value | |
− | + | end | |
− | + | return forallImpl(args, separator, conjunction, func) | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
end | end | ||
− | function | + | -- Служебная функция: удаляет дубликаты из отсортированного массива с нумерованными индексами |
− | + | 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 | + | -- Вызывает внутренний шаблон несколько раз, передавая в него блоки аргументов объемлющего шаблона |
− | + | function p.npc(frame) | |
+ | local args = frame:getParent().args | ||
+ | local templateFrame = frame:getParent() | ||
+ | local template = frame.args[1] | ||
+ | |||
+ | -- определение, блоки аргументов с какими номерами нужны: | ||
+ | -- если в объемлющем шаблоне есть "параметр12" и в вызове модуля есть "параметр", то вызывается 12-й блок | ||
+ | local nums = {} | ||
+ | for key, _ in pairs(args) do | ||
+ | local main, num = string.match(key, '^(.-)%s*(%d*)$') | ||
+ | num = tonumber(num) | ||
+ | -- учитывать "параметр12", только если задано "параметр" | ||
+ | if num and frame.args[main] then | ||
+ | table.insert(nums, num) | ||
+ | end | ||
+ | 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 | ||
− | + | -- Действует аналогично forall по числовой переменной, изменяющейся (по умолчанию, от 1) до f.args[2]. | |
− | + | function p.cycle(f) | |
− | local | + | local tf,ac,op=f:getParent(), {}, f.args.output or 'inline'; |
− | local | + | local sep=''; |
− | + | if op == 'newline' then | |
− | + | sep='\n'; | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
end | end | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
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 | ||
Строка 127: | Строка 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 | + | 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)} } | |
− | + | if order == 'desc' then | |
− | + | 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 |
− | + | 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 | ||
− | + | ||
− | + | return p | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | return |
Текущая версия на 22:47, 29 мая 2021
Для документации этого модуля может быть создана страница Модуль:Transclude/doc
local p={} -- Вызывает внутренний шаблон с аргументами объемлющего шаблона function p.call(frame) local template = frame.args[1] local args = frame:getParent().args return frame:expandTemplate{ title=template, args=args } end -- Общая реализация для forall и call local function forallImpl(args, separator, conjunction, func) -- нумерованные ключи из args local keys = {} -- перебор в произвольном порядке, даже для нумерованных ключей for key, value in pairs(args) do if type(key) == 'number' and value and value ~= '' then table.insert(keys, key) end end table.sort(keys) local results = {} for _, key in ipairs(keys) do local value = func(args[key]) table.insert(results, value) end return mw.text.listToText(results, separator, conjunction) end -- Вызывает внутренний шаблон, передавая ему нумерованные параметры объемлющего шаблона по-одному function p.forall(frame) local template = frame.args[1] local separator = frame.args.separator or '' local conjunction = frame.args.conjunction or separator local args = frame:getParent().args local func = function(value) return frame:expandTemplate{ title = template, args = {value} } -- или другой frame? end return forallImpl(args, separator, conjunction, func) end -- Берёт нумерованные аргументы объемлющего шаблона и склеивает их в единую строку function p.join(frame) local separator = frame.args[1] or '' local conjunction = frame.args[2] or separator local args = frame:getParent().args local func = function(value) return value end return forallImpl(args, separator, conjunction, func) end -- Служебная функция: удаляет дубликаты из отсортированного массива с нумерованными индексами 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 -- Вызывает внутренний шаблон несколько раз, передавая в него блоки аргументов объемлющего шаблона function p.npc(frame) local args = frame:getParent().args local templateFrame = frame:getParent() local template = frame.args[1] -- определение, блоки аргументов с какими номерами нужны: -- если в объемлющем шаблоне есть "параметр12" и в вызове модуля есть "параметр", то вызывается 12-й блок local nums = {} for key, _ in pairs(args) do local main, num = string.match(key, '^(.-)%s*(%d*)$') num = tonumber(num) -- учитывать "параметр12", только если задано "параметр" if num and frame.args[main] then table.insert(nums, num) end 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 -- Действует аналогично forall по числовой переменной, изменяющейся (по умолчанию, от 1) до f.args[2]. function p.cycle(f) local tf,ac,op=f:getParent(), {}, f.args.output or 'inline'; local sep=''; if op == 'newline' then sep='\n'; end for p,k in pairs(f.args) do if type(p)=='number' then if p>2 then ac[p-1]=k end else ac[p]=k end end local s,fh = f.args[2]:match('^%s*(%-?%d+)%s*%.%.') or 1, f.args[2]:match('%.%.%s*(%S.*)%s*$') or f.args[2] or ''; fh=tonumber(fh) or fh:match('^%s*(.-)%s*$'); s=tonumber(s); local acr={}; if not s then error('Начало цикла «'..s..'» — не число') end local function dc(order) local r=tf:expandTemplate{ title=f.args[1]; args={s,unpack(ac)} } if order == 'desc' then s=s-1; else s=s+1; end if r~='' then table.insert(acr,r); return r end end if type(fh)=='number' then if fh > s then while s<=fh do dc('asc') end else while s>=fh do dc('desc') end end elseif fh~='' then while tf:expandTemplate{ title=fh; args={s,unpack(ac)} } do dc('asc') end else while dc('asc') do end end return table.concat(acr, sep) end return p