Module:String: Difference between revisions

From Frontierpedia, the Microsoft Agent encyclopedia
en>WOSlinker
(replace_plain fix)
en>Dragons flight
(include more generic replacement function)
Line 127: Line 127:
     end     
     end     
      
      
     if type( plain ) == 'string' then
     plain = str._getBoolean( plain );
        plain = plain:lower();
        if plain == 'false' or plain == 'no' or plain == '0' then
            plain = false;
        else
            plain = true;
        end   
    end


     local start = mw.ustring.find( source_str, pattern, start_pos, plain )
     local start = mw.ustring.find( source_str, pattern, start_pos, plain )
Line 145: Line 138:


--[====[
--[====[
replace_plain
replace


This function allows one to replace a target string or pattern within another
This function allows one to replace a target string or pattern within another
Line 151: Line 144:


Usage:
Usage:
{{#invoke:String|replace_plain|source_str|pattern_string|replace_string|firstonlyflag}}
{{#invoke:String|replace_plain|source_str|pattern_string|replace_string|replacement_count|pattern_flag}}
OR
OR
{{#invoke:String|replace_plain|source=source_str|pattern=pattern_str|replace=replace_string|firstonly=firstonlyflag}}
{{#invoke:String|replace_plain|source=source_str|pattern=pattern_str|replace=replace_string|
  count=replacement_count|plain=pattern_flag}}


Parameters
Parameters
     source: The string to search
     source: The string to search
     patten: The string or pattern to find within source
     pattern: The string or pattern to find within source
     replace: The replacement text
     replace: The replacement text
     firstonly: Boolean flag indicating that only the first occurence found should be replaced
     count: The number of occurences to replace, defaults to all.
    plain: Boolean flag indicating that pattern should be understood as plain
        text and not as a Lua style regular expression, defaults to true
]====]
]====]
function str.replace_plain( frame )
function str.replace( frame )
     local new_args = str._getParameters( frame.args, {'source', 'pattern', 'replace', 'firstonly' } );  
     local new_args = str._getParameters( frame.args, {'source', 'pattern', 'replace', 'count', 'plain' } );  
     local source_str = new_args['source'] or '';
     local source_str = new_args['source'] or '';
     local pattern = new_args['pattern'] or '';
     local pattern = new_args['pattern'] or '';
     local replace = new_args['replace'] or '';
     local replace = new_args['replace'] or '';
     local firstonly = new_args['firstonly'] or '';
     local count = tonumber( new_args['count'] );
     firstonly = firstonly:lower();
     local plain = new_args['plain'] or true;
          
          
     if source_str == '' or pattern == '' then
     if source_str == '' or pattern == '' then
         return source_str;
         return source_str;
     end     
     end     
    plain = str._getBoolean( plain );


     local pattern_plain = mw.ustring.gsub(pattern, '%%', '%%%%');
     if plain then
    local replace_plain = mw.ustring.gsub(replace, '%%', '%%%%');
        pattern = str._escapePattern( pattern );
        replace = str._escapePattern( replace );
    end
   
     local result;
     local result;


     if firstonly == 'true' or firstonly == 'yes' or firstonly == '1' then
     if count ~= nil then
         result = mw.ustring.gsub( source_str, pattern_plain, replace_plain, 1 );
         result = mw.ustring.gsub( source_str, pattern, replace, count );
     else
     else
         result = mw.ustring.gsub( source_str, pattern_plain, replace_plain, n );
         result = mw.ustring.gsub( source_str, pattern, replace );
     end
     end      


     return result;
     return result;
Line 208: Line 208:
     return new_args;
     return new_args;
end         
end         
--[====[
Helper Function to interpret boolean strings
]====]
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' then
            boolean_value = false;
        else
            boolean_value = true;
        end   
    elseif type( boolean_str ) == 'boolean' then
        boolean_value = boolean_str;
    else
        error( 'No boolean value found' );
    end   
    return boolean_value
end
--[====[
Helper function that escapes all pattern characters so that they will be treated
as plain text.
]====]
function str._escapePattern( pattern_str )
    return mw.ustring.gsub( pattern_str, "([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1" );
end


return str
return str

Revision as of 19:31, 24 February 2013

Documentation for this module may be created at Module:String/doc

local str = {}

function str.len( frame )
    return mw.ustring.len( frame.args.s )
end

function str.sub( frame )
    return mw.ustring.sub( frame.args.s, tonumber( frame.args.i ), tonumber( frame.args.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 mw.ustring.match( frame.args.s, frame.args.pattern, tonumber( frame.args.i ) )
end

--[====[
pos

This function returns a single character from the target string at position pos.

Usage:
{{#invoke:String|pos|target_string|index_value}}
OR
{{#invoke:String|pos|target=target_string|pos=index_value}}

Parameters
    target: The string to search
    pos: The index for the character to return

If invoked using named parameters, Mediawiki will automatically remove any leading or
trailing whitespace from the target string.  In some circumstances this is desirable, in 
other cases one may want to preserve the whitespace.

The first character has an index value of 1.

If one requests a negative value, this function will select a character by counting backwards 
from the end of the string.  In other words pos = -1 is the same as asking for the last character.

A requested value of zero, or a value greater than the length of the string returns an error.
]====]
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 '<strong class="error">String index out of range</strong>';
    end    
    
    return mw.ustring.sub( target_str, pos, pos );
end

--[====[
str_find

This function duplicates the behavior of {{str_find}}, including all of its quirks.
This is provided in order to support existing templates, but is NOT RECOMMENDED for 
new code and templates.  New code is recommended to use the "find" function instead.

Returns the first index in "source" that is a match to "target".  Indexing is 1-based,
and the function returns -1 if the "target" string is not present in "source".

Important Note: If the "target" string is empty / missing, this function returns a
value of "1", which is generally unexpected behavior, and must be accounted for
separatetly.
]====]
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

--[====[
find

This function allows one to search for a target string or pattern within another
string.

Usage:
{{#invoke:String|find|source_str|target_string|start_index|plain_flag}}
OR
{{#invoke:String|find|source=source_str|target=target_str|start=start_index|plain=plain_flag}}

Parameters
    source: The string to search
    target: The string or pattern to find within source
    start: The index within the source string to start the search, defaults to 1
    plain: Boolean flag indicating that target should be understood as plain
        text and not as a Lua style regular expression, defaults to true

If invoked using named parameters, Mediawiki will automatically remove any leading or
trailing whitespace from the parameter.  In some circumstances this is desirable, in 
other cases one may want to preserve the whitespace.

This function returns the first index >= "start" where "target" can be found 
within "source".  Indices are 1-based.  If "target" is not found, then this 
function returns 0.  If either "source" or "target" are missing / empty, this
function also returns 0.

This function should be safe for UTF-8 strings.
]====]
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

--[====[
replace

This function allows one to replace a target string or pattern within another
string.

Usage:
{{#invoke:String|replace_plain|source_str|pattern_string|replace_string|replacement_count|pattern_flag}}
OR
{{#invoke:String|replace_plain|source=source_str|pattern=pattern_str|replace=replace_string|
   count=replacement_count|plain=pattern_flag}}

Parameters
    source: The string to search
    pattern: The string or pattern to find within source
    replace: The replacement text
    count: The number of occurences to replace, defaults to all.
    plain: Boolean flag indicating that pattern should be understood as plain
        text and not as a Lua style regular expression, defaults to true 
]====]
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 = str._escapePattern( 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

--[====[
Helper function that populates the argument list given that user may need to use a mix of
named and unnamed parameters.  This is relevant because named parameters are not
identical to unnamed parameters due to string trimming, and when dealing with strings
we sometimes want to either preserve or remove that whitespace depending on the application.
]====]
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        

--[====[
Helper Function to interpret boolean strings
]====]
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' then
            boolean_value = false;
        else
            boolean_value = true;
        end    
    elseif type( boolean_str ) == 'boolean' then
        boolean_value = boolean_str;
    else
        error( 'No boolean value found' );
    end    
    return boolean_value
end

--[====[
Helper function that escapes all pattern characters so that they will be treated 
as plain text.
]====]
function str._escapePattern( pattern_str )
    return mw.ustring.gsub( pattern_str, "([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1" );
end

return str