Модуль:parameters
Бул модулда шаблон далилдерди кайра иштетүү жана текшерүү менен камсыз кылат.
тартиби[түзөтүү]
process(args, params, return_unknown)
Параметрлер боюнча бир тизме менен далилдерди кайра иштетип, кайра иштетилген далилдерди камтыган үстөл кайтарат. args параметр иштелип аргументтерин аныктайт; Алар сен алкагында тартып алуу мүмкүн аргументтер бар: frame:getParent().args
. Грекия
параметр жарактуу көрсөткүчтөрдүн тизмесин аныктайт, ошондой эле стол турат. талаш параметр үстөлгө эмес экенин туш болсо, анда ката көрүнүп турат.
параметрлер стол индекстерин катары параметр аттары болушу керек, жана баалуулук катары параметр тегдеринин (балким, бош) стол. баалуулук катары бош стол параметри бар гана айтылат, бирок ал кандайдыр бир өзгөчө мамиле керек. Мүмкүн параметр теги төмөндө келтирилген.
Мисал параметрлери стол (from Module:котормолор):
{
[1] = {required = true, default = "und"},
[2] = {},
[3] = {list = true},
["alt"] = {},
["sc"] = {},
["tr"] = {},
}
аны тааныган_жок
, ысым менен чатакташа аркылуу келгенде кайра белгисиз параметр, чыныгы коюлган болсо, ката ишке кирүүдө чейин милдетин жол бербейт. Анын ордуна, кайра наркы баалуулуктардын бир жуп болуп саналат: экинчи иштетилбеген калган бардык таанылбаган далилдерди камтыйт, ал эми биринчи, адаттагыдай эле кайра иштетилген далилдер болуп саналат. Эгер Сиз шаблон кабыл алууга тийиш болгон далилдерди бүтүндөй комплекси бир белгилүү эмес, көп баскычтуу иштетүү, кыла берет. Мисалы, бир баян стол кээ бир жүйөлөрү боюнча кээ бир жалпы иштеп, бирок андан кийин белгилүү бир грамматика түрүн туткалары иштеп калган иштетүүнү кое турууга мүмкүн.
Параметр теги[түзөтүү]
required=true
- The parameter is required; an error is shown if it is not present. The template's page itself is an exception; no error is shown there.
allow_empty=true
- If the argument is an empty string value, it is not converted to
nil
, but kept as-is. type=
- Specifies what value type to convert the argument into. The default is to leave it as a text string. Alternatives are:
type="boolean"
- The value is treated as a boolean value, either true or false. No value, the empty string, and the strings "0", "no", "n" and "false" are treated as false, all other values are considered true.
type="number"
- The value is converted into a number, unless it is nil.
alias_of=
- Treat the parameter as an alias of another. When arguments are specified for this parameter, they will automatically be renamed and stored under the alias name. This allows for parameters with multiple alternative names, while still treating them as if they had only one name. It is even possible for the
alias_of=
to have a name that is not a parameter itself. list=
- Treat the parameter as a list of values, each having its own parameter name, rather than a single value. The parameters will have a number at the end, except for the first. For example,
list=true
on a parameter named "head" will include the parametershead=
,head2=
,head3=
and so on. If the parameter name is a number, another number doesn't get appended, but the counting simply continues, e.g. for parameter 3 the sequence is3=
,4=
,5=
etc. List parameters are returned as numbered lists, so for a template that is given the parametershead=a|head2=b|head3=c
, the processed value of the parameterhead
will be{"a", "b", "c"}
. - The value for
list=
can also be a string. This tells the module that parameters other than the first should have a different name, which is useful when the first parameter in a list is a number, but the remainder is named. An example would be for genders:list="g"
on a parameter named 1 would have parameters1=
,g2=
,g3=
etc. - If the number is not located at the end, it can be specified by putting an equal sign "=" at the number position. For example, parameters "f1accel", "f2accel", ... can be captured by using the parameter name "f=accel", as is in Module:headword/templates.
allow_holes=true
- This is used in conjunction with list-type parameters. By default, the values are tightly packed in the resulting list. This means that if, for example, an entry specified
head=a|head3=c
but nothead2=
, the returned list will be{"a", "c"}
, with the values stored as index 1 and 2, not 1 and 3. If it is desirable to keep the numbering intact, for example if the numbers of several list parameters correlate with each other (like those of{{compound}}
), then this tag can be specified. - If
allow_holes=true
is given, there may be nil values in between two real values, which makes many of Lua's table processing functions no longer work, like#
oripairs
. To remedy this, the resulting table will contain an additional named value,maxindex
, which tells you the highest numeric index that is present in the table. In the example above, the resulting table will now be{"a", nil, "c", maxindex=3}
. That way, you can iterate over the values from 1 tomaxindex
, while skipping nil values in between. default=
- Specifies a default value for the parameter, if it is absent or empty. When used on list parameters, this specifies a default value for the first item in the list only. Note that it is not possible to generate a default that depends on the value of other parameters.
- If used together with
required=true
, the default applies only to the template's page itself. This can be used to show an example text.
local export = {}
local function track(page, calling_module, calling_function, param_name)
local track = require("Module:debug/track")
local tracking_page = "parameters/" .. page
-- Cascades down in specificity, as each level is a prerequisite for the next.
track(tracking_page)
if calling_module then
track(tracking_page .. "/" .. calling_module)
if calling_function then
track(tracking_page .. "/" .. calling_module .. "/" .. calling_function)
if param_name then
track(tracking_page .. "/" .. calling_module .. "/" .. calling_function .. "/" .. param_name)
end
end
end
return true
end
function export.process(args, params, return_unknown, calling_module, calling_function)
local args_new = {}
if not calling_module then
track("no calling module")
end
if not calling_function then
track("no calling function", calling_module)
end
-- Process parameters for specific properties
local required = {}
local patterns = {}
local names_with_equal_sign = {}
local list_from_index = nil
for name, param in pairs(params) do
if param.required then
if param.alias_of then
track("required alias", calling_module, calling_function, name)
end
required[name] = true
end
if name == 1 and param.no_lang_code then
if not params["notlangcode"] then
error("The parameter \"notlangcode\" must be enabled for this template.", 2)
elseif not args["notlangcode"] and require("Module:languages").getByCode(args[name]) then
error("The parameter \"" .. name .. "\" should not be a language code.", 2)
end
end
if param.list then
-- A helper function to escape magic characters in a string
-- Magic characters: ^$()%.[]*+-?
local plain = require("Module:string/pattern_escape")
local key = name
if type(name) == "string" then
key = string.gsub(name, "=", "")
end
if param.default ~= nil then
args_new[key] = {param.default, maxindex = 1}
else
args_new[key] = {maxindex = 0}
end
if type(param.list) == "string" then
-- If the list property is a string, then it represents the name
-- to be used as the prefix for list items. This is for use with lists
-- where the first item is a numbered parameter and the
-- subsequent ones are named, such as 1, pl2, pl3.
if string.find(param.list, "=") then
patterns["^" .. string.gsub(plain(param.list), "=", "(%%d+)") .. "$"] = name
else
patterns["^" .. plain(param.list) .. "(%d+)$"] = name
end
elseif type(name) == "number" then
-- If the name is a number, then all indexed parameters from
-- this number onwards go in the list.
list_from_index = name
else
if string.find(name, "=") then
patterns["^" .. string.gsub(plain(name), "=", "(%%d+)") .. "$"] = string.gsub(name, "=", "")
else
patterns["^" .. plain(name) .. "(%d+)$"] = name
end
end
if string.find(name, "=") then
-- DO NOT SIDE-EFFECT A TABLE WHILE ITERATING OVER IT.
-- Some elements may be skipped or processed twice if you do.
-- Instead, track the changes we want to make to `params`, and
-- do them after the iteration over `params` is done.
table.insert(names_with_equal_sign, name)
end
elseif param.default ~= nil then
args_new[name] = param.default
end
end
--Process required changes to `params`.
if #names_with_equal_sign > 0 then
local m_params_data = calling_module and mw.loadData("Module:parameters/data")[calling_module]
-- If there is a ready-made version in the data module, use that.
if m_params_data and m_params_data[calling_function .. "_no_equals"] then
params = m_params_data[calling_function .. "_no_equals"]
-- Otherwise, shallow copy the params table and substitute the keys.
else
params = require("Module:table").shallowcopy(params)
for _, name in ipairs(names_with_equal_sign) do
track("name with equals", calling_module, calling_function, name)
params[string.gsub(name, "=", "")] = params[name]
params[name] = nil
end
end
end
-- Process the arguments
local args_unknown = {}
local max_index
for name, val in pairs(args) do
local index = nil
if type(name) == "number" then
if list_from_index ~= nil and name >= list_from_index then
index = name - list_from_index + 1
name = list_from_index
end
else
-- Does this argument name match a pattern?
for pattern, pname in pairs(patterns) do
index = mw.ustring.match(name, pattern)
-- It matches, so store the parameter name and the
-- numeric index extracted from the argument name.
if index then
index = tonumber(index)
name = pname
break
end
end
end
local param = params[name]
-- If a parameter without the trailing index was found, and
-- require_index is set on the param, set the param to nil to treat it
-- as if it isn't recognized.
if not index and param and param.require_index then
param = nil
end
-- If no index was found, use 1 as the default index.
-- This makes list parameters like g, g2, g3 put g at index 1.
-- If `separate_no_index` is set, then use 0 as the default instead.
index = index or (param and param.separate_no_index and 0) or 1
-- If the argument is not in the list of parameters, trigger an error.
-- return_unknown suppresses the error, and stores it in a separate list instead.
if not param then
if return_unknown then
args_unknown[name] = val
else
error("The parameter \"" .. name .. "\" is not used by this template.", 2)
end
else
-- Remove leading and trailing whitespace unless allow_whitespace is true.
if not param.allow_whitespace then
val = mw.text.trim(val)
end
-- Empty string is equivalent to nil unless allow_empty is true.
if val == "" and not param.allow_empty then
val = nil
-- Track empty parameters, unless (1) allow_empty is set or (2) they're numbered parameters where a higher numbered parameter is also in use (e.g. track {{l|en|term|}}, but not {{l|en||term}}).
if type(name) == "number" and not max_index then
-- Find the highest numbered parameter that's in use/an empty string, as we don't want parameters like 500= to mean we can't track any empty parameters with a lower index than 500.
local max_contiguous_index = 0
while args[max_contiguous_index + 1] do
max_contiguous_index = max_contiguous_index + 1
end
if max_contiguous_index > 0 then
for name, val in pairs(args) do
if type(name) == "number" and name > 0 and name <= max_contiguous_index and ((not max_index) or name > max_index) and val ~= "" then
max_index = name
end
end
end
max_index = max_index or 0
end
if type(name) ~= "number" or name > max_index then
track("empty parameter", calling_module, calling_function, name)
end
end
-- Convert to proper type if necessary.
if param.type == "boolean" then
val = not (not val or val == "" or val == "0" or val == "no" or val == "n" or val == "false")
elseif param.type == "number" then
val = tonumber(val)
elseif param.type then
track("unrecognized type", calling_module, calling_function, name)
track("unrecognized type/" .. tostring(param.type), calling_module, calling_function, name)
end
-- Can't use "if val" alone, because val may be a boolean false.
if val ~= nil then
-- Mark it as no longer required, as it is present.
required[param.alias_of or name] = nil
-- Store the argument value.
if param.list then
-- If the parameter is an alias of another, store it as the original,
-- but avoid overwriting it; the original takes precedence.
if not param.alias_of then
args_new[name][index] = val
-- Store the highest index we find.
args_new[name].maxindex = math.max(index, args_new[name].maxindex)
if args_new[name][0] then
args_new[name].default = args_new[name][0]
args_new[name][0] = nil
end
elseif args[param.alias_of] == nil then
if params[param.alias_of] and params[param.alias_of].list then
args_new[param.alias_of][index] = val
-- Store the highest index we find.
args_new[param.alias_of].maxindex = math.max(index, args_new[param.alias_of].maxindex)
else
args_new[param.alias_of] = val
end
end
else
-- If the parameter is an alias of another, store it as the original,
-- but avoid overwriting it; the original takes precedence.
if not param.alias_of then
args_new[name] = val
elseif args[param.alias_of] == nil then
if params[param.alias_of] and params[param.alias_of].list then
args_new[param.alias_of][1] = val
-- Store the highest index we find.
args_new[param.alias_of].maxindex = math.max(1, args_new[param.alias_of].maxindex)
else
args_new[param.alias_of] = val
end
end
end
end
end
end
-- The required table should now be empty.
-- If any entry remains, trigger an error, unless we're in the template namespace.
if mw.title.getCurrentTitle().namespace ~= 10 then
local list = {}
for name, param in pairs(required) do
table.insert(list, name)
end
if #list > 0 then
error('The parameters "' .. mw.text.listToText(list, '", "', '" and "') .. '" are required.', 2)
end
end
-- Remove holes in any list parameters if needed.
for name, val in pairs(args_new) do
if type(val) == "table" and not params[name].allow_holes then
args_new[name] = require("Module:parameters/remove_holes")(val)
end
end
if return_unknown then
return args_new, args_unknown
else
return args_new
end
end
return export