48,406
edits
No edit summary |
No edit summary |
||
| Line 2: | Line 2: | ||
local form_of_module = "Module:form of" | local form_of_module = "Module:form of" | ||
local functions_module = "Module:fun" | |||
local headword_data_module = "Module:headword/data" | |||
local languages_module = "Module:languages" | local languages_module = "Module:languages" | ||
local load_module = "Module:load" | local load_module = "Module:load" | ||
local parameters_module = "Module:parameters" | local parameters_module = "Module:parameters" | ||
local parameter_utilities_module = "Module:parameter utilities" | |||
local parse_interface_module = "Module:parse interface" | local parse_interface_module = "Module:parse interface" | ||
local string_utilities_module = "Module:string utilities" | local string_utilities_module = "Module:string utilities" | ||
local table_module = "Module:table" | |||
local utilities_module = "Module:utilities" | local utilities_module = "Module:utilities" | ||
| Line 14: | Line 17: | ||
local pairs = pairs | local pairs = pairs | ||
local require = require | local require = require | ||
-- FIXME: Finish [[Module:format utilities]]. | |||
-- local allowed_conj_set = require(format_utilities_module).allowed_conj_set_for_join_segments | |||
local allowed_conj_set = {["and"] = true, ["or"] = true, ["and/or"] = true} | |||
--[==[ | --[==[ | ||
| Line 21: | Line 28: | ||
decode_entities = require(string_utilities_module).decode_entities | decode_entities = require(string_utilities_module).decode_entities | ||
return decode_entities(...) | return decode_entities(...) | ||
end | |||
local function extend(...) | |||
extend = require(table_module).extend | |||
return extend(...) | |||
end | end | ||
| Line 41: | Line 53: | ||
gsplit = require(string_utilities_module).gsplit | gsplit = require(string_utilities_module).gsplit | ||
return gsplit(...) | return gsplit(...) | ||
end | |||
local function is_callable(...) | |||
is_callable = require(functions_module).is_callable | |||
return is_callable(...) | |||
end | end | ||
| Line 103: | Line 120: | ||
local m_form_of_pos | local m_form_of_pos | ||
local function get_m_form_of_pos() | local function get_m_form_of_pos() | ||
m_form_of_pos, get_m_form_of_pos = load_data( | m_form_of_pos, get_m_form_of_pos = load_data(headword_data_module).pos_aliases, nil | ||
return m_form_of_pos | return m_form_of_pos | ||
end | end | ||
| Line 118: | Line 135: | ||
[[Module:form of]], which contains the underlying implementing code and is meant to be called from other modules. | [[Module:form of]], which contains the underlying implementing code and is meant to be called from other modules. | ||
]==] | ]==] | ||
| Line 132: | Line 140: | ||
return { | return { | ||
-- Named params not controlling link display | -- Named params not controlling link display | ||
["cat"] = {list = true}, | ["cat"] = {list = true, sublist = "comma without whitespace", flatten = true}, | ||
["notext"] = {type = "boolean"}, | ["notext"] = {type = "boolean"}, | ||
["sort"] = | ["sort"] = true, | ||
["enclitic"] = | ["enclitic"] = true, | ||
-- FIXME! The following should only be available when withcap=1 in invocation args. Before doing that, need to | -- FIXME! The following should only be available when withcap=1 in invocation args or when withencap=1 and the | ||
-- language is "en". Before doing that, need to remove all uses of nocap= in other circumstances. | |||
["nocap"] = {type = "boolean"}, | ["nocap"] = {type = "boolean"}, | ||
["addl"] = true, -- additional text to display at the end, before the closing </span> | |||
["pagename"] = true, -- for testing, etc. | |||
[" | |||
["pagename"] = | |||
} | } | ||
end | end | ||
-- Split TAGSPECS (inflection tag specifications) on SPLIT_REGEX, which | -- Split TAGSPECS (inflection tag specifications) on SPLIT_REGEX, which | ||
| Line 243: | Line 168: | ||
local function parse_terms_with_inline_modifiers(paramname, val, param_mods, lang) | |||
local function parse_terms_with_inline_modifiers(paramname, val, lang) | |||
local function generate_obj(term) | local function generate_obj(term) | ||
return {lang = lang, term = decode_entities(term)} | return {lang = lang, term = decode_entities(term)} | ||
| Line 273: | Line 175: | ||
return parse_inline_modifiers(val, { | return parse_inline_modifiers(val, { | ||
paramname = paramname, | paramname = paramname, | ||
param_mods = | param_mods = param_mods, | ||
generate_obj = generate_obj, | generate_obj = generate_obj, | ||
splitchar = ",", | splitchar = ",", | ||
outer_container = {}, | |||
}) | }) | ||
end | end | ||
-- Modify PARAMS in-place by adding parameters that control the link to the | -- Modify PARAMS in-place by adding parameters that control the link to the | ||
| Line 291: | Line 188: | ||
-- will be the gloss, unless NO_NUMBERED_GLOSS is given. | -- will be the gloss, unless NO_NUMBERED_GLOSS is given. | ||
local function add_link_params(parent_args, params, term_param, no_numbered_gloss) | local function add_link_params(parent_args, params, term_param, no_numbered_gloss) | ||
params[term_param + 1] = {alias_of = "alt"} | params[term_param + 1] = {alias_of = "alt"} | ||
if not no_numbered_gloss then | if not no_numbered_gloss then | ||
| Line 306: | Line 193: | ||
end | end | ||
-- Numbered params controlling link display | -- Numbered params controlling link display | ||
params[term_param] | params[term_param] = true | ||
end | end | ||
| Line 333: | Line 209: | ||
-- Check the language-specific data for additional base lemma params. But if there's no language-specific data, | -- Check the language-specific data for additional base lemma params. But if there's no language-specific data, | ||
-- attempt any parent varieties as well (i.e. superordinate varieties). | -- attempt any parent varieties as well (i.e. superordinate varieties). | ||
local lang = get_lang(ine(parent_args[compat and "lang" or 1]) or ine(iargs | local lang = get_lang(ine(parent_args[compat and "lang" or 1]) or ine(iargs.lang) or "und", nil, true) | ||
while lang do | while lang do | ||
local langdata = safe_load_data((module_prefix or get_module_prefix()) .. lang:getCode()) | local langdata = safe_load_data((module_prefix or get_module_prefix()) .. lang:getCode()) | ||
| Line 340: | Line 216: | ||
if base_lemma_params then | if base_lemma_params then | ||
for _, param in ipairs(base_lemma_params) do | for _, param in ipairs(base_lemma_params) do | ||
params[param.param] = | params[param.param] = true | ||
end | end | ||
return base_lemma_params | return base_lemma_params | ||
| Line 347: | Line 223: | ||
lang = lang:getParent() | lang = lang:getParent() | ||
end | end | ||
end | |||
local function add_link_and_base_lemma_params(iargs, parent_args, params, term_param, compat, no_numbered_gloss) | |||
local base_lemma_params | |||
if not iargs.nolink and not iargs.linktext then | |||
add_link_params(parent_args, params, term_param, no_numbered_gloss) | |||
base_lemma_params = add_base_lemma_params(parent_args, iargs, params, compat) | |||
end | |||
return base_lemma_params | |||
end | |||
local function handle_withdot_withcap(iargs, params) | |||
local ignored_tracked_params = {} | |||
if iargs.withdot then | |||
params.dot = true | |||
params.nodot = {type = "boolean"} | |||
end | |||
if iargs.withcap and iargs.withencap then | |||
error("Internal error: Can specify only one of withcap= and withencap=") | |||
end | |||
if not iargs.withcap then | |||
params.cap = {type = "boolean"} | |||
ignored_tracked_params.nocap = iargs.withencap and "non-english" or "always" | |||
end | |||
return ignored_tracked_params | |||
end | end | ||
--[=[ | --[=[ | ||
Construct and return the full definition line for a form-of-type template invocation. `data` is an object with the | |||
argument specifying the | following fields: | ||
of args[1]), | * `template`: Approximate template name, for debug tracking; | ||
* `iargs`: processed invocation arguments; | |||
* `parent_args`: raw parent args from `frame:getParent().args`; | |||
* `params`: partially constructed params structure of the sort passed to `process()` in [[Module:parameters]], but | |||
without any link params; | |||
* `ignored_tracked_params`: params that are ignored but should be tracked, to be eventually removed; | |||
* `term_param`: the parent argument specifying the main entry; | |||
* `compat`: true if the language code is found in args.lang instead of args[1]; | |||
* `base_lemma_params`: if non-nil, a list of base lemma param objects of the sort stored in the language-specific data; | |||
* `do_form_of`: a function of one argument, `lemma_data`, that returns the actual definition-line text and any | |||
language-specific categories. See below. | |||
This function does several things: | |||
# If link parameters are called for (neither `iargs.nolink` nor `iargs.linktext` are given), augment the `params` | |||
structure with separate link parameters. | |||
# Modify the parent args as appropriate if invocation arguments def= or ignore= are given. | |||
# Parse the parent args, both for separate parameter properties and inline modifiers on the term parameter (which may | |||
consist of multiple comma-separated terms). | |||
# Compute categories to add to the page, including language-specific categories and any categories requested by the | |||
invocation or parent args. | |||
# Parse enclitic and extra base lemma parameters. | |||
# Construct the actual text using `do_form_of`. | |||
# Add a terminating period/dot as appropriate, along with the formatted categories. | |||
`do_form_of` takes one argument, `lemma_data`, which looks like this: | |||
{ | { | ||
lang = LANG, | lang = LANG, | ||
args = {ARG = VALUE, ARG = VALUE, ...}, | |||
lemmas = {LEMMA_OBJ, LEMMA_OBJ, ...}, | lemmas = {LEMMA_OBJ, LEMMA_OBJ, ...}, | ||
enclitics = {ENCLITIC_OBJ, ENCLITIC_OBJ, ...}, | enclitics = {ENCLITIC_OBJ, ENCLITIC_OBJ, ...}, | ||
base_lemmas = {BASE_LEMMA_OBJ, BASE_LEMMA_OBJ, ...}, | base_lemmas = {BASE_LEMMA_OBJ, BASE_LEMMA_OBJ, ...}, | ||
categories = {"CATEGORY", "CATEGORY", ...}, | categories = {"CATEGORY", "CATEGORY", ...}, | ||
posttext = "POSTTEXT" or nil, | |||
} | } | ||
| Line 365: | Line 296: | ||
* LANG is the language code; | * LANG is the language code; | ||
* ARGS is the parsed arguments, based on what the user specified; | |||
* LEMMAS is a sequence of objects specifying the main entries/lemmas, as passed to full_link in [[Module:links]]; | * LEMMAS is a sequence of objects specifying the main entries/lemmas, as passed to full_link in [[Module:links]]; | ||
however, if the invocation argument linktext= is given, it will be a string consisting of that text, and if the | however, if the invocation argument linktext= is given, it will be a string consisting of that text, and if the | ||
| Line 374: | Line 306: | ||
base lemma parameter (i.e. the relationship between the intermediate and base lemmas) and LEMMA_OBJ is of the same | base lemma parameter (i.e. the relationship between the intermediate and base lemmas) and LEMMA_OBJ is of the same | ||
format of ENCLITIC_OBJ, i.e. an object suitable to be passed to full_link in [[Module:links]]; PARAM_OBJ is of the | format of ENCLITIC_OBJ, i.e. an object suitable to be passed to full_link in [[Module:links]]; PARAM_OBJ is of the | ||
format { param = "PARAM", tags = {"TAG", "TAG", ...} } where PARAM is the name of the parameter to {{inflection of}} | format { param = "PARAM", tags = {"TAG", "TAG", ...} } where PARAM is the name of the parameter to | ||
{{inflection of}} etc. that holds the base lemma(s) of the specified relationship and the tags describe the | |||
relationship, such as {"comd"} or {"past", "part"}; | |||
* CATEGORIES is the categories to add the page to (consisting of any categories specified in the invocation or | * CATEGORIES is the categories to add the page to (consisting of any categories specified in the invocation or | ||
parent args and any tracking categories, but not any additional lang-specific categories that may be added by | parent args and any tracking categories, but not any additional lang-specific categories that may be added by | ||
{{inflection of}} or similar templates). | {{inflection of}} or similar templates); | ||
* POSTTEXT is text to display at the end of the form-of text, before the final </span> (or at the end of the first | |||
line, before the colon, in a multiline {{infl of}} call). | |||
`do_form_of` should return two arguments: | |||
(1) The actual definition-line text, marked up appropriately with <span>...</span> but without any terminating | |||
period/dot. | |||
(2) Any extra categories to add the page to (other than those that can be derived from parameters specified to the | |||
invocation or parent arguments, which will automatically be added to the page). | |||
]=] | ]=] | ||
local function | local function construct_form_of_text(data) | ||
local template, iargs, parent_args, params, no_numbered_gloss, do_form_of = | |||
data.template, data.iargs, data.parent_args, data.params, data.no_numbered_gloss, data.do_form_of | |||
local term_param = iargs.term_param | |||
local compat = iargs.lang or parent_args.lang | |||
term_param = term_param or compat and 1 or 2 | |||
-- Numbered params | |||
params[compat and "lang" or 1] = { | |||
required = not iargs.lang, | |||
type = "language", | |||
default = iargs.lang or "und" | |||
} | |||
local base_lemma_params = add_link_and_base_lemma_params(iargs, parent_args, params, term_param, compat, | |||
no_numbered_gloss) | |||
local ignored_tracked_params = handle_withdot_withcap(iargs, params) | |||
--[=[ | |||
Process parent arguments. This is similar to the following: | |||
require("Module:parameters").process(parent_args, params) | |||
but in addition it does the following: | |||
(1) Supplies default values for unspecified parent arguments as specified in | |||
DEFAULTS, which consist of specs of the form "ARG=VALUE". These are | |||
added to the parent arguments prior to processing, so boolean and number | |||
parameters will process the value appropriately. | |||
(2) Removes parent arguments specified in IGNORESPECS, which consist either | |||
of bare argument names to remove, or list-argument names to remove of the | |||
form "ARG:list". | |||
(3) Tracks the use of any parent arguments specified in TRACKED_PARAMS, which | |||
is a set-type table where the keys are arguments as they exist after | |||
processing (hence numeric arguments should be numbers, not strings) | |||
and the values should be boolean true. | |||
]=]-- | |||
local defaults = iargs.def | |||
local ignorespecs = iargs.ignore | |||
if defaults[1] or ignorespecs[1] then | |||
local new_parent_args = {} | |||
for _, default in ipairs(defaults) do | |||
local defparam, defval = default:match("^(.-)=(.*)$") | |||
if not defparam then | |||
error("Bad default spec " .. default) | |||
end | |||
new_parent_args[defparam] = defval | |||
end | |||
local params_to_ignore = {} | |||
local numbered_list_params_to_ignore = {} | |||
local named_list_params_to_ignore = {} | |||
for _, ignorespec in ipairs(ignorespecs) do | |||
for ignore in gsplit(ignorespec, ",") do | |||
local param = ignore:match("^(.*):list$") | |||
if param then | |||
if param:match("^%d+$") then | |||
insert(numbered_list_params_to_ignore, tonumber(param)) | |||
else | |||
insert(named_list_params_to_ignore, "^" .. pattern_escape(param) .. "%d*$") | |||
end | |||
else | |||
if ignore:match("^%d+$") then | |||
ignore = tonumber(ignore) | |||
end | |||
params_to_ignore[ignore] = true | |||
end | |||
end | |||
end | |||
for k, v in pairs(parent_args) do | |||
if not params_to_ignore[k] then | |||
local ignore_me = false | |||
if type(k) == "number" then | |||
for _, lparam in ipairs(numbered_list_params_to_ignore) do | |||
if k >= lparam then | |||
ignore_me = true | |||
break | |||
end | |||
end | |||
else | |||
for _, lparam in ipairs(named_list_params_to_ignore) do | |||
if k:match(lparam) then | |||
ignore_me = true | |||
break | |||
end | |||
end | |||
end | |||
if not ignore_me then | |||
new_parent_args[k] = v | |||
end | |||
end | |||
end | |||
parent_args = new_parent_args | |||
end | |||
local m_param_utils, param_mods | |||
local function init_param_mods() | |||
if not m_param_utils then | |||
m_param_utils = require(parameter_utilities_module) | |||
param_mods = m_param_utils.construct_param_mods { | |||
{group = {"link", "q", "l", "ref"}}, | |||
{param = "conj", set = allowed_conj_set, overall = true}, | |||
} | |||
end | |||
end | |||
local terms, args | |||
if iargs.nolink or iargs.linktext then | |||
args = process_params(parent_args, params) | |||
else | |||
init_param_mods() | |||
terms, args = m_param_utils.parse_term_with_inline_modifiers_and_separate_params { | |||
params = params, | |||
param_mods = param_mods, | |||
raw_args = parent_args, | |||
termarg = term_param, | |||
track_module = "form-of" .. (template and "/" .. template or ""), | |||
lang = compat and "lang" or 1, | |||
sc = "sc", | |||
-- Don't do this, doesn't seem to make sense. | |||
-- parse_lang_prefix = true, | |||
make_separate_g_into_list = true, | |||
process_args_before_parsing = function(args) | |||
-- For compatibility with the previous code, we accept a comma-separated list of genders in each of g=, | |||
-- g2=, etc. in addition to separate genders in g=/g2=/etc. | |||
if args.g and args.g[1] then | |||
local genders = {} | |||
for _, g in ipairs(args.g) do | |||
extend(genders, split(g, ",")) | |||
end | |||
args.g = genders | |||
end | |||
end, | |||
splitchar = ",", | |||
subitem_param_handling = "last", | |||
} | |||
end | |||
local lang = args[compat and "lang" or 1] | local lang = args[compat and "lang" or 1] | ||
| Line 390: | Line 467: | ||
local categories = {} | local categories = {} | ||
if not args | if not args.nocat then | ||
for _, cat in ipairs(iargs | for _, cat in ipairs(iargs.cat) do | ||
insert(categories, lang:getFullName() .. " " .. cat) | insert(categories, lang:getFullName() .. " " .. cat) | ||
end | end | ||
end | end | ||
for _, cat in ipairs(args | for _, cat in ipairs(args.cat) do | ||
insert(categories, lang:getFullName() .. " " .. cat) | insert(categories, lang:getFullName() .. " " .. cat) | ||
end | |||
-- Format the link, preceding text and categories | |||
local function add_term_tracking_categories(term) | |||
-- add tracking category if term is same as page title | |||
if term and mw.title.getCurrentTitle().text == (lang:makeEntryName(term)) then | |||
insert(categories, "Forms linking to themselves") | |||
end | |||
-- maybe add tracking category if primary entry doesn't exist (this is an | |||
-- expensive call so we don't do it by default) | |||
if iargs.noprimaryentrycat and term and mw.title.getCurrentTitle().nsText == "" | |||
and not mw.title.new(term):getContent() then | |||
insert(categories, lang:getFullName() .. " " .. iargs.noprimaryentrycat) | |||
end | |||
end | end | ||
local lemmas | local lemmas | ||
if iargs | if iargs.nolink then | ||
lemmas = nil | lemmas = nil | ||
elseif iargs | elseif iargs.linktext then | ||
lemmas = iargs | lemmas = iargs.linktext | ||
else | else | ||
if not terms.terms[1] then | |||
if not | |||
if mw.title.getCurrentTitle().nsText == "Template" then | if mw.title.getCurrentTitle().nsText == "Template" then | ||
term = "term" | terms.terms[1] = { | ||
lang = lang, | |||
term = "term" | |||
} | |||
else | else | ||
error("No linked-to term specified | error("No linked-to term specified") | ||
end | end | ||
end | end | ||
for _, termobj in ipairs(terms.terms) do | |||
if termobj.term then | |||
add_term_tracking_categories(termobj.term) | |||
end | |||
-- NOTE: Formerly, template arg sc= overrode inline modifier <sc:...>, which seems backwards, so I've | |||
-- changed it. Hopefully nothing depended on the old behavior. | |||
end | end | ||
lemmas = terms.terms | |||
end | end | ||
local enclitics | local enclitics, enclitic_conj | ||
if args.enclitic then | if args.enclitic then | ||
init_param_mods() | |||
local enclitics_obj = parse_terms_with_inline_modifiers("enclitic", args.enclitic, param_mods, lang) | |||
enclitics = enclitics_obj.terms | |||
enclitic_conj = enclitics_obj.conj | |||
end | end | ||
local base_lemmas = {} | local base_lemmas = {} | ||
| Line 456: | Line 532: | ||
local param = base_lemma_param_obj.param | local param = base_lemma_param_obj.param | ||
if args[param] then | if args[param] then | ||
init_param_mods() | |||
local base_lemmas_obj = parse_terms_with_inline_modifiers(param, args[param], param_mods, lang) | |||
insert(base_lemmas, { | insert(base_lemmas, { | ||
paramobj = base_lemma_param_obj, | paramobj = base_lemma_param_obj, | ||
lemmas = | lemmas = base_lemmas_obj.terms, | ||
conj = base_lemmas_obj.conj, | |||
}) | }) | ||
end | end | ||
| Line 464: | Line 543: | ||
end | end | ||
local posttext = iargs.posttext | |||
local addl = args.addl | |||
if addl then | |||
posttext = posttext or "" | |||
if addl:find("^[;:]") then | |||
posttext = posttext .. addl | |||
elseif addl:find("^_") then | |||
posttext = posttext .. " " .. addl:sub(2) | |||
else | |||
posttext = posttext .. ", " .. addl | |||
end | |||
end | |||
local lemma_data = { | |||
lang = lang, | lang = lang, | ||
args = args, | |||
lemmas = lemmas, | lemmas = lemmas, | ||
conj = terms and terms.conj or iargs.conj, | |||
enclitics = enclitics, | enclitics = enclitics, | ||
enclitic_conj = enclitic_conj, | |||
base_lemmas = base_lemmas, | base_lemmas = base_lemmas, | ||
categories = categories, | categories = categories, | ||
posttext = posttext, | |||
} | } | ||
local form_of_text, lang_cats = do_form_of(lemma_data) | local form_of_text, lang_cats = do_form_of(lemma_data) | ||
extend(lemma_data.categories, lang_cats) | |||
local text = form_of_text .. ( | local text = form_of_text .. ( | ||
args | args.nodot and "" or args.dot or iargs.withdot and "." or "" | ||
) | ) | ||
if #lemma_data.categories == 0 then | if #lemma_data.categories == 0 then | ||
return text | return text | ||
end | end | ||
return text .. format_categories(lemma_data.categories, lemma_data.lang, args | return text .. format_categories(lemma_data.categories, lemma_data.lang, args.sort, | ||
-- If lemma_is_sort_key is given, supply the first lemma term as the sort base if possible. If sort= is given, | -- If lemma_is_sort_key is given, supply the first lemma term as the sort base if possible. If sort= is given, | ||
-- it will override the base; otherwise, the base will be converted appropriately to a sort key using the | -- it will override the base; otherwise, the base will be converted appropriately to a sort key using the | ||
| Line 515: | Line 590: | ||
return { | return { | ||
["term_param"] = {type = "number"}, | ["term_param"] = {type = "number"}, | ||
["lang"] = | ["lang"] = true, -- To be used as the default code in params. | ||
["sc"] = {type = "script"}, | ["sc"] = {type = "script"}, | ||
["cat"] = {list = true}, | ["cat"] = {list = true, sublist = "comma without whitespace", flatten = true}, | ||
["ignore"] = {list = true}, | ["ignore"] = {list = true}, | ||
["def"] = {list = true}, | ["def"] = {list = true}, | ||
["conj"] = {set = allowed_conj_set, default = "and"}, | |||
["withcap"] = {type = "boolean"}, | ["withcap"] = {type = "boolean"}, | ||
["withencap"] = {type = "boolean"}, | |||
["withdot"] = {type = "boolean"}, | ["withdot"] = {type = "boolean"}, | ||
["nolink"] = {type = "boolean"}, | ["nolink"] = {type = "boolean"}, | ||
["linktext"] = | ["linktext"] = true, | ||
["posttext"] = | ["posttext"] = true, | ||
["noprimaryentrycat"] = | ["noprimaryentrycat"] = true, | ||
["lemma_is_sort_key"] = | ["lemma_is_sort_key"] = true, | ||
} | } | ||
end | |||
local function should_ucfirst_text(args, iargs, lang) | |||
return args.cap or (iargs.withcap or iargs.withencap and lang:getCode() == "en") and not args.nocap | |||
end | end | ||
| Line 551: | Line 633: | ||
: Categories to place the page into. The language name will automatically be prepended. Note that there is also a | : Categories to place the page into. The language name will automatically be prepended. Note that there is also a | ||
template param {{para|cat}} to specify categories at the template level. Use of {{para|nocat}} disables categorization | template param {{para|cat}} to specify categories at the template level. Use of {{para|nocat}} disables categorization | ||
of categories specified using invocation param {{para|cat}}, but not using template param {{para|cat}}. | of categories specified using invocation param {{para|cat}}, but not using template param {{para|cat}}. A single param | ||
can specify multiple comma-separated categories if no space follows the comma. | |||
; {{para|ignore}}, {{para|ignore2}}, ...: | ; {{para|ignore}}, {{para|ignore2}}, ...: | ||
: One or more template params to silently accept and ignore. Useful e.g. when the template takes additional parameters | : One or more template params to silently accept and ignore. Useful e.g. when the template takes additional parameters | ||
| Line 561: | Line 644: | ||
; {{para|withcap}} | ; {{para|withcap}} | ||
: Capitalize the first character of the text preceding the link, unless template param {{para|nocap}} is given. | : Capitalize the first character of the text preceding the link, unless template param {{para|nocap}} is given. | ||
; {{para|withencap}} | |||
: Capitalize the first character of the text preceding the link if the language is English and template param | |||
{{para|nocap}} is not given. | |||
; {{para|withdot}} | ; {{para|withdot}} | ||
: Add a final period after the link, unless template param {{para|nodot}} is given to suppress the period, or | : Add a final period after the link, unless template param {{para|nodot}} is given to suppress the period, or | ||
| Line 589: | Line 675: | ||
local iargs = process_params(frame.args, iparams) | local iargs = process_params(frame.args, iparams) | ||
local parent_args = frame:getParent().args | local parent_args = frame:getParent().args | ||
local params = get_common_template_params() | local params = get_common_template_params() | ||
if next(iargs.cat) then | |||
params.nocat = {type = "boolean"} | |||
if next(iargs | |||
params | |||
end | end | ||
return construct_form_of_text { | |||
template = "form-of-t", | |||
iargs = iargs, | |||
parent_args = parent_args, | |||
params = params, | |||
do_form_of = function(lemma_data) | |||
local args = lemma_data.args | |||
local text | |||
if args.notext then | |||
params | text = "" | ||
else | |||
text = iargs[1] | |||
if should_ucfirst_text(args, iargs, lemma_data.lang) then | |||
text = ucfirst(text) | |||
end | |||
end | |||
return format_form_of { | |||
text = text, lemmas = lemma_data.lemmas, conj = lemma_data.conj, enclitics = lemma_data.enclitics, | |||
base_lemmas = lemma_data.base_lemmas, lemma_face = "term", posttext = lemma_data.posttext | |||
}, {} | |||
return format_form_of{text = text, lemmas = lemma_data.lemmas, enclitics = lemma_data.enclitics, | |||
base_lemmas = lemma_data.base_lemmas, lemma_face = "term", posttext = | |||
end | end | ||
} | |||
end | end | ||
| Line 648: | Line 711: | ||
This is a wrapper around construct_form_of_text() and takes the following arguments: processed invocation arguments | This is a wrapper around construct_form_of_text() and takes the following arguments: processed invocation arguments | ||
IARGS, processed parent arguments ARGS, TERM_PARAM (the parent argument specifying the main entry), COMPAT (true if the | IARGS, processed parent arguments ARGS, TERM_PARAM (the parent argument specifying the main entry), COMPAT (true if the | ||
language code is found in args | language code is found in args.lang instead of args[1]), and TAGS, the list of (non-canonicalized) inflection tags. | ||
It returns that actual definition-line text including terminating period/full-stop, formatted categories, etc. and | It returns that actual definition-line text including terminating period/full-stop, formatted categories, etc. and | ||
should be directly returned as the template function's return value | should be directly returned as the template function's return value. | ||
]=] | ]=] | ||
local function construct_tagged_form_of_text(iargs, | local function construct_tagged_form_of_text(data) | ||
return construct_form_of_text | local template, iargs, parent_args, params, no_numbered_gloss, tags = | ||
function(lemma_data) | data.template, data.iargs, data.parent_args, data.params, data.no_numbered_gloss, data.tags | ||
-- Named params not controlling link display | |||
-- Always included because lang-specific categories may be added | |||
params.nocat = {type = "boolean"} | |||
params.p = true | |||
params.POS = {alias_of = "p"} | |||
return construct_form_of_text { | |||
template = template, | |||
iargs = iargs, | |||
parent_args = parent_args, | |||
params = params, | |||
no_numbered_gloss = no_numbered_gloss, | |||
do_form_of = function(lemma_data) | |||
local args = lemma_data.args | |||
if is_callable(tags) then | |||
tags = tags(args) | |||
end | |||
-- NOTE: tagged_inflections returns two values, so we do too. | -- NOTE: tagged_inflections returns two values, so we do too. | ||
return tagged_inflections{ | return tagged_inflections { | ||
lang = lemma_data.lang, | lang = lemma_data.lang, | ||
tags = tags, | tags = tags, | ||
lemmas = lemma_data.lemmas, | lemmas = lemma_data.lemmas, | ||
conj = lemma_data.conj, | |||
enclitics = lemma_data.enclitics, | enclitics = lemma_data.enclitics, | ||
enclitic_conj = lemma_data.enclitic_conj, | |||
base_lemmas = lemma_data.base_lemmas, | base_lemmas = lemma_data.base_lemmas, | ||
lemma_face = "term", | lemma_face = "term", | ||
POS = args | POS = args.p, | ||
pagename = args | pagename = args.pagename, | ||
-- Set no_format_categories because we do it ourselves in construct_form_of_text(). | -- Set no_format_categories because we do it ourselves in construct_form_of_text(). | ||
no_format_categories = true, | no_format_categories = true, | ||
nocat = args | nocat = args.nocat, | ||
notext = args | notext = args.notext, | ||
capfirst = args | capfirst = should_ucfirst_text(args, iargs, lemma_data.lang), | ||
posttext = | posttext = lemma_data.posttext, | ||
} | } | ||
end | end | ||
} | |||
end | end | ||
| Line 701: | Line 782: | ||
; {{para|def}}, {{para|def2}}, ... | ; {{para|def}}, {{para|def2}}, ... | ||
; {{para|withcap}} | ; {{para|withcap}} | ||
; {{para|withencap}} | |||
; {{para|withdot}} | ; {{para|withdot}} | ||
; {{para|nolink}} | ; {{para|nolink}} | ||
| Line 712: | Line 794: | ||
local iparams = get_common_invocation_params() | local iparams = get_common_invocation_params() | ||
iparams[1] = {list = true, required = true} | iparams[1] = {list = true, required = true} | ||
iparams | iparams.split_tags = true | ||
local iargs = process_params(frame.args, iparams) | local iargs = process_params(frame.args, iparams) | ||
local parent_args = frame:getParent().args | local parent_args = frame:getParent().args | ||
local params = get_common_template_params() | |||
return construct_tagged_form_of_text { | |||
template = "tagged-form-of-t", | |||
iargs = iargs, | |||
parent_args = parent_args, | |||
params = params, | |||
tags = split_inflection_tags(iargs[1], iargs.split_tags), | |||
} | } | ||
end | end | ||
| Line 770: | Line 818: | ||
: { {{TEMPLATE|LANG|MAIN_ENTRY_LINK|MAIN_ENTRY_DISPLAY_TEXT|TAG|TAG|...}}} | : { {{TEMPLATE|LANG|MAIN_ENTRY_LINK|MAIN_ENTRY_DISPLAY_TEXT|TAG|TAG|...}}} | ||
instead of | instead of | ||
: { {{TEMPLATE|LANG|MAIN_ENTRY_LINK|MAIN_ENTRY_DISPLAY_TEXT|GLOSS}}} | : { {{TEMPLATE|LANG|MAIN_ENTRY_LINK|MAIN_ENTRY_DISPLAY_TEXT|GLOSS}}} | ||
| Line 795: | Line 843: | ||
; {{para|def}}, {{para|def2}}, ... | ; {{para|def}}, {{para|def2}}, ... | ||
; {{para|withcap}} | ; {{para|withcap}} | ||
; {{para|withencap}} | |||
; {{para|withdot}} | ; {{para|withdot}} | ||
; {{para|nolink}} | ; {{para|nolink}} | ||
| Line 805: | Line 854: | ||
function export.inflection_of_t(frame) | function export.inflection_of_t(frame) | ||
local iparams = get_common_invocation_params() | local iparams = get_common_invocation_params() | ||
iparams | iparams.preinfl = {list = true} | ||
iparams | iparams.postinfl = {list = true} | ||
iparams | iparams.split_tags = true | ||
local iargs = process_params(frame.args, iparams) | local iargs = process_params(frame.args, iparams) | ||
local parent_args = frame:getParent().args | local parent_args = frame:getParent().args | ||
local params = get_common_template_params() | |||
local compat = iargs.lang or parent_args.lang | |||
local tagsind = (iargs.term_param or compat and 1 or 2) + 2 | |||
local compat = iargs | |||
params[tagsind] = {list = true, | params[tagsind] = {list = true, | ||
-- at least one inflection tag is required unless preinfl or postinfl tags are given | -- at least one inflection tag is required unless preinfl or postinfl tags are given | ||
required = #iargs | required = #iargs.preinfl == 0 and #iargs.postinfl == 0} | ||
return construct_tagged_form_of_text { | |||
template = "inflection-of-t", | |||
iargs = iargs, | |||
parent_args = parent_args, | |||
params = params, | |||
no_numbered_gloss = true, | |||
tags = function(args) | |||
local infls | |||
if not next(iargs.preinfl) and not next(iargs.postinfl) then | |||
-- If no preinfl or postinfl tags, just use the user-specified tags directly. | |||
infls = args[tagsind] | |||
else | |||
-- Otherwise, we need to prepend the preinfl tags and postpend the postinfl tags. If there's only one tag set | |||
-- (no semicolon), it's easier. Since this is common, we optimize for it. | |||
infls = {} | |||
local saw_semicolon = false | |||
for _, infl in ipairs(args[tagsind]) do | |||
params | if infl == ";" then | ||
saw_semicolon = true | |||
break | |||
end | |||
end | |||
local split_preinfl = split_inflection_tags(iargs.preinfl, iargs.split_tags) | |||
local split_postinfl = split_inflection_tags(iargs.postinfl, iargs.split_tags) | |||
if not saw_semicolon then | |||
extend(infls, split_preinfl) | |||
extend(infls, args[tagsind]) | |||
extend(infls, split_postinfl) | |||
else | |||
local groups = split_tag_set(args[tagsind]) | |||
for _, group in ipairs(groups) do | |||
if #infls > 0 then | |||
insert(infls, ";") | |||
end | |||
extend(infls, split_preinfl) | |||
extend(infls, group) | |||
extend(infls, split_postinfl) | |||
end | |||
end | end | ||
end | end | ||
end | return infls | ||
end, | |||
} | |||
end | end | ||
| Line 905: | Line 921: | ||
function export.normalize_pos(frame) | function export.normalize_pos(frame) | ||
local iparams = { | local iparams = { | ||
[1] = | [1] = true, | ||
["default"] = | ["default"] = true, | ||
} | } | ||
local iargs = process_params(frame.args, iparams) | local iargs = process_params(frame.args, iparams) | ||
if not iargs[1] and not iargs | if not iargs[1] and not iargs.default then | ||
error("Either 1= or default= must be given in the invocation args") | error("Either 1= or default= must be given in the invocation args") | ||
end | end | ||
if not iargs[1] then | if not iargs[1] then | ||
return iargs | return iargs.default | ||
end | end | ||
return (m_form_of_pos or get_m_form_of_pos())[iargs[1]] or iargs[1] | return (m_form_of_pos or get_m_form_of_pos())[iargs[1]] or iargs[1] | ||