summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--mrblib/string.rb30
-rw-r--r--test/t/string.rb10
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