Module:head

Revision as of 18:18, 25 July 2024 by TheNightAvl (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Documentation for this module may be created at Module:head/documentation

local export = {}

local m_labels = require("Module:labels")
local m_links = require("Module:links")
local m_gender_and_number = require("Module:gender and number")
local m_formatting = require("Module:formatting")

local non_lemma_pos = {
	["contraction"] = true,
}

local function is_non_lemma(pos)
	return (mw.ustring.find(pos, "%sform") or non_lemma_pos[pos] == true) and true or false
end

local function pluralize(word)
	local ending = mw.ustring.sub(word, -1)
	if ending == "h" and mw.ustring.sub(word, -2, -1) == "s" then ending = "sh" end
	if ending == "s" or ending == "z" or ending == "x" or ending == "sh" then
		return word .. "es"
	end
	return word .. "s"
end

local function format_headword(data)
	local head = data.term
	local cats = ""

	if is_non_lemma(data.pos) then
		cats = cats .. "[[Category:" .. data.language.name .. " non-lemma forms|" .. head .. "]]"
	else
		cats = cats .. "[[Category:" .. data.language.name .. " lemmas|" .. head .. "]]"
	end
	if mw.ustring.match(data.pos, "fix$") then cats = cats .. "[[Category:" .. data.language.name .. " affixes|" .. head .. "]]" end
	if mw.ustring.match(data.pos, " root$") then cats = cats .. "[[Category:" .. data.language.name .. " roots|" .. head .. "]]" end
	cats = cats .. "[[Category:" .. data.language.name .. " " .. pluralize(data.pos) .. "|" .. head .. "]]"
	
	if data.head then
		head = data.head
		if mw.ustring.match(head, "%*[^%*%[%]]*%[[^%*%]]+%][^%*]*%*") then
			for linker in mw.ustring.gmatch(head, "%*([^%*%[%]]*%[[^%*%[%]]+%][^%*]*)%*") do
				local with = mw.ustring.gsub(linker, "[%[%]]", "")
				local without = mw.ustring.gsub(linker, "%[[^%*%[%]]+%]", "")
				local escaped = mw.ustring.gsub(linker, "([%[%]%*])", "%%%1")
				head = mw.ustring.gsub(head, "%*" .. escaped .. "%*", "*" .. with .. ":" .. without .. "*")
			end
		end -- *word[s]* → *words:word*
		head = mw.ustring.gsub(head, "%*([^%*:]+):([^%*:]+)%*", "[[%2#" .. data.language.name .. "|%1]]") -- *word:link*
		head = mw.ustring.gsub(head, "%*([^%*]+)%*", "[[%1#" .. data.language.name .. "|%1]]") -- *word*
	elseif mw.ustring.find(head, " ") then
		local pieces = {}
		for piece in mw.ustring.gmatch(head, "%S+") do
			table.insert(pieces, "[[" .. piece .. "#" .. data.language.name .. "|" .. piece .. "]]")
		end
		head = table.concat(pieces, " ")
	end
	if data.language.proto then head = "*" .. head end
	if mw.ustring.find(data.term, " ") then cats = cats .. "[[Category:" .. data.language.name .. " multiword terms]]" end
	return m_formatting.wrap_face(head, data.language, "head"), cats
end

local function format_genders(data)
	if (not data.genders) or (type(data.genders) ~= "table") then return nil end
	return m_gender_and_number.format_genders(data.language, data.pos, data.genders)
end

local function format_inflections(data)
	if (not data.inflections) and (not data.labels) then return nil end
	local out = {}
	if data.inflections then
		for _, inflection in pairs(data.inflections) do
			if not inflection.label then error("headword inflection must have a label") end
			local i_forms = {}
			local i = 1
			while inflection[i] do
				if inflection.nolink then
					if data.language.proto then
						table.insert(i_forms, "<b>*" .. inflection[i] .. "</b>")
					else
						table.insert(i_forms, "<b>" .. inflection[i] .. "</b>")
					end
				else
					if mw.ustring.find(inflection[i], "%*") then
						if mw.ustring.find(inflection[i], "%*.*%*") then error("Only one * can be used in an inflection.") end
						local temp_links = {}
						if mw.ustring.find(inflection[i], "%*") then
							local before = mw.ustring.match(inflection[i], "^([^%*]+)%s*%*") or ""
							local before_space = mw.ustring.match(inflection[i], "^[^%*]+(%s*)%*") or ""
							local after = mw.ustring.match(inflection[i], "%*%s*([^%*]+)$") or ""
							local after_space = mw.ustring.match(inflection[i], "%*(%s*)[^%*]+$") or ""
							
							if before ~= "" then before = m_links.full_link({term = before, language = data.language}, "bold") end
							if after ~= "" then after = m_links.full_link({term = after, language = data.language}, "bold") end
							
							table.insert(i_forms, before .. before_space .. "'''" ..data.term .. "'''" .. after_space .. after)
						end
					else
						table.insert(i_forms, m_links.full_link({term = inflection[i], language = data.language}, "bold"))
					end
				end
				i = i + 1
			end
			if #i_forms > 0 then
				table.insert(out, "''" .. inflection.label .. "'' " .. table.concat(i_forms, ", "))
			end
		end
	end
	if data.labels and #data.labels > 0 then
		local labels_out = m_labels.make_labels(data.language, data.labels, data.nocat, true)
		if #labels_out > 0 then table.insert(out, 1, labels_out) end
	end
	if #out < 1 then return nil end
	return "(" .. table.concat(out, ", ") .. ")"
end

function export.full_head(data)
	local out = {}
	local cat = ""
	local head_out, head_cat = format_headword(data)
	if head_out then table.insert(out, head_out) end
	if head_cat and head_cat ~= "" then cat = cat .. head_cat end
	local genders_out, genders_cat = format_genders(data)
	if genders_out then table.insert(out, genders_out) end
	if genders_cat and genders_cat ~= "" then cat = cat .. genders_cat end
	local inflections = format_inflections(data)
	if inflections then table.insert(out, inflections) end
	return table.concat(out, " ") .. (data.nocat and "" or cat)
end

return export