Modul:inflection-docs

Description

szerkesztés

This module helps to automatically build elegant description of data-modules for Module:inflection.

I.e.: Module:inflection/data/uz-noun

Translation

szerkesztés

If you will find any mistakes or misprints in English please fill free to fix them here: Module:inflection-docs/i18n/en



-- Inflection-docs v0.9.5
-- 2015-07-10

-- This parameter `lang` should be changed when move source code to another wiktionary
-- It is used to get translations from corresponding i18n-module
local lang = 'en'

local export = {}

local u = require("Module:utils")
local wu = require("Module:wiki-utils")
local du = require("Module:inflection-docs-utils")
local i18n = mw.loadData("Module:inflection-docs/i18n/" .. lang)

local data

-- TODO: move this function to inflection-docs-utils
local function classes_order(t, key_1, key_2)
	if key_1 == nil then
		return true
	elseif key_2 == nil then
		return false
	end
	local order_class_names = du.get_ordered_classes(du.conditions)
	local key_1_index = 999
	local key_2_index = 999
	for i, order_class_name in pairs(order_class_names) do
		if key_1:match('^' .. order_class_name) then
			key_1_index = i
		end
		if key_2:match('^' .. order_class_name) then
			key_2_index = i
		end
	end
	if key_1_index ~= key_2_index then
		return key_1_index < key_2_index
	end
	return key_1 < key_2
end

-- Function to load corresponding data-module
local function load_data(frame)
	local data_name = frame.args['type']
	if data_name == '' then
		return 'Error in module [[Module:inflection-docs|inflection-docs]]: Name of data-module is absent.'
	end
	return mw.loadData("Module:inflection/data/" .. data_name);
end

-- Section "Template"
local function print_template_name()
	local r = string.format('=== %s ===\n', i18n.TEMPLATE_HEADER)
	r = r .. string.format('{{%s|%s}}\n\n', i18n.TEMPLATE_TEMPLATE, data['template'])
	return r
end

-- Section "Affixes in 'affixes'"
local function print_affixes()
	local r = ''
	r = r .. string.format("=== %s '''<code>affixes</code>''' %s ===\n", i18n.SECTION, i18n.AFFIXES_HEADER_DESC)
	r = r .. '{| ' .. wu.table_class() .. '\n'
	r = r .. string.format('! %s || %s || %s \n', i18n.NAME, i18n.VALUE, i18n.CHANGES)
	r = r .. '|-\n'
	for affix_key, affix_value in u.spairs(du.affixes, du.case_order) do
		changes = du.print_changes(du.affixes_changes, affix_key, wu.span_blue)
		_anchor = wu.anchor('var', affix_key) .. ' '
		r = r .. '| ' .. du.var(affix_key) .. '\n'
		r = r .. '| align=center | ' 
		if changes == '' then  -- we need this because if column 'Changes' is empty then anchor on empty cell is working in a wrong way.
			r = r .. _anchor
		end	
		r = r .. '"' .. wu.span_blue(affix_value) .. '"\n'
		r = r .. '|| '
		if changes then  -- if column 'Changes' is not empty then anchor should be on it.
			r = r .. _anchor
		end	
		r = r .. changes .. '\n'
		r = r .. '|-\n'
	end
	r = r .. '|}\n\n'
	return r
end

local function print_arguments()
	local r = ''
	r = r .. string.format('==== %s ====\n', i18n.ARGUMENTS_HEADER)
	r = r .. '{| ' .. wu.table_class() .. '\n'
	r = r .. string.format('! %s || %s \n', i18n.NAME, i18n.POSSIBLE_VALUES)
	r = r .. '|-\n'
	for key, value in u.spairs(du.args_values) do
		r = r .. '| ' .. du.arg(key) .. '\n'
		r = r .. '|| ' .. wu.anchor('arg', key) .. ' ' .. du.print_changes(du.args_values, key, wu.span_purple) .. '\n'
		r = r .. '|-\n'
	end
	r = r .. '|}\n\n'
	return r
end

local function print_condition_vars()
	local r = ''
	r = r .. string.format('==== %s ====\n', i18n.VARS_HEADER)
	r = r .. '{| ' .. wu.table_class() .. '\n'
	r = r .. string.format('! %s || %s \n', i18n.NAME, i18n.POSSIBLE_VALUES)
	r = r .. '|-\n'
	for var_name, var_values in u.spairs(du.condition_vars, du.case_order) do
		r = r .. '| ' .. du.var(var_name) .. '\n'
		r = r .. '|| ' .. wu.anchor('var', var_name) .. ' ' .. du.print_changes(du.condition_vars, var_name, wu.span_blue) .. '\n'
		r = r .. '|-\n'
	end
	r = r .. '|}\n\n'
	return r
end

local function print_conditions_rec(conditions, indent, colspan, prefix)
	local r = ''
	for i, condition in pairs(conditions) do
		local if_count = 0
		local then_count = 0
		local is_section = false
		local is_subsection = false
		local has_comment = false
		local has_sub_conditions = false
		local description_count = 0
		for param_name, param_value in pairs(condition) do
			if param_name == 'verdict' or param_name == 'actions' then
				then_count = then_count + 1
			elseif param_name == 'section' then
				is_section = true
				description_count = description_count + 1
			elseif param_name == 'subsection' then
				is_subsection = true
				description_count = description_count + 1
			elseif param_name == 'comment' then
				has_comment = true
				description_count = description_count + 1
			elseif param_name == 'sub_conditions' then
				has_sub_conditions = true
			else
				if_count = if_count + 1
			end
		end
		local has_conditions = (if_count > 0 or then_count > 0)
		local has_descriptions = (description_count > 0)
		local valign = ''
		if if_count > 0 or false then  -- temp
			valign = "valign='top' "
		end
		if is_section then
			r = r .. "| colspan='" .. colspan+2 .. "' style='background-color: #D4D4D4;' |\n"
			r = r .. '|-\n'
		elseif is_subsection then
			r = r .. "| colspan='" .. colspan+2 .. "' style='background-color: #E8E8E8;' |\n"
			r = r .. '|-\n'
		end
		local rowspan = ''
		if has_conditions and has_descriptions then
			rowspan = "rowspan='" .. (description_count + 1) .. "' "
		end
		if indent > 0 then
			r = r .. "| colspan=" .. indent .. " " .. rowspan .. "| " .. '\n'
		end
		r = r .. "| align='center' width='1' valign='top' " .. rowspan .. "| " .. wu.anchor('condition', prefix..i) .. ' ' .. wu.link('condition '..prefix..i, wu.span_green('#' .. prefix .. i)) .. '\n'
		if is_section then
			r = r .. '| colspan=' .. colspan+1 .. " style='background-color: #D4D4D4;' | " .. wu.anchor('condition', i) .. ' ' .. wu.bold(i18n.SECTION .. ': ' .. wu.span_darkblue(condition['section'])) .. '\n'
			r = r .. '|-\n'
		end
		if is_subsection then
			r = r .. '| colspan=' .. colspan+1 .. " style='background-color: #E8E8E8;' | " .. wu.anchor('condition', i) .. ' ' .. wu.bold(i18n.SUBSECTION .. ': ') .. wu.span_darkblue(condition['subsection']) .. '\n'
			r = r .. '|-\n'
		end
		if has_comment then
			r = r .. '| colspan=' .. colspan+1 .. ' | ' .. wu.anchor('condition', i) .. ' ' .. wu.italic(wu.bold(i18n.COMMENT .. ': ') .. wu.span_darkblue(condition['comment'])) .. '\n'
			r = r .. '|-\n'
		end
		if has_conditions then
			r = r .. '| colspan= ' .. colspan .. ' valign="center" | '
			list_prefix = ''
			if if_count > 0 then
				r = r .. "'''" .. i18n.IF .. "''' "
				if if_count == 2 then
					r = r .. wu.span_silver(string.format(" ''(%s)''", i18n.APPLY_BOTH))
				elseif if_count > 2 then
					r = r .. wu.span_silver(string.format(" ''(%s)''", i18n.APPLY_ALL))
				end
				if if_count > 1 then
					r = r .. '\n'
					list_prefix = '* '
				end
			else
				r = r .. wu.span_gray(string.format("''%s''", i18n.APPLY_ALWAYS)) .. '\n'
			end
			for param_name, param_value in pairs(condition) do
				if param_name == 'verdict' or param_name == 'actions' then
					-- skip
				elseif param_name == 'section' or param_name == 'subsection' or param_name == 'comment' then
					-- TODO
				elseif param_name == 'last' then
					r = r .. list_prefix .. i18n.ENDS_WITH .. ': ' .. du.join_values(param_value, wu.span_blue) .. '\n'
				elseif param_name == 'last_NOT' then
					r = r .. list_prefix .. i18n.DOESNT_END_WITH .. ': ' .. du.join_values(param_value, wu.span_blue) .. '\n'
				elseif param_name == 'pre_last' then  -- TODO: change to "penultimate"
					r = r .. list_prefix .. i18n.PRELAST_LETTER .. ': ' .. du.join_values(param_value, wu.span_blue) .. '\n'
				elseif param_name == 'pre_last_NOT' then
					r = r .. list_prefix .. i18n.PRELAST_LETTER_NOT .. ': ' .. du.join_values(param_value, wu.span_blue) .. '\n'
				elseif param_name:match("^arg") ~= nil or param_name:match("^var") ~= nil then
					local NOT = false
					local var_name
					if param_name:match("_NOT$") ~= nil then
						NOT = true
						param_name = param_name:sub(1, -5)
					end
					if param_name == 'arg' or param_name == 'var' then  -- arg = {'<name>', <values>}
						var_name = param_value[1]
						param_value = param_value[2]
					else
						var_name = param_name:sub(5)  -- arg_<name> = <values>
						param_name = param_name:sub(1, 3)
					end
					if param_name == 'arg' then
						r = r .. list_prefix .. i18n.SENT_ARGUMENT .. ' ' .. du.arg(var_name) .. ' '
						if NOT then
							r = r .. i18n.ARG_NOT_EQUAL .. ' '
						else
							r = r .. i18n.ARG_EQUAL .. ' '
						end
						r = r .. du.join_values(param_value, wu.span_purple) .. '\n'
					elseif param_name == 'var' then
						r = r .. list_prefix .. i18n.VAR .. ' ' .. du.var(var_name) .. ' '
						if NOT then
							r = r .. i18n.VAR_NOT_EQUAL .. ' '
						else
							r = r .. i18n.VAR_EQUAL .. ' '
						end
						r = r .. du.join_values(param_value, wu.span_blue) .. '\n'
					end
				elseif param_name == 'sub_conditions' then
					-- skip
				else
					r = r .. list_prefix .. param_name .. ' = ' .. du.join_values(param_value, wu.span_blue) .. '\n'
				end
			end
			r = r .. "| valign='center' | "
			--if if_count > 0 then
			--	r = r .. "'''" .. i18n.THEN .. "'''"
			--end
			r = r .. '\n'
			if condition['actions'] then
				actions = condition['actions']
				for j, action in pairs(actions) do
					if action[1] == 'set' then
						local var_name = action[2]
						local var_value = du.print_action_value(action[3])
						r = r .. i18n.SET .. ' ' .. du.var(var_name) .. ' ' .. i18n.SET_TO .. ' ' .. var_value .. '<br/>\n'
					elseif action[1] == 'add_class' then
						local class_name = action[2]
						r = r .. i18n.ADD_CLASS .. ' ' .. wu.link(i18n.CLASS..' '..class_name, wu.code_olive_bold(class_name)) .. "<br/>\n"
					else
						r = r .. i18n.ACTION .. " '''<code style='color: purple'>" .. action[1] .. "</code>''' (" .. action[2] .. ")<br/>\n"
					end
				end
			end
			r = r .. '|-\n'
		end
		if has_sub_conditions then
			r = r .. print_conditions_rec(condition['sub_conditions'], indent + 1, colspan - 1, prefix .. i .. '.')
		end
	end
	return r
end

-- Section "Condtitions"
local function print_conditions()
	-- TODO section names or groups in conditions
	local conditions_depth = du.get_conditions_depth(du.conditions)
	mw.log('conditions_depth =', conditions_depth)
	colspan = conditions_depth + 1
	local r = ''
	r = r .. string.format('==== %s ====\n', i18n.CONDITIONS_HEADER)
	r = r .. '{| ' .. wu.table_class() ..  '\n'
	r = r .. string.format('! width=1 | № || colspan=' .. colspan .. ' | %s || %s \n', i18n.CONDITIONS, i18n.ACTIONS)
	r = r .. '|-\n'
	r = r .. print_conditions_rec(du.conditions, 0, colspan, '')
	r = r .. '|}\n\n'
	return r
end

-- Section "Classes"
local function print_classes()
	local r = ''
	r = string.format("=== %s '''<code>classes</code>''' %s ===\n", i18n.SECTION, i18n.CLASSES_HEADER_DESC)
	for class_name, forms in u.spairs(du.classes, classes_order) do
		r = r .. '==== ' .. i18n.CLASS .. ' ' .. wu.code_olive_bold(class_name) .. ' ====\n'
		r = r .. '{| ' .. wu.table_class() .. '\n'
		r = r .. string.format('! %s || %s \n', i18n.FORM, i18n.VALUE)
		r = r .. '|-\n'
		for form_key, form_value in u.spairs(forms, du.case_order) do
			form_value = du.print_value(form_value)
			style = ''
			if form_value == '—' or form_value == '-' then
				style = ' align=center '
			end
			r = r .. '| ' .. wu.anchor('form', form_key) .. ' ' .. du.form(form_key) .. '\n'
			r = r .. '|' .. style .. '| ' .. form_value .. '\n'
			r = r .. '|-\n'
		end
		r = r .. '|}\n\n'
	end
	return r
end

local function print_utils()
	local utils = data['utils']
	-- TODO
	return ''
end

local function print_notes()
	local r = string.format('=== %s ===\n', i18n.NOTES_HEADER)
	r = r .. '* ' .. i18n.NOTE_SENTENCE_PART1 .. ' ' .. wu.code_blue(i18n.NOTE_VAR) .. ', ' .. wu.code_purple(i18n.NOTE_ARG) .. ', ' .. wu.span_green('#1') .. ', ' .. wu.code_maroon(i18n.NOTE_FORM)
	r = r .. i18n.NOTE_SENTENCE_PART2
	return r
end

-- Main function to call from template
function export.get(frame)
	data = load_data(frame)
	du.affixes = data['affixes']
	du.conditions = data['conditions']
	du.classes = data['classes']
	
	du.gen_form_keys()
	du.gen_args_values()
	du.gen_vars_changes()

	local result = '\n'
	result = result .. print_template_name()
	result = result .. print_affixes()
	result = result .. "=== " .. i18n.SECTION .. " '''<code>conditions</code>''' " .. i18n.CONDITIONS_HEADER_DESC .. " ===\n"
	result = result .. print_arguments()
	result = result .. print_condition_vars()
	result = result .. print_conditions()
	result = result .. print_classes()
	result = result .. print_utils()
	result = result .. print_notes()

	return frame:preprocess(result)
end

return export

-- TODO: в "actions": base.replace(/k$/, 'g')
-- TODO: === Секция <code>tests</code> <span style='font-weight: normal'>''(тестовые примеры)''</span> ===
-- TODO: если секция пуста, то не отображать заголовок!!!
-- TODO: шаблон {{inflection-docs}} и автоматическое определение названия дата-модуля