Skip to content

Instantly share code, notes, and snippets.

@tiegz
Created May 13, 2009 16:25
Show Gist options
  • Save tiegz/111107 to your computer and use it in GitHub Desktop.
Save tiegz/111107 to your computer and use it in GitHub Desktop.
An alternative to String#next/#succ for incrementing strings
describe String do
describe "#increment and #increment!" do
it 'should increment nothing to 1' do
"Something".increment.should == "Something1"
end
it 'should increment the digits in the string' do
"789".increment.should == "790"
end
it 'should pay attention to spacing' do
"Foo bar 3".increment.should == "Foo bar 4"
end
it 'should increment digits' do
" whateverrrr 99".increment.should == " whateverrrr 100"
end
it 'should set the original value with bang' do
x = " foobar 123"
x.increment!
x.should == " foobar 124"
end
it 'should follow the format if given' do
" foobar ".increment("(%s)").should == " foobar (1)"
" foobar (134)".increment("(%s)").should == " foobar (135)"
" foobar(134) ".increment("(%s)").should == " foobar(134) (1)"
" foobar [789]".increment.should == " foobar [789]1"
" foobar [789]".increment("[%s]").should == " foobar [790]"
end
it 'should set the original value with bang' do
x = " foobar (123)"
x.increment!("(%s)")
x.should == " foobar (124)"
end
end
end
class String
# This is different from #next/#succ because it only increments digits.
# Also, if it is incrementing from x-digits to y-digits, it will add the extra
# digit instead of resetting to 0 and keeping x-digits.
#
# "abcd".increment #=> "abcd1"
# "THX1138".increment #=> "THX1139"
# "<<koala>>".increment #=> "<<koala>>1"
# "1999zzz".increment #=> "1999zzz1"
# "ZZZ9999".increment #=> "ZZZ10000"
# "***".increment #=> "***1"
# "123".increment #=> "124"
# " 123 ".increment #=> " 123 1"
# " 123 ".increment #=> " 123 1"
#
# You can pass in an optional format for the numbers where %s is the placeholder
# for the digits:
#
# " foobar (1)".increment #=> " foobar (2)"
# " foobar (789) ".increment #=> " foobar (789) (1)"
#
def increment(format=nil)
regexp = format ? Regexp.new(Regexp.escape(format).gsub('%s', '\d+')) : /\d/
parts = format ? split(/(#{regexp})|(\D)/) : split(/(\D)/)
num = (format || "%s") % 0
parts.push(num) unless parts[-1] =~ regexp
parts[-1] = if format
parts[-1].sub(/(\d+)/) { |m| Integer(m) + 1 }
else
Integer(parts[-1]) + 1
end
parts.join
end
def increment!(format=nil)
replace(increment(format))
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment