Module:sish-headword

From Linguifex
Jump to navigation Jump to search


local export = {}
local pos_functions = {}

local force_cat = false -- for testing; if true, categories appear in non-mainspace pages

local langcode = "sish"
local lang = require("Module:languages").getByCode(langcode, true)
local langname = lang:getCanonicalName()

local require_when_needed = require("Module:utilities/require when needed")
local m_str_utils = require("Module:string utilities")
local m_table = require("Module:table")
local en_utilities_module = "Module:en-utilities"
local headword_module = "Module:headword"
local headword_data_module = "Module:headword/data"
local headword_utilities_module = "Module:headword utilities"
local m_headword_utilities = require_when_needed(headword_utilities_module)
local glossary_link = require_when_needed(headword_utilities_module, "glossary_link")
local links_module = "Module:links"
local parse_interface_module = "Module:parse interface"

local u = m_str_utils.char
local rfind = m_str_utils.find
local ulower = m_str_utils.lower
local unfd = mw.ustring.toNFD
local insert = table.insert

local list_param = {list = true, disallow_holes = true}
local boolean_param = {type = "boolean"}

local function ine(val)
	if val == "" then return nil else return val end
end

local function split_on_comma(val)
	if val:find(",") then
		return require(parse_interface_module).split_on_comma(val)
	else
		return {val}
	end
end

-- Parse and insert an inflection not requiring additional processing into `data.inflections`. The raw arguments come
-- from `args[field]`, which is parsed for inline modifiers. `label` is the label that the inflections are given;
-- sections enclosed in <<...>> are linked to the glossary. `accel` is the accelerator form, or nil.
local function parse_and_insert_inflection(pos, data, args, field, label, accel)
	m_headword_utilities.parse_and_insert_inflection {
		headdata = data,
		forms = args[field],
		paramname = field,
		label = label,
		accel = accel and {form = accel} or nil,
		splitchar = ",",
	}
end

-- The main entry point.
-- This is the only function that can be invoked from a template.
function export.show(frame)
	local iparams = {
		[1] = {required = true},
		def = {},
	}
	local iargs = require("Module:parameters").process(frame.args, iparams)
	local args = frame:getParent().args
	local poscat = iargs[1]
	local def = iargs.def

	local parargs = frame:getParent().args

	local params = {
		[1] = {list = "head", disallow_holes = true, template_default = def or "վիլֆը"},
		tr = {list = true, allow_holes = true},
		id = true,
		sort = true,
		-- no nolinkhead= because head in 1= should always be specified
		altform = boolean_param,
		pagename = true, -- for testing
	}

	if pos_functions[poscat] then
		local posparams = pos_functions[poscat].params
		if type(posparams) == "function" then
			posparams = posparams(lang)
		end
		for key, val in pairs(posparams) do
			params[key] = val
		end
	end

    local args = require("Module:parameters").process(parargs, params)

	local actual_poscat = poscat
	if pos_functions[poscat] then
		local get_actual_pos = pos_functions[poscat].get_actual_pos
		if get_actual_pos then
			actual_poscat = get_actual_pos(args)
		end
	end

	local pagename = args.pagename or mw.loadData(headword_data_module).pagename

	local heads = m_headword_utilities.parse_term_list_with_modifiers {
		forms = args[1],
		paramname = {1, "head"},
		is_head = true,
		include_mods = {"tr"},
		splitchar = ",",
	}

	local data = {
		lang = lang,
		pos_category = actual_poscat,
		categories = {},
		genders = {},
		inflections = {},
		pagename = pagename,
		id = args.id,
		sort_key = args.sort,
		force_cat_output = force_cat,
		is_suffix = false,
		no_redundant_head_cat = not heads[1],
		altform = args.altform,
	}

	local sc = lang:findBestScript(pagename)
	
	local other_sc
	
	if sc:getCode() == "Latn" then
		other_sc = "sish-Armn"
	elseif sc:getCode() == "sish-Armn" then
		other_sc = "Latn"
	end

	if not heads[1] then
		heads = {{term = pagename}}
	end
	local numheads = #heads

	-- Copy translit in trN= to head structure (it can also be specified using inline modifier <tr:...>).
	for i, tr in pairs(args.tr) do
		if type(i) == "number" then
			if i > numheads then
				error(("Specified value for tr%s= but only %s head%s available"):format(
					i, numheads, numheads == 1 and "" or "s"))
			end
			heads[i].tr = tr
		end
	end

	-- If pagename is Latin or Armenian, display the other-script transliteration as an inflection. Use manually
	-- specified translit if available, otherwise auto-translit.
	if other_sc then
		other_sc = require("Module:scripts").getByCode(other_sc)
		local inflection = {label = other_sc:getCanonicalName() .. " spelling"}

		if heads[1].tr == "-" then
			inflection.label = "not attested in " .. other_sc:getCanonicalName() .. " spelling"
		else
			for _, head in ipairs(heads) do
				local tr = head.tr
				
				if not tr then
					tr = require("Module:sish-translit").tr(require("Module:links").remove_links(head.term), "sish", sc:getCode())
				end
				
				insert(inflection, {term = tr, sc = other_sc})
			end
		end
		
		insert(data.inflections, inflection)
	end
	-- Now remove the translit from the `heads` structure so it doesn't display in the normal translit slot.
	for i, head in ipairs(heads) do
		if head.tr then
			if not other_sc then
				error(("Translit specified for head #%s when pagename is neither Latin nor Armenian"):format(i))
			end
			head.tr = nil
		end
	end
	data.heads = heads

	local singular_poscat = require(en_utilities_module).singularize(actual_poscat)
	
	return require(headword_module).full_headword(data)
end

pos_functions["letters"] = {
	params = {
		upper = true,
		lower = true,
	},
	func = function(args, data)
		if args.upper then
			insert(data.inflections, {label = "lower case", nil})
			insert(data.inflections, {label = "upper case", args.upper})
		elseif args.lower then
			insert(data.inflections, {label = "upper case", nil})
			insert(data.inflections, {label = "lower case", args.lower})
		end
	end,
}

-----------------------------------------------------------------------------------------
--                                Arbitrary part of speech                             --
-----------------------------------------------------------------------------------------

pos_functions["head"] = {
	params = {
		[2] = {required = true, template_default = "interjection"}, -- actual part of speech
	},
	get_actual_pos = function(args)
		return require(headword_module).canonicalize_pos(args[2])
	end,
}

return export