Module:la-utilities

Definition from Wiktionary, the free dictionary
Jump to: navigation, search
Module for working with Latin text.

See also: Module:la-utilities/testcases.

To test the firstDeclensionTable function, "Preview page with this template" with: Template:la-decl-first/documentation.


local m_links = require('Module:links')
 
local export = {}
 
local lang = require("Module:languages").getByCode("la")
 
-- A wrapper function allowing the contents of this module to be called from
-- templates. For example, '{{#invoke:la-utilities|main|strip_macrons|mȳthos}}'
-- produces 'mythos'.
function export.main(frame)
	if(frame.args[1] == 'strip_macrons') then
		return lang:makeEntryName(frame.args[2])
	end
	if type(p[frame.args[1]]) == 'function' then
		return p[frame.args[1]](frame.args[2], frame.args[3])
	else
		return p[frame.args[1]][frame.args[2]]
	end
end
 
-- public domain
-- via http://snippets.luacode.org/?p=snippets/Check_string_ends_with_other_string_74
local function endswith(s, send)
	return #s >= #send and s:find(send, #s-#send+1, true) and true or false
end
 
-- helper function
-- add suffixes to a stem based on which form is chosen
-- parameter baseform is unused. Will be needed for 2nd/3rd declensions
-- num = 'sg' 'pl' 'both' or nil (nil is same as 'both')
-- loc = true or false (to add locative)
function export.decline(form, stem, baseform, num, loc)
 
	local suffix = {
		['1st'] = { 
			['title']='[[Appendix:Latin first declension|First declension]]',
			['nom_sg']='Xa', ['gen_sg']='Xae', ['dat_sg']='Xae', ['acc_sg']='Xam', ['abl_sg']='Xā', ['voc_sg']='Xa', 
			['nom_pl']='Xae', ['gen_pl']='Xārum', ['dat_pl']='Xīs', ['acc_pl']='Xās', ['abl_pl']='Xīs', ['voc_pl']='Xae',
			['if_loc'] = { ['title'] = '[[Appendix:Latin first declension|First declension]] with locative.', 	
				['loc_sg']='Xae', ['loc_pl']='Xīs' } },
 
		['1st-abus'] = { ['stem']='X',
			['title']='[[Appendix:Latin first declension|First declension]] with dative/ablative plural in {{term||-ābus|lang=la}}.',
			['nom_sg']='Xa', ['gen_sg']='Xae', ['dat_sg']='Xae', ['acc_sg']='Xam', ['abl_sg']='Xā', ['voc_sg']='Xa', 
			['nom_pl']='Xae', ['gen_pl']='Xārum', ['dat_pl']='Xābus', ['acc_pl']='Xās', ['abl_pl']='Xābus', ['voc_pl']='Xae' },
 
		['1st-Greek'] = { ['stem']='X',
			['title']='[[Appendix:Latin first declension|First declension]], Greek type.',
			['nom_sg']='Xē', ['gen_sg']='Xēs', ['dat_sg']='Xae', ['acc_sg']='Xēn', ['abl_sg']='Xē', ['voc_sg']='Xē', 
			['nom_pl']='Xae', ['gen_pl']='Xārum', ['dat_pl']='Xīs', ['acc_pl']='Xās', ['abl_pl']='Xīs', ['voc_pl']='Xae' },
 
		['1st-Greek-Ma'] = { 
			['title']='[[Appendix:Latin first declension|First declension]], Greek type masculine in {{term||-ās|lang=la}}.',
			['nom_sg']='Xās', ['gen_sg']='Xae', ['dat_sg']='Xae', ['acc_sg']='Xān', ['abl_sg']='Xā', ['voc_sg']='Xā', 
			['nom_pl']='Xae', ['gen_pl']='Xārum', ['dat_pl']='Xīs', ['acc_pl']='Xās', ['abl_pl']='Xīs', ['voc_pl']='Xae' },
 
		['1st-Greek-Me'] = { 
			['title']='[[Appendix:Latin first declension|First declension]], Greek type masculine in {{term||-ēs|lang=la}}.',
			['nom_sg']='Xēs', ['gen_sg']='Xae', ['dat_sg']='Xae', ['acc_sg']='Xēn', ['abl_sg']='Xē', ['voc_sg']='Xē', 
			['nom_pl']='Xae', ['gen_pl']='Xārum', ['dat_pl']='Xīs', ['acc_pl']='Xās', ['abl_pl']='Xīs', ['voc_pl']='Xae' },
 
		['1st-am'] = { 
			['title']='[[Appendix:Latin first declension|First declension]] with nominative singular in {{term||-am|lang=la}}.',
			['nom_sg']='Xam', ['gen_sg']='Xae', ['dat_sg']='Xae', ['acc_sg']='Xam', ['abl_sg']='Xā', ['voc_sg']='Xam', 
			['nom_pl']='Xae', ['gen_pl']='Xārum', ['dat_pl']='Xīs', ['acc_pl']='Xās', ['abl_pl']='Xīs', ['voc_pl']='Xae' },
 
		['2nd'] = {
			['title']='[[Appendix:Latin second declension|Second declension]]',
			['nom_sg']='Xus', ['gen_sg']='Xī', ['dat_sg']='Xō', ['acc_sg']='Xum', ['abl_sg']='Xō',  ['voc_sg']='Xe', 
			['nom_pl']='Xī', ['gen_pl']='Xōrum', ['dat_pl']='Xīs', ['acc_pl']='Xōs', ['abl_pl']='Xīs', ['voc_pl']='Xī',
			['if_loc'] = { ['title'] = '[[Appendix:Latin second declension|Second declension]] with locative.', 
				['voc_sg']='Xos', ['loc_sg']='Xī', ['loc_pl']='Xīs' }  },
 
		['2nd-N'] = {
			['title']='[[Appendix:Latin second declension|Second declension]] neuter.',
			['nom_sg']='Xum', ['gen_sg']='Xī', ['dat_sg']='Xō', ['acc_sg']='Xum', ['abl_sg']='Xō',  ['voc_sg']='Xum', 
			['nom_pl']='Xa', ['gen_pl']='Xōrum', ['dat_pl']='Xīs', ['acc_pl']='Xa', ['abl_pl']='Xīs', ['voc_pl']='Xa',
			['if_loc'] = { ['title'] = '[[Appendix:Latin second declension|Second declension]] neuter with locative.', 
				['loc_sg']='Xī', ['loc_pl']='Xīs' } },
 
		['2nd-er'] = {
			['title']='[[Appendix:Latin second declension|Second declension]], nominative singular in {{term||-er|lang=la}}.',
			['nom_sg']='W', ['gen_sg']='Xī', ['dat_sg']='Xō', ['acc_sg']='Xum', ['abl_sg']='Xō',  ['voc_sg']='W', ['voc_sg2']='Xe',
			['nom_pl']='Xī', ['gen_pl']='Xōrum', ['dat_pl']='Xīs', ['acc_pl']='Xōs', ['abl_pl']='Xīs', ['voc_pl']='Xī' },
 
		['2nd-Greek'] = {
			['title']='[[Appendix:Latin second declension|Second declension]], Greek type',
			['nom_sg']='Xos', ['gen_sg']='Xī', ['dat_sg']='Xō', ['acc_sg']='Xon', ['acc_sg2']= 'Xum', ['abl_sg']='Xō', ['voc_sg']='Xe', 
			['nom_pl']='Xī', ['gen_pl']='Xōrum', ['dat_pl']='Xīs', ['acc_pl']='Xōs', ['abl_pl']='Xīs', ['voc_pl']='Xī' },
 
		['2nd-N-Greek'] = {
			['title']='[[Appendix:Latin second declension|Second declension]] neuter, Greek type',
			['nom_sg']='Xon', ['gen_sg']='Xī', ['dat_sg']='Xō', ['acc_sg']='Xon', ['abl_sg']='Xō', ['voc_sg']='Xon', 
			['nom_pl']='Xa', ['gen_pl']='Xōrum', ['dat_pl']='Xīs', ['acc_pl']='Xa', ['abl_pl']='Xīs', ['voc_pl']='Xa' },
 
		['2nd-ius'] = { -- todo: footnote for gen_sg
			['title']='[[Appendix:Latin second declension|Second declension]], nominative singular in {{term||-ius|lang=la}}.',
			['nom_sg']='Xïus', ['gen_sg']='Xïī', ['dat_sg']='Xiō', ['acc_sg']='Xium', ['abl_sg']='Xiō',  ['voc_sg']='Xī', 
			['nom_pl']='Xiī', ['gen_pl']='Xiōrum', ['dat_pl']='Xiīs', ['acc_pl']='Xiōs', ['abl_pl']='Xiīs', ['voc_pl']='Xiī'},
 
		['2nd-N-us'] = {
			['title']='[[Appendix:Latin second declension|Second declension]] neuter with nominative/accusative/vocative in {{term||-us|lang=la}}.',
			['nom_sg']='Xus', ['gen_sg']='Xī', ['dat_sg']='Xō', ['acc_sg']='Xus', ['abl_sg']='Xō', ['voc_sg']='Xus' } }
 
	local dtable = suffix[form]
	if (dtable == nil) then error ('form missing: ' .. form ) end
	dtable['stem'] = 'X'
	dtable['no_include'] = { ['if_loc']=true, ['table']=true, ['no_include']=true, ['no_expand']=true }
	dtable['no_expand'] = { ['title']=true, ['if_loc']=true, ['table']=true, ['no_include']=true, ['no_expand']=true }
 
	if loc == true then
		if (not dtable['if_loc']) then
			error('locative cannot be used here')
		end
		for key, value in pairs(dtable['if_loc']) do 
			dtable[key] = value
		end
	end
 
	for key, value in pairs(dtable) do 
		if (not dtable['no_expand'][key]) then
			-- if (value == nil) then error('value missing for key: ' .. key ) end
			-- if (stem == nil) then error('value missing for stem: ' .. stem ) end
			dtable[key] = value:gsub('X', stem)
			if (baseform ~= nil) then 
				dtable[key] = dtable[key]:gsub('W', baseform)
			end
		end
	end
 
	if num == 'sg' or num == 'pl' then
		-- todo: include sg/pl in title
		dtable['table']='la-decl-noun-table-single'
		dtable['num'] = num
	elseif num == nil and loc == true then
		-- default to num=sg (if not desired, num=pl or num=both should be set by calling method)
		dtable['table']='la-decl-noun-table-single'
		dtable['num'] = 'sg' -- todo: check dtable['num'] isn't already filleda
	else 
		dtable['table']='la-decl-noun-table'
	end
 
	-- not really needed now: values for expanding into old templates, which didn't have full table templates: (la-decl-1st-loc, la-decl-1st-p-loc)
	--dtable[1] = export.strip_macrons(stem)
	--dtable[2] = stem
	return dtable
end
 
-- turn certain values of a declension table into links
-- helper function
function export.linkify(dtable)
	local linkifable = {
		['nom-sg']=true, ['gen-sg']=true, ['dat-sg']=true, 
		['acc-sg']=true, ['abl-sg']=true, ['voc-sg']=true, ['loc-sg']=true,
		['nom-pl']=true, ['gen-pl']=true, ['dat-pl']=true, ['acc-pl']=true, 
		['abl-pl']=true, ['voc-pl']=true, ['loc-pl']=true
	}
 
	for key, value in pairs(dtable) do 
		if linkifable[key] then
			dtable[key] = m_links.full_link(value, nil, lang)
		end
	end
end
 
-- Build a declension table, for a first declension Latin word. 
-- See export.firstDeclensionTable for usage
function export.firstDeclensions(word, num, loc)
	-- the two exceptional words which won't work automatically:
	if word == 'dea' then word = 'deābus' elseif word == 'filia' then word = 'filiābus' end
 
	local suffixes = {['a']='1st', ['ābus']='1st-abus', ['ē']='1st-Greek', 
		['ās']='1st-Greek-Ma', ['ēs']='1st-Greek-Me', ['am']='1st-am'
		-- ['ae']='1st-pl', -- handle manually
		-- ['īs']='1st-loc-pl' -- handle manually
	}
	local stem
	word = mw.text.decode(word) -- sanitize
 
	if num ~= nil and num == '{{{num}}}' then
		num = nil -- defaults to 'both' (unless it's a locative)
	elseif num == 'p' then
		num = 'pl'
	elseif num == 's' then
		num = 'sg'
	end
 
	local useLoc = false
	if loc ~= nil and (loc == 'y' or loc == '1') then
		useLoc = true
	end
 
	if endswith(word, 'īs') and (num == nil or num == 'pl') then
		local key = 'īs'
		stem = word:sub(0, -(key:len())-1 )
		return export.decline('1st', stem, nil, 'pl', true)
	elseif endswith(word, 'ae') then
		stem = word:sub(0, -3)
		if (num == nil or num == 'pl') then
			-- treat as plural nominative
			return export.decline('1st', stem, nil, 'pl', useLoc)
		elseif num == 'sg' then
			 -- treat as locative. 
			 -- todo: tell the user to -loc template and -a word instead
			return export.decline('1st', stem, nil, 'sg', true) 
		else
			-- user has requested num=both.
			return export.decline('1st', stem, nil, num, useLoc)
		end
	end
 
	for key,value in pairs(suffixes) do 
		if endswith(word, key) then 
			stem = word:sub(0, -(key:len())-1)
			return export.decline(value, stem, nil, num, useLoc)
		end
	end
 
	-- error
	local allowed_endings = ''
	for key,value in pairs(suffixes) do 
		allowed_endings = allowed_endings .. '-' .. key .. ' '
	end
	error('Parameter 1 (' .. word .. ') is not a Latin word or does not have an allowed word ending: ' .. allowed_endings .. '. Please see [[Template:la-decl-first]] for more information.', 2)
end
 
 
-- Build a declension table, for a second declension Latin word. 
function export.secondDeclensions(word, word2, num, loc)
 
	local suffixes = {['ius']='2nd-ius', ['us']='2nd', ['um']='2nd-N', 
		['r']='2nd-er', -- ignored except by error message
		['os']='2nd-Greek', ['on']='2nd-N-Greek', 
		['ī']='2nd', ['a']='2nd-N'
		-- -loc	-N-loc	-N-us
	}
	local stem
	word = mw.text.decode(word) -- sanitize
 
	if word2 ~= nil and (word2 == '' or word2 == '{{{2}}}') then
		word2 = nil
	end
 
	if (word2 ~= nil) then word2 = mw.text.decode(word2) end
 
	-- TODO: too much copy/paste code
	if num ~= nil and num == '{{{num}}}' then
		num = nil -- defaults to 'both' (unless it's a locative)
	elseif num == 'p' then
		num = 'pl'
	elseif num == 's' then
		num = 'sg'
	end
 
	local useLoc = false
	if loc ~= nil and (loc == 'y' or loc == '1') then
		useLoc = true
	end
 
	if (useLoc) and (num == nil) then
		if endswith(word, 'us') then num = 'sg' 
		elseif endswith(word, 'um') then num = 'sg'
		elseif endswith(word, 'ī') then num = 'pl'
		elseif endswith(word, 'a') then num = 'pl' end
	end
 
	if endswith(word, 'us') and (useLoc == false) and (num == 'sg') then
		local key = 'us'
		stem = word:sub(0, -(key:len())-1)
		return export.decline('2nd-N-us', stem, nil, 'sg', useLoc)
	end
 
	if endswith(word, 'r') then
		if (word2 == nil or word2:len() < 2) then
			stem = word
			return export.decline('2nd-er', stem, word, num, useLoc)
		else
			local key = 'ī'
			stem = word2:sub(0, -(key:len())-1 )
			return export.decline('2nd-er', stem, word, num, useLoc)
		end
	end
 
	for key,value in pairs(suffixes) do 
		if endswith(word, key) then 
			stem = word:sub(0, -(key:len())-1)
			return export.decline(value, stem, nil, num, useLoc)
		end
	end
 
	-- error
	local allowed_endings = ''
	for key,value in pairs(suffixes) do 
		allowed_endings = allowed_endings .. '-' .. key .. ' '
	end
	error('Parameter 1 (' .. word .. ') is not a Latin word or does not have an allowed word ending: ' .. allowed_endings .. '. Please see [[Template:la-decl-first]] for more information.', 2)
end
 
-- Create a first declension table for a word. 
-- Parameters:
-- 1 = the Latin word, with macrons. Usually the singular nominative form. The exceptions are:
--       a) if the word allows a locative form, give that the singular plural form: (ending in -ae), unless it only plural, then use that form (-īs). use loc=s for only singular (hides the plural column)
--       b) the word allows an -ābus suffix, in which case give that form
-- loc=s = singular locative form (or use -ae ending for parameter 1)
-- loc=pl = plural locative form (or use -īs ending for parameter 1)
-- todo: replace loc parameter with num parameter, and make it work for all inputs
 
function export.firstDeclensionTable(frame)
	local NAMESPACE = mw.title.getCurrentTitle().nsText
	local word = frame.args[1]
	local num = frame.args['num']
	local loc = frame.args['loc']
 
	if word == nil or word == '' or word == '{{{1}}}' then
		if NAMESPACE == "Template" then
			word = "-a"
		else
			-- use page name
			-- error('Missing argument. 1 required (a Latin word). See [[Template:la-decl-first]] for usage information.') 
			word = mw.title.getCurrentTitle().text
		end
	end
 
	local decl = export.firstDeclensions(word, num, loc)
	-- export.linkify(decl) -- not strictly needed, as done by Template:l now.
 
	if decl['title'] ~= nil then
		decl['title'] = frame:preprocess(decl['title']) -- process any templates contained within the title parameter
	end
 
	local tablename = decl['table']
 
	for key, value in pairs(decl['no_include']) do 
		decl[key] = nil	
	end
 
	return frame:expandTemplate{title = tablename, args = decl}
end
 
function export.secondDeclensionTable(frame)
	local NAMESPACE = mw.title.getCurrentTitle().nsText
	local word = frame.args[1]
	local word2 = frame.args[2]
	local num = frame.args['num']
	local loc = frame.args['loc']
 
	if word == nil or word == '' or word == '{{{1}}}' then
		if NAMESPACE == "Template" then
			word = "-us"
		else
			-- use page name
			-- error('Missing argument. 1 required (a Latin word). See [[Template:la-decl-first]] for usage information.') 
			word = mw.title.getCurrentTitle().text
		end
	end
 
	local decl = export.secondDeclensions(word, word2, num, loc)
 
	-- too much copy/paste below here (TODO: make a function)
	if decl['title'] ~= nil then
		decl['title'] = frame:preprocess(decl['title']) -- process any templates contained within the title parameter
	end
 
	local tablename = decl['table']
 
	for key, value in pairs(decl['no_include']) do 
		decl[key] = nil	
	end
 
	return frame:expandTemplate{title = tablename, args = decl}
end
 
 
-- Create a declension table for a word. 
-- Parameters:
-- 1 = which declension: first, second, third, fourth, fifth (always first
-- 2 = the Latin word, with macrons. Usually the singular nominative form. The exceptions are:
--       a) for first declension words which allow a locative form, give that form (ending in -ae or -īs). Or use singular nominative and loc=s, or loc=pl (as for other declensions)
--       b) the word allows an -ābus suffix, in which case give that form
-- 3 = the stem (not used for first declension words)
-- loc=s = singular locative form
-- loc=pl = plural locative form
 
function export.declensionTable(frame)
	-- TODO
end
 
function export.strip_macrons(frame)
	return lang:makeEntryName(frame.args[1])
end
 
return export