Module:descendants: Difference between revisions

From Laenkea
Jump to navigation Jump to search
No edit summary
No edit summary
Line 8: Line 8:
local args = getArgs(frame)
local args = getArgs(frame)
local out = ""
local out = ""
local lang = m_languages.get_by_code(args[1])
local lang
if mw.ustring.find(args[1], "%_") then
lang = mw.ustring.match(args[1], "%_([^%_]+)$")
lang = m_languages.get_by_code(lang)
else
lang = m_languages.get_by_code(args[1])
end
local borrowed = args["borrowed"] or args["bor"] or args["b"]
local borrowed = args["borrowed"] or args["bor"] or args["b"]
local see_desc = args["see"]
local see_desc = args["see"]
Line 49: Line 55:
for _, lang in ipairs(list) do
for _, lang in ipairs(list) do
ancestors[lang] = {}
ancestors[lang] = {}
for _, test in ipairs(list) do
if mw.ustring.find(lang, "%_") then
if m_languages.get_by_code(lang).lineage[test] then
local ancestor_temp
table.insert(ancestors[lang], test)
for piece in mw.ustring.gmatch(lang, "([^%_]+)%_") do
if ancestor_temp then
ancestor_temp = ancestor_temp .. "_" .. piece
else
ancestor_temp = piece
end
table.insert(ancestors[lang], ancestor_temp)
end
else
for _, test in ipairs(list) do
if m_languages.get_by_code(lang).lineage[test] then
table.insert(ancestors[lang], test)
end
end
end
end
end
Line 91: Line 109:
local args = getArgs(frame)
local args = getArgs(frame)
local out = ""
local out = ""
local current_lang
local current_lang, code
local terms = {}
local terms = {}
local langs = {}
local langs = {}
Line 99: Line 117:
local lang_change = mw.ustring.match(term, "^([^%:%<]+)%:")
local lang_change = mw.ustring.match(term, "^([^%:%<]+)%:")
local lang_change_arged = mw.ustring.match(term, "^(.+%>)%:")
local lang_change_arged = mw.ustring.match(term, "^(.+%>)%:")
local from_lang
if i == 1 and not (lang_change or lang_change_arged) then error("Language code needs to be specified in the first parameter as xyz(<bor>):term₁") end
if i == 1 and not (lang_change or lang_change_arged) then error("Language code needs to be specified in the first parameter as xyz(<bor>):term₁") end
if lang_change or lang_change_arged then
if lang_change or lang_change_arged then
if lang_change then
if lang_change then
current_lang = m_languages.get_by_code(lang_change)
current_lang = lang_change
term = mw.ustring.gsub(term, "^[^%:]+%:%s*", "")
term = mw.ustring.gsub(term, "^[^%:]+%:%s*", "")
elseif lang_change_arged then
elseif lang_change_arged then
current_lang = m_languages.get_by_code(mw.ustring.match(lang_change_arged, "^[^%<]+"))
current_lang = mw.ustring.match(lang_change_arged, "^[^%<]+")
term = mw.ustring.gsub(term, "^.+%>%:%s*", "")
term = mw.ustring.gsub(term, "^.+%>%:%s*", "")
end
end
if terms[current_lang.code] == nil then
if mw.ustring.find(current_lang, "%_") then
terms[current_lang.code] = {}
from_lang, current_lang = mw.ustring.match(current_lang, "^(.*)%_([^%_]+)$")
table.insert(langs, current_lang.code)
if not mw.ustring.match(from_lang, "%_") then
if lang_change_arged then
lang_change_arged = lang_change_arged .. "<bor>"
else
lang_change_arged = "<bor>"
end
end
end
current_lang = m_languages.get_by_code(current_lang)
code = current_lang.code
if from_lang then code = from_lang .. "_" .. code end
if terms[code] == nil then
terms[code] = {}
table.insert(langs, code)
end
end
end
end
if lang_change_arged then
if lang_change_arged then
for lang_arg in mw.ustring.gmatch(lang_change_arged, "%<([^%>]+)%>") do
for lang_arg in mw.ustring.gmatch(lang_change_arged, "%<([^%>]+)%>") do
terms[current_lang.code][lang_arg] = true
terms[code][lang_arg] = true
end
end
end
end
table.insert(terms[current_lang.code], term)
if from_lang then terms[code]["from"] = from_lang end
table.insert(terms[code], term)
end
end

Revision as of 08:41, 30 May 2024

Underlies {{descendant}} and {{descendant tree}}.


local export = {}
local getArgs = require("Module:Arguments").getArgs
local m_links = require("Module:links")
local m_languages = require("Module:languages")
local m_inline = require("Module:inline")

function export.descendant(frame)
	local args = getArgs(frame)
	local out = ""
	local lang
	if mw.ustring.find(args[1], "%_") then
		lang = mw.ustring.match(args[1], "%_([^%_]+)$")
		lang = m_languages.get_by_code(lang)
	else
		lang = m_languages.get_by_code(args[1])
	end
	local borrowed = args["borrowed"] or args["bor"] or args["b"]
	local see_desc = args["see"]
	local noname = args["noname"]
	local lostcap = args["lost"] or "lost"
	
	if borrowed then out = "<span class=\"desc-arrow\" title=\"borrowed\">→</span>" .. out end
	if not noname then out = out .. lang.name .. ":&nbsp;" end
	
	if args[2] then
		local terms = {}
		local i = 2
		while args[i] do
			local term, term_args = m_inline.parse(args[i])
			table.insert(terms, m_links.full_link({
					language = lang,
					term = term,
					alt = term_args.alt,
					anchor = term_args.anchor or term_args.a,
					gloss = term_args.t,
					pos = term_args.pos,
					nobold = true,
				})
			)
			i = i + 1	
		end
		out = out .. table.concat(terms, ", ")
		if see_desc then out = out .. frame:expandTemplate{ title = 'see descendants' } end
	else
		out = out .. "— (''" .. lostcap .. "'')"
	end
	
	return out
end

function export.langtree(list)
	
	-- build in-set ancestry
	local ancestors = {}
	for _, lang in ipairs(list) do
		ancestors[lang] = {}
		if mw.ustring.find(lang, "%_") then
			local ancestor_temp
			for piece in mw.ustring.gmatch(lang, "([^%_]+)%_") do
				if ancestor_temp then
					ancestor_temp = ancestor_temp .. "_" .. piece
				else
					ancestor_temp = piece
				end
				table.insert(ancestors[lang], ancestor_temp)
			end
		else
			for _, test in ipairs(list) do
				if m_languages.get_by_code(lang).lineage[test] then
					table.insert(ancestors[lang], test)
				end
			end
		end
	end
	
	local structure = {}
	for lang, _ in pairs(ancestors) do
		if #ancestors[lang] == 0 then
			structure[lang] = {}
			ancestors[lang] = nil
		end
	end
	
	local swept = {}
	local function search_and_sort(superordinate)
		for mother, it in pairs(superordinate) do
			for lang, lang_ancestors in pairs(ancestors) do
				for i, lang_ancestor in ipairs(ancestors[lang]) do
					if swept[lang_ancestor] then table.remove(ancestors[lang], i) end
				end
			end
			for lang, lang_ancestors in pairs(ancestors) do
				if #lang_ancestors == 1 and lang_ancestors[1] == mother then
					superordinate[mother][lang] = {}
					swept[mother] = true
					ancestors[lang] = nil
				end
			end
			search_and_sort(it)
		end
	end
	
	search_and_sort(structure)
	return structure

end

function export.desctree(frame)
	local args = getArgs(frame)
	local out = ""
	local current_lang, code
	local terms = {}
	local langs = {}
	local indenter = args["indent"] or args["in"] or ""
	
	for i, term in ipairs(args) do --ryn:term1|term2|term3|rad:term1|term2 ...
		local lang_change = mw.ustring.match(term, "^([^%:%<]+)%:")
		local lang_change_arged = mw.ustring.match(term, "^(.+%>)%:")
		local from_lang
		if i == 1 and not (lang_change or lang_change_arged) then error("Language code needs to be specified in the first parameter as xyz(<bor>):term₁") end
		if lang_change or lang_change_arged then
			if lang_change then
				current_lang = lang_change
				term = mw.ustring.gsub(term, "^[^%:]+%:%s*", "")
			elseif lang_change_arged then
				current_lang = mw.ustring.match(lang_change_arged, "^[^%<]+")
				term = mw.ustring.gsub(term, "^.+%>%:%s*", "")
			end
			if mw.ustring.find(current_lang, "%_") then
				from_lang, current_lang = mw.ustring.match(current_lang, "^(.*)%_([^%_]+)$")
				if not mw.ustring.match(from_lang, "%_") then
					if lang_change_arged then
						lang_change_arged = lang_change_arged .. "<bor>"
					else
						lang_change_arged = "<bor>"
					end
				end
			end
			current_lang = m_languages.get_by_code(current_lang)
			code = current_lang.code
			if from_lang then code = from_lang .. "_" .. code end
			if terms[code] == nil then
				terms[code] = {}
				table.insert(langs, code)
			end
		end
		if lang_change_arged then
			for lang_arg in mw.ustring.gmatch(lang_change_arged, "%<([^%>]+)%>") do
				terms[code][lang_arg] = true
			end
		end
		if from_lang then terms[code]["from"] = from_lang end
		table.insert(terms[code], term)
	end
	
	local items = {}
	
	for lang, lang_args in pairs(terms) do
		table.insert(lang_args, 1, lang)
		items[lang] = export.descendant(lang_args)
	end
	
	-- BEGIN TRIAGE --
	
	local structure = export.langtree(langs)
	
	local outs = {}
	
	local it = 0
	function process_structure(tab)
		it = it + 1
		
		local sorter = {}
		local sorter_proto = {}
		for key, _ in pairs(tab) do
			if mw.ustring.find(key, "%-pro$") then
				table.insert(sorter_proto, key)
			else
				table.insert(sorter, key)
			end
		end
		table.sort(sorter)
		table.sort(sorter_proto)
		for _, key in ipairs(sorter_proto) do
			table.insert(sorter, key)	
		end
		
		for _, key in ipairs(sorter) do
			local out = " " .. items[key]
			for i = 1, it do
				out = "*" .. out	
			end
			out = indenter .. out
			table.insert(outs, out)
			process_structure(tab[key])
		end
		it = it - 1
	end
	
	process_structure(structure)
	
	return table.concat(outs, "\n")
	
end

return export

--[[
Debug console test string:
=p.descendant(mw.getCurrentFrame():newChild{title="whatever",args={"rad"}})
=p.desctree(mw.getCurrentFrame():newChild{title="whatever",args={"rad<bor>:hello", "aeg:hello", "hi", "ryn:hello", "rad-o:hello", "rad-pro:hello", "hrd-pro:hi", "ryn-o:hihe", "lfv-pro:hihe", "lfv-o:hihe", "lfv:hihe"}})
]]--