Skip to content

Commit 8df16b4

Browse files
authored
Do not treat numbers as word boundaries (#1)
* Fix camelCase conversion for acronyms containing numbers * Support acronyms that start with numbers * update module * Change default behavior * Remove unnecessary tests * Do not treat numbers as word boundaries * Number followed by capital letter is delimiting
1 parent 531aaa4 commit 8df16b4

File tree

6 files changed

+22
-76
lines changed

6 files changed

+22
-76
lines changed

README.md

+2-58
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,3 @@
1-
# strcase
2-
[![Godoc Reference](https://godoc.org/github.com/iancoleman/strcase?status.svg)](http://godoc.org/github.com/iancoleman/strcase)
3-
[![Build Status](https://travis-ci.com/iancoleman/strcase.svg)](https://travis-ci.com/iancoleman/strcase)
4-
[![Coverage](http://gocover.io/_badge/github.com/iancoleman/strcase?0)](http://gocover.io/github.com/iancoleman/strcase)
5-
[![Go Report Card](https://goreportcard.com/badge/github.com/iancoleman/strcase)](https://goreportcard.com/report/github.com/iancoleman/strcase)
1+
# go-strcase
62

7-
strcase is a go package for converting string case to various cases (e.g. [snake case](https://en.wikipedia.org/wiki/Snake_case) or [camel case](https://en.wikipedia.org/wiki/CamelCase)) to see the full conversion table below.
8-
9-
## Example
10-
11-
```go
12-
s := "AnyKind of_string"
13-
```
14-
15-
| Function | Result |
16-
|-------------------------------------------|----------------------|
17-
| `ToSnake(s)` | `any_kind_of_string` |
18-
| `ToSnakeWithIgnore(s, '.')` | `any_kind.of_string` |
19-
| `ToScreamingSnake(s)` | `ANY_KIND_OF_STRING` |
20-
| `ToKebab(s)` | `any-kind-of-string` |
21-
| `ToScreamingKebab(s)` | `ANY-KIND-OF-STRING` |
22-
| `ToDelimited(s, '.')` | `any.kind.of.string` |
23-
| `ToScreamingDelimited(s, '.', '', true)` | `ANY.KIND.OF.STRING` |
24-
| `ToScreamingDelimited(s, '.', ' ', true)` | `ANY.KIND OF.STRING` |
25-
| `ToCamel(s)` | `AnyKindOfString` |
26-
| `ToLowerCamel(s)` | `anyKindOfString` |
27-
28-
29-
## Install
30-
31-
```bash
32-
go get -u github.com/iancoleman/strcase
33-
```
34-
35-
## Custom Acronyms for ToCamel && ToLowerCamel
36-
37-
Often times text can contain specific acronyms which you need to be handled a certain way.
38-
Out of the box `strcase` treats the string "ID" as "Id" or "id" but there is no way to cater
39-
for every case in the wild.
40-
41-
To configure your custom acronym globally you can use the following before running any conversion
42-
43-
```go
44-
import (
45-
"github.com/iancoleman/strcase"
46-
)
47-
48-
func init() {
49-
// results in "Api" using ToCamel("API")
50-
// results in "api" using ToLowerCamel("API")
51-
strcase.ConfigureAcronym("API", "api")
52-
53-
// results in "PostgreSQL" using ToCamel("PostgreSQL")
54-
// results in "postgreSQL" using ToLowerCamel("PostgreSQL")
55-
strcase.ConfigureAcronym("PostgreSQL", "PostgreSQL")
56-
57-
}
58-
59-
```
3+
Forked from https://github.com/iancoleman/strcase

camel.go

+1-4
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,9 @@ func toCamelInitCase(s string, initCase bool) string {
6363
}
6464
prevIsCap = vIsCap
6565

66-
if vIsCap || vIsLow {
66+
if vIsCap || vIsLow || v >= '0' && v <= '9' {
6767
n.WriteByte(v)
6868
capNext = false
69-
} else if vIsNum := v >= '0' && v <= '9'; vIsNum {
70-
n.WriteByte(v)
71-
capNext = true
7269
} else {
7370
capNext = v == '_' || v == ' ' || v == '-' || v == '.'
7471
}

camel_test.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,11 @@ func toCamel(tb testing.TB) {
3939
{"many_many_words", "ManyManyWords"},
4040
{"AnyKind of_string", "AnyKindOfString"},
4141
{"odd-fix", "OddFix"},
42-
{"numbers2And55with000", "Numbers2And55With000"},
42+
{"numbers2And55with000", "Numbers2And55with000"},
4343
{"ID", "Id"},
4444
{"CONSTANT_CASE", "ConstantCase"},
45+
{"90s-kids", "90sKids"},
46+
{"k8s_version", "K8sVersion"},
4547
}
4648
for _, i := range cases {
4749
in := i[0]
@@ -72,6 +74,8 @@ func toLowerCamel(tb testing.TB) {
7274
{"some string", "someString"},
7375
{" some string", "someString"},
7476
{"CONSTANT_CASE", "constantCase"},
77+
{"90s-kids", "90sKids"},
78+
{"k8s_version", "k8sVersion"},
7579
}
7680
for _, i := range cases {
7781
in := i[0]

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
module github.com/iancoleman/strcase
1+
module github.com/zillow/go-strcase
22

33
go 1.16

snake.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,8 @@ func ToScreamingDelimited(s string, delimiter uint8, ignore string, screaming bo
8484
vIsNum := v >= '0' && v <= '9'
8585
nextIsCap := next >= 'A' && next <= 'Z'
8686
nextIsLow := next >= 'a' && next <= 'z'
87-
nextIsNum := next >= '0' && next <= '9'
8887
// add underscore if next letter case type is changed
89-
if (vIsCap && (nextIsLow || nextIsNum)) || (vIsLow && (nextIsCap || nextIsNum)) || (vIsNum && (nextIsCap || nextIsLow)) {
88+
if (vIsCap && nextIsLow || vIsLow && nextIsCap || vIsNum && nextIsCap) {
9089
prevIgnore := ignore != "" && i > 0 && strings.ContainsAny(string(s[i-1]), ignore)
9190
if !prevIgnore {
9291
if vIsCap && nextIsLow {
@@ -95,7 +94,7 @@ func ToScreamingDelimited(s string, delimiter uint8, ignore string, screaming bo
9594
}
9695
}
9796
n.WriteByte(v)
98-
if vIsLow || vIsNum || nextIsNum {
97+
if vIsLow || vIsNum && nextIsCap {
9998
n.WriteByte(delimiter)
10099
}
101100
continue

snake_test.go

+11-9
Original file line numberDiff line numberDiff line change
@@ -44,18 +44,20 @@ func toSnake(tb testing.TB) {
4444
{"ManyManyWords", "many_many_words"},
4545
{"manyManyWords", "many_many_words"},
4646
{"AnyKind of_string", "any_kind_of_string"},
47-
{"numbers2and55with000", "numbers_2_and_55_with_000"},
47+
{"numbers2and55with000", "numbers2and55with000"},
4848
{"JSONData", "json_data"},
4949
{"userID", "user_id"},
5050
{"AAAbbb", "aa_abbb"},
51-
{"1A2", "1_a_2"},
52-
{"A1B", "a_1_b"},
53-
{"A1A2A3", "a_1_a_2_a_3"},
54-
{"A1 A2 A3", "a_1_a_2_a_3"},
55-
{"AB1AB2AB3", "ab_1_ab_2_ab_3"},
56-
{"AB1 AB2 AB3", "ab_1_ab_2_ab_3"},
51+
{"1A2", "1_a2"},
52+
{"A1B", "a1_b"},
53+
{"A1A2A3", "a1_a2_a3"},
54+
{"A1 A2 A3", "a1_a2_a3"},
55+
{"AB1AB2AB3", "ab1_ab2_ab3"},
56+
{"AB1 AB2 AB3", "ab1_ab2_ab3"},
5757
{"some string", "some_string"},
5858
{" some string", "some_string"},
59+
{"K8sVersion", "k8s_version"},
60+
{"90sKids", "90s_kids"},
5961
}
6062
for _, i := range cases {
6163
in := i[0]
@@ -88,7 +90,7 @@ func toSnakeWithIgnore(tb testing.TB) {
8890
{"ManyManyWords", "many_many_words"},
8991
{"manyManyWords", "many_many_words"},
9092
{"AnyKind of_string", "any_kind_of_string"},
91-
{"numbers2and55with000", "numbers_2_and_55_with_000"},
93+
{"numbers2and55with000", "numbers2and55with000"},
9294
{"JSONData", "json_data"},
9395
{"AwesomeActivity.UserID", "awesome_activity.user_id", "."},
9496
{"AwesomeActivity.User.Id", "awesome_activity.user.id", "."},
@@ -135,7 +137,7 @@ func toDelimited(tb testing.TB) {
135137
{"ManyManyWords", "many@many@words"},
136138
{"manyManyWords", "many@many@words"},
137139
{"AnyKind of_string", "any@kind@of@string"},
138-
{"numbers2and55with000", "numbers@2@and@55@with@000"},
140+
{"numbers2and55with000", "numbers2and55with000"},
139141
{"JSONData", "json@data"},
140142
{"userID", "user@id"},
141143
{"AAAbbb", "aa@abbb"},

0 commit comments

Comments
 (0)