├── .gitignore
├── .goreleaser.yml
├── .travis.yml
├── LICENSE
├── README.md
├── case.go
├── case_test.go
├── cmd
└── casec
│ ├── convert.go
│ ├── convert_test.go
│ ├── main.go
│ ├── parse.go
│ └── parse_test.go
├── convert.go
├── convert_test.go
├── go.mod
├── go.sum
└── testdata
├── pascal2snake.py.in
├── pascal2snake.py.out
├── pascal2snake_ignore.py.in
├── pascal2snake_ignore.py.out
├── snake2camel.go.in
├── snake2camel.go.out
├── snake2camel_ignore.go.in
├── snake2camel_ignore.go.out
├── snake2pascal_lines_ignore.go.in
└── snake2pascal_lines_ignore.go.out
/.gitignore:
--------------------------------------------------------------------------------
1 | # Vendor
2 | vendor/
3 |
4 | # Build & binary
5 | dist/
6 | flog
7 |
8 | # Editors
9 | .vscode/
10 |
11 |
--------------------------------------------------------------------------------
/.goreleaser.yml:
--------------------------------------------------------------------------------
1 | project_name: casec
2 |
3 | before:
4 | hooks:
5 | - go mod download
6 |
7 | builds:
8 | - main: ./cmd/casec
9 | binary: casec
10 | goos:
11 | - windows
12 | - darwin
13 | - linux
14 | goarch:
15 | - amd64
16 |
17 | changelog:
18 | sort: asc
19 | filters:
20 | exclude:
21 | - '^docs:'
22 | - Update README.md
23 | - Merge pull request
24 | - Merge branch
25 |
26 | archive:
27 | format: tar.gz
28 | name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
29 | files:
30 | - LICENSE
31 | - README.md
32 |
33 | release:
34 | github:
35 | owner: mingrammer
36 | name: casec
37 | name_template: '{{.Tag}}'
38 |
39 | brew:
40 | name: casec
41 | github:
42 | owner: mingrammer
43 | name: homebrew-casec
44 | commit_author:
45 | name: mingrammer
46 | email: mingrammer@gmail.com
47 | homepage: https://github.com/mingrammer/casec
48 | description: "A text case converter"
49 | install: bin.install "casec"
50 | test: |
51 | system "#{bin}/casec -v"
52 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: go
2 |
3 | go:
4 | - "1.13.x"
5 | - "master"
6 |
7 | os:
8 | - linux
9 | - osx
10 |
11 | env:
12 | - GO111MODULE=on
13 |
14 | script:
15 | - go build ./cmd/casec
16 | - go test -v .
17 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 mingrammer
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Casec
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | A text case converter
15 |
16 |
17 |
18 | casec is a text case converter for programmers. casec now supports `upper`, `lower`, `title`, `camel`, `pascal`, `snake`, `kebab` (or `lisp`) cases.
19 |
20 | It also provides case conversion library not only command line tool.
21 |
22 | ## Installation
23 |
24 | ### Using go get
25 |
26 | > Go version 1.10 or higher is required.
27 |
28 | ```
29 | go get github.com/mingrammer/casec/...
30 | ```
31 |
32 | If you want to only download the `casec` library
33 |
34 | ```
35 | go get github.com/mingrammer/casec
36 | ```
37 |
38 | ### Using [homebrew](https://brew.sh)
39 |
40 | ```
41 | brew tap mingrammer/casec
42 | brew install casec
43 | ```
44 |
45 | ### Using .tar.gz archive
46 |
47 | Download gzip file from [Github Releases](https://github.com/mingrammer/casec/releases/latest) according to your OS. Then, copy the unzipped executable to under system path.
48 |
49 | ## Usage
50 |
51 | ### CLI
52 |
53 | Convert all words to snake case.
54 |
55 | ```bash
56 | $ casec -t snake main.py
57 | ```
58 |
59 | Convert all snake case to camel case.
60 |
61 | ```bash
62 | $ casec -f snake -t camel internal.go
63 | ```
64 |
65 | Convert only 20~50 lines from snake case to camel case.
66 |
67 | ```bash
68 | $ casec -f snake -t camel -l 20:50 internal.go
69 | ```
70 |
71 | Show how would have been converted. (dry-run)
72 |
73 | ```bash
74 | $ casec -f snake -t kebab -n match.lisp
75 | ```
76 |
77 | Convert all camel case to snake case except for words you don't want to convert. It is useful for preventing the keywords (reserved words) or conventions from converting.
78 |
79 | ```bash
80 | $ casec -f snake -t pascal -i '^package|var|const|if|for|range|return|func|go$' redis.go
81 | ```
82 |
83 | You can pass multiple ignore expressions.
84 |
85 | ```bash
86 | $ casec -f snake -t pascal -i '^package|var|const|if|for|range|return|func|go$' -i '^github|com$' redis.go
87 | ```
88 |
89 | ### Library
90 |
91 | > See details in [GoDoc](https://godoc.org/github.com/mingrammer/casec)
92 |
93 | ```go
94 | package main
95 |
96 | import (
97 | "fmt"
98 |
99 | "github.com/mingrammer/casec"
100 | )
101 |
102 | func main() {
103 | fmt.Println(casec.IsSnake("this_is_snake"))
104 | // Output: true
105 | fmt.Println(casec.IsCamel("thisIsNot_camelCase"))
106 | // Output: false
107 | fmt.Println(casec.Invert("Invert Me"))
108 | // Output: iNVERT mE
109 | fmt.Println(casec.ToCamel("write_rune"))
110 | // Output: writeRune
111 | fmt.Println(casec.ToSnake("IPAddress"))
112 | // Output: ip_address
113 | fmt.Println(casec.ToKebab("simpleJSONParser"))
114 | // Output: simple-json-parser
115 | }
116 | ```
117 |
118 | ## Known issues
119 |
120 | casec separates the words with non-letters (except `-` and `_`) including `.` and `/` letters. So, the `ignore` option of casec can not recognize the dot-or-slash separated word (ex. `"github.com/mingrammer/cfmt"`) as a single chunk. So if you want to prevent the import path of Go source code, for example, `import "github.com/mingrammer/cfmt"` from converting, you should pass the ignore expression as `-i "^(github|com|mingrammer|cfmt)$"`.
121 |
122 | Here is a (maybe) solution for solving this issue.
123 |
124 | 1. Treat the string surrounded with quotes ("" or '') as a single word optionally.
125 |
126 | ## License
127 |
128 | MIT
129 |
--------------------------------------------------------------------------------
/case.go:
--------------------------------------------------------------------------------
1 | package casec
2 |
3 | import (
4 | "errors"
5 | "strings"
6 |
7 | "github.com/mingrammer/cfmt"
8 | )
9 |
10 | // Case-specific delimiter
11 | const (
12 | SnakeDelimiter = '_'
13 | KebabDelimiter = '-'
14 | )
15 |
16 | // IsUpperCase checks the string is uppercase
17 | func IsUpper(s string) bool {
18 | return s == strings.ToUpper(s)
19 | }
20 |
21 | // IsLowerCase checks the string is lowercase
22 | func IsLower(s string) bool {
23 | return s == strings.ToLower(s)
24 | }
25 |
26 | // IsTitleCase checks the string is titlecase
27 | func IsTitle(s string) bool {
28 | return s == ToTitle(s)
29 | }
30 |
31 | // IsCamelCase checks the string is camelcase
32 | func IsCamel(s string) bool {
33 | return s == ToCamel(s)
34 | }
35 |
36 | // IsPascalCase checks the string is pascalcase
37 | func IsPascal(s string) bool {
38 | return s == ToPascal(s)
39 | }
40 |
41 | // IsSnakeCase checks the string is snakecase
42 | func IsSnake(s string) bool {
43 | return s == ToSnake(s)
44 | }
45 |
46 | // IsKebabCase checks the string is kebabcase
47 | func IsKebab(s string) bool {
48 | return s == ToKebab(s)
49 | }
50 |
51 | // IsCaseOf checks whether the string is a specific case
52 | func IsCaseOf(c, s string) (bool, error) {
53 | switch c {
54 | case "upper":
55 | return IsUpper(s), nil
56 | case "lower":
57 | return IsLower(s), nil
58 | case "title":
59 | return IsTitle(s), nil
60 | case "camel":
61 | return IsCamel(s), nil
62 | case "pascal":
63 | return IsPascal(s), nil
64 | case "snake":
65 | return IsSnake(s), nil
66 | case "kebab", "lisp":
67 | return IsKebab(s), nil
68 | }
69 | return false, errors.New(cfmt.Serrorf("%s is not valid case", c))
70 | }
71 |
--------------------------------------------------------------------------------
/case_test.go:
--------------------------------------------------------------------------------
1 | package casec
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func TestIsUpper(t *testing.T) {
8 | testCases := []struct {
9 | text string
10 | expected bool
11 | }{
12 | {text: "CASE", expected: true},
13 | {text: "UPPER_CASE", expected: true},
14 | {text: "Case", expected: false},
15 | {text: "cASE", expected: false},
16 | }
17 |
18 | for i, tc := range testCases {
19 | if is := IsUpper(tc.text); is != tc.expected {
20 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected, is)
21 | }
22 | }
23 | }
24 |
25 | func TestIsLower(t *testing.T) {
26 | testCases := []struct {
27 | text string
28 | expected bool
29 | }{
30 | {text: "case", expected: true},
31 | {text: "lower_case", expected: true},
32 | {text: "Case", expected: false},
33 | {text: "casE", expected: false},
34 | }
35 |
36 | for i, tc := range testCases {
37 | if is := IsLower(tc.text); is != tc.expected {
38 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected, is)
39 | }
40 | }
41 | }
42 |
43 | func TestIsTitle(t *testing.T) {
44 | testCases := []struct {
45 | text string
46 | expected bool
47 | }{
48 | {text: "Case", expected: true},
49 | {text: "Title Case", expected: true},
50 | {text: "case", expected: false},
51 | {text: "casE", expected: false},
52 | }
53 |
54 | for i, tc := range testCases {
55 | if is := IsTitle(tc.text); is != tc.expected {
56 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected, is)
57 | }
58 | }
59 | }
60 |
61 | func TestIsCamel(t *testing.T) {
62 | testCases := []struct {
63 | text string
64 | expected bool
65 | }{
66 | {text: "case", expected: true},
67 | {text: "camelCase", expected: true},
68 | {text: "PascalCase", expected: false},
69 | {text: "snake_case", expected: false},
70 | }
71 |
72 | for i, tc := range testCases {
73 | if is := IsCamel(tc.text); is != tc.expected {
74 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected, is)
75 | }
76 | }
77 | }
78 |
79 | func TestIsPascal(t *testing.T) {
80 | testCases := []struct {
81 | text string
82 | expected bool
83 | }{
84 | {text: "Case", expected: true},
85 | {text: "PascalCase", expected: true},
86 | {text: "camelCase", expected: false},
87 | {text: "snake_case", expected: false},
88 | }
89 |
90 | for i, tc := range testCases {
91 | if is := IsPascal(tc.text); is != tc.expected {
92 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected, is)
93 | }
94 | }
95 | }
96 |
97 | func TestIsSnake(t *testing.T) {
98 | testCases := []struct {
99 | text string
100 | expected bool
101 | }{
102 | {text: "case", expected: true},
103 | {text: "snake_case", expected: true},
104 | {text: "camelCase", expected: false},
105 | {text: "kebab-case", expected: false},
106 | }
107 |
108 | for i, tc := range testCases {
109 | if is := IsSnake(tc.text); is != tc.expected {
110 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected, is)
111 | }
112 | }
113 | }
114 |
115 | func TestIsKebab(t *testing.T) {
116 | testCases := []struct {
117 | text string
118 | expected bool
119 | }{
120 | {text: "case", expected: true},
121 | {text: "kebab-ase", expected: true},
122 | {text: "camelCase", expected: false},
123 | {text: "snake_case", expected: false},
124 | }
125 |
126 | for i, tc := range testCases {
127 | if is := IsKebab(tc.text); is != tc.expected {
128 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected, is)
129 | }
130 | }
131 | }
132 |
133 | func TestIsCaseOf(t *testing.T) {
134 | testCases := []struct {
135 | kind string
136 | text string
137 | expected bool
138 | }{
139 | {kind: "upper", text: "UPPERCASE", expected: true},
140 | {kind: "upper", text: "lowerase", expected: false},
141 | {kind: "lower", text: "lowercase", expected: true},
142 | {kind: "lower", text: "UPPERCASE", expected: false},
143 | {kind: "title", text: "Titlecase", expected: true},
144 | {kind: "title", text: "lowercase", expected: false},
145 | {kind: "camel", text: "camelCase", expected: true},
146 | {kind: "camel", text: "snake_case", expected: false},
147 | {kind: "pascal", text: "PascalCase", expected: true},
148 | {kind: "pascal", text: "camelCase", expected: false},
149 | {kind: "snake", text: "snake_case", expected: true},
150 | {kind: "snake", text: "camelCase", expected: false},
151 | {kind: "kebab", text: "kebab-case", expected: true},
152 | {kind: "kebab", text: "camelCase", expected: false},
153 | {kind: "unknown", text: "unknown", expected: false},
154 | }
155 |
156 | for i, tc := range testCases {
157 | if is, _ := IsCaseOf(tc.kind, tc.text); is != tc.expected {
158 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected, is)
159 | }
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/cmd/casec/convert.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "io/ioutil"
5 | "regexp"
6 | "strings"
7 | "unicode"
8 |
9 | "github.com/mingrammer/casec"
10 | )
11 |
12 | func isCaseSeparator(r rune) bool {
13 | return r == casec.SnakeDelimiter || r == casec.KebabDelimiter
14 | }
15 |
16 | func convertWord(word, src, tgt string) string {
17 | if src != "" {
18 | if is, _ := casec.IsCaseOf(src, word); is {
19 | word, _ = casec.ToCaseFor(tgt, word)
20 | }
21 | }
22 | return word
23 | }
24 |
25 | func convertText(text, src, tgt string, start, end int, ignoreRe *regexp.Regexp) string {
26 | var convLines []string
27 | lines := strings.Split(text, "\n")
28 | if start <= 0 {
29 | start = 1
30 | }
31 | if end <= 0 {
32 | end = len(lines)
33 | }
34 | for i, line := range lines {
35 | if i >= start-1 && i <= end-1 {
36 | conv := strings.Builder{}
37 | chunk := strings.Builder{}
38 | size := len(line)
39 | lastLetter := false
40 | for j, r := range line {
41 | if unicode.IsLetter(r) || isCaseSeparator(r) {
42 | chunk.WriteRune(r)
43 | if j < size-1 {
44 | continue
45 | }
46 | lastLetter = true
47 | }
48 | if chunk.Len() > 0 {
49 | word := chunk.String()
50 | if !ignoreRe.MatchString(word) {
51 | word = convertWord(word, src, tgt)
52 | }
53 | conv.WriteString(word)
54 | if lastLetter {
55 | break
56 | }
57 | chunk.Reset()
58 | }
59 | conv.WriteRune(r)
60 | }
61 | line = conv.String()
62 | }
63 | convLines = append(convLines, line)
64 | }
65 | out := strings.Join(convLines, "\n")
66 | return out
67 | }
68 |
69 | func convertFromText(text, src, tgt string, start, end int, ignoreRe *regexp.Regexp) (string, string) {
70 | conv := convertText(text, src, tgt, start, end, ignoreRe)
71 | return text, conv
72 | }
73 |
74 | func convertFromFile(fileName, src, tgt string, start, end int, ignoreRe *regexp.Regexp) (string, string, error) {
75 | b, err := ioutil.ReadFile(fileName)
76 | if err != nil {
77 | return "", "", err
78 | }
79 | text, conv := convertFromText(string(b), src, tgt, start, end, ignoreRe)
80 | return text, conv, nil
81 | }
82 |
--------------------------------------------------------------------------------
/cmd/casec/convert_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "io/ioutil"
5 | "regexp"
6 | "testing"
7 | )
8 |
9 | func TestConvertText_Pascal2Snake(t *testing.T) {
10 | orig, err := ioutil.ReadFile("../../testdata/pascal2snake.py.in")
11 | if err != nil {
12 | t.Error(err.Error())
13 | }
14 | expected, err := ioutil.ReadFile("../../testdata/pascal2snake.py.out")
15 | if err != nil {
16 | t.Error(err.Error())
17 | }
18 | re := regexp.MustCompile("^$")
19 | conv := convertText(string(orig), "pascal", "snake", 0, 0, re)
20 | if conv != string(expected) {
21 | t.Errorf("\nExpecting:\n%s\n\nGot:\n%s", string(expected), conv)
22 | }
23 | }
24 |
25 | func TestConvertText_Pascal2Snake_Ignore(t *testing.T) {
26 | orig, err := ioutil.ReadFile("../../testdata/pascal2snake_ignore.py.in")
27 | if err != nil {
28 | t.Error(err.Error())
29 | }
30 | expected, err := ioutil.ReadFile("../../testdata/pascal2snake_ignore.py.out")
31 | if err != nil {
32 | t.Error(err.Error())
33 | }
34 | re := regexp.MustCompile("^(None|CacheStore|InMemoryStore)$")
35 | conv := convertText(string(orig), "pascal", "snake", 0, 0, re)
36 | if conv != string(expected) {
37 | t.Errorf("\nExpecting:\n%s\n\nGot:\n%s", string(expected), conv)
38 | }
39 | }
40 |
41 | func TestConvertText_Snake2Camel(t *testing.T) {
42 | orig, err := ioutil.ReadFile("../../testdata/snake2camel.go.in")
43 | if err != nil {
44 | t.Error(err.Error())
45 | }
46 | expected, err := ioutil.ReadFile("../../testdata/snake2camel.go.out")
47 | if err != nil {
48 | t.Error(err.Error())
49 | }
50 | re := regexp.MustCompile("^$")
51 | conv := convertText(string(orig), "snake", "camel", 0, 0, re)
52 | if conv != string(expected) {
53 | t.Errorf("\nExpecting:\n%s\n\nGot:\n%s", string(expected), conv)
54 | }
55 | }
56 |
57 | func TestConvertText_Snake2Camel_Ignore(t *testing.T) {
58 | orig, err := ioutil.ReadFile("../../testdata/snake2camel_ignore.go.in")
59 | if err != nil {
60 | t.Error(err.Error())
61 | }
62 | expected, err := ioutil.ReadFile("../../testdata/snake2camel_ignore.go.out")
63 | if err != nil {
64 | t.Error(err.Error())
65 | }
66 | re := regexp.MustCompile("^(apache_common$|apache_combined|apache_error)$")
67 | conv := convertText(string(orig), "snake", "camel", 0, 0, re)
68 | if conv != string(expected) {
69 | t.Errorf("\nExpecting:\n%s\n\nGot:\n%s", string(expected), conv)
70 | }
71 | }
72 |
73 | func TestConvertText_Snake2Pascal_Lines_Ignore(t *testing.T) {
74 | orig, err := ioutil.ReadFile("../../testdata/snake2pascal_lines_ignore.go.in")
75 | if err != nil {
76 | t.Error(err.Error())
77 | }
78 | expected, err := ioutil.ReadFile("../../testdata/snake2pascal_lines_ignore.go.out")
79 | if err != nil {
80 | t.Error(err.Error())
81 | }
82 | re := regexp.MustCompile("^(switch|case|default|return|format|delta)$")
83 | conv := convertText(string(orig), "snake", "pascal", 8, 17, re)
84 | if conv != string(expected) {
85 | t.Errorf("\nExpecting:\n%s\n\nGot:\n%s", string(expected), conv)
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/cmd/casec/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "errors"
5 | "fmt"
6 | "io"
7 | "os"
8 | "regexp"
9 |
10 | "github.com/mingrammer/cfmt"
11 | "github.com/sergi/go-diff/diffmatchpatch"
12 | "github.com/urfave/cli"
13 | )
14 |
15 | // CLI information
16 | const (
17 | AppName = "casec"
18 | Author = "mingrammer"
19 | Email = "mingrammer@gmail.com"
20 | Version = "0.1.3"
21 | Usage = "A text case converter"
22 | UsageText = "casec [OPTIONS/FLAGS] [-x ] []"
23 | )
24 |
25 | // Custom exit codes
26 | const (
27 | errNoArguments = iota + 10
28 | errInvalidOptions
29 | )
30 |
31 | func main() {
32 | app := cli.NewApp()
33 | app.Name = AppName
34 | app.Author = Author
35 | app.Email = Email
36 | app.Version = Version
37 | app.Usage = Usage
38 | app.UsageText = UsageText
39 | app.Flags = []cli.Flag{
40 | cli.StringFlag{
41 | Name: "from, f",
42 | Usage: "source `CASE` in {upper,lower,title,camel,pascal,snake,kebab,lisp}",
43 | },
44 | cli.StringFlag{
45 | Name: "to, t",
46 | Usage: "target `CASE` in {upper,lower,title,camel,pascal,snake,kebab,lisp}",
47 | },
48 | cli.StringFlag{
49 | Name: "lines, l",
50 | Usage: "set lines `M:N` to be converted. empty means first or last line",
51 | },
52 | cli.StringSliceFlag{
53 | Name: "ignore, i",
54 | Usage: "ignore the text that matches the `PATTERNS`",
55 | },
56 | cli.BoolFlag{
57 | Name: "text, x",
58 | Usage: "read the input as raw text, not a file path",
59 | },
60 | cli.BoolFlag{
61 | Name: "dry-run, n",
62 | Usage: "show how would have been converted",
63 | },
64 | }
65 | app.Action = func(ctx *cli.Context) error {
66 | var err error
67 | var orig string
68 | var conv string
69 | var writer io.WriteCloser
70 |
71 | var src string
72 | var tgt string
73 | var start int
74 | var end int
75 | var ignoreRe *regexp.Regexp
76 | if len(ctx.Args()) == 0 {
77 | return errors.New(cfmt.Serror("There are no arguments"))
78 | }
79 | if src, err = parseSource(ctx.String("from")); err != nil {
80 | return err
81 | }
82 | if tgt, err = parseTarget(ctx.String("to")); err != nil {
83 | return err
84 | }
85 | if start, end, err = parseLines(ctx.String("lines")); err != nil {
86 | return err
87 | }
88 | if ignoreRe, err = parseIgnore(ctx.StringSlice("ignore")); err != nil {
89 | return err
90 | }
91 | input := ctx.Args().Get(0)
92 |
93 | if ctx.Bool("text") {
94 | orig, conv = convertFromText(input, src, tgt, start, end, ignoreRe)
95 | writer = os.Stdout
96 | } else {
97 | orig, conv, err = convertFromFile(input, src, tgt, start, end, ignoreRe)
98 | if err != nil {
99 | return err
100 | }
101 | writer, _ = os.OpenFile(input, os.O_RDWR, 0644)
102 | }
103 |
104 | if ctx.Bool("dry-run") {
105 | dmp := diffmatchpatch.New()
106 | diffs := dmp.DiffMain(orig, conv, false)
107 | fmt.Println(dmp.DiffPrettyText(diffs))
108 | } else {
109 | writer.Write([]byte(conv))
110 | writer.Close()
111 | }
112 | return nil
113 | }
114 |
115 | err := app.Run(os.Args)
116 | if err != nil {
117 | fmt.Println(err.Error())
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/cmd/casec/parse.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "errors"
5 | "regexp"
6 | "strconv"
7 | "strings"
8 |
9 | "github.com/mingrammer/cfmt"
10 | )
11 |
12 | var validCases = [8]string{"upper", "lower", "title", "camel", "pascal", "snake", "kebab", "lisp"}
13 |
14 | func parseNumber(s string) (int, error) {
15 | if s == "" {
16 | return 0, nil
17 | }
18 | i, err := strconv.Atoi(s)
19 | if err != nil {
20 | return 0, errors.New(cfmt.Serrorf("%s is not numeric", s))
21 | }
22 | return i, nil
23 | }
24 |
25 | func parseSource(s string) (string, error) {
26 | if s == "" {
27 | return "", nil
28 | }
29 | for _, c := range validCases {
30 | if c == s {
31 | return s, nil
32 | }
33 | }
34 | return "", errors.New(cfmt.Serrorf("%s is not valid case", s))
35 | }
36 |
37 | func parseTarget(s string) (string, error) {
38 | if s == "" {
39 | return "", errors.New(cfmt.Serrorf("You must specify target case"))
40 | }
41 | for _, c := range validCases {
42 | if c == s {
43 | return s, nil
44 | }
45 | }
46 | return "", errors.New(cfmt.Serrorf("%s is not valid case", s))
47 | }
48 |
49 | func parseLines(lines string) (int, int, error) {
50 | if lines == "" {
51 | return 0, 0, nil
52 | }
53 | split := strings.Split(lines, ":")
54 | if len(split) != 2 {
55 | return 0, 0, errors.New(cfmt.Serror("lines must be 'M:N' form"))
56 | }
57 | start, err := parseNumber(split[0])
58 | if err != nil {
59 | return 0, 0, err
60 | }
61 | end, err := parseNumber(split[1])
62 | if err != nil {
63 | return 0, 0, err
64 | }
65 | if end > 0 && start > end {
66 | return 0, 0, errors.New(cfmt.Serrorf("[%d] is not valid range", lines))
67 | }
68 | return start, end, nil
69 | }
70 |
71 | func parseIgnore(ignore []string) (*regexp.Regexp, error) {
72 | reExp := "^$"
73 | if len(ignore) > 0 {
74 | reExp = strings.Join(ignore, "|")
75 | }
76 | re, err := regexp.Compile(reExp)
77 | if err != nil {
78 | return nil, errors.New(cfmt.Serrorf("%s is not valid patten", reExp))
79 | }
80 | return re, nil
81 | }
82 |
--------------------------------------------------------------------------------
/cmd/casec/parse_test.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "regexp"
5 | "testing"
6 | )
7 |
8 | func TestParseNumber(t *testing.T) {
9 | testCases := []struct {
10 | input string
11 | expected int
12 | }{
13 | {input: "", expected: 0},
14 | {input: "3", expected: 3},
15 | }
16 |
17 | failingTestCases := []struct {
18 | input string
19 | expected int
20 | }{
21 | {input: "i0", expected: 0},
22 | }
23 |
24 | for i, tc := range testCases {
25 | n, err := parseNumber(tc.input)
26 | if n != tc.expected {
27 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected, n)
28 | }
29 | if err != nil {
30 | t.Errorf("[%d] There must be no errors", i+1)
31 | }
32 | }
33 |
34 | for i, tc := range failingTestCases {
35 | n, err := parseNumber(tc.input)
36 | if n != tc.expected {
37 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected, n)
38 | }
39 | if err == nil {
40 | t.Errorf("[%d] There must be errors", i+1)
41 | }
42 | }
43 | }
44 |
45 | func TestParseSource(t *testing.T) {
46 | testCases := []struct {
47 | input string
48 | expected string
49 | }{
50 | {input: "", expected: ""},
51 | {input: "snake", expected: "snake"},
52 | }
53 |
54 | failingTestCases := []struct {
55 | input string
56 | expected string
57 | }{
58 | {input: "special", expected: ""},
59 | }
60 |
61 | for i, tc := range testCases {
62 | src, err := parseSource(tc.input)
63 | if src != tc.expected {
64 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected, src)
65 | }
66 | if err != nil {
67 | t.Errorf("[%d] There must be no errors", i+1)
68 | }
69 | }
70 |
71 | for i, tc := range failingTestCases {
72 | src, err := parseSource(tc.input)
73 | if src != tc.expected {
74 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected, src)
75 | }
76 | if err == nil {
77 | t.Errorf("[%d] There must be errors", i+1)
78 | }
79 | }
80 | }
81 |
82 | func TestParseTarget(t *testing.T) {
83 | testCases := []struct {
84 | input string
85 | expected string
86 | }{
87 | {input: "camel", expected: "camel"},
88 | }
89 |
90 | failingTestCases := []struct {
91 | input string
92 | expected string
93 | }{
94 | {input: "", expected: ""},
95 | {input: "special", expected: ""},
96 | }
97 |
98 | for i, tc := range testCases {
99 | tgt, err := parseTarget(tc.input)
100 | if tgt != tc.expected {
101 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected, tgt)
102 | }
103 | if err != nil {
104 | t.Errorf("[%d] There must be no errors", i+1)
105 | }
106 | }
107 |
108 | for i, tc := range failingTestCases {
109 | src, err := parseTarget(tc.input)
110 | if src != tc.expected {
111 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected, src)
112 | }
113 | if err == nil {
114 | t.Errorf("[%d] There must be errors", i+1)
115 | }
116 | }
117 | }
118 |
119 | func TestParseLines(t *testing.T) {
120 | testCases := []struct {
121 | input string
122 | expected1 int
123 | expected2 int
124 | }{
125 | {input: "5:10", expected1: 5, expected2: 10},
126 | {input: "5:", expected1: 5, expected2: 0},
127 | {input: ":10", expected1: 0, expected2: 10},
128 | {input: ":", expected1: 0, expected2: 0},
129 | {input: "", expected1: 0, expected2: 0},
130 | }
131 |
132 | failingTestCases := []struct {
133 | input string
134 | expected1 int
135 | expected2 int
136 | }{
137 | {input: "5:2", expected1: 0, expected2: 0},
138 | {input: "1:10:2", expected1: 0, expected2: 0},
139 | }
140 |
141 | for i, tc := range testCases {
142 | start, end, err := parseLines(tc.input)
143 | if start != tc.expected1 {
144 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected1, start)
145 | }
146 | if end != tc.expected2 {
147 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected2, end)
148 | }
149 | if err != nil {
150 | t.Errorf("[%d] There must be no errors", i+1)
151 | }
152 | }
153 |
154 | for i, tc := range failingTestCases {
155 | start, end, err := parseLines(tc.input)
156 | if start != tc.expected1 {
157 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected1, start)
158 | }
159 | if end != tc.expected2 {
160 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected2, end)
161 | }
162 | if err == nil {
163 | t.Errorf("[%d] There must be errors", i+1)
164 | }
165 | }
166 | }
167 |
168 | func TestParseIgnore(t *testing.T) {
169 | testCases := []struct {
170 | input []string
171 | expected *regexp.Regexp
172 | }{
173 | {input: []string{}, expected: regexp.MustCompile("^$")},
174 | {input: []string{"^*.com$"}, expected: regexp.MustCompile("^*.com$")},
175 | {input: []string{"github", "bitbucket"}, expected: regexp.MustCompile("github|bitbucket")},
176 | {input: []string{"^(github|bitbucket)$"}, expected: regexp.MustCompile("^(github|bitbucket)$")},
177 | }
178 |
179 | failingTestCases := []struct {
180 | input []string
181 | expected *regexp.Regexp
182 | }{
183 | {input: []string{"*.com"}, expected: nil},
184 | }
185 |
186 | for i, tc := range testCases {
187 | re, err := parseIgnore(tc.input)
188 | if re.String() != tc.expected.String() {
189 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected, re)
190 | }
191 | if err != nil {
192 | t.Errorf("[%d] There must be no errors", i+1)
193 | }
194 | }
195 |
196 | for i, tc := range failingTestCases {
197 | re, err := parseIgnore(tc.input)
198 | if re != nil || tc.expected != nil {
199 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected, re)
200 | }
201 | if err == nil {
202 | t.Errorf("[%d] There must be errors", i+1)
203 | }
204 | }
205 | }
206 |
--------------------------------------------------------------------------------
/convert.go:
--------------------------------------------------------------------------------
1 | package casec
2 |
3 | import (
4 | "errors"
5 | "strings"
6 | "unicode"
7 | "unicode/utf8"
8 |
9 | "github.com/mingrammer/cfmt"
10 | )
11 |
12 | func isCaseSeparator(r rune) bool {
13 | return r == SnakeDelimiter || r == KebabDelimiter
14 | }
15 |
16 | func isSeparator(r rune) bool {
17 | return unicode.IsSpace(r) || isCaseSeparator(r)
18 | }
19 |
20 | // Invert inverts the UPPERCASE to lowercase and vice versa
21 | func Invert(s string) string {
22 | var out strings.Builder
23 | for _, r := range s {
24 | switch {
25 | case unicode.IsUpper(r):
26 | out.WriteRune(unicode.ToLower(r))
27 | case unicode.IsLower(r):
28 | out.WriteRune(unicode.ToUpper(r))
29 | default:
30 | out.WriteRune(r)
31 | }
32 | }
33 | return out.String()
34 | }
35 |
36 | // ToUpperCase converts the string to uppercase
37 | func ToUpper(s string) string {
38 | if !utf8.ValidString(s) {
39 | return s
40 | }
41 | s = strings.TrimFunc(s, unicode.IsSpace)
42 | return strings.ToUpper(s)
43 | }
44 |
45 | // ToLowerCase converts the string to lowercase
46 | func ToLower(s string) string {
47 | if !utf8.ValidString(s) {
48 | return s
49 | }
50 | s = strings.TrimFunc(s, unicode.IsSpace)
51 | return strings.ToLower(s)
52 | }
53 |
54 | // ToTitleCase converts the string to titlecase
55 | func ToTitle(s string) string {
56 | if !utf8.ValidString(s) {
57 | return s
58 | }
59 | s = strings.TrimFunc(s, unicode.IsSpace)
60 | return strings.Title(s)
61 | }
62 |
63 | // ToCamelCase converts the string to camelcase
64 | // Use strings.Map?
65 | func ToCamel(s string) string {
66 | if !utf8.ValidString(s) {
67 | return s
68 | }
69 | s = strings.TrimFunc(s, unicode.IsSpace)
70 | out := strings.Builder{}
71 | prev := rune(-1)
72 | for _, r := range s {
73 | switch {
74 | case prev < 0:
75 | out.WriteRune(unicode.ToLower(r))
76 | case isSeparator(prev):
77 | out.WriteRune(unicode.ToTitle(r))
78 | case !isSeparator(r):
79 | out.WriteRune(r)
80 | }
81 | prev = r
82 | }
83 | return out.String()
84 | }
85 |
86 | // ToPascalCase converts the string to pascalcase
87 | func ToPascal(s string) string {
88 | if !utf8.ValidString(s) {
89 | return s
90 | }
91 | s = strings.TrimFunc(s, unicode.IsSpace)
92 | out := strings.Builder{}
93 | prev := rune(-1)
94 | for _, r := range s {
95 | switch {
96 | case prev < 0:
97 | out.WriteRune(unicode.ToTitle(r))
98 | case isSeparator(prev):
99 | out.WriteRune(unicode.ToTitle(r))
100 | case !isSeparator(r):
101 | out.WriteRune(r)
102 | }
103 | prev = r
104 | }
105 | return out.String()
106 | }
107 |
108 | // ToSnakeCase converts the string to snakecase
109 | func ToSnake(s string) string {
110 | if !utf8.ValidString(s) {
111 | return s
112 | }
113 | s = strings.TrimFunc(s, unicode.IsSpace)
114 | out := strings.Builder{}
115 | for i := 0; i < len(s); i++ {
116 | switch {
117 | case unicode.IsUpper(rune(s[i])):
118 | // If the previous letter is lowercase, add '_' letter before the current letter
119 | if i > 0 {
120 | if unicode.IsLower(rune(s[i-1])) {
121 | out.WriteRune(SnakeDelimiter)
122 | }
123 | }
124 | // If the previous letter and the next letter are uppercase and lowercase, respectively, add '_' letter before the current letter
125 | if i > 0 && i < len(s)-1 {
126 | if unicode.IsUpper(rune(s[i-1])) && unicode.IsLower(rune(s[i+1])) {
127 | out.WriteRune(SnakeDelimiter)
128 | }
129 | }
130 | out.WriteRune(unicode.ToLower(rune(s[i])))
131 | case isSeparator(rune(s[i])):
132 | out.WriteRune(SnakeDelimiter)
133 | default:
134 | out.WriteByte(s[i])
135 | }
136 | }
137 | return out.String()
138 | }
139 |
140 | // ToKebabCase converts the string to kebabcase
141 | func ToKebab(s string) string {
142 | if !utf8.ValidString(s) {
143 | return s
144 | }
145 | s = strings.TrimFunc(s, unicode.IsSpace)
146 | out := strings.Builder{}
147 | for i := 0; i < len(s); i++ {
148 | switch {
149 | case unicode.IsUpper(rune(s[i])):
150 | // If the previous letter is lowercase, add '-' letter before the current letter
151 | if i > 0 {
152 | if unicode.IsLower(rune(s[i-1])) {
153 | out.WriteRune(KebabDelimiter)
154 | }
155 | }
156 | // If the previous letter and the next letter are uppercase and lowercase, respectively, add '-' letter before the current letter
157 | if i > 0 && i < len(s)-1 {
158 | if unicode.IsUpper(rune(s[i-1])) && unicode.IsLower(rune(s[i+1])) {
159 | out.WriteRune(KebabDelimiter)
160 | }
161 | }
162 | out.WriteRune(unicode.ToLower(rune(s[i])))
163 | case isSeparator(rune(s[i])):
164 | out.WriteRune(KebabDelimiter)
165 | default:
166 | out.WriteByte(s[i])
167 | }
168 | }
169 | return out.String()
170 | }
171 |
172 | // ToCaseFor converts the string to specific case
173 | func ToCaseFor(c, s string) (string, error) {
174 | switch c {
175 | case "upper":
176 | return ToUpper(s), nil
177 | case "lower":
178 | return ToLower(s), nil
179 | case "title":
180 | return ToTitle(s), nil
181 | case "camel":
182 | return ToCamel(s), nil
183 | case "pascal":
184 | return ToPascal(s), nil
185 | case "snake":
186 | return ToSnake(s), nil
187 | case "kebab", "lisp":
188 | return ToKebab(s), nil
189 | }
190 | return "", errors.New(cfmt.Serrorf("%s is not valid case", c))
191 | }
192 |
--------------------------------------------------------------------------------
/convert_test.go:
--------------------------------------------------------------------------------
1 | package casec
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func TestInvert(t *testing.T) {
8 | testCases := []struct {
9 | text string
10 | expected string
11 | }{
12 | {text: "UPPERCASE", expected: "uppercase"},
13 | {text: "lowercase", expected: "LOWERCASE"},
14 | {text: "mIxEdCaSe", expected: "MiXeDcAsE"},
15 | {text: "weird-Case", expected: "WEIRD-cASE"},
16 | }
17 |
18 | for i, tc := range testCases {
19 | if s := Invert(tc.text); s != tc.expected {
20 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected, s)
21 | }
22 | }
23 | }
24 |
25 | func TestToUpper(t *testing.T) {
26 | testCases := []struct {
27 | text string
28 | expected string
29 | }{
30 | {text: "case", expected: "CASE"},
31 | {text: "upper_case", expected: "UPPER_CASE"},
32 | {text: "This is a sentence", expected: "THIS IS A SENTENCE"},
33 | }
34 |
35 | for i, tc := range testCases {
36 | if s := ToUpper(tc.text); s != tc.expected {
37 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected, s)
38 | }
39 | }
40 | }
41 |
42 | func TestToLower(t *testing.T) {
43 | testCases := []struct {
44 | text string
45 | expected string
46 | }{
47 | {text: "Case", expected: "case"},
48 | {text: "LOWER_CASE", expected: "lower_case"},
49 | {text: "This is a sentence", expected: "this is a sentence"},
50 | }
51 |
52 | for i, tc := range testCases {
53 | if s := ToLower(tc.text); s != tc.expected {
54 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected, s)
55 | }
56 | }
57 | }
58 |
59 | func TestToTitle(t *testing.T) {
60 | testCases := []struct {
61 | text string
62 | expected string
63 | }{
64 | {text: "case", expected: "Case"},
65 | {text: "title_case", expected: "Title_case"},
66 | {text: "This is a sentence", expected: "This Is A Sentence"},
67 | }
68 |
69 | for i, tc := range testCases {
70 | if s := ToTitle(tc.text); s != tc.expected {
71 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected, s)
72 | }
73 | }
74 | }
75 |
76 | func TestToCamel(t *testing.T) {
77 | testCases := []struct {
78 | text string
79 | expected string
80 | }{
81 | {text: "case", expected: "case"},
82 | {text: "snake_case", expected: "snakeCase"},
83 | {text: "This is a sentence", expected: "thisIsASentence"},
84 | {text: "ConsecutiveUPPERCase", expected: "consecutiveUPPERCase"},
85 | {text: "Unknown-SpecialCase", expected: "unknownSpecialCase"},
86 | }
87 |
88 | for i, tc := range testCases {
89 | if s := ToCamel(tc.text); s != tc.expected {
90 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected, s)
91 | }
92 | }
93 | }
94 |
95 | func TestToPascal(t *testing.T) {
96 | testCases := []struct {
97 | text string
98 | expected string
99 | }{
100 | {text: "case", expected: "Case"},
101 | {text: "snake_case", expected: "SnakeCase"},
102 | {text: "This is a sentence", expected: "ThisIsASentence"},
103 | {text: "consecutiveUPPERCase", expected: "ConsecutiveUPPERCase"},
104 | {text: "Unknown-SpecialCase", expected: "UnknownSpecialCase"},
105 | }
106 |
107 | for i, tc := range testCases {
108 | if s := ToPascal(tc.text); s != tc.expected {
109 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected, s)
110 | }
111 | }
112 | }
113 |
114 | func TestToSnake(t *testing.T) {
115 | testCases := []struct {
116 | text string
117 | expected string
118 | }{
119 | {text: "case", expected: "case"},
120 | {text: "camelCase", expected: "camel_case"},
121 | {text: "This is a sentence", expected: "this_is_a_sentence"},
122 | {text: "ConsecutiveUPPERCase", expected: "consecutive_upper_case"},
123 | {text: "Unknown-SpecialCase", expected: "unknown_special_case"},
124 | }
125 |
126 | for i, tc := range testCases {
127 | if s := ToSnake(tc.text); s != tc.expected {
128 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected, s)
129 | }
130 | }
131 | }
132 |
133 | func TestToKebab(t *testing.T) {
134 | testCases := []struct {
135 | text string
136 | expected string
137 | }{
138 | {text: "case", expected: "case"},
139 | {text: "camelCase", expected: "camel-case"},
140 | {text: "This is a sentence", expected: "this-is-a-sentence"},
141 | {text: "ConsecutiveUPPERCase", expected: "consecutive-upper-case"},
142 | {text: "Unknown-SpecialCase", expected: "unknown-special-case"},
143 | }
144 |
145 | for i, tc := range testCases {
146 | if s := ToKebab(tc.text); s != tc.expected {
147 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected, s)
148 | }
149 | }
150 | }
151 |
152 | func TestToCaseFor(t *testing.T) {
153 | testCases := []struct {
154 | kind string
155 | text string
156 | expected string
157 | }{
158 | {kind: "upper", text: "uppercase", expected: "UPPERCASE"},
159 | {kind: "lower", text: "LOWERCASE", expected: "lowercase"},
160 | {kind: "title", text: "titlecase", expected: "Titlecase"},
161 | {kind: "camel", text: "camel_case", expected: "camelCase"},
162 | {kind: "pascal", text: "pascal_case", expected: "PascalCase"},
163 | {kind: "snake", text: "snakeCase", expected: "snake_case"},
164 | {kind: "kebab", text: "kebabCase", expected: "kebab-case"},
165 | {kind: "unknown", text: "unknown", expected: ""},
166 | }
167 |
168 | for i, tc := range testCases {
169 | if s, _ := ToCaseFor(tc.kind, tc.text); s != tc.expected {
170 | t.Errorf("[%d] Expecting %v, got %v", i+1, tc.expected, s)
171 | }
172 | }
173 | }
174 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/mingrammer/casec
2 |
3 | require (
4 | github.com/davecgh/go-spew v1.1.1 // indirect
5 | github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e // indirect
6 | github.com/mattn/go-isatty v0.0.4 // indirect
7 | github.com/mingrammer/cfmt v1.1.0
8 | github.com/pmezard/go-difflib v1.0.0 // indirect
9 | github.com/sergi/go-diff v1.0.0
10 | github.com/stretchr/testify v1.2.2 // indirect
11 | github.com/urfave/cli v1.20.0
12 | golang.org/x/sys v0.0.0-20181212120007-b05ddf57801d // indirect
13 | )
14 |
15 | go 1.13
16 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3 | github.com/fatih/color v1.6.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
4 | github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e h1:9MlwzLdW7QSDrhDjFlsEYmxpFyIoXmYRon3dt0io31k=
5 | github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
6 | github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
7 | github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
8 | github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
9 | github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
10 | github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
11 | github.com/mingrammer/cfmt v1.1.0 h1:fAALVQC+aa20fCvghuB5W6zBAAsGWKGdcZmexpPrvwo=
12 | github.com/mingrammer/cfmt v1.1.0/go.mod h1:Jqg1Lq43AMo3ggnIEpvIDbca1VSvdHDg0H13eDG+/ys=
13 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
14 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
15 | github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
16 | github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
17 | github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
18 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
19 | github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
20 | github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
21 | golang.org/x/sys v0.0.0-20180315095008-cc7307a45468/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
22 | golang.org/x/sys v0.0.0-20181212120007-b05ddf57801d h1:G59MrP9Qg6bymPjN3yGmqnmuCEH1h0eFP8zpRpl1RiU=
23 | golang.org/x/sys v0.0.0-20181212120007-b05ddf57801d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
24 |
--------------------------------------------------------------------------------
/testdata/pascal2snake.py.in:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 |
4 | def ParseURI(uri):
5 | """Extracts the host, port and db from an uri"""
6 | host, port, db = uri, 6379, 0
7 | if len(host.split('/')) == 2:
8 | host, db = host.split('/')
9 | if len(host.split(':')) == 2:
10 | host, port = host.split(':')
11 | return host, int(port), int(db)
12 |
13 |
14 | if __name__ == '__main__':
15 | argv = sys.argv
16 | IPAddress, Port, DBNum = ParseURI(argv)
17 | print("ip address: ", IPAddress)
18 | print("port: ", Port)
19 | print("db: ", DBNum)
--------------------------------------------------------------------------------
/testdata/pascal2snake.py.out:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 |
4 | def parse_uri(uri):
5 | """extracts the host, port and db from an uri"""
6 | host, port, db = uri, 6379, 0
7 | if len(host.split('/')) == 2:
8 | host, db = host.split('/')
9 | if len(host.split(':')) == 2:
10 | host, port = host.split(':')
11 | return host, int(port), int(db)
12 |
13 |
14 | if __name__ == '__main__':
15 | argv = sys.argv
16 | ip_address, port, db_num = parse_uri(argv)
17 | print("ip address: ", ip_address)
18 | print("port: ", port)
19 | print("db: ", db_num)
--------------------------------------------------------------------------------
/testdata/pascal2snake_ignore.py.in:
--------------------------------------------------------------------------------
1 | import json
2 |
3 | from fitter.cachestore import CacheStore
4 |
5 |
6 | class InMemoryStore(CacheStore):
7 | def __init__(self):
8 | self.KVStore = {}
9 |
10 | def get(self, Key):
11 | return json.loads(self.KVStore[Key]) if Key in self.KVStore else None
12 |
13 | def set(self, Key, Value):
14 | self.KVStore[Key] = json.dumps(Value)
--------------------------------------------------------------------------------
/testdata/pascal2snake_ignore.py.out:
--------------------------------------------------------------------------------
1 | import json
2 |
3 | from fitter.cachestore import CacheStore
4 |
5 |
6 | class InMemoryStore(CacheStore):
7 | def __init__(self):
8 | self.kv_store = {}
9 |
10 | def get(self, key):
11 | return json.loads(self.kv_store[key]) if key in self.kv_store else None
12 |
13 | def set(self, key, value):
14 | self.kv_store[key] = json.dumps(value)
--------------------------------------------------------------------------------
/testdata/snake2camel.go.in:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "compress/gzip"
5 | "io"
6 | "os"
7 | )
8 |
9 | func new_writer(log_type string, log_file_name string) (io.WriteCloser, error) {
10 | switch log_type {
11 | case "stdout":
12 | return os.Stdout, nil
13 | case "log":
14 | log_file, err := os.Create(log_file_name)
15 | if err != nil {
16 | return nil, err
17 | }
18 | return log_file, nil
19 | case "gz":
20 | log_file, err := os.Create(log_file_name)
21 | if err != nil {
22 | return nil, err
23 | }
24 | return gzip.NewWriter(log_file), nil
25 | default:
26 | return nil, nil
27 | }
28 | }
--------------------------------------------------------------------------------
/testdata/snake2camel.go.out:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "compress/gzip"
5 | "io"
6 | "os"
7 | )
8 |
9 | func newWriter(logType string, logFileName string) (io.WriteCloser, error) {
10 | switch logType {
11 | case "stdout":
12 | return os.Stdout, nil
13 | case "log":
14 | logFile, err := os.Create(logFileName)
15 | if err != nil {
16 | return nil, err
17 | }
18 | return logFile, nil
19 | case "gz":
20 | logFile, err := os.Create(logFileName)
21 | if err != nil {
22 | return nil, err
23 | }
24 | return gzip.NewWriter(logFile), nil
25 | default:
26 | return nil, nil
27 | }
28 | }
--------------------------------------------------------------------------------
/testdata/snake2camel_ignore.go.in:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "time"
5 | )
6 |
7 | func new_log(format string, delta time.Duration) string {
8 | switch format {
9 | case "apache_common":
10 | return new_apache_common_log(delta)
11 | case "apache_combined":
12 | return new_apache_combined_log(delta)
13 | case "apache_error":
14 | return new_apache_error_log(delta)
15 | default:
16 | return ""
17 | }
18 | }
--------------------------------------------------------------------------------
/testdata/snake2camel_ignore.go.out:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "time"
5 | )
6 |
7 | func newLog(format string, delta time.Duration) string {
8 | switch format {
9 | case "apache_common":
10 | return newApacheCommonLog(delta)
11 | case "apache_combined":
12 | return newApacheCombinedLog(delta)
13 | case "apache_error":
14 | return newApacheErrorLog(delta)
15 | default:
16 | return ""
17 | }
18 | }
--------------------------------------------------------------------------------
/testdata/snake2pascal_lines_ignore.go.in:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "time"
5 | )
6 |
7 | func new_log(format string, delta time.Duration) string {
8 | switch format {
9 | case "apache_common":
10 | return new_apache_common_log(delta)
11 | case "apache_combined":
12 | return new_apache_combined_log(delta)
13 | case "apache_error":
14 | return new_apache_error_log(delta)
15 | default:
16 | return ""
17 | }
18 | }
--------------------------------------------------------------------------------
/testdata/snake2pascal_lines_ignore.go.out:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "time"
5 | )
6 |
7 | func new_log(format string, delta time.Duration) string {
8 | switch format {
9 | case "ApacheCommon":
10 | return NewApacheCommonLog(delta)
11 | case "ApacheCombined":
12 | return NewApacheCombinedLog(delta)
13 | case "ApacheError":
14 | return NewApacheErrorLog(delta)
15 | default:
16 | return ""
17 | }
18 | }
--------------------------------------------------------------------------------