Difference between revisions of "Module:String"

From FIThydrowiki
Jump to navigation Jump to search
what>Dragons flight
(add description and whitespace handling option for len)
what>Dragons flight
(improves commenting, adds whitespace and error handling to sub, improvements to error handling generally.)
Line 1: Line 1:
 +
--[[ 
 +
 +
This module is intended to provide access to basic string functions.
 +
 +
Most of the functions provided here can be invoked with named parameters,
 +
unnamed parameters, or a mixture.  If named parameters are used, Mediawiki will
 +
automatically remove any leading or trailing whitespace from the parameter. 
 +
Depending on the intended use, it may be advantageous to either preserve or
 +
remove such whitespace.
 +
 +
Global options
 +
    ignore_errors: If set to 'true' or 1, any error condition will result in
 +
        an empty string being returned rather than an error message. 
 +
       
 +
    error_category: If an error occurs, specifies the name of a category to
 +
        include with the error message.  The default category is 
 +
        [Category:Errors reported by Module String].  If set to an empty
 +
        string, no category will be added during an error.   
 +
]]
 +
 
local str = {}
 
local str = {}
  
--[====[
+
--[[
 
len
 
len
  
Line 9: Line 29:
 
{{#invoke:String|len|target_string|}}
 
{{#invoke:String|len|target_string|}}
 
OR
 
OR
{{#invoke:String|pos|s=target_string}}
+
{{#invoke:String|len|s=target_string}}
  
 
Parameters
 
Parameters
Line 16: Line 36:
 
If invoked using named parameters, Mediawiki will automatically remove any leading or
 
If invoked using named parameters, Mediawiki will automatically remove any leading or
 
trailing whitespace from the target string.   
 
trailing whitespace from the target string.   
]====]
+
]]
 
function str.len( frame )
 
function str.len( frame )
 
     local new_args = str._getParameters( frame.args, {'s'} );
 
     local new_args = str._getParameters( frame.args, {'s'} );
Line 23: Line 43:
 
end
 
end
  
 +
--[[
 +
sub
 +
 +
This function returns a substring of the target string at specified indices.
 +
 +
Usage:
 +
{{#invoke:String|sub|target_string|start_index|end_index}}
 +
OR
 +
{{#invoke:String|sub|s=target_string|i=start_index|j=end_index}}
 +
 +
Parameters
 +
    s: The string to return a subset of
 +
    i: The fist index of the substring to return, defaults to 1.
 +
    j: The last index of the string to return, defaults to the last character.
 +
   
 +
The first character of the string is assigned an index of 1.  If either i or j
 +
is a negative value, it is interpreted the same as selecting a character by
 +
counting from the end of the string.  Hence, a value of -1 is the same as
 +
selecting the last character of the string.
 +
 +
If the requested indices are out of range for the given string, an error is
 +
reported.
 +
]]
 
function str.sub( frame )
 
function str.sub( frame )
     return mw.ustring.sub( frame.args.s, tonumber( frame.args.i ), tonumber( frame.args.j ) )
+
     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 );
 +
 
 +
    -- Convert negatives for range checking
 +
    if i < 0 then
 +
        i = len + i + 1;
 +
    end
 +
    if j < 0 then
 +
        j = len + j + 1;
 +
    end
 +
    if j < i then
 +
        return str._error( 'String subset indices out of order' );
 +
    end
 +
   
 +
    if i > len or j > len or i < 1 or j < 1 then
 +
        return str._error( 'String subset index out of range' );
 +
    end
 +
   
 +
    return mw.ustring.sub( s, i, j )
 
end
 
end
  
Line 37: Line 102:
 
end
 
end
  
--[====[
+
--[[
 
pos
 
pos
  
Line 61: Line 126:
  
 
A requested value of zero, or a value greater than the length of the string returns an error.
 
A requested value of zero, or a value greater than the length of the string returns an error.
]====]
+
]]
 
function str.pos( frame )
 
function str.pos( frame )
 
     local new_args = str._getParameters( frame.args, {'target', 'pos'} );
 
     local new_args = str._getParameters( frame.args, {'target', 'pos'} );
Line 68: Line 133:
  
 
     if pos == 0 or math.abs(pos) > mw.ustring.len( target_str ) then
 
     if pos == 0 or math.abs(pos) > mw.ustring.len( target_str ) then
         return '<strong class="error">String index out of range</strong>';
+
         return str._error( 'String index out of range' );
 
     end     
 
     end     
 
      
 
      
Line 74: Line 139:
 
end
 
end
  
--[====[
+
--[[
 
str_find
 
str_find
  
Line 87: Line 152:
 
value of "1", which is generally unexpected behavior, and must be accounted for
 
value of "1", which is generally unexpected behavior, and must be accounted for
 
separatetly.
 
separatetly.
]====]
+
]]
 
function str.str_find( frame )
 
function str.str_find( frame )
 
     local new_args = str._getParameters( frame.args, {'source', 'target'} );
 
     local new_args = str._getParameters( frame.args, {'source', 'target'} );
Line 105: Line 170:
 
end
 
end
  
--[====[
+
--[[
 
find
 
find
  
Line 133: Line 198:
  
 
This function should be safe for UTF-8 strings.
 
This function should be safe for UTF-8 strings.
]====]
+
]]
 
function str.find( frame )
 
function str.find( frame )
 
     local new_args = str._getParameters( frame.args, {'source', 'target', 'start', 'plain' } );  
 
     local new_args = str._getParameters( frame.args, {'source', 'target', 'start', 'plain' } );  
Line 155: Line 220:
 
end
 
end
  
--[====[
+
--[[
 
replace
 
replace
  
Line 174: Line 239:
 
     plain: Boolean flag indicating that pattern should be understood as plain
 
     plain: Boolean flag indicating that pattern should be understood as plain
 
         text and not as a Lua style regular expression, defaults to true  
 
         text and not as a Lua style regular expression, defaults to true  
]====]
+
]]
 
function str.replace( frame )
 
function str.replace( frame )
 
     local new_args = str._getParameters( frame.args, {'source', 'pattern', 'replace', 'count', 'plain' } );  
 
     local new_args = str._getParameters( frame.args, {'source', 'pattern', 'replace', 'count', 'plain' } );  
Line 204: Line 269:
 
end
 
end
  
--[====[
+
--[[
 
Helper function that populates the argument list given that user may need to use a mix of
 
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
 
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
 
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.
 
we sometimes want to either preserve or remove that whitespace depending on the application.
]====]
+
]]
 
function str._getParameters( frame_args, arg_list )
 
function str._getParameters( frame_args, arg_list )
 
     local new_args = {};
 
     local new_args = {};
Line 227: Line 292:
 
end         
 
end         
  
--[====[
+
--[[
 +
Helper function to handle error messages.
 +
]]
 +
function str._error( error_str )
 +
    local frame = mw.getCurrentFrame();
 +
    local error_category = frame.args.error_category or 'Errors reported by Module String';
 +
    local ignore_errors = frame.args.ignore_errors or false;
 +
   
 +
    if str._getBoolean(ignore_errors) then
 +
        return '';
 +
    end
 +
   
 +
    local error_str = '<strong class="error">String Module Error: ' .. error_str .. '</strong>';
 +
    if error_category ~= '' then
 +
        error_str = '[[Category:' .. error_category .. ']]' .. error_str;
 +
    end       
 +
   
 +
    return error_str;
 +
end
 +
 
 +
--[[
 
Helper Function to interpret boolean strings
 
Helper Function to interpret boolean strings
]====]
+
]]
 
function str._getBoolean( boolean_str )
 
function str._getBoolean( boolean_str )
 
     local boolean_value;
 
     local boolean_value;
Line 248: Line 333:
 
end
 
end
  
--[====[
+
--[[
 
Helper function that escapes all pattern characters so that they will be treated  
 
Helper function that escapes all pattern characters so that they will be treated  
 
as plain text.
 
as plain text.
]====]
+
]]
 
function str._escapePattern( pattern_str )
 
function str._escapePattern( pattern_str )
 
     return mw.ustring.gsub( pattern_str, "([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1" );
 
     return mw.ustring.gsub( pattern_str, "([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1" );

Revision as of 02:06, 25 February 2013

--[[

This module is intended to provide access to basic string functions.

Most of the functions provided here can be invoked with named parameters, unnamed parameters, or a mixture. If named parameters are used, Mediawiki will automatically remove any leading or trailing whitespace from the parameter. Depending on the intended use, it may be advantageous to either preserve or remove such whitespace.

Global options

   ignore_errors: If set to 'true' or 1, any error condition will result in 
       an empty string being returned rather than an error message.  
       
   error_category: If an error occurs, specifies the name of a category to 
       include with the error message.  The default category is  
       [Category:Errors reported by Module String].  If set to an empty
       string, no category will be added during an error.    

]]

local str = {}

--[[ len

This function returns the length of the target string.

Usage: Script error: No such module "String". OR Script error: No such module "String".

Parameters

   s: The string whose length to report

If invoked using named parameters, Mediawiki will automatically remove any leading or trailing whitespace from the target string. ]] function str.len( frame )

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

end

--[[ sub

This function returns a substring of the target string at specified indices.

Usage: Script error: No such module "String". OR Script error: No such module "String".

Parameters

   s: The string to return a subset of
   i: The fist index of the substring to return, defaults to 1.
   j: The last index of the string to return, defaults to the last character.
   

The first character of the string is assigned an index of 1. If either i or j is a negative value, it is interpreted the same as selecting a character by counting from the end of the string. Hence, a value of -1 is the same as selecting the last character of the string.

If the requested indices are out of range for the given string, an error is reported. ]] 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 );
   -- Convert negatives for range checking
   if i < 0 then
       i = len + i + 1;
   end
   if j < 0 then
       j = len + j + 1;
   end
   if j < i then
       return str._error( 'String subset indices out of order' );
   end
   
   if i > len or j > len or i < 1 or j < 1 then
       return str._error( 'String subset index out of range' );
   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 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: Script error: No such module "String". OR Script error: No such module "String".

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 str._error( 'String index out of range' );
   end    
   
   return mw.ustring.sub( target_str, pos, pos );

end

--[[ str_find

This function duplicates the behavior of Template: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: Script error: No such module "String". OR Script error: No such module "String".

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: Script error: No such module "String". OR Script error: No such module "String".

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 handle error messages. ]] function str._error( error_str )

   local frame = mw.getCurrentFrame();
   local error_category = frame.args.error_category or 'Errors reported by Module String';
   local ignore_errors = frame.args.ignore_errors or false;
   
   if str._getBoolean(ignore_errors) then
       return ;
   end
   
   local error_str = 'String Module Error: ' .. error_str .. '';
   if error_category ~=  then
       error_str =  .. error_str;
   end        
   
   return error_str;

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