Module:grc-decl/table

Definition from Wiktionary, the free dictionary
Jump to: navigation, search

local m_links = require('Module:links')
local lang = require('Module:languages').getByCode('grc')
local m_dialects = mw.loadData('Module:grc:Dialects')
local m_grc_tr = require('Module:grc-translit')
local m_script_utils = require("Module:script utilities")
local m_accent = require('Module:grc-accent')

local export = {}

local UNDERTIE = mw.ustring.char(0x35C) -- actually "combining double breve below"
local d = require("Module:grc-utilities/data").diacritics

--[[
	Basic letters with and without diacritics, plus digamma and combining
	diacritics.
]]
local word_characters = table.concat{
	'ΆΈ-ώϜϝἀ-ᾼῂ-ῌῐ-',
	-- capital iota with oxia, normalized to capital iota with tonos if entered
	-- literally in a string
	mw.ustring.char(0x1FDB),
	'Ὶῠ-Ῥῲ-ῼ',
	d.macron, d.breve,
	d.rough, d.smooth, d.diaeresis,
	d.acute, d.grave, d.circum,
	d.subscript,
	UNDERTIE,
}

local nonAttic_note = 'Dialects other than Attic are not well attested. ' ..
	'Some forms may be based on conjecture. Use with caution.'
local Attic_note = 'This table gives Attic inflectional endings. ' ..
	'For declension in other dialects, see [[Appendix:Ancient Greek dialectal declension]].'

local form_redirects = {
	AS = 'NS',
	VS = 'NS',
	DD = 'GD',
	AD = 'ND',
	VD = 'ND',
	AP = 'NP',
	VP = 'NP',
}

local function make_repl(mapping)
	return function(key) return mapping[key] end
end

local function entry_link(term, alt)
	return m_links.full_link({ lang = lang, term = term, alt = alt, tr = '-' }, nil, false)
end

local function link(alt)
	if alt == '-' then
		return '-'
	end
	
	alt = mw.ustring.gsub(alt, 'σ$', 'ς') --just in case
	local stripped = mw.ustring.gsub(alt, UNDERTIE, '')
	if mw.ustring.match(stripped, "%b()") then
		local with_paren_content, no_paren_content =
				mw.ustring.gsub(stripped, '[%(%)]', ''),
				mw.ustring.gsub(stripped, '%b()', '')
		return mw.ustring.gsub(alt,
			'(%(?)([^%(%)]+)(%)?)',
			function(open_paren, content, close_paren)
				if open_paren == '(' and close_paren == ')' then
					return open_paren ..
							entry_link(with_paren_content, content) ..
							close_paren
				else
					return entry_link(no_paren_content, content)
				end
			end)
	else
		return entry_link(stripped, alt)
	end
end

local function link_form(args, f, istitle)
	local t = args.adjective and args.atable or args.ctable
	local q
	
	-- grab the form
	if args[f] then
		q = args[f]
		require('Module:debug').track('grc-decl/form-override')
	elseif f == 'NDP' then
		q = args.form_cache['MDP']
	elseif t[f] then
		q = t[f]
	elseif form_redirects[f] then
		q = args.form_cache[form_redirects[f]]
	elseif form_redirects[f:sub(2)] then
		q = args.form_cache[f:sub(1, 1) .. form_redirects[f:sub(2)]]
	elseif f:match('N[^N].') then
		q = args.form_cache['M' .. f:sub(2)]
	end
	
	if q == nil or q == '-' or q == '—' then return '—' end
	
	-- if it is a title form, strip all but the first variation
	if istitle then
		q = mw.ustring.match(q, '[^,/]+') --capture up to comma or slash (needs standardization)
		q = mw.ustring.gsub(q, '%s+$', '') --strip final whitespace
		if (not args.adjective and f:match('N.')) or
				(args.adjective and f:match('MN.')) then -- find the nominative
			local accent = m_accent.get_accent_term(q)
			if accent ~= nil then
				table.insert(args.categories, 'Ancient Greek ' .. accent .. ' terms')
			end
		end
	else
		-- convert commas to slashes and space the slashes for legibility
		q = mw.ustring.gsub(q, '%s*[/,]%s*', ' / ')
		args.form_cache[f] = q
	end
	
	-- concat article
	if (not args.adjective) and args.article[f] and f:sub(1, 1) ~= 'V' then
		q = args.article[f] .. ' ' .. q
	end
	
	--[[
		An Ancient Greek word character optionally preceded by a hyphen or
		followed by a sequence of word characters or parentheses.
		Matches -ᾰ́ς, σοῖσι(ν), as well as cases with parentheses in the middle
		of the word.
	]]
	local x, _ = mw.ustring.gsub(q, '%-?[' .. word_characters .. '][' .. word_characters .. '()]*', link)
	
	if istitle then
		return x
	else
		return x .. '<br/>' .. m_script_utils.tag_translit(m_grc_tr.tr(q), lang, "default", 'style="color: #888;"')
	end
end

local function make_title(args)
	local q = {}
	table.insert(q, args.declheader .. ' of ')
	if args.number.S then
		table.insert(q, link_form(args, 'NS', true) .. '; ' .. link_form(args, 'GS', true))
	elseif args.number.D then
		table.insert(q, link_form(args, 'ND', true) .. '; ' .. link_form(args, 'GD', true))
	else
		table.insert(q, link_form(args, 'NP', true) .. '; ' .. link_form(args, 'GP', true))
	end
	
	if args.dial then
		table.insert(args.titleapp, require("Module:alternative forms").getLabel(args.dial, m_dialects))
	end
	
	if #args.titleapp > 0 then
		table.insert(q, ' (' .. table.concat(args.titleapp, ', ') .. ')')
	end
	
	return table.concat(q)
end

local function make_rows(args, nums)
	local s = {}
	args.form_cache = {}
	for _, i in ipairs({ 'Nominative', 'Genitive', 'Dative', 'Accusative', 'Vocative' }) do
		table.insert(s, '|-\n!style="background:#C0C0C0;font-style:italic;"| ' .. i .. '\n')
		for _, j in ipairs(nums) do
			table.insert(s, '|style="background:#F5F5F5;"| ' .. link_form(args, i:sub(1, 1) .. j:sub(1, 1)) .. '\n')
		end
	end
	return table.concat(s)
end

local function make_notes(args)
	if args.dial and args.dial ~= 'att' then
		table.insert(args.notes, 1, nonAttic_note)
	else
		table.insert(args.notes, 1, Attic_note)
	end
	
	if args.user_notes then -- add user notes
		table.insert(args.notes, args.user_notes)
	end
	
	if args.debug then
		table.insert(args.notes, args.debug)
	end
	
	return '|-\n!style="background:#C0C0C0;font-style:italic;"| Notes:\n|' .. (args.adjective and '\n|' or '') ..
			'style="background:#F5F5F5; text-align:left; font-size:90%;" colspan="13"| <span class="use-with-mention">' ..
			table.concat(args.notes, '\n') .. '</span>\n'
end

function export.make_table(args)
	local nums = {}
	if args.number.S then table.insert(nums, 'Singular') end
	if args.number.D then table.insert(nums, 'Dual') end
	if args.number.P then table.insert(nums, 'Plural') end
	local s = {
		[=[<div class="NavFrame" style="clear:both; width:]=], (args.number.F and '100%' or '44%'), [=[;">
<div class="NavHead" align="center">]=], make_title(args), [=[</div>
<div class="NavContent">
<center>
{| style="width:100%; background:#A9A9A9; color:#000000; text-align:center;" class="inflection-table" cellspacing="1"
!style="background:#B0C4DE;font-style:italic;width:]=], (args.number.F and '16%' or '37%'), [=[;"| Case / #
]=]
	}
	local width = args.number.F and 'width:28%;' or ''
	for _, j in ipairs(nums) do
		table.insert(s, '!style="background:#C0C0C0;font-style:italic;' .. width .. '"| ' .. j .. '\n')
	end
	table.insert(s, make_rows(args, nums))
	table.insert(s, make_notes(args))
	table.insert(s, [=[|}</center></div></div>]=])
	if #args.categories > 0 and mw.title.getCurrentTitle().nsText ~= "Appendix" then
		table.insert(s, require('Module:utilities').format_categories(args.categories, lang))
	end
	return table.concat(s)
end

local function make_title_adj(args)
	if args.title then
		return args.title
	else
		local q = {}
		table.insert(q, args.adeclheader .. ' of ')
		
		local number
		if args.number.S then
			number = 'S'
		elseif args.number.D then
			number = 'D'
		else
			number = 'P'
		end
		
		if args.act[2] then
			table.insert(q, link_form(args, 'MN' .. number, true) .. '; ' ..
				link_form(args, 'FN' .. number, true) .. '; ' ..
				link_form(args, 'NN' .. number, true))
		else
			table.insert(q, link_form(args, 'MN' .. number, true) .. '; ' ..
				link_form(args, 'NN' .. number, true))
		end
		
		if args.dial then
			table.insert(args.titleapp, require("Module:alternative forms").getLabel(args.dial, m_dialects))
		end
		
		if #args.titleapp > 0 then
			table.insert(q, ' (' .. table.concat(args.titleapp, ', ') .. ')')
		end
		
		return table.concat(q)
	end
end

local function make_rows_adj(args, nums)
	local s = {}
	args.form_cache = {}
	for _, i in ipairs({ 'Nominative', 'Genitive', 'Dative', 'Accusative', 'Vocative' }) do
		table.insert(s, '|-\n!style="background:#C0C0C0;font-style:italic;"| ' .. i .. '\n')
		for _, j in ipairs(nums) do
			table.insert(s, '|\n')
			local f = i:sub(1, 1) .. j:sub(1, 1)
			table.insert(s, '|style="background:#F5F5F5;"| ' .. link_form(args, 'M' .. f) .. '\n')
			if args.act[2] then
				table.insert(s, '|style="background:#F5F5F5;"| ' .. link_form(args, 'F' .. f) .. '\n')
			end
			table.insert(s, '|style="background:#F5F5F5;"| ' .. link_form(args, 'N' .. f) .. '\n')
		end
	end
	return table.concat(s)
end

local function make_acs_adj(args, nums)
	-- this should only apply to pronouns. I think.
	if #nums < 3 then return '' end
	
	-- get the adverb (we couldn't do this before)
	args.atable.adv = args.atable.adv or
			mw.ustring.gsub(mw.ustring.gsub(args.atable['MGP'], 'ν$', 'ς'), 'ν<', 'ς<')
	args.atable.comp = args.atable.comp
	args.atable.super = args.atable.super
	
	local fill = {
		colspan = (args.act[2]) and '3' or '2',
		adv = link_form(args, 'adv'),
		comp = link_form(args, 'comp'),
		super = link_form(args, 'super'),
	}
	
	local s = [=[|-
!style="background:#B0C4DE;" rowspan="2"| ''Derived forms''
|
|style="background:#C0C0C0;" colspan={{{colspan}}} | ''Adverb''
|
|style="background:#C0C0C0;" colspan={{{colspan}}} | ''Comparative''
|
|style="background:#C0C0C0;" colspan={{{colspan}}} | ''Superlative''
|-
|
|style="background:#F5F5F5;" colspan={{{colspan}}} | {{{adv}}}
|
|style="background:#F5F5F5;" colspan={{{colspan}}} | {{{comp}}}
|
|style="background:#F5F5F5;" colspan={{{colspan}}} | {{{super}}}
]=]
	s = mw.ustring.gsub(s, "{{{([a-z0-9_]+)}}}", make_repl(fill))
	return s
end

function export.make_table_adj(args)
	local nums = {}
	if args.number.S then table.insert(nums, 'Singular') end
	if args.number.D then table.insert(nums, 'Dual') end
	if args.number.P then table.insert(nums, 'Plural') end
	local s = {
		[=[<div class="NavFrame" style="clear:both; width:100%;">
<div class="NavHead" align="center">]=], make_title_adj(args), [=[</div>
<div class="NavContent">
<center>
{| style="width:100%; background:#A9A9A9; color:#000000; text-align:center;" class="inflection-table" cellspacing="1"
!style="background:#CECECE;"| ''Number''
]=]
	}
	local threept = (args.act[2])
	local colspan = threept and '3' or '2'
	local th = threept and [=[''
!style="background:#C0C0C0;"| '']=] or [=[ / ]=]
	
	for _, j in ipairs(nums) do
		table.insert(s, [=[!style="width:0.5%" |
!style="background:#CECECE;width:28%" colspan=]=] .. colspan .. "| ''" .. j .. "''\n")
	end
	table.insert(s, [=[|-
!style="background:#B0C4DE;"|''Case/Gender''
]=])
	for _, _ in ipairs(nums) do
		table.insert(s, [=[|
!style="background:#C0C0C0;"| ''Masculine]=] .. th .. [=[Feminine''
!style="background:#C0C0C0;"| ''Neuter''
]=])
	end
	table.insert(s, make_rows_adj(args, nums))
	table.insert(s, make_acs_adj(args, nums))
	table.insert(s, make_notes(args))
	table.insert(s, [=[|}</center></div></div>]=])
	if #args.categories > 0 and mw.title.getCurrentTitle().nsText ~= "Appendix" then
		table.insert(s, require('Module:utilities').format_categories(args.categories, lang))
	end
	return table.concat(s)
end

return export