|
|
Line 10: |
Line 10: |
|
| |
|
| Global options | | Global options |
| ignore_errors: If set to 'true' or 1, any error condition will result in
| | ignore_errors: If set to 'true' or 1, any error condition will result in |
| an empty string being returned rather than an error message.
| | an empty string being returned rather than an error message. |
|
| |
|
| error_category: If an error occurs, specifies the name of a category to
| | error_category: If an error occurs, specifies the name of a category to |
| include with the error message. The default category is
| | include with the error message. The default category is |
| [Category:Errors reported by Module String].
| | [Category:Errors reported by Module String]. |
|
| |
|
| no_category: If set to 'true' or 1, no category will be added if an error
| | no_category: If set to 'true' or 1, no category will be added if an error |
| is generated.
| | is generated. |
|
| |
|
| Unit tests for this module are available at Module:String/tests. | | Unit tests for this module are available at Module:String/tests. |
Line 36: |
Line 36: |
|
| |
|
| Parameters | | Parameters |
| s: The string whose length to report
| | s: The string whose length to report |
|
| |
|
| If invoked using named parameters, Mediawiki will automatically remove any leading or | | If invoked using named parameters, Mediawiki will automatically remove any leading or |
Line 42: |
Line 42: |
| ]] | | ]] |
| function str.len( frame ) | | function str.len( frame ) |
| local new_args = str._getParameters( frame.args, {'s'} ) | | local new_args = str._getParameters( frame.args, {'s'} ); |
| local s = new_args['s'] or '' | | local s = new_args['s'] or ''; |
| return mw.ustring.len( s ) | | return mw.ustring.len( s ) |
| end | | end |
Line 58: |
Line 58: |
|
| |
|
| Parameters | | Parameters |
| s: The string to return a subset of
| | s: The string to return a subset of |
| i: The fist index of the substring to return, defaults to 1.
| | 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.
| | 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 | | The first character of the string is assigned an index of 1. If either i or j |
Line 71: |
Line 71: |
| ]] | | ]] |
| function str.sub( frame ) | | function str.sub( frame ) |
| local new_args = str._getParameters( frame.args, { 's', 'i', 'j' } ) | | local new_args = str._getParameters( frame.args, { 's', 'i', 'j' } ); |
| local s = new_args['s'] or '' | | local s = new_args['s'] or ''; |
| local i = tonumber( new_args['i'] ) or 1 | | local i = tonumber( new_args['i'] ) or 1; |
| local j = tonumber( new_args['j'] ) or -1 | | local j = tonumber( new_args['j'] ) or -1; |
|
| |
|
| local len = mw.ustring.len( s ) | | local len = mw.ustring.len( s ); |
|
| |
|
| -- Convert negatives for range checking | | -- Convert negatives for range checking |
| if i < 0 then | | if i < 0 then |
| i = len + i + 1 | | i = len + i + 1; |
| end | | end |
| if j < 0 then | | if j < 0 then |
| j = len + j + 1 | | j = len + j + 1; |
| end | | end |
|
| |
|
| if i > len or j > len or i < 1 or j < 1 then | | if i > len or j > len or i < 1 or j < 1 then |
| return str._error( 'String subset index out of range' ) | | return str._error( 'String subset index out of range' ); |
| end | | end |
| if j < i then | | if j < i then |
| return str._error( 'String subset indices out of order' ) | | return str._error( 'String subset indices out of order' ); |
| end | | end |
|
| |
|
Line 113: |
Line 113: |
|
| |
|
| Usage: | | Usage: |
| {{#invoke:String|match|source_string|pattern_string|start_index|match_number|plain_flag|nomatch_output}} | | {{#invoke:String|match|source_string|pattern_string|start_index|match_number|plain_flag|nomatch}} |
| OR | | OR |
| {{#invoke:String|match|s=source_string|pattern=pattern_string|start=start_index | | {{#invoke:String|pos|s=source_string|pattern=pattern_string|start=start_index |
| |match=match_number|plain=plain_flag|nomatch=nomatch_output}}
| | |match=match_number|plain=plain_flag|nomatch=nomatch_output}} |
|
| |
|
| Parameters | | Parameters |
| s: The string to search
| | s: The string to search |
| pattern: The pattern or string to find within the string
| | pattern: The pattern or string to find within the string |
| start: The index within the source string to start the search. The first
| | start: The index within the source string to start the search. The first |
| character of the string has index 1. Defaults to 1.
| | character of the string has index 1. Defaults to 1. |
| match: In some cases it may be possible to make multiple matches on a single
| | match: In some cases it may be possible to make multiple matches on a single |
| string. This specifies which match to return, where the first match is
| | string. This specifies which match to return, where the first match is |
| match= 1. If a negative number is specified then a match is returned
| | match= 1. If a negative number is specified then a match is returned |
| counting from the last match. Hence match = -1 is the same as requesting
| | counting from the last match. Hence match = -1 is the same as requesting |
| the last match. Defaults to 1.
| | the last match. Defaults to 1. |
| plain: A flag indicating that the pattern should be understood as plain
| | plain: A flag indicating that the pattern should be understood as plain |
| text. Defaults to false.
| | text. Defaults to false. |
| nomatch: If no match is found, output the "nomatch" value rather than an error.
| | nomatch: If no match is found, output the "nomatch" value rather than an error. |
|
| |
|
| If invoked using named parameters, Mediawiki will automatically remove any leading or | | If invoked using named parameters, Mediawiki will automatically remove any leading or |
Line 143: |
Line 143: |
| For information on constructing Lua patterns, a form of [regular expression], see: | | For information on constructing Lua patterns, a form of [regular expression], see: |
|
| |
|
| * http://www.lua.org/manual/5.1/manual.html#5.4.1 | | * https://www.lua.org/manual/5.1/manual.html#5.4.1 |
| * http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns | | * https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns |
| * http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Ustring_patterns | | * https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Ustring_patterns |
|
| |
|
| ]] | | ]] |
| -- This sub-routine is exported for use in other modules | | -- This sub-routine is exported for use in other modules |
| function str._match( s, pattern, start, match_index, plain_flag, nomatch ) | | function str._match( s, pattern, start, match_index, plain, nomatch ) |
| if s == '' then | | if s == '' then |
| return str._error( 'Target string is empty' ) | | return str._error( 'Target string is empty' ); |
| end | | end |
| if pattern == '' then | | if pattern == '' then |
| return str._error( 'Pattern string is empty' ) | | return str._error( 'Pattern string is empty' ); |
| end | | end |
| start = tonumber(start) or 1 | | start = tonumber(start) or 1 |
| if math.abs(start) < 1 or math.abs(start) > mw.ustring.len( s ) then | | if math.abs(start) < 1 or math.abs(start) > mw.ustring.len( s ) then |
| return str._error( 'Requested start is out of range' ) | | return str._error( 'Requested start is out of range' ); |
| end | | end |
| if match_index == 0 then | | if match_index == 0 then |
| return str._error( 'Match index is out of range' ) | | return str._error( 'Match index is out of range' ); |
| end | | end |
| if plain_flag then | | if plain_flag then |
| pattern = str._escapePattern( pattern ) | | pattern = str._escapePattern( pattern ); |
| end | | end |
|
| |
|
Line 173: |
Line 173: |
| else | | else |
| if start > 1 then | | if start > 1 then |
| s = mw.ustring.sub( s, start ) | | s = mw.ustring.sub( s, start ); |
| end | | end |
|
| |
|
| local iterator = mw.ustring.gmatch(s, pattern) | | local iterator = mw.ustring.gmatch(s, pattern); |
| if match_index > 0 then | | if match_index > 0 then |
| -- Forward search | | -- Forward search |
| for w in iterator do | | for w in iterator do |
| match_index = match_index - 1 | | match_index = match_index - 1; |
| if match_index == 0 then | | if match_index == 0 then |
| result = w | | result = w; |
| break | | break; |
| end | | end |
| end | | end |
| else | | else |
| -- Reverse search | | -- Reverse search |
| local result_table = {} | | local result_table = {}; |
| local count = 1 | | local count = 1; |
| for w in iterator do | | for w in iterator do |
| result_table[count] = w | | result_table[count] = w; |
| count = count + 1 | | count = count + 1; |
| end | | end |
|
| |
|
| result = result_table[ count + match_index ] | | result = result_table[ count + match_index ]; |
| end | | end |
| end | | end |
Line 201: |
Line 201: |
| if result == nil then | | if result == nil then |
| if nomatch == nil then | | if nomatch == nil then |
| return str._error( 'Match not found' ) | | return str._error( 'Match not found' ); |
| else | | else |
| return nomatch | | return nomatch; |
| end | | end |
| else | | else |
| return result | | return result; |
| end | | end |
| end | | end |
| -- This is the entry point for #invoke:String|match | | -- This is the entry point for #invoke:String|match |
| function str.match( frame ) | | function str.match( frame ) |
| local new_args = str._getParameters( frame.args, {'s', 'pattern', 'start', 'match', 'plain', 'nomatch'} ) | | local new_args = str._getParameters( frame.args, {'s', 'pattern', 'start', 'match', 'plain', 'nomatch'} ); |
| local s = new_args['s'] or '' | | local s = new_args['s'] or ''; |
| local start = tonumber( new_args['start'] ) or 1 | | local start = tonumber( new_args['start'] ) or 1; |
| local plain_flag = str._getBoolean( new_args['plain'] or false ) | | local plain_flag = str._getBoolean( new_args['plain'] or false ); |
| local pattern = new_args['pattern'] or '' | | local pattern = new_args['pattern'] or ''; |
| local match_index = math.floor( tonumber(new_args['match']) or 1 ) | | local match_index = math.floor( tonumber(new_args['match']) or 1 ); |
| local nomatch = new_args['nomatch'] | | local nomatch = new_args['nomatch']; |
|
| |
|
| return str._match( s, pattern, start, match_index, plain_flag, nomatch ) | | return str._match( s, pattern, start, match_index, plain, nomatch ) |
| end | | end |
|
| |
|
Line 233: |
Line 233: |
|
| |
|
| Parameters | | Parameters |
| target: The string to search
| | target: The string to search |
| pos: The index for the character to return
| | pos: The index for the character to return |
|
| |
|
| If invoked using named parameters, Mediawiki will automatically remove any leading or | | If invoked using named parameters, Mediawiki will automatically remove any leading or |
Line 248: |
Line 248: |
| ]] | | ]] |
| 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'} ); |
| local target_str = new_args['target'] or '' | | local target_str = new_args['target'] or ''; |
| local pos = tonumber( new_args['pos'] ) or 0 | | local pos = tonumber( new_args['pos'] ) or 0; |
|
| |
|
| 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 str._error( 'String index out of range' ) | | return str._error( 'String index out of range' ); |
| end | | end |
|
| |
|
| return mw.ustring.sub( target_str, pos, pos ) | | return mw.ustring.sub( target_str, pos, pos ); |
| end | | end |
|
| |
|
Line 274: |
Line 274: |
| ]] | | ]] |
| 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'} ); |
| local source_str = new_args['source'] or '' | | local source_str = new_args['source'] or ''; |
| local target_str = new_args['target'] or '' | | local target_str = new_args['target'] or ''; |
|
| |
|
| if target_str == '' then | | if target_str == '' then |
| return 1 | | return 1; |
| end | | end |
|
| |
|
Line 302: |
Line 302: |
|
| |
|
| Parameters | | Parameters |
| source: The string to search
| | source: The string to search |
| target: The string or pattern to find within source
| | target: The string or pattern to find within source |
| start: The index within the source string to start the search, defaults to 1
| | 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
| | plain: Boolean flag indicating that target 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 |
|
| |
|
| If invoked using named parameters, Mediawiki will automatically remove any leading or | | If invoked using named parameters, Mediawiki will automatically remove any leading or |
Line 320: |
Line 320: |
| ]] | | ]] |
| 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' } ); |
| local source_str = new_args['source'] or '' | | local source_str = new_args['source'] or ''; |
| local pattern = new_args['target'] or '' | | local pattern = new_args['target'] or ''; |
| local start_pos = tonumber(new_args['start']) or 1 | | local start_pos = tonumber(new_args['start']) or 1; |
| local plain = new_args['plain'] or true | | local plain = new_args['plain'] or true; |
|
| |
|
| if source_str == '' or pattern == '' then | | if source_str == '' or pattern == '' then |
| return 0 | | return 0; |
| end | | end |
|
| |
|
| plain = str._getBoolean( plain ) | | plain = str._getBoolean( plain ); |
|
| |
|
| local start = mw.ustring.find( source_str, pattern, start_pos, plain ) | | local start = mw.ustring.find( source_str, pattern, start_pos, plain ) |
Line 353: |
Line 353: |
|
| |
|
| Parameters | | Parameters |
| source: The string to search
| | source: The string to search |
| pattern: 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 |
| count: The number of occurences to replace, defaults to all.
| | count: The number of occurences to replace, defaults to all. |
| 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' } ); |
| 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 count = tonumber( new_args['count'] ) | | local count = tonumber( new_args['count'] ); |
| local plain = new_args['plain'] or true | | 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 ) | | plain = str._getBoolean( plain ); |
|
| |
|
| if plain then | | if plain then |
| pattern = str._escapePattern( pattern ) | | pattern = str._escapePattern( pattern ); |
| replace = mw.ustring.gsub( replace, "%%", "%%%%" ) --Only need to escape replacement sequences. | | replace = mw.ustring.gsub( replace, "%%", "%%%%" ); --Only need to escape replacement sequences. |
| end | | end |
|
| |
|
| local result | | local result; |
|
| |
|
| if count ~= nil then | | if count ~= nil then |
| result = mw.ustring.gsub( source_str, pattern, replace, count ) | | result = mw.ustring.gsub( source_str, pattern, replace, count ); |
| else | | else |
| result = mw.ustring.gsub( source_str, pattern, replace ) | | result = mw.ustring.gsub( source_str, pattern, replace ); |
| end | | end |
|
| |
|
| return result | | return result; |
| end | | end |
|
| |
|
| --[[ | | --[[ |
| simple function to pipe string.rep to templates.
| | simple function to pipe string.rep to templates. |
| ]] | | ]] |
| | |
| function str.rep( frame ) | | function str.rep( frame ) |
| local repetitions = tonumber( frame.args[2] ) | | local repetitions = tonumber( frame.args[2] ) |
Line 412: |
Line 413: |
|
| |
|
| Parameters | | Parameters |
| pattern_string: The pattern string to escape.
| | pattern_string: The pattern string to escape. |
| ]] | | ]] |
| function str.escapePattern( frame ) | | function str.escapePattern( frame ) |
| local pattern_str = frame.args[1] | | local pattern_str = frame.args[1] |
| if not pattern_str then | | if not pattern_str then |
| return str._error( 'No pattern string specified' ) | | return str._error( 'No pattern string specified' ); |
| end | | end |
| local result = str._escapePattern( pattern_str ) | | local result = str._escapePattern( pattern_str ) |
| return result | | return result |
| end
| |
|
| |
| --[[
| |
| count
| |
| This function counts the number of occurrences of one string in another.
| |
| ]]
| |
| function str.count(frame)
| |
| local args = str._getParameters(frame.args, {'source', 'pattern', 'plain'})
| |
| local source = args.source or ''
| |
| local pattern = args.pattern or ''
| |
| local plain = str._getBoolean(args.plain or true)
| |
| if plain then
| |
| pattern = str._escapePattern(pattern)
| |
| end
| |
| local _, count = mw.ustring.gsub(source, pattern, '')
| |
| return count
| |
| end
| |
|
| |
| --[[
| |
| endswith
| |
| This function determines whether a string ends with another string.
| |
| ]]
| |
| function str.endswith(frame)
| |
| local args = str._getParameters(frame.args, {'source', 'pattern'})
| |
| local source = args.source or ''
| |
| local pattern = args.pattern or ''
| |
| if pattern == '' then
| |
| -- All strings end with the empty string.
| |
| return "yes"
| |
| end
| |
| if mw.ustring.sub(source, -mw.ustring.len(pattern), -1) == pattern then
| |
| return "yes"
| |
| else
| |
| return ""
| |
| end
| |
| end
| |
|
| |
| --[[
| |
| join
| |
|
| |
| Join all non empty arguments together; the first argument is the separator.
| |
| Usage:
| |
| {{#invoke:String|join|sep|one|two|three}}
| |
| ]]
| |
| function str.join(frame)
| |
| local args = {}
| |
| local sep
| |
| for _, v in ipairs( frame.args ) do
| |
| if sep then
| |
| if v ~= '' then
| |
| table.insert(args, v)
| |
| end
| |
| else
| |
| sep = v
| |
| end
| |
| end
| |
| return table.concat( args, sep or '' )
| |
| end | | end |
|
| |
|
Line 487: |
Line 431: |
| ]] | | ]] |
| function str._getParameters( frame_args, arg_list ) | | function str._getParameters( frame_args, arg_list ) |
| local new_args = {} | | local new_args = {}; |
| local index = 1 | | local index = 1; |
| local value | | local value; |
|
| |
|
| for _, arg in ipairs( arg_list ) do | | for i,arg in ipairs( arg_list ) do |
| value = frame_args[arg] | | value = frame_args[arg] |
| if value == nil then | | if value == nil then |
| value = frame_args[index] | | value = frame_args[index]; |
| index = index + 1 | | index = index + 1; |
| end | | end |
| new_args[arg] = value | | new_args[arg] = value; |
| end | | end |
|
| |
|
| return new_args | | return new_args; |
| end | | end |
|
| |
|
Line 507: |
Line 451: |
| ]] | | ]] |
| function str._error( error_str ) | | function str._error( error_str ) |
| local frame = mw.getCurrentFrame() | | local frame = mw.getCurrentFrame(); |
| local error_category = frame.args.error_category or 'Errors reported by Module String' | | local error_category = frame.args.error_category or 'Errors reported by Module String'; |
| local ignore_errors = frame.args.ignore_errors or false | | local ignore_errors = frame.args.ignore_errors or false; |
| local no_category = frame.args.no_category or false | | local no_category = frame.args.no_category or false; |
|
| |
|
| if str._getBoolean(ignore_errors) then | | if str._getBoolean(ignore_errors) then |
| return '' | | return ''; |
| end | | end |
|
| |
|
| local error_str = '<strong class="error">String Module Error: ' .. error_str .. '</strong>' | | local error_str = '<strong class="error">String Module Error: ' .. error_str .. '</strong>'; |
| if error_category ~= '' and not str._getBoolean( no_category ) then | | if error_category ~= '' and not str._getBoolean( no_category ) then |
| error_str = '[[Category:' .. error_category .. ']]' .. error_str | | error_str = '[[Category:' .. error_category .. ']]' .. error_str; |
| end | | end |
|
| |
|
| return error_str | | return error_str; |
| end | | end |
|
| |
|
Line 528: |
Line 472: |
| ]] | | ]] |
| function str._getBoolean( boolean_str ) | | function str._getBoolean( boolean_str ) |
| local boolean_value | | local boolean_value; |
|
| |
|
| if type( boolean_str ) == 'string' then | | if type( boolean_str ) == 'string' then |
| boolean_str = boolean_str:lower() | | boolean_str = boolean_str:lower(); |
| if boolean_str == 'false' or boolean_str == 'no' or boolean_str == '0' | | if boolean_str == 'false' or boolean_str == 'no' or boolean_str == '0' |
| or boolean_str == '' then | | or boolean_str == '' then |
| boolean_value = false | | boolean_value = false; |
| else | | else |
| boolean_value = true | | boolean_value = true; |
| end | | end |
| elseif type( boolean_str ) == 'boolean' then | | elseif type( boolean_str ) == 'boolean' then |
| boolean_value = boolean_str | | boolean_value = boolean_str; |
| else | | else |
| error( 'No boolean value found' ) | | error( 'No boolean value found' ); |
| end | | end |
| return boolean_value | | return boolean_value |
Line 551: |
Line 495: |
| ]] | | ]] |
| function str._escapePattern( pattern_str ) | | function str._escapePattern( pattern_str ) |
| return mw.ustring.gsub( pattern_str, "([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1" ) | | return mw.ustring.gsub( pattern_str, "([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1" ); |
| end
| |
| | |
| --[[
| |
| check if string is a number
| |
| ]]
| |
| function str.isNumber( frame )
| |
| if not tonumber( frame.args[1] ) then
| |
| return 0
| |
| else
| |
| return 1
| |
| end
| |
| end | | end |
|
| |
|
| return str | | return str |