New upstream version 0.0~git20170425.0.1c7f653
Diego M. Rodriguez
7 years ago
0 | language: go | |
1 | ||
2 | go: | |
3 | - 1.2 | |
4 | - 1.3 | |
5 | - tip | |
6 | ||
7 | install: go get -t -d -v ./... && go build -v ./... |
0 | Copyright (c) 2015 Serenize UG (haftungsbeschränkt) | |
1 | ||
2 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
3 | of this software and associated documentation files (the "Software"), to deal | |
4 | in the Software without restriction, including without limitation the rights | |
5 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
6 | copies of the Software, and to permit persons to whom the Software is | |
7 | furnished to do so, subject to the following conditions: | |
8 | ||
9 | The above copyright notice and this permission notice shall be included in | |
10 | all copies or substantial portions of the Software. | |
11 | ||
12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
13 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
14 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
15 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
16 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
17 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
18 | THE SOFTWARE. |
0 | # snaker | |
1 | ||
2 | [![Build Status](https://travis-ci.org/serenize/snaker.svg?branch=master)](https://travis-ci.org/serenize/snaker) | |
3 | [![GoDoc](https://godoc.org/github.com/serenize/snaker?status.svg)](https://godoc.org/github.com/serenize/snaker) | |
4 | ||
5 | This is a small utility to convert camel cased strings to snake case and back, except some defined words. | |
6 | ||
7 | ## QBS Usage | |
8 | ||
9 | To replace the original toSnake and back algorithms for [https://github.com/coocood/qbs](https://github.com/coocood/qbs) | |
10 | you can easily use snaker: | |
11 | ||
12 | Import snaker | |
13 | ```go | |
14 | import ( | |
15 | github.com/coocood/qbs | |
16 | github.com/serenize/snaker | |
17 | ) | |
18 | ``` | |
19 | ||
20 | Register the snaker methods to qbs | |
21 | ```go | |
22 | qbs.ColumnNameToFieldName = snaker.SnakeToCamel | |
23 | qbs.FieldNameToColumnName = snaker.CamelToSnake | |
24 | ``` |
0 | // Package snaker provides methods to convert CamelCase names to snake_case and back. | |
1 | // It considers the list of allowed initialsms used by github.com/golang/lint/golint (e.g. ID or HTTP) | |
2 | package snaker | |
3 | ||
4 | import ( | |
5 | "strings" | |
6 | "unicode" | |
7 | ) | |
8 | ||
9 | // CamelToSnake converts a given string to snake case | |
10 | func CamelToSnake(s string) string { | |
11 | var result string | |
12 | var words []string | |
13 | var lastPos int | |
14 | rs := []rune(s) | |
15 | ||
16 | for i := 0; i < len(rs); i++ { | |
17 | if i > 0 && unicode.IsUpper(rs[i]) { | |
18 | if initialism := startsWithInitialism(s[lastPos:]); initialism != "" { | |
19 | words = append(words, initialism) | |
20 | ||
21 | i += len(initialism) - 1 | |
22 | lastPos = i | |
23 | continue | |
24 | } | |
25 | ||
26 | words = append(words, s[lastPos:i]) | |
27 | lastPos = i | |
28 | } | |
29 | } | |
30 | ||
31 | // append the last word | |
32 | if s[lastPos:] != "" { | |
33 | words = append(words, s[lastPos:]) | |
34 | } | |
35 | ||
36 | for k, word := range words { | |
37 | if k > 0 { | |
38 | result += "_" | |
39 | } | |
40 | ||
41 | result += strings.ToLower(word) | |
42 | } | |
43 | ||
44 | return result | |
45 | } | |
46 | ||
47 | func snakeToCamel(s string, upperCase bool) string { | |
48 | var result string | |
49 | ||
50 | words := strings.Split(s, "_") | |
51 | ||
52 | for i, word := range words { | |
53 | if upperCase || i > 0 { | |
54 | if upper := strings.ToUpper(word); commonInitialisms[upper] { | |
55 | result += upper | |
56 | continue | |
57 | } | |
58 | } | |
59 | ||
60 | if (upperCase || i > 0) && len(word) > 0 { | |
61 | w := []rune(word) | |
62 | w[0] = unicode.ToUpper(w[0]) | |
63 | result += string(w) | |
64 | } else { | |
65 | result += word | |
66 | } | |
67 | } | |
68 | ||
69 | return result | |
70 | } | |
71 | ||
72 | // SnakeToCamel returns a string converted from snake case to uppercase | |
73 | func SnakeToCamel(s string) string { | |
74 | return snakeToCamel(s, true) | |
75 | } | |
76 | ||
77 | // SnakeToCamelLower returns a string converted from snake case to lowercase | |
78 | func SnakeToCamelLower(s string) string { | |
79 | return snakeToCamel(s, false) | |
80 | } | |
81 | ||
82 | // startsWithInitialism returns the initialism if the given string begins with it | |
83 | func startsWithInitialism(s string) string { | |
84 | var initialism string | |
85 | // the longest initialism is 5 char, the shortest 2 | |
86 | for i := 1; i <= 5; i++ { | |
87 | if len(s) > i-1 && commonInitialisms[s[:i]] { | |
88 | initialism = s[:i] | |
89 | } | |
90 | } | |
91 | return initialism | |
92 | } | |
93 | ||
94 | // commonInitialisms, taken from | |
95 | // https://github.com/golang/lint/blob/206c0f020eba0f7fbcfbc467a5eb808037df2ed6/lint.go#L731 | |
96 | var commonInitialisms = map[string]bool{ | |
97 | "ACL": true, | |
98 | "API": true, | |
99 | "ASCII": true, | |
100 | "CPU": true, | |
101 | "CSS": true, | |
102 | "DNS": true, | |
103 | "EOF": true, | |
104 | "GUID": true, | |
105 | "HTML": true, | |
106 | "HTTP": true, | |
107 | "HTTPS": true, | |
108 | "ID": true, | |
109 | "IP": true, | |
110 | "JSON": true, | |
111 | "LHS": true, | |
112 | "OS": true, | |
113 | "QPS": true, | |
114 | "RAM": true, | |
115 | "RHS": true, | |
116 | "RPC": true, | |
117 | "SLA": true, | |
118 | "SMTP": true, | |
119 | "SQL": true, | |
120 | "SSH": true, | |
121 | "TCP": true, | |
122 | "TLS": true, | |
123 | "TTL": true, | |
124 | "UDP": true, | |
125 | "UI": true, | |
126 | "UID": true, | |
127 | "UUID": true, | |
128 | "URI": true, | |
129 | "URL": true, | |
130 | "UTF8": true, | |
131 | "VM": true, | |
132 | "XML": true, | |
133 | "XMPP": true, | |
134 | "XSRF": true, | |
135 | "XSS": true, | |
136 | } |
0 | package snaker | |
1 | ||
2 | import ( | |
3 | . "github.com/onsi/ginkgo" | |
4 | . "github.com/onsi/gomega" | |
5 | ||
6 | "testing" | |
7 | ) | |
8 | ||
9 | func TestDb(t *testing.T) { | |
10 | RegisterFailHandler(Fail) | |
11 | RunSpecs(t, "Snaker Suite") | |
12 | } |
0 | package snaker | |
1 | ||
2 | import ( | |
3 | . "github.com/onsi/ginkgo" | |
4 | . "github.com/onsi/gomega" | |
5 | ) | |
6 | ||
7 | var _ = Describe("Snaker", func() { | |
8 | Describe("CamelToSnake test", func() { | |
9 | It("should return an empty string on an empty input", func() { | |
10 | Expect(CamelToSnake("")).To(Equal("")) | |
11 | }) | |
12 | ||
13 | It("should work with one word", func() { | |
14 | Expect(CamelToSnake("One")).To(Equal("one")) | |
15 | }) | |
16 | ||
17 | It("should return an uppercase string as seperate words", func() { | |
18 | Expect(CamelToSnake("ONE")).To(Equal("o_n_e")) | |
19 | }) | |
20 | ||
21 | It("should return ID as lowercase", func() { | |
22 | Expect(CamelToSnake("ID")).To(Equal("id")) | |
23 | }) | |
24 | ||
25 | It("should work with a single lowercase character", func() { | |
26 | Expect(CamelToSnake("i")).To(Equal("i")) | |
27 | }) | |
28 | ||
29 | It("should work with a single uppcase character", func() { | |
30 | Expect(CamelToSnake("I")).To(Equal("i")) | |
31 | }) | |
32 | ||
33 | It("should return a long text as expected", func() { | |
34 | Expect(CamelToSnake("ThisHasToBeConvertedCorrectlyID")).To( | |
35 | Equal("this_has_to_be_converted_correctly_id")) | |
36 | }) | |
37 | ||
38 | It("should return the text as expected if the initialism is in the middle", func() { | |
39 | Expect(CamelToSnake("ThisIDIsFine")).To(Equal("this_id_is_fine")) | |
40 | }) | |
41 | ||
42 | It("should work with long initialism", func() { | |
43 | Expect(CamelToSnake("ThisHTTPSConnection")).To(Equal("this_https_connection")) | |
44 | }) | |
45 | ||
46 | It("should work with multi initialisms", func() { | |
47 | Expect(CamelToSnake("HelloHTTPSConnectionID")).To(Equal("hello_https_connection_id")) | |
48 | }) | |
49 | ||
50 | It("sould work with concat initialisms", func() { | |
51 | Expect(CamelToSnake("HTTPSID")).To(Equal("https_id")) | |
52 | }) | |
53 | }) | |
54 | ||
55 | Describe("SnakeToCamel test", func() { | |
56 | It("should return an empty string on an empty input", func() { | |
57 | Expect(SnakeToCamel("")).To(Equal("")) | |
58 | }) | |
59 | ||
60 | It("should not blow up on trailing _", func() { | |
61 | Expect(SnakeToCamel("potato_")).To(Equal("Potato")) | |
62 | }) | |
63 | ||
64 | It("should return a snaked text as camel case", func() { | |
65 | Expect(SnakeToCamel("this_has_to_be_uppercased")).To( | |
66 | Equal("ThisHasToBeUppercased")) | |
67 | }) | |
68 | ||
69 | It("should return a snaked text as camel case, except the word ID", func() { | |
70 | Expect(SnakeToCamel("this_is_an_id")).To(Equal("ThisIsAnID")) | |
71 | }) | |
72 | ||
73 | It("should return 'id' not as uppercase", func() { | |
74 | Expect(SnakeToCamel("this_is_an_identifier")).To(Equal("ThisIsAnIdentifier")) | |
75 | }) | |
76 | ||
77 | It("should simply work with id", func() { | |
78 | Expect(SnakeToCamel("id")).To(Equal("ID")) | |
79 | }) | |
80 | }) | |
81 | ||
82 | Describe("SnakeToCamelLower test", func() { | |
83 | It("should return an empty string on an empty input", func() { | |
84 | Ω(SnakeToCamelLower("")).To(Equal("")) | |
85 | }) | |
86 | ||
87 | It("should not blow up on trailing _", func() { | |
88 | Ω(SnakeToCamelLower("potato_")).To(Equal("potato")) | |
89 | }) | |
90 | ||
91 | It("should return a snaked text as camel case", func() { | |
92 | Ω(SnakeToCamelLower("this_has_to_be_uppercased")).To( | |
93 | Equal("thisHasToBeUppercased")) | |
94 | }) | |
95 | ||
96 | It("should return a snaked text as camel case, except the word ID", func() { | |
97 | Ω(SnakeToCamelLower("this_is_an_id")).To(Equal("thisIsAnID")) | |
98 | }) | |
99 | ||
100 | It("should return 'id' not as uppercase", func() { | |
101 | Ω(SnakeToCamelLower("this_is_an_identifier")).To(Equal("thisIsAnIdentifier")) | |
102 | }) | |
103 | ||
104 | It("should simply work with id", func() { | |
105 | Ω(SnakeToCamelLower("id")).To(Equal("id")) | |
106 | }) | |
107 | ||
108 | It("should simply work with leading id", func() { | |
109 | Ω(SnakeToCamelLower("id_me_please")).To(Equal("idMePlease")) | |
110 | }) | |
111 | }) | |
112 | }) |