Skip to content

Commit a503dad

Browse files
committed
Merge pull request #14 from chrissie1/master
added toquantity on Int extensionadn refactored pascalhumanizer and truncate (a little)
2 parents 53fb841 + db5de6f commit a503dad

File tree

17 files changed

+347
-61
lines changed

17 files changed

+347
-61
lines changed

README.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ The current build status on the CI server is <a href="http://teamcity.jetbrains.
1515
- [Number to words] (#numbertowords)
1616
- [To quantity] (#toquantity)
1717
- [Humanize] (#humanize)
18+
- [DeHumanize] (#dehumanize)
19+
- [Roman numerals] (#romannumerals)
1820

1921
# <a id="features">Features</a>
2022

@@ -263,6 +265,23 @@ Gives the value in ordinal words.
263265
"cases".toQuantity(2, showAsQuantity = ShowQuantityAs.Words) => "two cases"
264266
```
265267

268+
### Extension method toQuantity for Int objects
269+
270+
```kotlin
271+
1.toQuantity("case") => "1 case"
272+
1.toQuantity("cases") => "1 case"
273+
10.toQuantity("case") => "10 cases"
274+
275+
1.toQuantity("cases", showAsQuantity = ShowQuantityAs.None) => "case"
276+
2.toQuantity("cases", showAsQuantity = ShowQuantityAs.None) => "cases"
277+
278+
1.toQuantity("cases", showAsQuantity = ShowQuantityAs.Numeric) => "1 case"
279+
2.toQuantity("cases", showAsQuantity = ShowQuantityAs.Numeric) => "1 case"
280+
281+
1.toQuantity("cases", showAsQuantity = ShowQuantityAs.Words) => "one case"
282+
2.toQuantity("cases", showAsQuantity = ShowQuantityAs.Words) => "two cases"
283+
```
284+
266285
## <a id="humanize">Humanize</a>
267286

268287
### Extension method humanize for String objects
@@ -282,3 +301,35 @@ Turns pascalcased strings into sentences.
282301
283302
"CanHumanizeIntoUpperCase".humanize(LetterCasing.AllCaps) => "CAN HUMANIZE INTO UPPER CASE"
284303
```
304+
305+
## <a id="dehumanize">Dehumanize</a>
306+
307+
### Extension method dehumanize for String objects
308+
309+
Turns sentences into pascalcased strings.
310+
311+
```kotlin
312+
"Pascal case input string is turned into sentence".dehumanize() => "PascalCaseInputStringIsTurnedIntoSentencePascal case input string is turned into sentence"
313+
```
314+
315+
## <a id="romannumerals">RomanNumerals</a>
316+
317+
### Extension method toRoman for Int objects
318+
319+
Turns an Int into Roman numeral. Limit from 1 to 3999.
320+
321+
```kotlin
322+
1.toRoman() => "I"
323+
2.toRoman() => "II"
324+
4.toRoman() => "IV"
325+
```
326+
327+
### Extension method fromRoman for String objects
328+
329+
Turns a Roman numeral into an Int. Limit from 1 to 3999.
330+
331+
```kotlin
332+
"I".toRoman() => 1
333+
"II".toRoman() => 2
334+
"IV".toRoman() => 4
335+
```
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.humanizer.jvm
2+
3+
fun String.dehumanize() : String
4+
{
5+
return this
6+
.split(" ")
7+
.let{it.map{it.capitalize()}}
8+
.makeString("")
9+
}

src/main/kotlin/org/humanizer/jvm/Inflector.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.humanizer.jvm
22

33
import java.util.regex.Pattern
4+
import org.humanizer.jvm.exceptions.NoRuleFoundException
45

56
fun String.camelize(): String {
67
var previousWasUnderscore = false
Lines changed: 10 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,16 @@
11
package org.humanizer.jvm
22

3-
4-
5-
fun String.humanize(letterCasing : LetterCasing = LetterCasing.Sentence): String {
6-
val regex = "(?<=[a-z])(?=[A-Z0-9])|(?<=[0-9])(?=[A-Za-z])|(?<=[A-Z])(?=[0-9])|(?<=[A-Z])(?=[A-Z][a-z])"
7-
8-
if(letterCasing == LetterCasing.LowerCase) return this.replaceAll("${regex}|(_)|(-)", " $0").trim().replace("_","").toLowerCase()
9-
if(letterCasing == LetterCasing.Title) {
10-
return this
11-
.split("${regex}|(_)|(-)")
12-
.let{ it.map{ if(it.checkAllCaps() && it.length() > 1) it else it.capitalize()} }
13-
.makeString(" ")}
14-
if(letterCasing == LetterCasing.AllCaps) return this.replaceAll("${regex}|(_)|(-)", " $0").trim().replace("_","").toUpperCase()
15-
if(letterCasing == LetterCasing.Sentence) {
16-
if(this.contains("_"))
17-
return this.replace("_"," ")
18-
else
19-
return this
20-
.split(regex)
21-
.let{ it.map{ if(it.checkAllCaps() && it.length() > 1) it else it.toLowerCase()} }
22-
.makeString(" ")
23-
.capitalize()
24-
.replace(" i ", " I ")}
25-
return this
3+
import org.humanizer.jvm.letterCasings.*
4+
5+
fun String.humanize(letterCasing : LetterCasing = LetterCasing.Sentence): String {
6+
when (letterCasing) {
7+
LetterCasing.LowerCase -> return this.letterCasingLowerCase()
8+
LetterCasing.AllCaps -> return this.letterCasingUpperCase()
9+
LetterCasing.Title -> return this.letterCasingTitle()
10+
LetterCasing.Sentence -> return this.letterCasingSentence()
11+
}
12+
return this
2613
}
2714

28-
fun String.checkAllCaps(): Boolean
29-
{
30-
return this.all{it.isUpperCase()}
31-
}
32-
33-
fun String.removerUnderscore()
34-
{}
3515

36-
enum class LetterCasing
37-
{
38-
Title
39-
AllCaps
40-
LowerCase
41-
Sentence
42-
}
4316

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package org.humanizer.jvm
2+
3+
import org.humanizer.jvm.exceptions.ArgumentOutOfRangeException
4+
import java.util.regex.Pattern
5+
import org.humanizer.jvm.exceptions.ArgumentException
6+
7+
fun Int.toRoman() : String
8+
{
9+
val minValue = 1
10+
val maxValue = 3999
11+
val maxRomanNumeralLength = 15
12+
13+
if ((this < minValue) || (this > maxValue))
14+
throw ArgumentOutOfRangeException(this,minValue, maxValue)
15+
16+
var sb = StringBuilder(maxRomanNumeralLength)
17+
18+
var result = this
19+
romanNumerals().forEach()
20+
{
21+
while (result / it.second > 0)
22+
{
23+
sb.append(it.first)
24+
result -= it.second
25+
}
26+
}
27+
28+
return sb.toString()
29+
}
30+
31+
fun String.fromRoman() : Int
32+
{
33+
var input = this.trim().toUpperCase();
34+
35+
var length = input.length;
36+
37+
if ((length == 0) || input.isInvalidRomanNumeral())
38+
throw ArgumentException("Empty or invalid Roman numeral string. The input was $input.");
39+
40+
var total = 0;
41+
var i = length;
42+
43+
while (i > 0)
44+
{
45+
var digit = romanNumerals().single{ it.first == input[i-1].toString()}.second
46+
47+
if (i > 1)
48+
{
49+
var previousDigit = romanNumerals().single{ it.first == input[i - 2].toString()}.second
50+
51+
if (previousDigit < digit)
52+
{
53+
digit -= previousDigit
54+
i--
55+
}
56+
}
57+
i--
58+
total += digit
59+
}
60+
61+
return total
62+
}
63+
64+
fun String.isInvalidRomanNumeral() : Boolean
65+
{
66+
return !Pattern.compile("^(?i:(?=[MDCLXVI])((M{0,3})((C[DM])|(D?C{0,3}))?((X[LC])|(L?XX{0,2})|L)?((I[VX])|(V?(II{0,2}))|V)?))$", Pattern.CASE_INSENSITIVE).matcher(this).matches()
67+
}
68+
69+
fun romanNumerals() : List<Pair<String, Int>>
70+
{
71+
return listOf(
72+
"M" to 1000 ,
73+
"CM" to 900 ,
74+
"D" to 500,
75+
"CD" to 400,
76+
"C" to 100,
77+
"XC" to 90,
78+
"L" to 50,
79+
"XL" to 40,
80+
"X" to 10,
81+
"IX" to 9,
82+
"V" to 5,
83+
"IV" to 4,
84+
"I" to 1)
85+
}

src/main/kotlin/org/humanizer/jvm/ToQuantity.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ fun String.toQuantity(quantity: Int, showQuantityAs: ShowQuantityAs = ShowQuanti
2424
return this
2525
}
2626

27+
fun Int.toQuantity(unit: String, showQuantityAs: ShowQuantityAs = ShowQuantityAs.Numeric) : String
28+
{
29+
return unit.toQuantity(this, showQuantityAs)
30+
}
31+
2732
enum class ShowQuantityAs
2833
{
2934
None
Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
package org.humanizer.jvm
22

3-
import org.humanizer.jvm.truncators.truncateFixedLength
4-
import org.humanizer.jvm.truncators.truncateFixedNumberOfCharacters
5-
import org.humanizer.jvm.truncators.truncateFixedNumberOfWords
6-
import org.humanizer.jvm.truncators.UnsupportedTruncatorException
7-
3+
import org.humanizer.jvm.truncators.*
84

95
fun String.truncate(length: Int, truncationString: String = "…", truncator: Truncator = Truncator.FixedLength, truncateFrom: TruncateFrom = TruncateFrom.Right) : String {
106
when (truncator) {
@@ -13,15 +9,4 @@ fun String.truncate(length: Int, truncationString: String = "…", truncator: Tr
139
Truncator.FixedNumberOfWords -> return truncateFixedNumberOfWords(this,length,truncationString,truncateFrom)
1410
else -> throw UnsupportedTruncatorException()
1511
}
16-
}
17-
18-
enum class Truncator {
19-
FixedLength
20-
FixedNumberOfCharacters
21-
FixedNumberOfWords
22-
}
23-
24-
enum class TruncateFrom {
25-
Left
26-
Right
2712
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package org.humanizer.jvm.exceptions
2+
3+
class ArgumentException(argument: String): Exception("${argument}")
4+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package org.humanizer.jvm.exceptions
2+
3+
class ArgumentOutOfRangeException(argument: Int, minValue: Int, maxValue:Int): Exception("The argument ${argument} is out of range, the range is $minValue to $maxValue.")
4+
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
package org.humanizer.jvm
1+
package org.humanizer.jvm.exceptions
22

33
class NoRuleFoundException(val inflection: String): Exception("Can't ${inflection} this word, could not find a rule to match.")
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package org.humanizer.jvm.letterCasings
2+
3+
fun letterCasingRegex(suffix:String = "") : String{
4+
return "(?<=[a-z])(?=[A-Z0-9])|(?<=[0-9])(?=[A-Za-z])|(?<=[A-Z])(?=[0-9])|(?<=[A-Z])(?=[A-Z][a-z])$suffix"
5+
}
6+
7+
fun String.checkAllCaps(): Boolean
8+
{
9+
return this.all{it.isUpperCase()}
10+
}
11+
12+
fun String.letterCasingUpperCase() : String {
13+
return this
14+
.replaceAll(letterCasingRegex("|(_)|(-)"), " $0")
15+
.trim()
16+
.replace("_","")
17+
.toUpperCase()
18+
}
19+
20+
fun String.letterCasingTitle(): String {
21+
return this
22+
.split(letterCasingRegex("|(_)|(-)"))
23+
.let{ it.map{ if(it.checkAllCaps() && it.length() > 1) it else it.capitalize()} }
24+
.makeString(" ")
25+
}
26+
27+
fun String.letterCasingLowerCase() : String {
28+
return this
29+
.replaceAll(letterCasingRegex("|(_)|(-)"), " $0")
30+
.trim()
31+
.replace("_","")
32+
.toLowerCase()
33+
}
34+
35+
fun String.letterCasingSentence(): String {
36+
if(this.contains("_"))
37+
return this.replace("_"," ")
38+
else
39+
return this
40+
.split(letterCasingRegex())
41+
.let{ it.map{ if(it.checkAllCaps() && it.length() > 1) it else it.toLowerCase()} }
42+
.makeString(" ")
43+
.capitalize()
44+
.replace(" i ", " I ")
45+
}
46+
47+
enum class LetterCasing {
48+
Title
49+
AllCaps
50+
LowerCase
51+
Sentence
52+
}
53+
54+

src/main/kotlin/org/humanizer/jvm/truncators/Truncators.kt

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
package org.humanizer.jvm.truncators
22

3-
import org.humanizer.jvm.TruncateFrom
4-
5-
63
fun truncateFixedLength(value: String, length: Int, truncationString: String, truncateFrom: TruncateFrom) : String
74
{
85
var adjustedLength = length - (truncationString.length - 1)
@@ -69,3 +66,14 @@ fun truncateFixedNumberOfWords(value: String, length: Int, truncationString: Str
6966
return "${truncationString}${t.reverse()}"
7067
}
7168
}
69+
70+
enum class Truncator {
71+
FixedLength
72+
FixedNumberOfCharacters
73+
FixedNumberOfWords
74+
}
75+
76+
enum class TruncateFrom {
77+
Left
78+
Right
79+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package org.humanizer.jvm.tests
2+
3+
import org.spek.Spek
4+
import org.spek.givenData
5+
import org.humanizer.jvm.humanize
6+
import org.spek.shouldEqual
7+
import org.humanizer.jvm.dehumanize
8+
9+
public class DeHumanizerTests(): Spek() {
10+
{
11+
12+
var data = listOf(
13+
"Pascal case sentence is camelized" to "PascalCaseSentenceIsCamelized",
14+
"Title Case Sentence Is Camelized" to "TitleCaseSentenceIsCamelized",
15+
"Mixed case sentence Is Camelized" to "MixedCaseSentenceIsCamelized",
16+
"lower case sentence is camelized" to "LowerCaseSentenceIsCamelized",
17+
"" to "")
18+
19+
givenData(data) {
20+
val (input, expected) = it
21+
on("calling deHumanize on $input", {
22+
val actual = input.dehumanize()
23+
it("should become ${it.component2()}", {
24+
shouldEqual(expected, actual)
25+
})
26+
})
27+
}
28+
}
29+
}
30+

0 commit comments

Comments
 (0)