Модуль:Transclude: различия между версиями
Материал из ChronoWiki
Перейти к навигацииПерейти к поискуLirik (обсуждение | вклад) м (1 версия импортирована) |
Lirik (обсуждение | вклад) м (1 версия импортирована) |
||
| (не показана 1 промежуточная версия 1 участника) | |||
| Строка 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 } | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | return | ||
end | end | ||
| − | function | + | -- Общая реализация для forall и call |
| − | local | + | 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 = {} | local results = {} | ||
| − | for | + | for _, key in ipairs(keys) do |
| − | + | local value = func(args[key]) | |
| − | + | table.insert(results, value) | |
| − | |||
end | end | ||
| − | return mw.text.listToText( results, separator, conjunction ) | + | |
| + | return mw.text.listToText(results, separator, conjunction) | ||
end | end | ||
| − | function | + | -- Вызывает внутренний шаблон, передавая ему нумерованные параметры объемлющего шаблона по-одному |
| − | + | 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 | 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 | 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 | 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 | |
| − | return | + | 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 tf,ac,op=f:getParent(), {}, f.args.output or 'inline'; | local tf,ac,op=f:getParent(), {}, f.args.output or 'inline'; | ||
local sep=''; | local sep=''; | ||
| Строка 156: | Строка 151: | ||
return table.concat(acr, sep) | 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