Mòdulu:String

Di Vikidia
Vai alla navigazione Vai alla ricerca

La ducumintazzioni di stu mòdulu si pò criari nta Mòdulu:String/doc

local str = {}

function str.len( frame )
    local new_args = str._getParameters( frame.args, {'s'} );
    local s = new_args['s'] or '';
    return mw.ustring.len( s )
end

function str.sub( frame )
    local new_args = str._getParameters( frame.args, { 's', 'i', 'j' } );
    local s = new_args['s'] or '';
    local i = tonumber( new_args['i'] ) or 1;
    local j = tonumber( new_args['j'] ) or -1;

    local len = mw.ustring.len( s );

    if i < 0 then
        i = len + i + 1;
    end
    if j < 0 then
        j = len + j + 1;
    end

    if i > len or j > len or i < 1 or j < 1 then
        return str._error( 'Ìnnici fora dî stremi dâ stringa' );
    end
    if j < i then
        return str._error( 'Ìnnici n òrdini sbagghiatu' );
    end

    return mw.ustring.sub( s, i, j )
end

function str.sublength( frame )
    local i = tonumber( frame.args.i ) or 0
    local len = tonumber( frame.args.len )
    return mw.ustring.sub( frame.args.s, i + 1, len and ( i + len ) )
end

function str.match(frame)
    return str._match(frame.args)
end

function str._match( args )
    local new_args = str._getParameters( args, {'s', 'pattern', 'start', 'match', 'plain', 'nomatch'} );
    local s = new_args['s'] or '';
    local start = tonumber( new_args['start'] ) or 1;
    local plain_flag = str._getBoolean( new_args['plain'] or false );
    local pattern = new_args['pattern'] or '';
    local match_index = math.floor( tonumber(new_args['match']) or 1 );
    local nomatch = new_args['nomatch'];

    if s == '' then
        return nomatch or str._error( 'La stringa n unni circari è vacanti' );
    end
    if pattern == '' then
        return nomatch or str._error( "La stringa o pattern d'arricircari è vacanti" );
    end
    if math.abs(start) < 1 or math.abs(start) > mw.ustring.len( s ) then
        return nomatch or str._error( 'La pusizzioni nizziali richiesta è fora dî stremi dâ stringa' );
    end
    if match_index == 0 then
        return nomatch or str._error( 'Match index è nuḍḍu' );
    end
    if plain_flag then
        pattern = str._escapePattern( pattern );
    end

    local result
    if match_index == 1 then
        result = mw.ustring.match( s, pattern, start )
    else
        if start > 1 then
            s = mw.ustring.sub( s, start );
        end

        local iterator = mw.ustring.gmatch(s, pattern);
        if match_index > 0 then
            -- Ricerca in avanti
            for w in iterator do
                match_index = match_index - 1;
                if match_index == 0 then
                    result = w;
                    break;
                end
            end
        else
            local result_table = {};
            local count = 1;
            for w in iterator do
                result_table[count] = w;
                count = count + 1;
            end

            result = result_table[ count + match_index ];
        end
    end

    if result == nil then
        if nomatch == nil then
            return str._error( 'Currispunnenza nun attruvata' );
        else
            return nomatch;
        end
    else
        return result;
    end
end

function str.pos( frame )
    local new_args = str._getParameters( frame.args, {'target', 'pos'} );
    local target_str = new_args['target'] or '';
    local pos = tonumber( new_args['pos'] ) or 0;

    if pos == 0 or math.abs(pos) > mw.ustring.len( target_str ) then
        return str._error( 'Indice della stringa fuori dagli estremi' );
    end

    return mw.ustring.sub( target_str, pos, pos );
end

function str.str_find( frame )
    local new_args = str._getParameters( frame.args, {'source', 'target'} );
    local source_str = new_args['source'] or '';
    local target_str = new_args['target'] or '';

    if target_str == '' then
        return 1;
    end

    local start = mw.ustring.find( source_str, target_str, 1, true )
    if start == nil then
        start = -1
    end

    return start
end

function str.find( frame )
    local new_args = str._getParameters( frame.args, {'source', 'target', 'start', 'plain' } );
    local source_str = new_args['source'] or '';
    local pattern = new_args['target'] or '';
    local start_pos = tonumber(new_args['start']) or 1;
    local plain = new_args['plain'] or true;

    if source_str == '' or pattern == '' then
        return 0;
    end

    plain = str._getBoolean( plain );

    local start = mw.ustring.find( source_str, pattern, start_pos, plain )
    if start == nil then
        start = 0
    end

    return start
end

function str.replace( frame )
    local new_args = str._getParameters( frame.args, {'source', 'pattern', 'replace', 'count', 'plain' } );
    local source_str = new_args['source'] or '';
    local pattern = new_args['pattern'] or '';
    local replace = new_args['replace'] or '';
    local count = tonumber( new_args['count'] );
    local plain = new_args['plain'] or true;

    if source_str == '' or pattern == '' then
        return source_str;
    end
    plain = str._getBoolean( plain );

    if plain then
        pattern = str._escapePattern( pattern );
        replace = mw.ustring.gsub( replace, "%%", "%%%%" );
    end

    local result;

    if count ~= nil then
        result = mw.ustring.gsub( source_str, pattern, replace, count );
    else
        result = mw.ustring.gsub( source_str, pattern, replace );
    end

    return result;
end

function str.rep( frame )
    local repetitions = tonumber( frame.args[2] )
    if not repetitions then
        if frame.args[2] == '' then
            return ''
        else
            return str._error( 'la funzione rep si aspetta un secondo parametro con il numero di ripetizioni, ricevuto "' .. ( frame.args[2] or '' ) .. '"' )
        end
    end
    return mw.ustring.rep( frame.args[1] or '', repetitions )
end

function str.decode( frame )
    local valid_enctype = { QUERY = true, WIKI = true, PATH = true}

    local new_args = str._getParameters(frame.args, {'source', 'enctype'})
    local source = new_args['source'] or ''
    local enc_type = new_args['enctype'] or 'QUERY'
    if not valid_enctype[enc_type] then
        enc_type = 'QUERY'
    end
    return mw.uri.decode(source, enc_type)
end

function str.collate( frame )

    local collation = {
        { '[áàăắằẵẳâấầẫẩǎåǻäǟãȧǡąāảȁȃạặậḁⱥᶏᴂɐᶐɒ]' , 'a'},
        {'[ÁÀĂẮẰẴẲÂẤẦẪẨǍÅÅǺÄǞÃȦǠĄĀẢȀȂẠẶẬḀȺᴁ]', 'A'},
        {'[ḃḅḇbƀɓ]', 'b'},
        {'[ḂḄḆɃ]', 'B'},
        {'[ćĉčċçḉȼƈ]', 'c'},
        {'[ĆĈČĊÇḈȻƇ]', 'C'},
        {'[đḍḓḏðď]', 'd'},
        {'[ĐḌḒḎÐĎ]', 'D'},
        {'[éèèêếềễểěëẽėȩḝęēḗḕẻȅȇẹệḙḛǝ]', 'e'},
        {'[ÉÈÈÊẾỀỄỂĚËẼĖȨḜĘĒḖḔẺȄȆẸỆḘḚƎ]', 'E'},
        {'[ḟⅎ]', 'f'},
        {'[ḞℲ]', 'F'},
        {'[ǵğĝǧġģḡᵹɠ]', 'g'},
        {'[ǴĞĜǦĠĢḠƓ]', 'G'},
        {'[ĥȟḧḣḩħḥḫẖ]', 'h'},
        {'[ĤȞḦḢḨĦḤḪ]', 'H'},
        {'[íìĭîǐïḯĩįīỉȉȋịḭı]', 'i'},
        {'[ÍÌĬÎǏÏḮĨĮĪỈȈȊỊḬİ]', 'I'},
        {'[ĵǰ]', 'j'},
        {'[Ĵ]', 'J'},
        {'[ḱǩķ]', 'k'},
        {'[ḰǨĶ]', 'K'},
        {'[ĺľļłḷḹḽḻl·l·ŀƚⱡ]', 'l'},
        {'[ĹĽĻŁḶḸḼḺL·L·ĿȽⱠ]', 'L'},
        {'[ḿṁṃ]', 'm'},
        {'[ḾṀṂ]', 'M'},
        {'[ńǹňñṅņṇṋṉ]', 'n'},
        {'[ŃǸŇÑṄŅṆṊṈ]', 'N'},
        {'[óòŏôốồỗổǒöȫőõṍṏȭȯȱøǿǫǭōṓṑỏȍȏơớờỡởợọộ]', 'o'},
        {'[ÓÒŎÔỐỒỖỔǑÖȪŐÕṌṎȬȮȰØǾǪǬŌṒṐỎȌȎƠỚỜỠỞỢỌỘ]', 'O'},
        {'[ṕṗ]', 'p'},
        {'[ṔṖ]', 'P'},
        {'[ŕřṙŗȑȓṛṝṟ]', 'r'},
        {'[ŔŘṘŖȐȒṚṜṞ]', 'R'},
        {'[śṥŝšṧṡşṣṩș]', 's'},
        {'[ŚṤŜŠṦṠŞṢṨȘ]', 'S'},
        {'[ťṫẗţṭțṱṯ]', 't'},
        {'[ŤṪŢṬȚṰṮ]', 'T'},
        {'[úùŭûǔůüǘǜǚǖűũṹųūṻủȕȗưứừữửựụṳṷṵʉ]', 'u'},
        {'[ÚÙŬÛǓŮÜǗǛǙǕŰŨṸŲŪṺỦȔȖƯỨỪỮỬỰỤṲṶṴɄ]', 'U'},
        {'[ṽṿʋ]', 'v'},
        {'[ṼṾƲ]', 'V'},
        {'[ẃẁŵẘẅẇẉⱳ]', 'w'},
        {'[ẂẀŴ̊ẄẆẈⱲ]', 'W'},
        {'[ýỳŷẙÿỹẏȳỷỵɏƴ]', 'y'},
        {'[ÝỲŶ̊ŸỸẎȲỶỴɎƳ]', 'Y'},
        {'[źẑžżẓẕƶȥʐⱬ]', 'z'},
        {'[ŹẐŽŻẒẔƵȤʐⱫ]', 'Z'},
    }

    local new_args = str._getParameters(frame.args, {'source'})
    local source = new_args['source'] or ''
    --local source = mw.ustring.toNFC(source)

    for _, el in ipairs(collation) do
        source = mw.ustring.gsub( source, el[1], el[2])
    end
    return source
end

function str.titolo_alfa(frame)
    local articoli = {"Il ","Lu","Li", "Lo ", "La ", "L'", "Gli ", "Le ","Nu","Na","N'", "Un ", "Uno ", "Una ", "Un'", "The ", "An ", "Les ", "El ", "Los ", "Las ", "Der ", "Das "}

    local source = frame.args[1]
    if not source or source == '' then
        source = mw.title.getCurrentTitle().text 
    end
    if not source or source == '' then
        return ''
    end
    source = mw.ustring.gsub(source, ' %(.*%)$', '')
    source = str.collate( { args = { source } } )
    source = mw.ustring.gsub(source, "^['%(%.¡¿ ]*", '')
    for _,article in ipairs(articoli) do
        source = mw.ustring.gsub(source, "^(" .. article .. ")(.*)$", "%2, %1")
    end
    source = mw.ustring.gsub(source, '^%l', mw.ustring.upper)
    source = mw.text.trim(source)
    return source
end

local Param = {}
Param.__index = Param

function Param.new(par_name, alt_name)
    if  par_name ~= "$index" and not mw.ustring.find(par_name, '#') then par_name = par_name .. '#' end;
    return setmetatable({
        name = par_name,
        base_name = mw.ustring.gsub(par_name, ' ?#', '', 1),
        alt = alt_name or ''
     }, Param)
end

function Param:get_other_value(args, index)
    if self.name == '$index' then
        return tostring(index), true
    else
        return args[mw.ustring.gsub(self.name, '#', tostring(index), 1)] or '', false
    end
end

function Param:get_first_value(args, index, base_index)
    function value_or_nil (s)
        if s and s~= '' then return s end
        return nil
    end

    if self.name == '$index' then
        return tostring(index), true
    end
    if index == base_index then
        return value_or_nil(args[mw.ustring.gsub(self.name, '#', tostring(index), 1)]) or 
               value_or_nil(args[self.base_name]) or value_or_nil(args[self.alt]) or '', false
    else
        return value_or_nil(args[mw.ustring.gsub(self.name, '#', tostring(index), 1)]) or 
               value_or_nil(args[self.alt]) or '', false
    end
end


setmetatable(Param, { __call = function(_, ...) return Param.new(...) end })

local Message = {}
Message.__index = Message

function Message.new(msg)
    msg = mw.ustring.gsub(msg, '\\{', '{')
    msg = mw.ustring.gsub(msg, '\\}', '}')
    local frame = mw.getCurrentFrame():getParent() or mw.getCurrentFrame()

    return setmetatable({
        msg =  msg,
        values = {},
        frame = frame,
     }, Message)
end

function Message:reset_values()
    self.values = {}
end

function Message:add_value(value)
    self.values[#self.values+1] = value
end

function Message:text()
    return self.frame:preprocess(mw.message.newRawMessage(self.msg, self.values):plain())
end

setmetatable(Message, { __call = function(_, ...) return Message.new(...) end })

function str.arraytostring(frame)

    local base_args = frame.args
    local params = {}
    if not base_args then return str._error('Lista paràmitri vacanti') end
    local index = 1
    while true do
        local par_name = base_args['par' .. index] or (index == 1 and base_args['par']) or ''
        if par_name == '' then break end;
        local alt_name = base_args['altpar' .. index] or (index == 1 and base_args['altpar']) or ''
        params[index] = Param(par_name, alt_name)
        index = index + 1
    end
    local msg = base_args.msg or '$1'
    local message = Message(msg)
    elements = {}
    local Nmax = tonumber(base_args.Nmax) or tonumber(base_args.nmax) or 0
    local base_index = tonumber(base_args.baseindex) or tonumber(base_args.baseIndex) or 1
    local index = tonumber(base_args.Nmin) or tonumber(base_args.nmin) or base_index
    local Nobbligatori = tonumber(base_args.Nobbligatori) or tonumber(base_args.nobbligatori) or base_index-1
    local indentazione = base_args.indentazione or nil
    local args = frame:getParent().args
    local found = false

    for i, param in ipairs(params) do
        local v, is_index = param:get_first_value(args, index, base_index)
        if (not(is_index) or base_index<=Nobbligatori) and v ~= '' then found = true end
        message:add_value(v)
    end
    if found then
        elements[#elements+1] = message:text()
        index = index + 1
    end
    while true do
        if Nmax > 0 and index > Nmax then break end
        message:reset_values()
        found = false
        for i, param in ipairs(params) do
            local v, is_index = param:get_other_value(args, index)
            if (not(is_index) or index<=Nobbligatori) and v ~= '' then found = true end
            message:add_value(v)
        end
        if found then
            elements[#elements+1] = message:text()
        elseif index >= Nobbligatori then
            break
        end
        index = index + 1
    end
    if #elements == 0 then return '' end
    local pre, post, separatore, congiunzione, indent = '', '', '', '', ''
    local lista = base_args.lista or ''
    if lista == 'appuntata' or (lista =='infobox' and #elements >1) then
        pre = '<UL><LI>'
        post = '</LI>\n</UL>'
        separatore = '</LI>\n<LI>'
        congiunzione = separatore
    elseif lista == 'ordinata' then
        pre = '<OL><LI>'
        post = '</LI>\n</OL>'
        separatore = '</LI>\n<LI>'
        congiunzione = separatore
    else
        pre = base_args.pre or ''
        post = base_args.post or ''
        separatore = base_args.separatore or ''
        congiunzione = base_args.congiunzione or separatore
    end
    if indentazione then
        local current_indentazione = indentazione
        for i, msg in ipairs(elements) do
            elements[i] = current_indentazione .. elements[i]
            current_indentazione = current_indentazione .. indentazione 
        end
    end
    return pre .. mw.text.listToText(elements, separatore, congiunzione) .. post
end

function str.listtostring(frame)

    local base_args = frame.args
    local params = {}
    if not base_args then return str._error('Lista paràmitri vacanti') end
    local base_index = tonumber(base_args.base_index) or 1
    local par_number = tonumber(base_args.par_number) or 1
    local Nmax = tonumber(base_args.nmax) or 0
    local Nobbligatori = tonumber(base_args.nobbligatori) or base_index-1
    local message = Message(base_args.msg or '$1')
    elements = {}
    local index = base_index
    local args = frame:getParent().args
    local found = true
    while true do
        if Nmax > 0 and index > Nmax then break end
        message:reset_values()
        found = false
        for i = index, index+par_number-1 do
            message:add_value(args[i] or '')
            if args[i] then
                found = true
            end
        end
        if found then 
            elements[#elements+1] = message:text()
        elseif index > Nobbligatori then
            break
        end
        index = index + par_number
    end
    if #elements == 0 then return '' end
    local pre, post, separatore, congiunzione = '', '', '', ''
    local lista = base_args.lista or ''
    if lista == 'appuntata' or (lista =='infobox' and #elements >1) then
        pre = '<UL><LI>'
        post = '</LI>\n</UL>'
        separatore = '</LI>\n<LI>'
        congiunzione = separatore
    elseif lista == 'ordinata' then
        pre = '<OL><LI>'
        post = '</LI>\n</OL>'
        separatore = '</LI>\n<LI>'
        congiunzione = separatore
    else
        pre = base_args.pre or ''
        post = base_args.post or ''
        separatore = base_args.separatore or ''
        congiunzione = base_args.congiunzione or separatore
    end
    return pre .. mw.text.listToText(elements, separatore, congiunzione) .. post
end

function str.checkIP(frame)

	local ip = frame.args[1] or ''

  	local chunks = {ip:match("^(%d+)%.(%d+)%.(%d+)%.(%d+)$")}
 	if #chunks == 4 then
    	for _,v in pairs(chunks) do
    		if tonumber(v) > 255 then return '' end
    	end
    	return ip
  	end

	local chunks = {ip:match("^"..(("([a-fA-F0-9]*):"):rep(8):gsub(":$","$")))}
	if #chunks == 8	or #chunks < 8 and ip:match('::') and not ip:gsub("::","",1):match('::') then
		for _,v in pairs(chunks) do
			if #v > 0 and tonumber(v, 16) > 65535 then 
				return '' 
			end
    	end
    return ip
  end
  return ''
end

function str._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

function str._error( error_str )
    local frame = mw.getCurrentFrame();
    local error_category = frame.args.error_category or 'Errura ripurtati dû mòdulu String';
    local ignore_errors = frame.args.ignore_errors or false;
    local no_category = frame.args.no_category or false;

    if str._getBoolean(ignore_errors) then
        return '';
    end

    local error_str = '<strong class="error">Errura ntû mòdulu string: ' .. error_str .. '</strong>';
    if error_category ~= '' and not str._getBoolean( no_category ) then
        error_str = '[[Catigurìa:' .. error_category .. ']]' .. error_str;
    end

    return error_str;
end

function str._getBoolean( boolean_str )
    local boolean_value;

    if type( boolean_str ) == 'string' then
        boolean_str = boolean_str:lower();
        if boolean_str == 'false' or boolean_str == 'no' or boolean_str == '0'
                or booleean_str == 'fàrsu' or boolean_str == '' then
            boolean_value = false;
        else
            boolean_value = true;
        end
    elseif type( boolean_str ) == 'boolean' then
        boolean_value = boolean_str;
    else
        error('Nuḍḍu valuri booleanu attruvatu' );
    end
    return boolean_value
end

function str._escapePattern( pattern_str )
    return mw.ustring.gsub( pattern_str, "([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1" );
end

return str