-
-
Save vicomte/6324231 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* An implementation of Ruby's string.succ method. | |
* By Devon Govett | |
* | |
* Returns the successor to str. The successor is calculated by incrementing characters starting | |
* from the rightmost alphanumeric (or the rightmost character if there are no alphanumerics) in the | |
* string. Incrementing a digit always results in another digit, and incrementing a letter results in | |
* another letter of the same case. | |
* | |
* If the increment generates a carry, the character to the left of it is incremented. This | |
* process repeats until there is no carry, adding an additional character if necessary. | |
* | |
* succ("abcd") == "abce" | |
* succ("THX1138") == "THX1139" | |
* succ("<<koala>>") == "<<koalb>>" | |
* succ("1999zzz") == "2000aaa" | |
* succ("ZZZ9999") == "AAAA0000" | |
* | |
* if strictSeparators is true, any carry operation works only on the segment within | |
* the bounds of a non alphanumeric character, or alternating type. Defaults to adding | |
* a numeric if it can't find any. | |
* | |
* succ("aaa-999", true) == "aaa-1000" | |
* succ("234zzz", true) == "234aaaa" | |
* | |
*/ | |
function succ(input,strictSeparators) { | |
var alphabet = 'abcdefghijklmnopqrstuvwxyz'; | |
if (input.length < 2 && !input.match(/\w/)) { | |
result = input + alphabet.charAt(0); | |
} else { | |
if (input.length > 1 | |
&& typeof strictSeparators !== 'undefined' | |
&& strictSeparators === true) { | |
allAlphas = input.match(/[a-z0-9]/i); | |
var lastChar = input.substring(input.lastIndexOf(allAlphas[allAlphas.length - 1])+1,1); | |
if (lastChar.match(/[a-z]/i)) { | |
regex = /[^A-Za-z]/g; | |
} else { | |
regex = /\D/g; | |
} | |
var segments = input.match(regex); | |
if (segments) { | |
rIndex = input.lastIndexOf(segments[segments.length - 1]); | |
if (rIndex != 'undefined' && rIndex >= 0) { | |
var origString = input; | |
input = input.substring(rIndex + 1); | |
origString = origString.substring(0,rIndex + 1); | |
} | |
} | |
} | |
var length = alphabet.length, | |
result = input, | |
i = input.length; | |
while(i >= 0) { | |
var last = input.charAt(--i), | |
next = '', | |
carry = false; | |
if (isNaN(last)) { | |
index = alphabet.indexOf(last.toLowerCase()); | |
if (index === -1) { | |
next = last; | |
carry = true; | |
} | |
else { | |
var isUpperCase = last === last.toUpperCase(); | |
next = alphabet.charAt((index + 1) % length); | |
if (isUpperCase) { | |
next = next.toUpperCase(); | |
} | |
carry = index + 1 >= length; | |
if (carry && i === 0) { | |
var added = isUpperCase ? 'A' : 'a'; | |
result = added + next + result.slice(1); | |
break; | |
} | |
} | |
} | |
else { | |
next = +last + 1; | |
if(next > 9 && !strictSeparators) { | |
next = 0; | |
carry = true; | |
} | |
if (carry && i === 0) { | |
result = '1' + next + result.slice(1); | |
break; | |
} | |
} | |
result = result.slice(0, i) + next + result.slice(i + 1); | |
if (!carry) { | |
break; | |
} | |
} | |
} | |
if (typeof origString !== 'undefined' && origString.length > 0) { | |
result = origString + result; | |
} | |
return result; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment