|
|
| (не показано 20 промежуточных версий этого же участника) |
| Строка 1: |
Строка 1: |
| -- source: https://en.wikipedia.org/wiki/Module:Params
| | local p = {} |
| --- ---
| |
| --- LOCAL ENVIRONMENT ---
| |
| --- ________________________________ ---
| |
| --- ---
| |
|
| |
|
| | -- Загрузка данных |
| | local chemData = mw.loadData("Модуль:IanComradeBot/chem prototypes.json/data") |
| | local seedsData = mw.loadData("Модуль:IanComradeBot/prototypes/seeds.json/data") |
|
| |
|
| | | local function kelvinToCelsius(k) |
| --[[ Abstract utilities ]]--
| | return k - 273.15 |
| ----------------------------
| |
| | |
| | |
| -- Helper function for `string.gsub()` (for managing zero-padded numbers)
| |
| function zero_padded(str) | |
| return ("%03d%s"):format(#str, str)
| |
| end | | end |
|
| |
|
| | | local function findSeedById(id, data) |
| -- Helper function for `table.sort()` (for natural sorting)
| | for _, seed in ipairs(data) do |
| function natural_sort(var1, var2)
| | if seed.id == id then |
| return tostring(var1):gsub("%d+", zero_padded) <
| | return seed |
| tostring(var2):gsub("%d+", zero_padded)
| | end |
| | end |
| | return nil |
| end | | end |
|
| |
|
| | | local function formatCharacteristics(seed) |
| -- Return a copy or a reference to a table
| | local parts = { |
| local function copy_or_ref_table(src, refonly) | | ("[[Гидропоника#Потенция|Потенция]]: %s"):format(seed.potency or 1), |
| if refonly then return src end
| | ("[[Гидропоника#Урожайность|Урожайность]]: %s"):format(seed.yield), |
| newtab = {}
| | ("[[Гидропоника#Срок жизни|Срок жизни]]: %s"):format(seed.lifespan), |
| for key, val in pairs(src) do newtab[key] = val end
| | ("[[Гидропоника#Созревание|Созревание]]: %s"):format(seed.maturation), |
| return newtab
| | ("[[Гидропоника#Производство|Производство]]: %s"):format(seed.production), |
| | ("[[Гидропоника#Стадии роста|Стадии роста]]: %s"):format(seed.growthStages or 6), |
| | } |
| | return table.concat(parts, '<br>') |
| end | | end |
|
| |
|
| | | local function formatConditions(seed) |
| -- Remove numerical elements from a table, shifting everything to the left
| | local parts = { |
| function remove_numerical_keys(tbl, idx, len) | | ("[[Гидропоника#Потребление воды|Вода]]: %s"):format(seed.waterConsumption or 0.5), |
| local cache = {}
| | ("[[Гидропоника#Потребление нутриентов|Удобрение]]: %s"):format(seed.nutrientConsumption or 0.75), |
| local tmp = idx + len - 1
| | ("[[Гидропоника#Оптимальная температура|Темп.]]: %.2f°C"):format(kelvinToCelsius(seed.idealHeat or 293)), |
| for key, val in pairs(tbl) do
| | } |
| if type(key) == 'number' and key >= idx then
| | return table.concat(parts, '<br>') |
| if key > tmp then cache[key - len] = val end
| |
| tbl[key] = nil
| |
| end
| |
| end
| |
| for key, val in pairs(cache) do tbl[key] = val end
| |
| end | | end |
|
| |
|
| | | local function formatHarvestType(seed) |
| -- Make a reduced copy of a table (shifting in both directions if necessary)
| | return seed.harvestRepeat and "[[Гидропоника#Тип урожая|" .. tostring(seed.harvestRepeat) .. "]]" or "-" |
| function copy_table_reduced(tbl, idx, len) | |
| local ret = {}
| |
| local tmp = idx + len - 1
| |
| if idx > 0 then
| |
| for key, val in pairs(tbl) do
| |
| if type(key) ~= 'number' or key < idx then
| |
| ret[key] = val
| |
| elseif key > tmp then ret[key - len] = val end
| |
| end
| |
| elseif tmp > 0 then
| |
| local nshift = 1 - idx
| |
| for key, val in pairs(tbl) do
| |
| if type(key) ~= 'number' then ret[key] = val
| |
| elseif key > tmp then ret[key - tmp] = val
| |
| elseif key < idx then ret[key + nshift] = val end
| |
| end
| |
| else
| |
| for key, val in pairs(tbl) do
| |
| if type(key) ~= 'number' or key > tmp then
| |
| ret[key] = val
| |
| elseif key < idx then ret[key + len] = val end
| |
| end
| |
| end
| |
| return ret
| |
| end | | end |
| | | local function formatHarvestType(seed) |
| | | local harvestRepeat = seed.harvestRepeat |
| -- Make an expanded copy of a table (shifting in both directions if necessary)
| | if harvestRepeat == "Repeat" then |
| function copy_table_expanded(tbl, idx, len) | | return "[[Гидропоника#Тип урожая|Многолетнее]]" |
| local ret = {}
| | elseif harvestRepeat == "SelfHarvest" then |
| local tmp = idx + len - 1
| | return "[[Гидропоника#Тип урожая|Самосбор]]" |
| if idx > 0 then
| | else |
| for key, val in pairs(tbl) do
| | return "[[Гидропоника#Тип урожая|Однолетнее]]" |
| if type(key) ~= 'number' or key < idx then
| | end |
| ret[key] = val
| |
| else ret[key + len] = val end
| |
| end
| |
| elseif tmp > 0 then
| |
| local nshift = idx - 1
| |
| for key, val in pairs(tbl) do
| |
| if type(key) ~= 'number' then ret[key] = val
| |
| elseif key > 0 then ret[key + tmp] = val
| |
| elseif key < 1 then ret[key + nshift] = val end
| |
| end
| |
| else
| |
| for key, val in pairs(tbl) do
| |
| if type(key) ~= 'number' or key > tmp then
| |
| ret[key] = val
| |
| else ret[key - len] = val end
| |
| end
| |
| end
| |
| return ret
| |
| end | | end |
|
| |
|
| | | local function formatChemicals(seed) |
| -- Move a key from a table to another, but only if under a different name and | | if not seed.chemicals then return "-" end |
| -- always parsing numerical strings as numbers
| | local list = {} |
| function steal_if_renamed(val, src, skey, dest, dkey)
| | for chemId, vals in pairs(seed.chemicals) do |
| local realkey = tonumber(dkey) or dkey:match'^%s*(.-)%s*$'
| | local entry = chemData[chemId] |
| if skey ~= realkey then
| | local chemName = entry and entry.name or chemId |
| dest[realkey] = val
| | table.insert(list, string.format( |
| src[skey] = nil
| | "<li>[[Химия#chem_%s|%s]] (мин: %s, макс: %s, дел: %s)</li>", |
| end
| | chemId, chemName, vals.Min or 0, vals.Max or 0, vals.PotencyDivisor or 1 |
| | )) |
| | end |
| | return "<ul>" .. table.concat(list) .. "</ul>" |
| end | | end |
|
| |
|
| | | local function formatMutations(seed, data) |
| | | if not seed.mutationPrototypes then return "-" end |
| --[[ Public strings ]]--
| | local list = {} |
| ------------------------
| | for _, mu in ipairs(seed.mutationPrototypes) do |
| | | local target = findSeedById(mu, data) |
| | | if target and target.productPrototypes then |
| -- Special match keywords (functions and modifiers MUST avoid these names)
| | for _, prod in ipairs(target.productPrototypes) do |
| local mkeywords = {
| | table.insert(list, ("<li>{{Предмет|%s|link=Гидропоника#{{#invoke:Entity Lookup|getname|%s}}}}</li>"):format(prod, prod)) |
| ['or'] = 0,
| | end |
| --pattern = 1, -- Simply uncommenting enables the option
| | end |
| plain = 2,
| | end |
| strict = 3
| | return "<ul>" .. table.concat(list) .. "</ul>" |
| }
| |
| | |
| | |
| -- Sort functions (functions and modifiers MUST avoid these names)
| |
| local sortfunctions = { | |
| --alphabetically = false, -- Simply uncommenting enables the option
| |
| 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`)
| |
| | |
| ]]--
| |
| local mapping_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)
| |
| local memoryslots = {
| |
| i = 'itersep',
| |
| l = 'lastsep',
| |
| p = 'pairsep',
| |
| h = 'header',
| |
| f = 'footer',
| |
| n = 'ifngiven'
| |
| } | |
| | |
| | |
| -- Functions and modifiers MUST avoid these names too: `let`
| |
| | |
| | |
| | |
| --[[ Module's private environment ]]--
| |
| --------------------------------------
| |
| | |
| | |
| -- Maximum number of numerical 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)
| |
| local maxfill = 1024
| |
| | |
| | |
| -- The private table of functions
| |
| local library = {}
| |
| | |
| | |
| -- Functions that can only be invoked in first position
| |
| local static_iface = {}
| |
| | |
| | |
| -- Create a new context
| |
| local function context_new()
| |
| local ctx = {}
| |
| ctx.luaname = 'Module:Params' --[[ or `frame:getTitle()` ]]--
| |
| ctx.iterfunc = pairs
| |
| ctx.firstposonly = static_iface
| |
| ctx.n_available = maxfill
| |
| return ctx
| |
| end
| |
| | |
| | |
| -- Move to the next action within the user-given list
| |
| local function context_iterate(ctx, n_forward)
| |
| local nextfn
| |
| if ctx.pipe[n_forward] ~= nil then
| |
| nextfn = ctx.pipe[n_forward]:match'^%s*(.*%S)'
| |
| end
| |
| if nextfn == nil then error(ctx.luaname ..
| |
| ': You must specify a function to call', 0) end
| |
| if library[nextfn] == nil then
| |
| if ctx.firstposonly[nextfn] == nil then error(ctx.luaname ..
| |
| ': The function ‘' .. nextfn .. '’ does not exist', 0)
| |
| else error(ctx.luaname .. ': The ‘' .. nextfn ..
| |
| '’ directive can only appear in first position', 0)
| |
| end
| |
| end
| |
| remove_numerical_keys(ctx.pipe, 1, n_forward)
| |
| return library[nextfn]
| |
| end | | end |
|
| |
|
| | | local function generateHeader() |
| -- Main loop | | return [[ |
| local function main_loop(ctx, start_with)
| | {| id="BOTANY" class="wikitable sortable mw-collapsible" style="width:100%;" |
| local fn = start_with
| | ! rowspan="2" style="width:10%;" | Плод |
| repeat fn = fn(ctx) until not fn
| | ! rowspan="2" class="unsortable" style="width:5%;" | Семена |
| | ! rowspan="2" class="unsortable" style="width:5%;" | Растение |
| | ! colspan="3" class="unsortable" style="width:30%;" id="no-highlight" | Характеристики |
| | ! rowspan="2" class="unsortable" style="width:30%;" | Содержит вещества |
| | ! rowspan="2" style="width:20%;" | Мутации |
| | |- |
| | ! style="width:10%;" class="unsortable" | Рост |
| | ! style="width:10%;" class="unsortable" | Условия |
| | ! style="width:5%;" class="unsortable" | Тип сбора |
| | ]] |
| end | | end |
|
| |
|
| | | local function generateFooter() |
| -- Parse the arguments of the `mapping_*` and `renaming_*` class of modifiers
| | return "|}" |
| function parse_child_args(dest, src, n_skip, default_style) | |
| local style
| |
| local shf
| |
| local tmp = src[n_skip + 1]
| |
| if tmp ~= nil then style = mapping_styles[tmp:match'^%s*(.-)%s*$'] end
| |
| if style == nil then
| |
| style = default_style
| |
| shf = n_skip - 1
| |
| else shf = n_skip end
| |
| local names
| |
| local nargs
| |
| local pin = style[2] + shf
| |
| local n_exist = style[3]
| |
| local karg = style[4]
| |
| local varg = style[5]
| |
| tmp = style[6]
| |
| if tmp > -1 then
| |
| tmp = src[tmp + shf]
| |
| karg = tonumber(tmp)
| |
| if karg == nil then karg = tmp:match'^%s*(.-)%s*$'
| |
| else n_exist = math.max(n_exist, karg) end
| |
| end
| |
| tmp = style[7]
| |
| if tmp > -1 then
| |
| tmp = src[tmp + shf]
| |
| varg = tonumber(tmp)
| |
| if varg == nil then varg = tmp:match'^%s*(.-)%s*$'
| |
| else n_exist = math.max(n_exist, varg) end
| |
| end
| |
| if src[pin] ~= nil and src[pin]:match'^%s*let%s*$' then
| |
| names = {}
| |
| repeat
| |
| tmp = src[pin + 1] or ''
| |
| names[tonumber(tmp) or tmp:match'^%s*(.-)%s*$' or ''] =
| |
| src[pin + 2]
| |
| pin = pin + 3
| |
| until src[pin] == nil or not src[pin]:match'^%s*let%s*$'
| |
| end
| |
| tmp = tonumber(src[pin])
| |
| if tmp ~= nil then
| |
| if tmp < 0 then tmp = -1 end
| |
| shf = n_exist - pin
| |
| for idx = pin + 1, pin + tmp do dest[idx + shf] = src[idx] end
| |
| nargs = pin + tmp + 1
| |
| else nargs = pin end
| |
| if names ~= nil then
| |
| for key, val in pairs(names) do dest[key] = val end
| |
| end
| |
| tmp = style[1]
| |
| if (tmp == 3 or tmp == 2) and dest[karg] ~= nil then
| |
| tmp = tmp - 2 end
| |
| if (tmp == 3 or tmp == 1) and dest[varg] ~= nil then
| |
| tmp = tmp - 1 end
| |
| return nargs, tmp, karg, varg
| |
| end | | end |
|
| |
|
| | function p.table(frame) |
| | local data = mw.loadData("Модуль:IanComradeBot/prototypes/seeds.json/data") |
| | local rows = {} |
|
| |
|
| -- Parse the arguments of the `with_*_matching` class of modifiers
| | for _, seed in ipairs(data) do |
| local function parse_pattern_args(ctx, ptns, fname)
| | local prodId = seed.productPrototypes[1] |
| local state = 0
| | local seedId = seed.packetPrototype |
| local cnt = 1
| | local seedName = string.format('{{#invoke:Entity Lookup|getname|%s}}', seedId) |
| local keyw
| |
| local nptns = 0
| |
| for _, val in ipairs(ctx.pipe) do
| |
| if state == 0 then
| |
| nptns = nptns + 1
| |
| ptns[nptns] = { val, false, false }
| |
| state = -1
| |
| else
| |
| keyw = val:match'^%s*(.*%S)'
| |
| if keyw == nil or mkeywords[keyw] == nil or (
| |
| state > 0 and mkeywords[keyw] > 0
| |
| ) then break
| |
| else
| |
| state = mkeywords[keyw]
| |
| if state > 1 then ptns[nptns][2] = true end
| |
| if state == 3 then ptns[nptns][3] = true end
| |
| end
| |
| end
| |
| cnt = cnt + 1
| |
| end
| |
| if state == 0 then error(ctx.luaname .. ', ‘' .. fname ..
| |
| '’: No pattern was given', 0) end
| |
| return cnt
| |
| end
| |
|
| |
|
| | local anchor = string.format('{{anchor|%s}}', seedName) |
| | local fruitImg = string.format( |
| | '{{Предмет|%s|size=64px|vertical=1|imageTooltip=1|link=%s}}', |
| | prodId, seedName |
| | ) |
| | local seedImg = string.format( |
| | '{{Предмет|%s|size=64px|vertical=1|imageTooltip=1|l=|link=%s}}', |
| | seedId, seedName |
| | ) |
| | local plantImg = string.format( |
| | '{{Предмет|%s-harvest|size=64px|l=|link=%s}}', |
| | seedId, seedName |
| | ) |
|
| |
|
| -- Map parameters' values using a custom callback and a referenced table
| | local colGrowth = formatCharacteristics(seed) |
| function map_values(tbl, margs, karg, varg, looptype, fn)
| | local colConditions = formatConditions(seed) |
| if looptype == 1 then
| | local colHarvest = formatHarvestType(seed) |
| for key, val in pairs(tbl) do
| | local colChemicals = formatChemicals(seed) |
| margs[varg] = val
| | local colMutations = formatMutations(seed, data) |
| tbl[key] = fn()
| |
| end
| |
| elseif looptype == 3 then
| |
| for key, val in pairs(tbl) do
| |
| margs[karg] = key
| |
| margs[varg] = val
| |
| tbl[key] = fn()
| |
| end
| |
| elseif looptype == 2 then
| |
| for key in pairs(tbl) do
| |
| margs[karg] = key
| |
| tbl[key] = fn()
| |
| end
| |
| elseif looptype == 0 then
| |
| for key in pairs(tbl) do
| |
| tbl[key] = fn()
| |
| end
| |
| end
| |
| end
| |
|
| |
|
| | local row = frame:preprocess(string.format( |
| | [[|- |
| | ! %s |
| | ! %s |
| | ! %s |
| | | %s |
| | | %s |
| | | %s |
| | | %s |
| | | %s ]], |
| | fruitImg, seedImg, plantImg, |
| | colGrowth, colConditions, colHarvest, |
| | colChemicals, colMutations |
| | )) |
| | table.insert(rows, row) |
| | end |
|
| |
|
| -- Map parameters' names using a custom callback and a referenced table
| | return generateHeader() .. table.concat(rows, '\n') .. '\n' .. generateFooter() |
| function map_names(tbl, rargs, karg, varg, looptype, fn)
| |
| local cache = {}
| |
| if looptype == 2 then
| |
| for key, val in pairs(tbl) do
| |
| rargs[karg] = key
| |
| steal_if_renamed(val, tbl, key, cache, fn())
| |
| end
| |
| elseif looptype == 3 then
| |
| for key, val in pairs(tbl) do
| |
| rargs[karg] = key
| |
| rargs[varg] = val
| |
| steal_if_renamed(val, tbl, key, cache, fn())
| |
| end
| |
| elseif looptype == 1 then
| |
| for key, val in pairs(tbl) do
| |
| rargs[varg] = val
| |
| steal_if_renamed(val, tbl, key, cache, fn())
| |
| end
| |
| elseif looptype == 0 then
| |
| for key, val in pairs(tbl) do
| |
| steal_if_renamed(val, tbl, key, cache, fn())
| |
| end
| |
| end
| |
| for key, val in pairs(cache) do tbl[key] = val end
| |
| end | | end |
|
| |
|
| | function p.main(frame) |
| | local args = frame.args |
| | local id = args[1] |
| | local mode = mw.text.trim(args[2] or ""):lower() |
| | local seed = findSeedById(id, seedsData) |
| | if not seed then return "" end |
|
| |
|
| -- Concatenate the numerical keys from the table of parameters to the numerical
| | if mode == "growth" then |
| -- keys from the table of options; non-numerical keys from the table of options
| | return formatCharacteristics(seed) |
| -- will prevail over colliding non-numerical keys from the table of parameters
| | elseif mode == "conditions" then |
| local function concat_params(ctx)
| | return formatConditions(seed) |
| local tbl = ctx.params
| | elseif mode == "harvest" then |
| local size = table.maxn(ctx.pipe)
| | return formatHarvestType(seed) |
| local retval = {}
| | elseif mode == "chemicals" then |
| if ctx.subset == 1 then
| | return formatChemicals(seed) |
| -- We need only the sequence
| | elseif mode == "mutations" then |
| for key, val in ipairs(tbl) do retval[key + size] = val end
| | return formatMutations(seed, seedsData) |
| else
| | else |
| if ctx.subset == -1 then
| | return "" |
| for key, val in ipairs(tbl) do tbl[key] = nil end
| | end |
| end
| |
| for key, val in pairs(tbl) do
| |
| if type(key) == 'number' then retval[key + size] = val
| |
| else retval[key] = val end
| |
| end
| |
| end
| |
| for key, val in pairs(ctx.pipe) do retval[key] = val end
| |
| return retval
| |
| end | | end |
|
| |
|
| | | return p |
| -- Flush the parameters by calling a custom function for each value (after this
| |
| -- function has been invoked `ctx.params` will be no longer usable)
| |
| local function flush_params(ctx, fn)
| |
| local tbl = ctx.params
| |
| if ctx.subset == 1 then
| |
| for key, val in ipairs(tbl) do fn(key, val) end
| |
| return
| |
| end
| |
| if ctx.subset == -1 then
| |
| for key, val in ipairs(tbl) do tbl[key] = nil end
| |
| end
| |
| if ctx.dosort then
| |
| local nums = {}
| |
| local words = {}
| |
| local nlen = 0
| |
| local wlen = 0
| |
| for key, val in pairs(tbl) do
| |
| if type(key) == 'number' then
| |
| nlen = nlen + 1
| |
| nums[nlen] = key
| |
| else
| |
| wlen = wlen + 1
| |
| words[wlen] = key
| |
| end
| |
| end
| |
| table.sort(nums)
| |
| table.sort(words, natural_sort)
| |
| for idx = 1, nlen do fn(nums[idx], tbl[nums[idx]]) end
| |
| for idx = 1, wlen do fn(words[idx], tbl[words[idx]]) end
| |
| return
| |
| end
| |
| if ctx.subset ~= -1 then
| |
| for key, val in ipairs(tbl) do
| |
| fn(key, val)
| |
| tbl[key] = nil
| |
| end
| |
| end
| |
| for key, val in pairs(tbl) do fn(key, val) end
| |
| end
| |
| | |
| | |
| | |
| --[[ Modifiers ]]--
| |
| -----------------------------
| |
| | |
| | |
| -- Syntax: #invoke:params|sequential|pipe to
| |
| library.sequential = function(ctx)
| |
| if ctx.subset == -1 then error(ctx.luaname ..
| |
| ': The two directives ‘non-sequential’ and ‘sequential’ are in contradiction with each other', 0) end
| |
| if ctx.dosort then error(ctx.luaname ..
| |
| ': The ‘all_sorted’ directive is redundant when followed by ‘sequential’', 0) end
| |
| ctx.iterfunc = ipairs
| |
| ctx.subset = 1
| |
| return context_iterate(ctx, 1)
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|non-sequential|pipe to
| |
| library['non-sequential'] = function(ctx)
| |
| if ctx.subset == 1 then error(ctx.luaname ..
| |
| ': The two directives ‘sequential’ and ‘non-sequential’ are in contradiction with each other', 0) end
| |
| ctx.iterfunc = pairs
| |
| ctx.subset = -1
| |
| return context_iterate(ctx, 1)
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|sort|pipe to
| |
| library.all_sorted = function(ctx)
| |
| if ctx.subset == 1 then error(ctx.luaname ..
| |
| ': The ‘all_sorted’ directive is redundant after ‘sequential’', 0) end
| |
| ctx.dosort = true
| |
| return context_iterate(ctx, 1)
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|setting|directives|...|pipe to
| |
| library.setting = function(ctx)
| |
| local opts = ctx.pipe
| |
| local cmd = opts[1]
| |
| if cmd ~= nil then
| |
| cmd = cmd:gsub('%s+', ''):gsub('/+', '/'):match'^/*(.*[^/])'
| |
| end
| |
| if cmd == nil then error(ctx.luaname ..
| |
| ', ‘setting’: No directive was given', 0) end
| |
| local sep = string.byte('/')
| |
| local argc = 2
| |
| local dest = {}
| |
| local vname
| |
| local chr
| |
| for idx = 1, #cmd do
| |
| chr = cmd:byte(idx)
| |
| if chr == sep then
| |
| for key, val in ipairs(dest) do
| |
| ctx[val] = opts[argc]
| |
| dest[key] = nil
| |
| end
| |
| argc = argc + 1
| |
| else
| |
| vname = memoryslots[string.char(chr)]
| |
| if vname == nil then error(ctx.luaname ..
| |
| ', ‘setting’: Unknown slot "' ..
| |
| string.char(chr) .. '"', 0) end
| |
| table.insert(dest, vname)
| |
| end
| |
| end
| |
| for key, val in ipairs(dest) do ctx[val] = opts[argc] end
| |
| return context_iterate(ctx, argc + 1)
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|squeezing|pipe to
| |
| library.squeezing = function(ctx)
| |
| local tbl = ctx.params
| |
| local store = {}
| |
| local indices = {}
| |
| local newlen = 0
| |
| for key, val in pairs(tbl) do
| |
| if type(key) == 'number' then
| |
| newlen = newlen + 1
| |
| indices[newlen] = key
| |
| store[key] = val
| |
| tbl[key] = nil
| |
| end
| |
| end
| |
| table.sort(indices)
| |
| for idx = 1, newlen do tbl[idx] = store[indices[idx]] end
| |
| return context_iterate(ctx, 1)
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|filling_the_gaps|pipe to
| |
| library.filling_the_gaps = function(ctx)
| |
| local tbl = ctx.params
| |
| local nmin = 1
| |
| local nmax = nil
| |
| local nnums = -1
| |
| local tmp = {}
| |
| for key, val in pairs(tbl) do
| |
| if type(key) == 'number' then
| |
| if nmax == nil then
| |
| if key < nmin then nmin = key end
| |
| nmax = key
| |
| elseif key > nmax then nmax = key
| |
| elseif key < nmin then nmin = key end
| |
| nnums = nnums + 1
| |
| tmp[key] = val
| |
| end
| |
| end
| |
| if nmax ~= nil and nmax - nmin > nnums then
| |
| ctx.n_available = ctx.n_available + nmin + nnums - nmax
| |
| if ctx.n_available < 0 then error(ctx.luaname ..
| |
| ', ‘filling_the_gaps’: It is possible to fill at most ' ..
| |
| tostring(maxfill) .. ' parameters', 0) end
| |
| for idx = nmin, nmax, 1 do tbl[idx] = '' end
| |
| for key, val in pairs(tmp) do tbl[key] = val end
| |
| end
| |
| return context_iterate(ctx, 1)
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|clearing|pipe to
| |
| library.clearing = function(ctx)
| |
| local tbl = ctx.params
| |
| local numericals = {}
| |
| for key, val in pairs(tbl) do
| |
| if type(key) == 'number' then
| |
| numericals[key] = val
| |
| tbl[key] = nil
| |
| end
| |
| end
| |
| for key, val in ipairs(numericals) do tbl[key] = val end
| |
| return context_iterate(ctx, 1)
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|cutting|left cut|right cut|pipe to
| |
| library.cutting = function(ctx)
| |
| local lcut = tonumber(ctx.pipe[1])
| |
| if lcut == nil then error(ctx.luaname ..
| |
| ', ‘cutting’: Left cut must be a number', 0) end
| |
| local rcut = tonumber(ctx.pipe[2])
| |
| if rcut == nil then error(ctx.luaname ..
| |
| ', ‘cutting’: Right cut must be a number', 0) end
| |
| local tbl = ctx.params
| |
| local len = #tbl
| |
| if lcut < 0 then lcut = len + lcut end
| |
| if rcut < 0 then rcut = len + rcut end
| |
| local tot = lcut + rcut
| |
| if tot > 0 then
| |
| local cache = {}
| |
| if tot >= len then
| |
| for key in ipairs(tbl) do tbl[key] = nil end
| |
| tot = len
| |
| else
| |
| for idx = len - rcut + 1, len, 1 do tbl[idx] = nil end
| |
| for idx = 1, lcut, 1 do tbl[idx] = nil end
| |
| end
| |
| for key, val in pairs(tbl) do
| |
| if type(key) == 'number' and key > 0 then
| |
| if key > len then cache[key - tot] = val
| |
| else cache[key - lcut] = val end
| |
| tbl[key] = nil
| |
| end
| |
| end
| |
| for key, val in pairs(cache) do tbl[key] = val end
| |
| end
| |
| return context_iterate(ctx, 3)
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|cropping|left crop|right crop|pipe to
| |
| library.cropping = function(ctx)
| |
| local lcut = tonumber(ctx.pipe[1])
| |
| if lcut == nil then error(ctx.luaname ..
| |
| ', ‘cropping’: Left crop must be a number', 0) end
| |
| local rcut = tonumber(ctx.pipe[2])
| |
| if rcut == nil then error(ctx.luaname ..
| |
| ', ‘cropping’: Right crop must be a number', 0) end
| |
| local tbl = ctx.params
| |
| local nmin
| |
| local nmax
| |
| for key in pairs(tbl) do
| |
| if type(key) == 'number' then
| |
| if nmin == nil then
| |
| nmin = key
| |
| nmax = key
| |
| elseif key > nmax then nmax = key
| |
| elseif key < nmin then nmin = key end
| |
| end
| |
| end
| |
| if nmin ~= nil then
| |
| local len = nmax - nmin + 1
| |
| if lcut < 0 then lcut = len + lcut end
| |
| if rcut < 0 then rcut = len + rcut end
| |
| if lcut + rcut - len > -1 then
| |
| for key in pairs(tbl) do
| |
| if type(key) == 'number' then tbl[key] = nil end
| |
| end
| |
| elseif lcut + rcut > 0 then
| |
| for idx = nmax - rcut + 1, nmax do tbl[idx] = nil end
| |
| for idx = nmin, nmin + lcut - 1 do tbl[idx] = nil end
| |
| local lshift = nmin + lcut - 1
| |
| if lshift > 0 then
| |
| for idx = lshift + 1, nmax, 1 do
| |
| tbl[idx - lshift] = tbl[idx]
| |
| tbl[idx] = nil
| |
| end
| |
| end
| |
| end
| |
| end
| |
| return context_iterate(ctx, 3)
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|purging|start offset|length|pipe to
| |
| library.purging = function(ctx)
| |
| local idx = tonumber(ctx.pipe[1])
| |
| if idx == nil then error(ctx.luaname ..
| |
| ', ‘purging’: Start offset must be a number', 0) end
| |
| local len = tonumber(ctx.pipe[2])
| |
| if len == nil then error(ctx.luaname ..
| |
| ', ‘purging’: Length must be a number', 0) end
| |
| local tbl = ctx.params
| |
| if len < 1 then
| |
| len = len + table.maxn(tbl)
| |
| if idx > len then return context_iterate(ctx, 3) end
| |
| len = len - idx + 1
| |
| end
| |
| ctx.params = copy_table_reduced(tbl, idx, len)
| |
| return context_iterate(ctx, 3)
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|backpurging|start offset|length|pipe to
| |
| library.backpurging = function(ctx)
| |
| local last = tonumber(ctx.pipe[1])
| |
| if last == nil then error(ctx.luaname ..
| |
| ', ‘backpurging’: Start offset must be a number', 0) end
| |
| local len = tonumber(ctx.pipe[2])
| |
| if len == nil then error(ctx.luaname ..
| |
| ', ‘backpurging’: Length must be a number', 0) end
| |
| local idx
| |
| local tbl = ctx.params
| |
| if len > 0 then
| |
| idx = last - len + 1
| |
| else
| |
| for key in pairs(tbl) do
| |
| if type(key) == 'number' and (idx == nil or
| |
| key < idx) then idx = key end
| |
| end
| |
| if idx == nil then return context_iterate(ctx, 3) end
| |
| idx = idx - len
| |
| if last < idx then return context_iterate(ctx, 3) end
| |
| len = last - idx + 1
| |
| end
| |
| ctx.params = copy_table_reduced(ctx.params, idx, len)
| |
| return context_iterate(ctx, 3)
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|rotating|pipe to
| |
| library.rotating = function(ctx)
| |
| local tbl = ctx.params
| |
| local numericals = {}
| |
| local nmax = 0
| |
| for key, val in pairs(tbl) do
| |
| if type(key) == 'number' then
| |
| numericals[key] = val
| |
| tbl[key] = nil
| |
| if key > nmax then nmax = key end
| |
| end
| |
| end
| |
| for key, val in pairs(numericals) do tbl[nmax - key + 1] = val end
| |
| return context_iterate(ctx, 1)
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|pivoting|pipe to
| |
| --[[
| |
| library.pivoting = function(ctx)
| |
| local tbl = ctx.params
| |
| local shift = #tbl + 1
| |
| if shift < 2 then return library.rotating(ctx) end
| |
| local numericals = {}
| |
| for key, val in pairs(tbl) do
| |
| if type(key) == 'number' then
| |
| numericals[key] = val
| |
| tbl[key] = nil
| |
| end
| |
| end
| |
| for key, val in pairs(numericals) do tbl[shift - key] = val end
| |
| return context_iterate(ctx, 1)
| |
| end
| |
| ]]--
| |
| | |
| | |
| -- Syntax: #invoke:params|mirroring|pipe to
| |
| --[[
| |
| library.mirroring = function(ctx)
| |
| local tbl = ctx.params
| |
| local numericals = {}
| |
| local nmax
| |
| local nmin
| |
| for key, val in pairs(tbl) do
| |
| if type(key) == 'number' then
| |
| numericals[key] = val
| |
| tbl[key] = nil
| |
| if nmax == nil then
| |
| nmax = key
| |
| nmin = key
| |
| elseif key > nmax then nmax = key
| |
| elseif key < nmin then nmin = key end
| |
| end
| |
| end
| |
| for key, val in pairs(numericals) do tbl[nmax + nmin - key] = val end
| |
| return context_iterate(ctx, 1)
| |
| end
| |
| ]]--
| |
| | |
| | |
| -- Syntax: #invoke:params|swapping|pipe to
| |
| --[[
| |
| library.swapping = function(ctx)
| |
| local tbl = ctx.params
| |
| local cache = {}
| |
| local nsize = 0
| |
| local tmp
| |
| 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)
| |
| local sortfn
| |
| if ctx.pipe[1] ~= nil then sortfn = sortfunctions[ctx.pipe[1]] end
| |
| if sortfn then table.sort(ctx.params, sortfn)
| |
| else table.sort(ctx.params) end -- i.e. either `false` or `nil`
| |
| if sortfn == nil then return context_iterate(ctx, 1) end
| |
| return context_iterate(ctx, 2)
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|inserting|position|how many|...|pipe to
| |
| --[[
| |
| library.inserting = function(ctx)
| |
| -- NOTE: `ctx.params` might be the original metatable! As a modifier,
| |
| -- this function MUST create a copy of it before returning
| |
| local idx = tonumber(ctx.pipe[1])
| |
| if idx == nil then error(ctx.luaname ..
| |
| ', ‘inserting’: Position must be a number', 0) end
| |
| local len = tonumber(ctx.pipe[2])
| |
| if len == nil or len < 1 then error(ctx.luaname ..
| |
| ', ‘inserting’: The amount must be a number greater than zero', 0) end
| |
| local opts = ctx.pipe
| |
| local tbl = copy_table_expanded(ctx.params, idx, len)
| |
| for key = idx, idx + len - 1 do tbl[key] = opts[key - idx + 3] end
| |
| ctx.params = tbl
| |
| return context_iterate(ctx, len + 3)
| |
| end
| |
| ]]--
| |
| | |
| | |
| -- Syntax: #invoke:params|imposing|name|value|pipe to
| |
| library.imposing = function(ctx)
| |
| if ctx.pipe[1] == nil then error(ctx.luaname ..
| |
| ', ‘imposing’: Missing parameter name to impose', 0) end
| |
| local key = ctx.pipe[1]:match'^%s*(.-)%s*$'
| |
| ctx.params[tonumber(key) or key] = ctx.pipe[2]
| |
| return context_iterate(ctx, 3)
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|discarding|name|[how many]|pipe to
| |
| library.discarding = function(ctx)
| |
| if ctx.pipe[1] == nil then error(ctx.luaname ..
| |
| ', ‘discarding’: Missing parameter name to discard', 0) end
| |
| local key = ctx.pipe[1]
| |
| local len = tonumber(ctx.pipe[2])
| |
| if len == nil then
| |
| ctx.params[tonumber(key) or key:match'^%s*(.-)%s*$'] = nil
| |
| return context_iterate(ctx, 2)
| |
| end
| |
| key = tonumber(key)
| |
| if key == nil then error(ctx.luaname ..
| |
| ', ‘discarding’: A range was provided, but the initial parameter name is not numerical', 0) end
| |
| if len < 1 then error(ctx.luaname ..
| |
| ', ‘discarding’: A range can only be a number greater than zero', 0) end
| |
| for idx = key, key + len - 1 do ctx.params[idx] = nil end
| |
| return context_iterate(ctx, 3)
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|with_name_matching|pattern 1|[plain flag 1]|[or]
| |
| -- |[pattern 2]|[plain flag 2]|[or]|[...]|[pattern N]|[plain flag
| |
| -- N]|pipe to
| |
| library.with_name_matching = function(ctx)
| |
| local tbl = ctx.params
| |
| local patterns = {}
| |
| local argc = parse_pattern_args(ctx, patterns, 'with_name_matching')
| |
| local nomatch
| |
| for key in pairs(tbl) do
| |
| nomatch = true
| |
| for _, ptn in ipairs(patterns) do
| |
| if not ptn[3] then
| |
| if string.find(key, ptn[1], 1, ptn[2]) then
| |
| nomatch = false
| |
| break
| |
| end
| |
| elseif key == ptn[1] then
| |
| nomatch = false
| |
| break
| |
| end
| |
| end
| |
| if nomatch then tbl[key] = nil end
| |
| end
| |
| return context_iterate(ctx, argc)
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|with_name_not_matching|pattern 1|[plain flag 1]
| |
| -- |[and]|[pattern 2]|[plain flag 2]|[and]|[...]|[pattern N]|[plain
| |
| -- flag N]|pipe to
| |
| library.with_name_not_matching = function(ctx)
| |
| local tbl = ctx.params
| |
| local patterns = {}
| |
| local argc = parse_pattern_args(ctx, patterns,
| |
| 'with_name_not_matching')
| |
| local yesmatch
| |
| for key in pairs(tbl) do
| |
| yesmatch = true
| |
| for _, ptn in ipairs(patterns) do
| |
| if ptn[3] then
| |
| if key ~= ptn[1] then
| |
| yesmatch = false
| |
| break
| |
| end
| |
| elseif not string.find(key, ptn[1], 1, ptn[2]) then
| |
| yesmatch = false
| |
| break
| |
| end
| |
| end
| |
| if yesmatch then tbl[key] = nil end
| |
| end
| |
| return context_iterate(ctx, argc)
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|with_value_matching|pattern 1|[plain flag 1]|[or]
| |
| -- |[pattern 2]|[plain flag 2]|[or]|[...]|[pattern N]|[plain flag
| |
| -- N]|pipe to
| |
| library.with_value_matching = function(ctx)
| |
| local tbl = ctx.params
| |
| local patterns = {}
| |
| local argc = parse_pattern_args(ctx, patterns, 'with_value_matching')
| |
| local nomatch
| |
| for key, val in pairs(tbl) do
| |
| nomatch = true
| |
| for _, ptn in ipairs(patterns) do
| |
| if ptn[3] then
| |
| if val == ptn[1] then
| |
| nomatch = false
| |
| break
| |
| end
| |
| elseif string.find(val, ptn[1], 1, ptn[2]) then
| |
| nomatch = false
| |
| break
| |
| end
| |
| end
| |
| if nomatch then tbl[key] = nil end
| |
| end
| |
| return context_iterate(ctx, argc)
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|with_value_not_matching|pattern 1|[plain flag 1]
| |
| -- |[and]|[pattern 2]|[plain flag 2]|[and]|[...]|[pattern N]|[plain
| |
| -- flag N]|pipe to
| |
| library.with_value_not_matching = function(ctx)
| |
| local tbl = ctx.params
| |
| local patterns = {}
| |
| local argc = parse_pattern_args(ctx, patterns,
| |
| 'with_value_not_matching')
| |
| local yesmatch
| |
| for key, val in pairs(tbl) do
| |
| yesmatch = true
| |
| for _, ptn in ipairs(patterns) do
| |
| if ptn[3] then
| |
| if val ~= ptn[1] then
| |
| yesmatch = false
| |
| break
| |
| end
| |
| elseif not string.find(val, ptn[1], 1, ptn[2]) then
| |
| yesmatch = false
| |
| break
| |
| end
| |
| end
| |
| if yesmatch then tbl[key] = nil end
| |
| end
| |
| return context_iterate(ctx, argc)
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|trimming_values|pipe to
| |
| library.trimming_values = function(ctx)
| |
| local tbl = ctx.params
| |
| for key, val in pairs(tbl) do tbl[key] = val:match'^%s*(.-)%s*$' end
| |
| return context_iterate(ctx, 1)
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|mapping_by_calling|template name|[call
| |
| -- style]|[let]|[...][number of additional parameters]|[parameter
| |
| -- 1]|[parameter 2]|[...]|[parameter N]|pipe to
| |
| library.mapping_by_calling = function(ctx)
| |
| local opts = ctx.pipe
| |
| local tname
| |
| if opts[1] ~= nil then tname = opts[1]:match'^%s*(.*%S)' end
| |
| if tname == nil then error(ctx.luaname ..
| |
| ', ‘mapping_by_calling’: No template name was provided', 0) end
| |
| local margs = {}
| |
| local argc, looptype, karg, varg = parse_child_args(margs, opts, 1,
| |
| mapping_styles.values_only)
| |
| local model = { title = tname, args = margs }
| |
| map_values(ctx.params, margs, karg, varg, looptype, function()
| |
| return ctx.frame:expandTemplate(model)
| |
| end)
| |
| return context_iterate(ctx, argc)
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|mapping_by_invoking|module name|function
| |
| -- name|[call style]|[let]|[...]|[number of additional
| |
| -- arguments]|[argument 1]|[argument 2]|[...]|[argument N]|pipe to
| |
| library.mapping_by_invoking = function(ctx)
| |
| local opts = ctx.pipe
| |
| local mname
| |
| local fname
| |
| if opts[1] ~= nil then mname = opts[1]:match'^%s*(.*%S)' end
| |
| if mname == nil then error(ctx.luaname ..
| |
| ', ‘mapping_by_invoking’: No module name was provided', 0) end
| |
| if opts[2] ~= nil then fname = opts[2]:match'^%s*(.*%S)' end
| |
| if fname == nil then error(ctx.luaname ..
| |
| ', ‘mapping_by_invoking’: No function name was provided', 0) end
| |
| local margs = {}
| |
| local argc, looptype, karg, varg = parse_child_args(margs, opts, 2,
| |
| mapping_styles.values_only)
| |
| local model = { title = 'Module:' .. mname, args = margs }
| |
| local mfunc = require(model.title)[fname]
| |
| if mfunc == nil then error(ctx.luaname ..
| |
| ', ‘mapping_by_invoking’: The function ‘' .. fname ..
| |
| '’ does not exist', 0) end
| |
| map_values(ctx.params, margs, karg, varg, looptype, function()
| |
| return mfunc(ctx.frame:newChild(model))
| |
| end)
| |
| return context_iterate(ctx, argc)
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|mapping_by_magic|parser function|[call
| |
| -- style]|[let]|[...][number of additional arguments]|[argument
| |
| -- 1]|[argument 2]|[...]|[argument N]|pipe to
| |
| library.mapping_by_magic = function(ctx)
| |
| local opts = ctx.pipe
| |
| local magic
| |
| if opts[1] ~= nil then magic = opts[1]:match'^%s*(.*%S)' end
| |
| if magic == nil then error(ctx.luaname ..
| |
| ', ‘mapping_by_magic’: No parser function was provided', 0) end
| |
| local margs = {}
| |
| local argc, looptype, karg, varg = parse_child_args(margs, opts, 1,
| |
| mapping_styles.values_only)
| |
| map_values(ctx.params, margs, karg, varg, looptype, function()
| |
| return ctx.frame:callParserFunction(magic, margs)
| |
| end)
| |
| return context_iterate(ctx, argc)
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|renaming_by_calling|template name|[call
| |
| -- style]|[let]|[...][number of additional parameters]|[parameter
| |
| -- 1]|[parameter 2]|[...]|[parameter N]|pipe to
| |
| library.renaming_by_calling = function(ctx)
| |
| local opts = ctx.pipe
| |
| local tname
| |
| if opts[1] ~= nil then tname = opts[1]:match'^%s*(.*%S)' end
| |
| if tname == nil then error(ctx.luaname ..
| |
| ', ‘renaming_by_calling’: No template name was provided', 0) end
| |
| local rargs = {}
| |
| local argc, looptype, karg, varg = parse_child_args(rargs, opts, 1,
| |
| mapping_styles.names_only)
| |
| local model = { title = tname, args = rargs }
| |
| map_names(ctx.params, rargs, karg, varg, looptype, function()
| |
| return ctx.frame:expandTemplate(model)
| |
| end)
| |
| return context_iterate(ctx, argc)
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|renaming_by_invoking|module name|function
| |
| -- name|[call style]|[let]|[...]|[number of additional
| |
| -- arguments]|[argument 1]|[argument 2]|[...]|[argument N]|pipe to
| |
| library.renaming_by_invoking = function(ctx)
| |
| local opts = ctx.pipe
| |
| local mname
| |
| local fname
| |
| if opts[1] ~= nil then mname = opts[1]:match'^%s*(.*%S)' end
| |
| if mname == nil then error(ctx.luaname ..
| |
| ', ‘renaming_by_invoking’: No module name was provided', 0) end
| |
| if opts[2] ~= nil then fname = opts[2]:match'^%s*(.*%S)' end
| |
| if fname == nil then error(ctx.luaname ..
| |
| ', ‘renaming_by_invoking’: No function name was provided', 0) end
| |
| local rargs = {}
| |
| local argc, looptype, karg, varg = parse_child_args(rargs, opts, 2,
| |
| mapping_styles.names_only)
| |
| local model = { title = 'Module:' .. mname, args = rargs }
| |
| local mfunc = require(model.title)[fname]
| |
| if mfunc == nil then error(ctx.luaname ..
| |
| ', ‘renaming_by_invoking’: The function ‘' .. fname ..
| |
| '’ does not exist', 0) end
| |
| map_names(ctx.params, rargs, karg, varg, looptype, function()
| |
| return mfunc(ctx.frame:newChild(model))
| |
| end)
| |
| return context_iterate(ctx, argc)
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|renaming_by_magic|parser function|[call
| |
| -- style]|[let]|[...][number of additional arguments]|[argument
| |
| -- 1]|[argument 2]|[...]|[argument N]|pipe to
| |
| library.renaming_by_magic = function(ctx)
| |
| local opts = ctx.pipe
| |
| local magic
| |
| if opts[1] ~= nil then magic = opts[1]:match'^%s*(.*%S)' end
| |
| if magic == nil then error(ctx.luaname ..
| |
| ', ‘renaming_by_magic’: No parser function was provided', 0) end
| |
| local rargs = {}
| |
| local argc, looptype, karg, varg = parse_child_args(rargs, opts, 1,
| |
| mapping_styles.names_only)
| |
| map_names(ctx.params, rargs, karg, varg, looptype, function()
| |
| return ctx.frame:callParserFunction(magic, rargs)
| |
| end)
| |
| return context_iterate(ctx, argc)
| |
| end
| |
| | |
| | |
| | |
| --[[ Functions ]]--
| |
| -----------------------------
| |
| | |
| | |
| -- Syntax: #invoke:params|count
| |
| library.count = function(ctx)
| |
| -- NOTE: `ctx.pipe` and `ctx.params` might be the original metatables!
| |
| local retval = 0
| |
| for _ in ctx.iterfunc(ctx.params) do retval = retval + 1 end
| |
| if ctx.subset == -1 then retval = retval - #ctx.params end
| |
| ctx.text = retval
| |
| return false
| |
| 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!
| |
| local opts = ctx.pipe
| |
| local tname
| |
| if opts[1] ~= nil then tname = opts[1]:match'^%s*(.*%S)' end
| |
| if tname == nil then error(ctx.luaname ..
| |
| ', ‘concat_and_call’: No template name was provided', 0) end
| |
| remove_numerical_keys(opts, 1, 1)
| |
| ctx.text = ctx.frame:expandTemplate{
| |
| title = tname,
| |
| args = concat_params(ctx)
| |
| }
| |
| return false
| |
| 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!
| |
| local opts = ctx.pipe
| |
| local mname
| |
| local fname
| |
| if opts[1] ~= nil then mname = opts[1]:match'^%s*(.*%S)' end
| |
| if mname == nil then error(ctx.luaname ..
| |
| ', ‘concat_and_invoke’: No module name was provided', 0) end
| |
| if opts[2] ~= nil then fname = opts[2]:match'^%s*(.*%S)' end
| |
| if fname == nil then error(ctx.luaname ..
| |
| ', ‘concat_and_invoke’: No function name was provided', 0) end
| |
| remove_numerical_keys(opts, 1, 2)
| |
| local mfunc = require('Module:' .. mname)[fname]
| |
| if mfunc == nil then error(ctx.luaname ..
| |
| ', ‘concat_and_invoke’: The function ‘' .. fname ..
| |
| '’ does not exist', 0) end
| |
| ctx.text = mfunc(ctx.frame:newChild{
| |
| title = 'Module:' .. fname,
| |
| args = concat_params(ctx)
| |
| })
| |
| return false
| |
| 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!
| |
| local opts = ctx.pipe
| |
| local magic
| |
| if opts[1] ~= nil then magic = opts[1]:match'^%s*(.*%S)' end
| |
| if magic == nil then error(ctx.luaname ..
| |
| ', ‘concat_and_magic’: No parser function was provided', 0) end
| |
| remove_numerical_keys(opts, 1, 1)
| |
| ctx.text = ctx.frame:callParserFunction(magic, concat_params(ctx))
| |
| return false
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|value_of|parameter name
| |
| library.value_of = function(ctx)
| |
| -- NOTE: `ctx.pipe` and `ctx.params` might be the original metatables!
| |
| local opts = ctx.pipe
| |
| local kstr
| |
| if opts[1] ~= nil then kstr = opts[1]:match'^%s*(.*%S)' end
| |
| if kstr == nil then error(ctx.luaname ..
| |
| ', ‘value_of’: No parameter name was provided', 0) end
| |
| local knum = tonumber(kstr)
| |
| local len = #ctx.params
| |
| local val = ctx.params[knum or kstr]
| |
| if val ~= nil and (
| |
| ctx.subset ~= -1 or knum == nil or knum > len or knum < 1
| |
| ) and (
| |
| ctx.subset ~= 1 or (knum ~= nil and knum <= len and knum > 0)
| |
| ) then
| |
| ctx.text = (ctx.header or '') .. val .. (ctx.footer or '')
| |
| return false
| |
| end
| |
| ctx.text = ctx.ifngiven or ''
| |
| return false
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|list
| |
| library.list = function(ctx)
| |
| -- NOTE: `ctx.pipe` might be the original metatable!
| |
| local kvs = ctx.pairsep or ''
| |
| local pps = ctx.itersep or ''
| |
| local ret = {}
| |
| local nss = 0
| |
| flush_params(
| |
| ctx,
| |
| function(key, val)
| |
| ret[nss + 1] = pps
| |
| ret[nss + 2] = key
| |
| ret[nss + 3] = kvs
| |
| ret[nss + 4] = val
| |
| nss = nss + 4
| |
| end
| |
| )
| |
| if nss > 0 then
| |
| if nss > 4 and ctx.lastsep ~= nil then
| |
| ret[nss - 3] = ctx.lastsep
| |
| end
| |
| ret[1] = ctx.header or ''
| |
| if ctx.footer ~= nil then ret[nss + 1] = ctx.footer end
| |
| ctx.text = table.concat(ret)
| |
| return false
| |
| end
| |
| ctx.text = ctx.ifngiven or ''
| |
| return false
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|list_values
| |
| library.list_values = function(ctx)
| |
| -- NOTE: `ctx.pipe` might be the original metatable!
| |
| local pps = ctx.itersep or ''
| |
| local ret = {}
| |
| local nss = 0
| |
| flush_params(
| |
| ctx,
| |
| function(key, val)
| |
| ret[nss + 1] = pps
| |
| ret[nss + 2] = val
| |
| nss = nss + 2
| |
| end
| |
| )
| |
| if nss > 0 then
| |
| if nss > 2 and ctx.lastsep ~= nil then
| |
| ret[nss - 1] = ctx.lastsep
| |
| end
| |
| ret[1] = ctx.header or ''
| |
| if ctx.footer ~= nil then ret[nss + 1] = ctx.footer end
| |
| ctx.text = table.concat(ret)
| |
| return false
| |
| end
| |
| ctx.text = ctx.ifngiven or ''
| |
| return false
| |
| end
| |
| | |
| | |
| -- Syntax: #invoke:params|for_each|wikitext
| |
| library.for_each = function(ctx)
| |
| -- NOTE: `ctx.pipe` might be the original metatable!
| |
| local txt = ctx.pipe[1] or ''
| |
| local pps = ctx.itersep or ''
| |
| local ret = {}
| |
| local nss = 0
| |
| flush_params(
| |
| ctx,
| |
| function(key, val)
| |
| ret[nss + 1] = pps
| |
| ret[nss + 2] = txt:gsub('%$#', key):gsub('%$@', val)
| |
| nss = nss + 2
| |
| end
| |
| )
| |
| if nss > 0 then
| |
| if nss > 2 and ctx.lastsep ~= nil then
| |
| ret[nss - 1] = ctx.lastsep
| |
| end
| |
| ret[1] = ctx.header or ''
| |
| if ctx.footer ~= nil then ret[nss + 1] = ctx.footer end
| |
| ctx.text = table.concat(ret)
| |
| return false
| |
| end
| |
| ctx.text = ctx.ifngiven or ''
| |
| return false
| |
| 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)
| |
| local opts = ctx.pipe
| |
| local tname
| |
| if opts[1] ~= nil then tname = opts[1]:match'^%s*(.*%S)' end
| |
| if tname == nil then error(ctx.luaname ..
| |
| ', ‘call_for_each’: No template name was provided', 0) end
| |
| local model = { title = tname, args = opts }
| |
| local ccs = ctx.itersep or ''
| |
| local ret = {}
| |
| local nss = 0
| |
| table.insert(opts, 1, true)
| |
| flush_params(
| |
| ctx,
| |
| function(key, val)
| |
| opts[1] = key
| |
| opts[2] = val
| |
| ret[nss + 1] = ccs
| |
| ret[nss + 2] = ctx.frame:expandTemplate(model)
| |
| nss = nss + 2
| |
| end
| |
| )
| |
| if nss > 0 then
| |
| if nss > 2 and ctx.lastsep ~= nil then
| |
| ret[nss - 1] = ctx.lastsep
| |
| end
| |
| ret[1] = ctx.header or ''
| |
| if ctx.footer ~= nil then ret[nss + 1] = ctx.footer end
| |
| ctx.text = table.concat(ret)
| |
| return false
| |
| end
| |
| ctx.text = ctx.ifngiven or ''
| |
| return false
| |
| 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)
| |
| local opts = ctx.pipe
| |
| local mname
| |
| local fname
| |
| if opts[1] ~= nil then mname = opts[1]:match'^%s*(.*%S)' end
| |
| if mname == nil then error(ctx.luaname ..
| |
| ', ‘invoke_for_each’: No module name was provided', 0) end
| |
| if opts[2] ~= nil then fname = opts[2]:match'^%s*(.*%S)' end
| |
| if fname == nil then error(ctx.luaname ..
| |
| ', ‘invoke_for_each’: No function name was provided', 0) end
| |
| local model = { title = 'Module:' .. mname, args = opts }
| |
| local mfunc = require(model.title)[fname]
| |
| local ccs = ctx.itersep or ''
| |
| local ret = {}
| |
| local nss = 0
| |
| flush_params(
| |
| ctx,
| |
| function(key, val)
| |
| opts[1] = key
| |
| opts[2] = val
| |
| ret[nss + 1] = ccs
| |
| ret[nss + 2] = mfunc(ctx.frame:newChild(model))
| |
| nss = nss + 2
| |
| end
| |
| )
| |
| if nss > 0 then
| |
| if nss > 2 and ctx.lastsep ~= nil then
| |
| ret[nss - 1] = ctx.lastsep
| |
| end
| |
| ret[1] = ctx.header or ''
| |
| if ctx.footer ~= nil then ret[nss + 1] = ctx.footer end
| |
| ctx.text = table.concat(ret)
| |
| return false
| |
| end
| |
| ctx.text = ctx.ifngiven or ''
| |
| return false
| |
| 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)
| |
| local opts = ctx.pipe
| |
| local magic
| |
| if opts[1] ~= nil then magic = opts[1]:match'^%s*(.*%S)' end
| |
| if magic == nil then error(ctx.luaname ..
| |
| ', ‘magic_for_each’: No parser function was provided', 0) end
| |
| local ccs = ctx.itersep or ''
| |
| local ret = {}
| |
| local nss = 0
| |
| table.insert(opts, 1, true)
| |
| flush_params(
| |
| ctx,
| |
| function(key, val)
| |
| opts[1] = key
| |
| opts[2] = val
| |
| ret[nss + 1] = ccs
| |
| ret[nss + 2] = ctx.frame:callParserFunction(magic,
| |
| opts)
| |
| nss = nss + 2
| |
| end
| |
| )
| |
| if nss > 0 then
| |
| if nss > 2 and ctx.lastsep ~= nil then
| |
| ret[nss - 1] = ctx.lastsep
| |
| end
| |
| ret[1] = ctx.header or ''
| |
| if ctx.footer ~= nil then ret[nss + 1] = ctx.footer end
| |
| ctx.text = table.concat(ret)
| |
| return false
| |
| end
| |
| ctx.text = ctx.ifngiven or ''
| |
| return false
| |
| 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)
| |
| local opts = ctx.pipe
| |
| local tname
| |
| if opts[1] ~= nil then tname = opts[1]:match'^%s*(.*%S)' end
| |
| if tname == nil then error(ctx.luaname ..
| |
| ', ‘call_for_each_value’: No template name was provided', 0) end
| |
| local model = { title = tname, args = opts }
| |
| local ccs = ctx.itersep or ''
| |
| local ret = {}
| |
| local nss = 0
| |
| flush_params(
| |
| ctx,
| |
| function(key, val)
| |
| opts[1] = val
| |
| ret[nss + 1] = ccs
| |
| ret[nss + 2] = ctx.frame:expandTemplate(model)
| |
| nss = nss + 2
| |
| end
| |
| )
| |
| if nss > 0 then
| |
| if nss > 2 and ctx.lastsep ~= nil then
| |
| ret[nss - 1] = ctx.lastsep
| |
| end
| |
| ret[1] = ctx.header or ''
| |
| if ctx.footer ~= nil then ret[nss + 1] = ctx.footer end
| |
| ctx.text = table.concat(ret)
| |
| return false
| |
| end
| |
| ctx.text = ctx.ifngiven or ''
| |
| return false
| |
| 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)
| |
| local opts = ctx.pipe
| |
| local mname
| |
| local fname
| |
| if opts[1] ~= nil then mname = opts[1]:match'^%s*(.*%S)' end
| |
| if mname == nil then error(ctx.luaname ..
| |
| ', ‘invoke_for_each_value’: No module name was provided', 0) end
| |
| if opts[2] ~= nil then fname = opts[2]:match'^%s*(.*%S)' end
| |
| if fname == nil then error(ctx.luaname ..
| |
| ', ‘invoke_for_each_value’: No function name was provided', 0) end
| |
| local model = { title = 'Module:' .. mname, args = opts }
| |
| local mfunc = require(model.title)[fname]
| |
| local ccs = ctx.itersep or ''
| |
| local ret = {}
| |
| local nss = 0
| |
| remove_numerical_keys(opts, 1, 1)
| |
| flush_params(
| |
| ctx,
| |
| function(key, val)
| |
| opts[1] = val
| |
| ret[nss + 1] = ccs
| |
| ret[nss + 2] = mfunc(ctx.frame:newChild(model))
| |
| nss = nss + 2
| |
| end
| |
| )
| |
| if nss > 0 then
| |
| if nss > 2 and ctx.lastsep ~= nil then
| |
| ret[nss - 1] = ctx.lastsep
| |
| end
| |
| ret[1] = ctx.header or ''
| |
| if ctx.footer ~= nil then ret[nss + 1] = ctx.footer end
| |
| ctx.text = table.concat(ret)
| |
| return false
| |
| end
| |
| ctx.text = ctx.ifngiven or ''
| |
| return false
| |
| 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)
| |
| local opts = ctx.pipe
| |
| local magic
| |
| if opts[1] ~= nil then magic = opts[1]:match'^%s*(.*%S)' end
| |
| if magic == nil then error(ctx.luaname ..
| |
| ', ‘magic_for_each_value’: No parser function was provided', 0) end
| |
| local ccs = ctx.itersep or ''
| |
| local ret = {}
| |
| local nss = 0
| |
| flush_params(
| |
| ctx,
| |
| function(key, val)
| |
| opts[1] = val
| |
| ret[nss + 1] = ccs
| |
| ret[nss + 2] = ctx.frame:callParserFunction(magic,
| |
| opts)
| |
| nss = nss + 2
| |
| end
| |
| )
| |
| if nss > 0 then
| |
| if nss > 2 and ctx.lastsep ~= nil then
| |
| ret[nss - 1] = ctx.lastsep
| |
| end
| |
| ret[1] = ctx.header or ''
| |
| if ctx.footer ~= nil then ret[nss + 1] = ctx.footer end
| |
| ctx.text = table.concat(ret)
| |
| return false
| |
| end
| |
| ctx.text = ctx.ifngiven or ''
| |
| return false
| |
| 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!
| |
| local opts = ctx.pipe
| |
| local tmp
| |
| if opts[1] ~= nil then tmp = opts[1]:match'^%s*(.*%S)' end
| |
| if tmp == nil then error(ctx.luaname ..
| |
| ', ‘call_for_each_group’: No template name was provided', 0) end
| |
| local model = { title = tmp }
| |
| local ccs = ctx.itersep or ''
| |
| local nss = 0
| |
| local prefix
| |
| local gid
| |
| local groups = {}
| |
| local ret = {}
| |
| opts = {}
| |
| for key, val in pairs(ctx.pipe) do
| |
| if type(key) == 'number' then opts[key - 1] = val
| |
| else opts[key] = val end
| |
| end
| |
| ctx.pipe = opts
| |
| for key, val in pairs(ctx.params) do
| |
| prefix, gid = tostring(key):match'^%s*(.-)%s*(%-?%d*)%s*$'
| |
| gid = tonumber(gid) or ''
| |
| if groups[gid] == nil then groups[gid] = {} end
| |
| tmp = tonumber(prefix)
| |
| if tmp ~= nil then
| |
| if tmp < 1 then prefix = tmp - 1 else prefix = tmp end
| |
| end
| |
| groups[gid][prefix] = val
| |
| end
| |
| ctx.params = groups
| |
| flush_params(
| |
| ctx,
| |
| function(gid, group)
| |
| for key, val in pairs(opts) do group[key] = val end
| |
| group[0] = gid
| |
| model.args = group
| |
| ret[nss + 1] = ccs
| |
| ret[nss + 2] = ctx.frame:expandTemplate(model)
| |
| nss = nss + 2
| |
| end
| |
| )
| |
| if nss > 0 then
| |
| if nss > 2 and ctx.lastsep ~= nil then
| |
| ret[nss - 1] = ctx.lastsep
| |
| end
| |
| ret[1] = ctx.header or ''
| |
| if ctx.footer ~= nil then ret[nss + 1] = ctx.footer end
| |
| ctx.text = table.concat(ret)
| |
| return false
| |
| end
| |
| ctx.text = ctx.ifngiven or ''
| |
| return false
| |
| end
| |
| | |
| | |
| | |
| --- ---
| |
| --- PUBLIC ENVIRONMENT ---
| |
| --- ________________________________ ---
| |
| --- ---
| |
| | |
| | |
| | |
| --[[ First-position-only modifiers ]]--
| |
| ---------------------------------------
| |
| | |
| | |
| -- Syntax: #invoke:params|new|pipe to
| |
| --[[
| |
| static_iface.new = function(frame)
| |
| local ctx = context_new()
| |
| ctx.frame = frame:getParent()
| |
| ctx.pipe = copy_or_ref_table(frame.args, false)
| |
| ctx.params = {}
| |
| main_loop(ctx, context_iterate(ctx, 1))
| |
| return ctx.text
| |
| end
| |
| ]]--
| |
| | |
| | |
| | |
| --[[ First-position-only functions ]]--
| |
| ---------------------------------------
| |
| | |
| | |
| | |
| -- Syntax: #invoke:params|self
| |
| static_iface.self = function(frame)
| |
| return frame:getParent():getTitle()
| |
| end
| |
| | |
| | |
| | |
| --[[ Public metatable of functions ]]--
| |
| ---------------------------------------
| |
| | |
| | |
| | |
| return setmetatable(static_iface, {
| |
| __index = function(iface, _fname_)
| |
| local ctx = context_new()
| |
| local fname = _fname_:match'^%s*(.*%S)'
| |
| if fname == nil then error(ctx.luaname ..
| |
| ': You must specify a function to call', 0) end
| |
| if library[fname] == nil then error(ctx.luaname ..
| |
| ': The function ‘' .. fname .. '’ does not exist', 0) end
| |
| return function(frame)
| |
| local func = library[fname]
| |
| local refpipe = {
| |
| count = true,
| |
| value_of = true,
| |
| list = true,
| |
| list_values = true,
| |
| for_each = true,
| |
| call_for_each_group = true
| |
| }
| |
| local refparams = {
| |
| --inserting = true,
| |
| count = true,
| |
| concat_and_call = true,
| |
| concat_and_invoke = true,
| |
| concat_and_magic = true,
| |
| value_of = true,
| |
| call_for_each_group = true
| |
| }
| |
| ctx.frame = frame:getParent()
| |
| ctx.pipe = copy_or_ref_table(frame.args, refpipe[fname])
| |
| ctx.params = copy_or_ref_table(ctx.frame.args, refparams[fname])
| |
| main_loop(ctx, func)
| |
| return ctx.text
| |
| end
| |
| end
| |
| })
| |