diff options
| -rw-r--r-- | mrblib/string.rb | 30 | ||||
| -rw-r--r-- | test/t/string.rb | 10 |
2 files changed, 33 insertions, 7 deletions
diff --git a/mrblib/string.rb b/mrblib/string.rb index 26dbdcb9c..f91b5a23c 100644 --- a/mrblib/string.rb +++ b/mrblib/string.rb @@ -124,15 +124,31 @@ class String # # ISO 15.2.10.5.36 def sub(*args, &block) - if args.size == 2 - pre, post = split(args[0], 2) - return self unless post # The sub target wasn't found in the string - pre + args[1].__sub_replace(pre, args[0], post) + post - elsif args.size == 1 && block - split(args[0], 2).join(block.call(args[0])) + unless (1..2).include?(args.length) + raise ArgumentError, "wrong number of arguments (given #{args.length}, expected 2)" + end + + pattern, replace = *args + pattern = pattern.to_str + if args.length == 2 && block + block = nil + end + if !block + replace = replace.to_str + end + result = [] + this = dup + found = index(pattern) + return this unless found + result << this[0, found] + offset = found + pattern.length + result << if block + block.call(pattern).to_s else - raise ArgumentError, "wrong number of arguments" + replace.__sub_replace(this[0, found], pattern, this[offset..-1] || "") end + result << this[offset..-1] if offset < length + result.join end ## diff --git a/test/t/string.rb b/test/t/string.rb index c99457d7e..a4139622a 100644 --- a/test/t/string.rb +++ b/test/t/string.rb @@ -585,6 +585,16 @@ assert('String#sub', '15.2.10.5.36') do assert_equal 'aBcabc', 'abcabc'.sub('b', 'B') assert_equal 'aBcabc', 'abcabc'.sub('b') { |w| w.capitalize } assert_equal 'aa$', 'aa#'.sub('#', '$') + assert_equal '.abc', "abc".sub("", ".") + + str = "abc" + miss = str.sub("X", "Z") + assert_equal str, miss + assert_not_equal str.object_id, miss.object_id + + a = [] + assert_equal '.abc', "abc".sub("") { |i| a << i; "." } + assert_equal [""], a end assert('String#sub with backslash') do |
