Module:User:Surjection/adapted

This is a private module sandbox of Surjection, for their own experimentation. Items in this module may be added and removed at Surjection's discretion; do not rely on this module's stability.


local export = {}
local m_languages = require("Module:languages")
local m_scripts = require("Module:scripts")
local m_affix = require("Module:affix")
local m_etymology = require("Module:etymology")
local m_links = require("Module:links")

local function link_part(part)
	return m_links.full_link({
		term = part[1],
		alt = part.alt,
		lang = part.lang,
		sc = part.sc,
		id = part.id,
		genders = part.genders,
		tr = part.tr,
		ts = part.ts,
		gloss = part.gloss,
		pos = part.pos,
		lit = part.lit
	}, "term", true)
end

local function adapted(lang, sc, source, parts, pos, sort_key, allow_categories, nocap)
	local nonaffix_index
	local affixes = 0
	
	if source and lang:getCode() == source:getCode() then
		error("Use [[Template:affix]] instead for derivations within the same language")
	end
	
	for index, part in ipairs(parts) do
		local affix_type, affix_part = m_affix.get_affix_type(lang, sc, part[1])
		part["affix_type"] = affix_type
		if affix_type == nil then
			if source == nil then
				error("If the source language is -, all terms must be valid affixes")
			end
			if nonaffix_index ~= nil then
				error("Exactly one non-affix is required (consider using [[Template:affix]] and |langN= instead)")
			end
			nonaffix_index = index
			part.lang = source
		else
			part.lang = lang
			part.sc = part.sc or sc
			affixes = affixes + 1
		end
		part[1] = affix_part
	end
	
	if source ~= nil and nonaffix_index == nil then
		error("Exactly one non-affix is required (there must be a borrowed term to adapt)")
	end
	
	if affixes < 1 then
		error("At least one affix is required (or use [[Template:bor]])")
	end
	
	-- ping Surjection if this will ever be needed...
	if affixes > 1 then
		error("Only one affix (which may be a circumfix) is allowed for adaptation")
	end
	
	local output = ""
	local categories = {}
	
	if source ~= nil then
		output = m_etymology.format_etyl(lang, source, sort_key, nil, not allow_categories) .. " " .. link_part(parts[nonaffix_index])
		m_etymology.insert_borrowed_cat(categories, lang, source)
		output = output .. ", adapted using the "
	else
		output = (nocap and "adapted" or "Adapted") .. " using the "
	end
	
	local encountered_affix_types = {}
	local encountered_affixes = {}
	
	for index, part in ipairs(parts) do
		if index ~= nonaffix_index then
			local affix_type = part.affix_type
			local affix_list_index = encountered_affix_types[affix_type]
			if not affix_list_index then
				table.insert(encountered_affixes, {})
				encountered_affix_types[affix_type] = #encountered_affixes
				affix_list_index = #encountered_affixes
			end
			table.insert(encountered_affixes[affix_list_index], part)
		end
	end
	
	local affix_type_outputs = {}
	local lang_cat_name = lang:getCanonicalName()
	local lang_pos = pos or "words"
	for _, affixes in ipairs(encountered_affixes) do
		local type = affixes[1].affix_type
		local prefix
		if #affixes > 1 then
			prefix = require("Module:string utilities").pluralize(type)
		else
			prefix = type
		end
		local links = {}
		for _, affix in ipairs(affixes) do
			table.insert(links, link_part(affix))
			local cat_name = lang_cat_name .. " borrowed " .. lang_pos .. " adapted using the " .. type .. " " .. affix[1]
			if affix.id then
				cat_name = cat_name .. " (" .. affix.id .. ")"
			end
			table.insert(categories, cat_name)
		end
		table.insert(affix_type_outputs, prefix .. " " .. table.concat(links, " + "))
	end
	output = output .. mw.text.listToText(affix_type_outputs, ", ", '<span class="serial-comma">,</span><span class="serial-and"> and</span>')
	
	if allow_categories then
		output = output .. require("Module:utilities").format_categories(categories, lang, sort_key)
	end
	return output
end

function export.adapted_t(frame)
	local params = {
		[1] = {required = true, default = "und"},
		[2] = {required = true, default = "und"},
		[3] = {list = true, allow_holes = true},
		
		["t"] = {list = true, allow_holes = true, require_index = true},
		["gloss"] = {list = true, allow_holes = true, require_index = true, alias_of = "t"},
		["tr"] = {list = true, allow_holes = true, require_index = true},
		["ts"] = {list = true, allow_holes = true, require_index = true},
		["g"] = {list = true, allow_holes = true, require_index = true},
		["id"] = {list = true, allow_holes = true, require_index = true},
		["alt"] = {list = true, allow_holes = true, require_index = true},
		["q"] = {list = true, allow_holes = true, require_index = true},
		-- Note, lit1=, lit2=, ... are different from lit=
		["partlit"] = {list = "lit", allow_holes = true, require_index = true},
		["pos"] = {},
		-- Note, pos1=, pos2=, ... are different from pos=
		["partpos"] = {list = "pos", allow_holes = true, require_index = true},
		["sc"] = {},
		-- Note, sc1=, sc2=, ... are different from sc=; the former apply to
		-- individual arguments when lang1=, lang2=, ... is specified, while
		-- the latter applies to all arguments where langN=... isn't specified
		["partsc"] = {list = "sc", allow_holes = true, require_index = true},
		["sort"] = {},
		["nocat"] = {type = "boolean"},
		["nocap"] = {type = "boolean"}
	}

	local args = require("Module:parameters").process(frame:getParent().args, params)
	local lang = m_languages.getByCode(args[1], 1)
	local sc = args["sc"] and m_scripts.getByCode(args["sc"], "sc") or m_scripts.findBestScript(mw.title.getCurrentTitle().text, text)
	local source = args[2] ~= "-" and m_languages.getByCode(args[2], 2, true) or nil
	
	local parts = {}
	for index, part in ipairs(args[3]) do
		table.insert(parts, {
			[1] = part,
			gloss = args.t[index],
			tr = args.tr[index],
			ts = args.ts[index],
			genders = args.g[index] and mw.text.split(args.g[index], ",") or nil,
			id = args.id[index],
			alt = args.alt[index],
			q = args.q[index],
			lit = args.partlit[index],
			pos = args.partpos[index],
			sc = args.partsc[index] and m_scripts.getByCode(args.partsc[index], "sc" .. tostring(index)) or nil
		})
	end
	
	return adapted(lang, sc, source, parts, args["pos"], args["sort"], not args["nocat"], args["nocap"])
end

return export