Модуль:hyphenation

Материал из Викисловаря
Документация

Модуль предназначен для расстановки знаков переноса в строке. Этот модуль используется в шаблоне {{перенос}}.

Описание функций и параметров

  • hyphenate — функция форматирования строки в ссылки.
    Принимает один два параметра, которые могут иметь значения:
    1. text= — исходная строка (обязательный)
    2. delimiter= — символ переноса (необязательный, по умолчанию = "¦")

Технические детали

Для расстановки переноса используется алгоритм П. Христова в модификации Дымченко и Варсанофьева.

Длина символа переноса должна быть равна 1. Обрабатываются только русские и английские слова состоящие из символов латиницы и кириллицы и знака ударения (акут). Не допускается более одного знака ударения в слове. Символы пунктуации игнорируются.

Примеры

Код Результат
{{#invoke:hyphenation|hyphenate|speak}} spe¦ak
{{#invoke:hyphenation|hyphenate|говори́ть}} го¦во¦ри́ть
{{#invoke:hyphenation|hyphenate|подытожить|-}} по-ды-то-жить
{{перенос|вводи́ть в заблужде́ние}} вво¦ди́ть в заб¦луж¦де́¦ние
{{#invoke:hyphenation|hyphenate|lead astray}} le¦ad ast¦ray
local p = {}

--[[
hyphenate
 
Эта функция расставляет переносы по алгоритму П. Христова в модификации Дымченко и Варсанофьева.
 
Использование:
{{#invoke:hyphenation|hyphenate|текст|разделитель}}
или 
{{#invoke:hyphenation|hyphenate|text=текст|delimiter=разделитель}}
]]

function p.hyphenate(frame)
	-- разбор параметров
    local function getParameters( frame_args, arg_list )
        local new_args = {};
        local index = 1;
        local value;
        for i,arg in ipairs( arg_list ) do
            value = frame_args[arg]
            if value == nil then
                value = frame_args[index];
                index = index + 1;
            end
            new_args[arg] = value;
        end
        return new_args;
    end	
	-- разделение строки 
    local function mygsplit(str, pattern) 
        local l = mw.ustring.len( str );
        return function (state, s)
            if s <= l then
                local e, n = mw.ustring.find( str, pattern, s, false );
                local ret;
                local sep = '';
                if not e then
                    ret = mw.ustring.sub( str, s );
                    s = l + 1
                elseif n < e then
                    ret = mw.ustring.sub( str, s, e );
                    if e < l then
                        s = e + 1;
                    else
                        s = l + 1;
                    end
                else
                    ret = e > s and mw.ustring.sub( str, s, e - 1 ) or '';
                    sep = mw.ustring.sub( str, e, n );
                    s = n + 1
                end
                return s, ret, sep
            else
                s = nil;
                return s, ret, sep
            end
        end, nil, 1 -- iterator, state, initial value
    end 
    -- растановка переносов в тексте
    local function parse(text, sep)
		local x = "йьъ";      -- специальная
		local g = "аеёиоуыэюяaeiouy"; -- гласная
		local s = "бвгджзклмнпрстфхцчшщbcdfghjklmnpqrstvwxz"; -- согласная
		local rules = {
			{ "xgg", 1 },
			{ "xgs", 1 },
			{ "xsg", 1 },
			{ "xss", 1 },
			{ "gssssg", 3 },
			{ "gsssg", 3 },
			{ "gsssg", 2 },
			{ "sgsg", 2 },
			{ "gssg", 2 },
			{ "sggg", 2 },
			{ "sggs", 2 }
		};
		local sb ='';
		local ltext = mw.ustring.lower(text);
		ltext = mw.ustring.gsub(ltext, mw.ustring.char(769), ''); -- убираем знаки ударени
		-- заменяем символы в строке символами шаблона
		for i=1, mw.ustring.len(ltext) do
			local c = mw.ustring.sub( ltext, i, i);
			if (mw.ustring.find(x, c, 1, true) ~= nil) then
				sb = sb .. 'x';
			elseif (mw.ustring.find(g, c, 1, true) ~= nil) then
				sb = sb .. 'g';
			elseif (mw.ustring.find(s, c, 1, true) ~= nil) then
				sb = sb .. 's';
			end
		end
		for i, ru in pairs(rules) do
			local hp = ru[1]; -- шаблон
			local pos = ru[2]; -- позиция
			local index = mw.ustring.find(sb, hp, 1, true);
			while index ~= nil do 
				local acutpos = mw.ustring.find( text,  mw.ustring.char(769), 1, true); -- позиция знака ударения
				local actualIndex = index + pos -1;
				sb = mw.ustring.sub( sb, 1, actualIndex) .. sep .. mw.ustring.sub( sb, actualIndex+1);
				-- mw.log('acutpos = ' .. tostring(acutpos) .. ', index=' .. tostring(actualIndex))
				if acutpos ~= nil and acutpos-1 <= actualIndex then
					actualIndex = actualIndex +1;
				end
				text = mw.ustring.sub( text, 1, actualIndex) .. sep .. mw.ustring.sub( text, actualIndex+1);
				index = mw.ustring.find(sb, hp, 1, true);
			end
		end
		return text;
    end
	local args = frame.args;
	if args[1] == nil then
		args = frame:getParent().args;
	end
	local new_args = getParameters( args, {'text', 'delimiter' } );
	local text = new_args['text'] or '';
	local delimiter = new_args['delimiter'] or '¦';
	local pattern = '[%s%p]+';
	local result = '';
	for i, str, sep in mygsplit(text, pattern ) do
        if str ~= '' then
            result = result .. parse(str, delimiter);
        end
        if sep ~= '' then
            result = result .. sep;
		end
	end
	if result == '' then
		return text;
	else
		return result;
	end
end

return p;