diff --git a/.goreleaser.yml b/.goreleaser.yml new file mode 100644 index 0000000..10d3cca --- /dev/null +++ b/.goreleaser.yml @@ -0,0 +1,70 @@ +# This is an example goreleaser.yaml file with some sane defaults. +# Make sure to check the documentation at http://goreleaser.com +project_name: caseit +env: + - GO111MODULE=on +before: + hooks: + - go mod tidy +builds: +- env: + - CGO_ENABLED=0 + goos: + - darwin + - freebsd + - linux + - netbsd + - openbsd + - windows + ignore: + - goos: darwin + goarch: 386 + ldflags: + - -s -w + main: ./cmd/caseit/main.go +archives: + - files: + - CHANGELOG.md + - LICENSE + - README.md + format_overrides: + - goos: windows + format: zip + replacements: + 386: i386 + amd64: x86_64 + darwin: macos + # darwin: macOS + # freebsd: FreeBSD + # linux: Linux + # netbsd: NetBSD + # openbsd: OpenBSD + # caseit: CaseIt + # windows: Windows + wrap_in_directory: true +nfpms: + # note that this is an array of nfpm configs + - formats: + - deb + - rpm + # ID of the nfpm config, must be unique. + # Defaults to "default". + id: caseit + homepage: "https://github.com/runeimp/caseit" + license: MIT + replacements: + 386: i386 + amd64: x86_64 + darwin: macos +checksum: + name_template: 'checksums.txt' +# signs: +# - artifacts: checksum +snapshot: + name_template: "{{ .Tag }}-next" +changelog: + sort: asc + filters: + exclude: + - '^docs:' + - '^test:' diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..5bb93e9 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,11 @@ +ChangeLog: +========== + +v1.0.0 +------ + +Initial release + +* Added all planned casing options +* Added all planned command line options + diff --git a/Justfile b/Justfile index 3f4905e..7a75eba 100644 --- a/Justfile +++ b/Justfile @@ -12,9 +12,9 @@ build: # Run CaseIt -run +args='"Case the words"': +run cmd="word" arg="-s" +args='" ALL CAPS to go thru 1--6 of the 1/2 with the correct CIA ID over GRPC"': @just _term-wipe - go run cmd/caseit/main.go {{args}} + go run cmd/caseit/main.go {{cmd}} {{arg}} {{args}} _term-wipe: diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b959557 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 RuneImp + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index 2b9ed64..32bc7bc 100644 --- a/README.md +++ b/README.md @@ -3,49 +3,301 @@ CaseIt Case conversion library and command line tool written in Go +CLI Tool v1.0.0 +Library v1.0.0 + Case Conversions Implemented ---------------------------- -* NoDelimiter - * [x] `lowercase` - * [x] `camelCase` - * [x] `PascalCase` - * [x] `UPPERCASE` +### Word Casing + +* lower case -- All words in statement are lower cased. +* Title Case (simple) -- All words have the first character upper cased. All other letters are left as they were initially. +* Title Case (forced) -- All letters in a word after the first are lower cased. +* Title Case (coder) -- Like simple title case but also checks if a word is a common initialism such as gRPC, OAuth, OpenID, etc. and enforces the initialism. +* Title Case (smart) -- Like simple title case but also lower cases small words such as "a", "the", etc. Uses my [titlecase][] library which is based on [Python Titlecase][]. +* UPPER CASE -- All words upper cased. + +### Word Delimiters + +Each of the word casing options are then paired with a word separation option + +* CamelCase AKA No Delimiter + * `lowercase` + * `camelCase` -- Initial word is always lower cased. + * `TitleCase` + * `ForcedTitleCase` + * `CoderTitleCase` + * `SmartTitleCase` + * `PascalCase` -- The same a `ForcedTitleCase` + * `UPPERCASE` +* char\*case - Any delimiter for those who simply need _more options_. `*` is the default delimiter if you don't specify one with `-d` or `--delimiter`. + * `dot*lower*case` + * `Dot*Title*Case` + * `Dot*Forced*Title*Case` + * `Dot*Coder*Title*Case` + * `Dot*Smart*Title*Case` + * `DOT*UPPER*CASE` * dot.case - * [x] `dot.lower.case` - * [x] `Dot.Title.Case` - * [x] `DOT.UPPER.CASE` + * `dot.lower.case` + * `Dot.Title.Case` + * `Dot.Forced.Title.Case` + * `Dot.Coder.Title.Case` + * `Dot.Smart.Title.Case` + * `DOT.UPPER.CASE` * kebab-case - * [x] `kebab-lower-case` - * [x] `Kebab-Title-Case` - * [x] `KEBAB-UPPER-CASE` -* Separate Words - * [x] `separate words lower case` - * [x] `Separate Words Title Case` - * [ ] `Separate Words Smart Title Case` (words like "a", "the", etc. are not title cased) - * [x] `SEPARATE WORDS UPPER CASE` + * `kebab-lower-case` + * `Kebab-Title-Case` + * `Kebab-Forced-Title-Case` + * `Kebab-Coder-Title-Case` + * `Kebab-Smart-Title-Case` + * `KEBAB-UPPER-CASE` * `snake_case` - * [x] `snake_case` - * [x] `Snake_Title_Case` - * [x] `SNAKE_UPPER_CASE` + * `snake_case` + * `Snake_Title_Case` + * `Snake_Forced_Title_Case` + * `Snake_Coder_Title_Case` + * `Snake_Smart_Title_Case` + * `SNAKE_UPPER_CASE` +* Word Case AKA Space Case + * `separate words lower case` + * `Separate Words Title Case` + * `Separate Words Forced Title Case` + * `Dot.Coder.Title.Case` + * `Separate Words Smart Title Case` (words like "a", "the", etc. are not title cased) + * `SEPARATE WORDS UPPER CASE` Features -------- * Case conversion -* No external libraries. This may change with a later version but in general striving to be as pure as reasonable. -* The only tool I've seen that can do `Snake_Title_Case` which is why I created this. +* Word delimitation +* No external libraries. OK, that's not entirely true. But the one external library is my own [titlecase][] package. :angel: +* I wanted a tool that could also do `Snake_Title_Case`. I couldn't find one so I created this tool. + + +Example +------- + +### Help + +```text +$ caseit +Processes input string(s) providing conversion to almost any code standard desired, including proper title casing. +CaseIt v1.0.0 +Usage: caseit + +Options: + --help, -h display this help and exit + --version display version and exit + +Commands: + all All commands used + camel Words are not separated by a delimiter + char Character specified separated words + dot Dot separated words + kebab Hyphen separated words + snake Underscore separated words + word Space separated words +``` + + +#### Subcommand Help + +```text +$ caseit snake -h +Processes input string(s) providing conversion to almost any code standard desired, including proper title casing. +CaseIt v1.0.0 +Usage: caseit snake [--all] [--force] [--lower] [--title] [--coder] [--smart] [--upper] [INPUT [INPUT ...]] + +Positional arguments: + INPUT The input string(s) to process + +Options: + --all, -a Use all options + --force, -f Forced Title_Snake_Case - Words in all caps will be forced to initial letter upper and the rest lower. Commonly used for database names. + --lower, -l Python's traditional_snake_case. This is the default. + --title, -t Title_Snake_Case - Words that are all caps are left all caps. Commonly used for database names. + --coder, -c Coder Title_Snake_Case - Words that are common initialisms are properly cased for the initialism. Otherwise force title cased. Commonly used for database names. + --smart, -s Smart Title_Snake_Case - Uses code based on Python Titlecase which is smart about small words, etc. Commonly used for database names. + --upper, -u UPPER_SNAKE_CASE or CONSTANTS_CASE in many languages. + --help, -h display this help and exit + --version display version and exit +``` + + +### snake_case + +#### Default Case Only (lower for snake_case) + +```bash +$ caseit snake "This OAuth test" " ALL CAPS to go thru 1--6 of the 1/2 with the correct CIA ID over GRPC" +Source: "This OAuth test" + " ALL CAPS to go thru 1--6 of the 1/2 with the correct CIA ID over GRPC" + snake_case: + lower: this_oauth_test + + lower: all_caps_to_go_thru_1_6_of_the_1_2_with_the_correct_cia_id_over_grpc + +``` + +#### Force Case, Coder Case, and Smart Case + +```bash +$ caseit snake -f -c -s "This OAuth test" " ALL CAPS to go thru 1--6 of the 1/2 with the correct CIA ID over GRPC" +Source: "This OAuth test" + " ALL CAPS to go thru 1--6 of the 1/2 with the correct CIA ID over GRPC" + snake_case: + Force: This_Oauth_Test + Coder: This_OAuth_Test + Smart: This_OAuth_Test + + Force: All_Caps_To_Go_Thru_1_6_Of_The_1_2_With_The_Correct_Cia_Id_Over_Grpc + Coder: All_Caps_To_Go_Thru_1_6_Of_The_1_2_With_The_Correct_CIA_ID_Over_gRPC + Smart: ALL_CAPS_to_Go_Thru_1_6_of_the_1_2_with_the_Correct_CIA_ID_Over_GRPC + +``` + +### The Kitchen Sink + +#### All cases and all styles + +```bash +$ caseit all "This OAuth test" " ALL CAPS to go thru 1--6 of the 1/2 with the correct CIA ID over GRPC" +Source: "This OAuth test" + " ALL CAPS to go thru 1--6 of the 1/2 with the correct CIA ID over GRPC" + CamelCase: + lower: thisoauthtest + camel: thisOauthTest + Force: ThisOauthTest + Title: ThisOAuthTest + Coder: ThisOAuthTest + Smart: ThisOAuthTest +Pascal: ThisOauthTest + UPPER: THISOAUTHTEST + + lower: allcapstogothru16ofthe12withthecorrectciaidovergrpc + camel: allCapsToGoThru16OfThe12WithTheCorrectCiaIdOverGrpc + Force: AllCapsToGoThru16OfThe12WithTheCorrectCiaIdOverGrpc + Title: ALLCAPSToGoThru16OfThe12WithTheCorrectCIAIDOverGRPC + Coder: AllCapsToGoThru16OfThe12WithTheCorrectCIAIDOvergRPC + Smart: ALLCAPStoGoThru16ofthe12withtheCorrectCIAIDOverGRPC +Pascal: AllCapsToGoThru16OfThe12WithTheCorrectCiaIdOverGrpc + UPPER: ALLCAPSTOGOTHRU16OFTHE12WITHTHECORRECTCIAIDOVERGRPC + + char*case: + lower: this.oauth.test + Force: This.Oauth.Test + Title: This.OAuth.Test + Coder: This.OAuth.Test + Smart: This.OAuth.Test + UPPER: THIS.OAUTH.TEST + + lower: all.caps.to.go.thru.1.6.of.the.1.2.with.the.correct.cia.id.over.grpc + Force: All.Caps.To.Go.Thru.1.6.Of.The.1.2.With.The.Correct.Cia.Id.Over.Grpc + Title: ALL.CAPS.To.Go.Thru.1.6.Of.The.1.2.With.The.Correct.CIA.ID.Over.GRPC + Coder: All.Caps.To.Go.Thru.1.6.Of.The.1.2.With.The.Correct.CIA.ID.Over.gRPC + Smart: ALL.CAPS.to.Go.Thru.1.6.of.the.1.2.with.the.Correct.CIA.ID.Over.GRPC + UPPER: ALL.CAPS.TO.GO.THRU.1.6.OF.THE.1.2.WITH.THE.CORRECT.CIA.ID.OVER.GRPC + + dot.case: + lower: this.oauth.test + Force: This.Oauth.Test + Title: This.OAuth.Test + Coder: This.OAuth.Test + Smart: This.OAuth.Test + UPPER: THIS.OAUTH.TEST + + lower: all.caps.to.go.thru.1.6.of.the.1.2.with.the.correct.cia.id.over.grpc + Force: All.Caps.To.Go.Thru.1.6.Of.The.1.2.With.The.Correct.Cia.Id.Over.Grpc + Title: ALL.CAPS.To.Go.Thru.1.6.Of.The.1.2.With.The.Correct.CIA.ID.Over.GRPC + Coder: All.Caps.To.Go.Thru.1.6.Of.The.1.2.With.The.Correct.CIA.ID.Over.gRPC + Smart: ALL.CAPS.to.Go.Thru.1.6.of.the.1.2.with.the.Correct.CIA.ID.Over.GRPC + UPPER: ALL.CAPS.TO.GO.THRU.1.6.OF.THE.1.2.WITH.THE.CORRECT.CIA.ID.OVER.GRPC + + kebab-case: + lower: this-oauth-test + Force: This-Oauth-Test + Title: This-OAuth-Test + Coder: This-OAuth-Test + Smart: This-OAuth-Test + UPPER: THIS-OAUTH-TEST + + lower: all-caps-to-go-thru-1-6-of-the-1-2-with-the-correct-cia-id-over-grpc + Force: All-Caps-To-Go-Thru-1-6-Of-The-1-2-With-The-Correct-Cia-Id-Over-Grpc + Title: ALL-CAPS-To-Go-Thru-1-6-Of-The-1-2-With-The-Correct-CIA-ID-Over-GRPC + Coder: All-Caps-To-Go-Thru-1-6-Of-The-1-2-With-The-Correct-CIA-ID-Over-gRPC + Smart: ALL-CAPS-to-Go-Thru-1-6-of-the-1-2-with-the-Correct-CIA-ID-Over-GRPC + UPPER: ALL-CAPS-TO-GO-THRU-1-6-OF-THE-1-2-WITH-THE-CORRECT-CIA-ID-OVER-GRPC + + snake_case: + lower: this_oauth_test + Force: This_Oauth_Test + Title: This_OAuth_Test + Coder: This_OAuth_Test + Smart: This_OAuth_Test + UPPER: THIS_OAUTH_TEST + + lower: all_caps_to_go_thru_1_6_of_the_1_2_with_the_correct_cia_id_over_grpc + Force: All_Caps_To_Go_Thru_1_6_Of_The_1_2_With_The_Correct_Cia_Id_Over_Grpc + Title: ALL_CAPS_To_Go_Thru_1_6_Of_The_1_2_With_The_Correct_CIA_ID_Over_GRPC + Coder: All_Caps_To_Go_Thru_1_6_Of_The_1_2_With_The_Correct_CIA_ID_Over_gRPC + Smart: ALL_CAPS_to_Go_Thru_1_6_of_the_1_2_with_the_Correct_CIA_ID_Over_GRPC + UPPER: ALL_CAPS_TO_GO_THRU_1_6_OF_THE_1_2_WITH_THE_CORRECT_CIA_ID_OVER_GRPC + + Word Case: + lower: this oauth test + Force: This Oauth Test + Title: This OAuth Test + Coder: This OAuth Test + Smart: This OAuth Test + UPPER: THIS OAUTH TEST + + lower: all caps to go thru 1 6 of the 1 2 with the correct cia id over grpc + Force: All Caps To Go Thru 1 6 Of The 1 2 With The Correct Cia Id Over Grpc + Title: ALL CAPS To Go Thru 1 6 Of The 1 2 With The Correct CIA ID Over GRPC + Coder: All Caps To Go Thru 1 6 Of The 1 2 With The Correct CIA ID Over gRPC + Smart: ALL CAPS to Go Thru 1 6 of the 1 2 with the Correct CIA ID Over GRPC + UPPER: ALL CAPS TO GO THRU 1 6 OF THE 1 2 WITH THE CORRECT CIA ID OVER GRPC + +``` + + ToDo: ----- -* [ ] Add all the casing options -* [ ] Add more options to `caseit` command line tool -* [ ] Add custom delimiter support for input -* [ ] Add custom delimiter support for output +* [x] Add all the casing options +* [x] Add more options to `caseit` command line tool +* [x] Add custom delimiter support for CLI input +* [x] Add custom delimiter support for library output +* [ ] Add unit tests * [ ] Update Create the docs -* [ ] Update `caseit.Separatem()` to handle things like "ID or other ALL CAPS casing" to maintain the caps when possible +* [x] Update `caseit.Separatem()` to handle things like "ID or other ALL CAPS casing" to maintain the caps when possible * [ ] Setup cross-compiling for releases + +References +---------- + +My main reference in starting this was [Properly Capitalizing a Title][] and a quick review of the other similar products that already existed. + + +Similar Products +---------------- + +* [strcase by Ian Coleman][] -- Very close to what I did with CaseIt. There are a few features in both that are present in the other. +* [go-strcase by Adrian Stoewer][] -- This one is fine if you just need `kebab-case`, `snake_case`, `camelCase`, and `PascalCase`. +* [snaker by Serenize UG] -- This one only handles `snake_case`, `camelCase`, and `PascalCase`. But also is aware of common initialisms and words with odd capitalization usage such as ID and OAuth and inspired my usage of that concept in this app. + + + +[go-strcase by Adrian Stoewer]: https://github.com/stoewer/go-strcase +[Properly Capitalizing a Title]: https://golangcookbook.com/chapters/strings/title/ +[Python Titlecase]: https://github.com/ppannuto/python-titlecase +[snaker by Serenize UG]: https://github.com/serenize/snaker +[strcase by Ian Coleman]: https://github.com/iancoleman/strcase +[titlecase]: https://github.com/runeimp/titlecase + diff --git a/caseit.go b/caseit.go new file mode 100644 index 0000000..1d3276e --- /dev/null +++ b/caseit.go @@ -0,0 +1,311 @@ +package caseit + +import ( + "fmt" + "regexp" + "strings" + "unicode" + + // titlecase "github.com/igorsobreira/titlecase" + // titlecase "github.com/KenjiTakahashi/tu/titlecase" + "github.com/runeimp/titlecase" +) + +const Version = "1.0.0" + +var ( + spaceRE = regexp.MustCompile(`\s+`) + UseCodeBreak = false +) + +// Idea modified from +// https://github.com/serenize/snaker/blob/master/snaker.go#L102 +var commonInitialismsAndOddballs = map[string]string{ + "ACL": "ACL", + "API": "API", + "ASCII": "ASCII", + "CIA": "CIA", + "CPU": "CPU", + "CSS": "CSS", + "DNS": "DNS", + "EOF": "EOF", + "ETA": "ETA", + "FBI": "FBI", + "GPU": "GPU", + "GRPC": "gRPC", + "GUID": "GUID", + "GRAPHQL": "GraphQL", + "HTML": "HTML", + "HTTP": "HTTP", + "HTTPS": "HTTPS", + "ID": "ID", + "IP": "IP", + "IRS": "IRS", + "JAVASCRIPT": "JavaScript", + "JSON": "JSON", + "LHS": "LHS", + "NSA": "NSA", + "OAUTH": "OAuth", + "OPENID": "OpenID", + "OS": "OS", + "QPS": "QPS", + "RAM": "RAM", + "RHS": "RHS", + "RPC": "RPC", + "SLA": "SLA", + "SMTP": "SMTP", + "SQL": "SQL", + "SSH": "SSH", + "TCP": "TCP", + "TLS": "TLS", + "TTL": "TTL", + "UDP": "UDP", + "UI": "UI", + "UID": "UID", + "URI": "URI", + "URL": "URL", + "UTF8": "UTF8", + "UTF16": "UTF16", + "UTF32": "UTF32", + "UUID": "UUID", + "VM": "VM", + "VR": "VR", + "XML": "XML", + "XMPP": "XMPP", + "XSRF": "XSRF", + "XSS": "XSS", +} + +func CamelCase(s string) (r string) { + return DelimiterCase(s, "", "Force", true) +} + +func CamelCoderCase(s string) (r string) { + return DelimiterCase(s, "", "Coder", true) +} + +func capitalize(s string) (r string) { + for _, word := range strings.Fields(s) { + r = r + " " + capitalizeWord(word) + } + return r[1:] +} + +func capitalizeWord(w string) string { + upper := strings.ToUpper(w) + if word, ok := commonInitialismsAndOddballs[upper]; ok == true { + return word + } + word := strings.ToLower(w) + word = strings.Title(word) + return word +} + +func DelimiterCase(s, d, m string, f bool) (r string) { + r = PreprocessString(s) + + switch strings.ToLower(m) { + case "coder": + r = capitalize(r) + case "force": + r = strings.ToLower(r) + r = strings.Title(r) + case "lower": + r = strings.ToLower(r) + case "smart": + r = titlecase.Convert(r) + case "title": + r = strings.Title(r) + case "upper": + r = strings.ToUpper(r) + default: + e := fmt.Errorf("Unknown mode: %q", m) + // fmt.Printf("ERROR: %s\n", e.Error()) + panic(e.Error()) + return r + } + + if f { + r = fmt.Sprintf("%s%s", strings.ToLower(r[0:1]), r[1:]) + } + + r = strings.ReplaceAll(r, " ", d) + + return r +} + +func DotCoderCase(s string) (r string) { + return DelimiterCase(s, ".", "Coder", false) +} + +func DotLowerCase(s string) (r string) { + return DelimiterCase(s, ".", "lower", false) +} + +func DotForceCase(s string) (r string) { + return DelimiterCase(s, ".", "Force", false) +} + +func DotTitleCase(s string) (r string) { + return DelimiterCase(s, ".", "Title", false) +} + +func DotSmartCase(s string) (r string) { + return DelimiterCase(s, ".", "Smart", false) +} + +func DotUpperCase(s string) (r string) { + return DelimiterCase(s, ".", "UPPER", false) +} + +func KebabCoderCase(s string) (r string) { + return DelimiterCase(s, "-", "Coder", false) +} + +func KebabCase(s string) (r string) { + return DelimiterCase(s, "-", "lower", false) +} + +func KebabForceCase(s string) (r string) { + return DelimiterCase(s, "-", "Force", false) +} + +func KebabTitleCase(s string) (r string) { + return DelimiterCase(s, "-", "Title", false) +} + +func KebabSmartCase(s string) (r string) { + return DelimiterCase(s, "-", "Smart", false) +} + +func KebabUpperCase(s string) (r string) { + return DelimiterCase(s, "-", "UPPER", false) +} + +func NoDelimiterCamelCase(s string) (r string) { + return CamelCase(s) +} + +func NoDelimiterCamelCoderCase(s string) (r string) { + return DelimiterCase(s, "", "Coder", true) +} + +func NoDelimiterLowerCase(s string) (r string) { + return DelimiterCase(s, "", "lower", true) +} + +func NoDelimiterPascalCase(s string) (r string) { + return PascalCase(s) +} + +func NoDelimiterUpperCase(s string) (r string) { + return DelimiterCase(s, "", "UPPER", false) +} + +func PascalCase(s string) (r string) { + return DelimiterCase(s, "", "Force", false) +} + +func PascalCoderCase(s string) (r string) { + return DelimiterCase(s, "", "Coder", false) +} + +func PreprocessString(s string) (r string) { + p := ' ' + + for _, c := range s { + r += Separatem(p, c) + p = c + } + + r = strings.TrimSpace(r) + + return spaceRE.ReplaceAllString(r, " ") +} + +/* +MEETS CRITERIA to continue with Diagnostic Evaluation--Sufficient Emotional/Behavioral Needs have been Identified Above +*/ + +// Separatem takes p (previous), and c (current) and compares them to determine how to separate them, if necessary. +func Separatem(p, c rune) (r string) { + // If p and c are different cases return them concatenated with a space between + // If c is a dot, hyphen, underscore, slash, colon, or semicolon then convert it to a space + // NOTE: Consider scenarios with other delimiters and where to handle them. Probably not here. + switch c { + case '.', '-', '_', '/', ':', ';', '=', '+', '*': + // Replace with space + // fmt.Printf("%q is a delimiter\n", c) + r = " " + case 0x27, ',', '(', ')', '[', ']', '{', '}', '<', '>': + // Drop + r = "" + case '&': + // Symbol to word + r = "and" + default: + if UseCodeBreak && unicode.IsLetter(p) && unicode.IsLetter(c) { + // if unicode.IsLower(p) && unicode.IsUpper(c) || unicode.IsUpper(p) && unicode.IsLower(c) { + if unicode.IsLower(p) && unicode.IsUpper(c) { + // fmt.Printf("%q and %q is are opposite case\n", p, c) + r = fmt.Sprintf(" %s", string(c)) + } else { + // fmt.Printf("%q is a letter\n", c) + r = string(c) + } + } else { + // fmt.Printf("%q or %q is not a letter\n", p, c) + r = string(c) + } + } + return r +} + +func SnakeCase(s string) (r string) { + return DelimiterCase(s, "_", "lower", false) +} + +func SnakeCoderCase(s string) (r string) { + return DelimiterCase(s, "_", "Coder", false) +} + +func SnakeForceCase(s string) (r string) { + return DelimiterCase(s, "_", "Force", false) +} + +func SnakeTitleCase(s string) (r string) { + return DelimiterCase(s, "_", "Title", false) +} + +func SnakeSmartCase(s string) (r string) { + return DelimiterCase(s, "_", "Smart", false) +} + +func SnakeUpperCase(s string) (r string) { + return DelimiterCase(s, "_", "UPPER", false) +} + +func SpaceCoderCase(s string) (r string) { + return DelimiterCase(s, " ", "Coder", false) +} + +func SpaceForceCase(s string) (r string) { + return DelimiterCase(s, " ", "Force", false) +} + +func SpaceLowerCase(s string) (r string) { + return DelimiterCase(s, " ", "lower", false) +} + +func SpaceTitleCase(s string) (r string) { + return DelimiterCase(s, " ", "Title", false) +} + +func SpaceSmartCase(s string) (r string) { + return DelimiterCase(s, " ", "Smart", false) +} + +func SpaceUpperCase(s string) (r string) { + r = PreprocessString(s) + return strings.ToUpper(r) +} diff --git a/cmd/caseit/main.go b/cmd/caseit/main.go new file mode 100644 index 0000000..dc61568 --- /dev/null +++ b/cmd/caseit/main.go @@ -0,0 +1,527 @@ +package main + +import ( + "fmt" + "os" + + "github.com/runeimp/caseit" + + arg "github.com/alexflint/go-arg" +) + +/* + * CONSTANTS + */ +const ( + AppDesc = "Processes input string(s) providing conversion to almost any code standard desired, including proper title casing." + AppName = "CaseIt" + AppAbbreviation = "CI" + AppVerMajor = 1 + AppVerMinor = 0 + AppVerPatch = 0 + AppVerPre = "" + CLIName = "caseit" +) + +/* + * DERIVED CONSTANTS AS VARIABLES + */ +var ( + AppVersion = fmt.Sprintf("%d.%d.%d%s", AppVerMajor, AppVerMinor, AppVerPatch, AppVerPre) + AppMeta = AppMetaData{ + CLI: CLIName, + Desc: AppDesc, + Label: fmt.Sprintf("%s v%s", AppName, AppVersion), + Name: AppName, + Version: AppVersion, + VerMajor: AppVerMajor, + VerMinor: AppVerMinor, + VerPatch: AppVerPatch, + } + falsePointer = &[]bool{false}[0] + truePointer = &[]bool{true}[0] +) + +/* + * TYPES + */ +type ( + // AppMetaData defines meta-data about an application + AppMetaData struct { + CLI string + Desc string + Label string + Name string + VerMajor uint + VerMinor uint + VerPatch uint + VerPre string + Version string + } + + AllCMD struct { + Input []string `arg:"positional" help:"The input string(s) to process"` + All bool `arg:"-a" help:"Use all options. This is the default."` + Camel bool `arg:"-C" help:"camelCase - Commonly used in Perl, JavaScript, and many other languages for variables and functions. Also for private properties in Go."` + Force bool `arg:"-f" help:"Forced Title Case - Words in all caps will be forced to initial letter upper and the rest lower."` + Lower bool `arg:"-l" help:"lower case - Commonly used for most of a sentence."` + Title bool `arg:"-t" help:"Title Case - Words that are all caps are left all caps."` + Coder bool `arg:"-c" help:"Coder Title Case - Words that are common initialisms are properly cased for the initialism. Otherwise force title cased."` + Smart bool `arg:"-s" help:"Smart Title Case - Uses code based on Python Titlecase which is smart about small words, etc."` + Pascal bool `arg:"-p" help:"PascalCase - Words in all caps will be forced to initial letter upper and the rest lower. Common in Pascal and for public properties in Go."` + Upper bool `arg:"-u" help:"UPPER CASE - Commonly used for movie titles."` + } + + CamelCMD struct { + Input []string `arg:"positional" help:"The input string(s) to process"` + All bool `arg:"-a" help:"Use all options"` + Force bool `arg:"-f" help:"Forced TitleNodilCase - Words in all caps will be forced to initial letter upper and the rest lower."` + Lower bool `arg:"-l" help:"titlenodilcase - Commonly used for environment variables."` + Camel *bool `arg:"-C" help:"camelCase - Commonly used in Perl, JavaScript, and many other languages for variables and functions. Also for private properties in Go. This is the default."` + Title bool `arg:"-t" help:"TitleNodilCase - Words that are all caps are left all caps."` + Coder bool `arg:"-c" help:"Coder TitleNodilCase - Words that are common initialisms are properly cased for the initialism. Otherwise force title cased."` + Pascal bool `arg:"-p" help:"PascalCase - Words in all caps will be forced to initial letter upper and the rest lower. Common in Pascal and for public properties in Go."` + Smart bool `arg:"-s" help:"Smart TitleNodilCase - Uses code based on Python Titlecase which is smart about small words, etc."` + Upper bool `arg:"-u" help:"TITLENODILCASE - Commonly used for environment variables."` + } + + DelimitedCMD struct { + Input []string `arg:"positional" help:"The input string(s) to process"` + Delimiter string `arg:"-d" default:"*" help:"The delimiter to use between words` + All bool `arg:"-a" help:"Use all options"` + Force bool `arg:"-f" help:"Forced Title*Kebab*Case - Words in all caps will be forced to initial letter upper and the rest lower."` + Lower bool `arg:"-l" help:"lower*kebab*case - Commonly used for CSS class names and file names on POSIX systems. This is the default."` + Title bool `arg:"-t" help:"Title*Kebab*Case - Words that are all caps are left all caps."` + Coder bool `arg:"-c" help:"Coder Title*Kebab*Case - Words that are common initialisms are properly cased for the initialism. Otherwise force title cased."` + Smart bool `arg:"-s" help:"Smart Title*Kebab*Case - Uses code based on Python Titlecase which is smart about small words, etc."` + Upper bool `arg:"-u" help:"UPPER*KEBAB*CASE - Commonly used for important file names on POSIX systems?"` + } + + DotCMD struct { + Input []string `arg:"positional" help:"The input string(s) to process"` + All bool `arg:"-a" help:"Use all options"` + Force bool `arg:"-f" help:"Forced Title.Dot.Case - Words in all caps will be forced to initial letter upper and the rest lower."` + Lower bool `arg:"-l" help:"lower.dot.case - Commonly to JavaScript and JSON dot notation."` + Title bool `arg:"-t" help:"Title.Dot.Case - Words that are all caps are left all caps."` + Coder bool `arg:"-c" help:"Coder Title.Dot.Case - Words that are common initialisms are properly cased for the initialism. Otherwise force title cased."` + Smart bool `arg:"-s" help:"Smart Title.Dot.Case - Uses code based on Python Titlecase which is smart about small words, etc."` + Upper bool `arg:"-u" help:"UPPER.DOT.CASE - Commonly used for ...?"` + } + + KebabCMD struct { + Input []string `arg:"positional" help:"The input string(s) to process"` + All bool `arg:"-a" help:"Use all options"` + Force bool `arg:"-f" help:"Forced Title-Kebab-Case - Words in all caps will be forced to initial letter upper and the rest lower."` + Lower bool `arg:"-l" help:"lower-kebab-case - Commonly used for CSS class names and file names on POSIX systems. This is the default."` + Title bool `arg:"-t" help:"Title-Kebab-Case - Words that are all caps are left all caps."` + Coder bool `arg:"-c" help:"Coder Title-Kebab-Case - Words that are common initialisms are properly cased for the initialism. Otherwise force title cased."` + Smart bool `arg:"-s" help:"Smart Title-Kebab-Case - Uses code based on Python Titlecase which is smart about small words, etc."` + Upper bool `arg:"-u" help:"UPPER-KEBAB-CASE - Commonly used for important file names on POSIX systems?"` + } + + SnakeCMD struct { + Input []string `arg:"positional" help:"The input string(s) to process"` + All bool `arg:"-a" help:"Use all options"` + Force bool `arg:"-f" help:"Forced Title_Snake_Case - Words in all caps will be forced to initial letter upper and the rest lower. Commonly used for database names."` + Lower bool `arg:"-l" help:"Python's traditional_snake_case. This is the default."` + Title bool `arg:"-t" help:"Title_Snake_Case - Words that are all caps are left all caps. Commonly used for database names."` + Coder bool `arg:"-c" help:"Coder Title_Snake_Case - Words that are common initialisms are properly cased for the initialism. Otherwise force title cased. Commonly used for database names."` + Smart bool `arg:"-s" help:"Smart Title_Snake_Case - Uses code based on Python Titlecase which is smart about small words, etc. Commonly used for database names."` + Upper bool `arg:"-u" help:"UPPER_SNAKE_CASE or CONSTANTS_CASE in many languages."` + } + + SpaceCMD struct { + Input []string `arg:"positional" help:"The input string(s) to process"` + All bool `arg:"-a" help:"Use all options"` + Force bool `arg:"-f" help:"Forced Title Case - Words in all caps will be forced to initial letter upper and the rest lower."` + Lower bool `arg:"-l" help:"lower case - Commonly used for most of a sentence."` + Title bool `arg:"-t" help:"Title Case - Words that are all caps are left all caps."` + Coder bool `arg:"-c" help:"Coder Title Case - Words that are common initialisms are properly cased for the initialism. Otherwise force title cased."` + Smart bool `arg:"-s" help:"Smart Title Case - Uses code based on Python Titlecase which is smart about small words, etc. This is the default."` + Upper bool `arg:"-u" help:"UPPER CASE - Commonly used for movie titles."` + } + + appArgs struct { + AllCMD *AllCMD `arg:"subcommand:all" help:"All commands used"` + Camel *CamelCMD `arg:"subcommand:camel" help:"Words are not separated by a delimiter"` + Char *DelimitedCMD `arg:"subcommand:char" help:"Character specified separated words"` + Dot *DotCMD `arg:"subcommand:dot" help:"Dot separated words"` + Kebab *KebabCMD `arg:"subcommand:kebab" help:"Hyphen separated words"` + Snake *SnakeCMD `arg:"subcommand:snake" help:"Underscore separated words"` + Word *SpaceCMD `arg:"subcommand:word" help:"Space separated words"` + } +) + +func (appArgs) Description() string { + return AppMeta.Desc +} + +func (appArgs) Version() string { + return AppMeta.Label +} + +/* + * LOCAL FUNCTIONS + */ + +func rangeAllCase(subCMD *AllCMD, inputList []string, delimiter string, firstWordLower bool) { + // fmt.Printf("rangeAllCase() | subCMD = %#v\n", subCMD) + for _, input := range inputList { + if subCMD.All || subCMD.Lower { + fmt.Printf(" lower: %s\n", caseit.DelimiterCase(input, delimiter, "lower", firstWordLower)) + } + if delimiter == "" && (subCMD.All || subCMD.Camel) { + fmt.Printf(" camel: %s\n", caseit.CamelCase(input)) + // fmt.Printf(" Camel: %s\n", caseit.DelimiterCase(input, delimiter, "Force", true)) + } + if subCMD.All || subCMD.Force { + fmt.Printf(" Force: %s\n", caseit.DelimiterCase(input, delimiter, "Force", firstWordLower)) + } + if subCMD.All || subCMD.Title { + fmt.Printf(" Title: %s\n", caseit.DelimiterCase(input, delimiter, "Title", firstWordLower)) + } + if subCMD.All || subCMD.Coder { + fmt.Printf(" Coder: %s\n", caseit.DelimiterCase(input, delimiter, "Coder", firstWordLower)) + } + if subCMD.All || subCMD.Smart { + fmt.Printf(" Smart: %s\n", caseit.DelimiterCase(input, delimiter, "Smart", firstWordLower)) + } + if delimiter == "" && (subCMD.All || subCMD.Pascal) { + fmt.Printf("Pascal: %s\n", caseit.PascalCase(input)) + // fmt.Printf("Pascal: %s\n", caseit.DelimiterCase(input, delimiter, "Smart", firstWordLower)) + } + if subCMD.All || subCMD.Upper { + fmt.Printf(" UPPER: %s\n", caseit.DelimiterCase(input, delimiter, "UPPER", firstWordLower)) + } + fmt.Println() + } +} + +func rangeCamelCase(subCMD *CamelCMD, inputList []string) { + fmt.Println(" CamelCase:") + delimiter := "" + firstWordLower := false + for _, input := range inputList { + if subCMD.All || subCMD.Lower { + fmt.Printf(" lower: %s\n", caseit.DelimiterCase(input, delimiter, "lower", firstWordLower)) + } + // fmt.Printf("rangeCamelCase() | subCMD.Camel = %#v | truePointer = %#v\n", subCMD.Camel, truePointer) + if subCMD.All || subCMD.Camel != nil && subCMD.Camel == truePointer { + fmt.Printf(" camel: %s\n", caseit.CamelCase(input)) + } + if subCMD.All || subCMD.Force { + fmt.Printf(" Force: %s\n", caseit.DelimiterCase(input, delimiter, "Force", firstWordLower)) + } + if subCMD.All || subCMD.Title { + fmt.Printf(" Title: %s\n", caseit.DelimiterCase(input, delimiter, "Title", firstWordLower)) + } + if subCMD.All || subCMD.Coder { + fmt.Printf(" Coder: %s\n", caseit.DelimiterCase(input, delimiter, "Coder", firstWordLower)) + } + if subCMD.All || subCMD.Smart { + fmt.Printf(" Smart: %s\n", caseit.DelimiterCase(input, delimiter, "Smart", firstWordLower)) + } + if subCMD.All || subCMD.Pascal { + fmt.Printf("Pascal: %s\n", caseit.PascalCase(input)) + } + if subCMD.All || subCMD.Upper { + fmt.Printf(" UPPER: %s\n", caseit.DelimiterCase(input, delimiter, "UPPER", firstWordLower)) + } + fmt.Println() + } +} + +func rangeDelimitedCase(subCMD *DelimitedCMD, inputList []string, delimiter string, firstWordLower bool) { + // fmt.Printf("rangeAllCase() | subCMD = %#v\n", subCMD) + for _, input := range inputList { + if subCMD.All || subCMD.Lower { + fmt.Printf(" lower: %s\n", caseit.DelimiterCase(input, delimiter, "lower", firstWordLower)) + } + // if delimiter == "" && (subCMD.All || subCMD.Camel) { + // fmt.Printf(" camel: %s\n", caseit.CamelCase(input)) + // // fmt.Printf(" Camel: %s\n", caseit.DelimiterCase(input, delimiter, "Force", true)) + // } + if subCMD.All || subCMD.Force { + fmt.Printf(" Force: %s\n", caseit.DelimiterCase(input, delimiter, "Force", firstWordLower)) + } + if subCMD.All || subCMD.Title { + fmt.Printf(" Title: %s\n", caseit.DelimiterCase(input, delimiter, "Title", firstWordLower)) + } + if subCMD.All || subCMD.Coder { + fmt.Printf(" Coder: %s\n", caseit.DelimiterCase(input, delimiter, "Coder", firstWordLower)) + } + if subCMD.All || subCMD.Smart { + fmt.Printf(" Smart: %s\n", caseit.DelimiterCase(input, delimiter, "Smart", firstWordLower)) + } + // if delimiter == "" && (subCMD.All || subCMD.Pascal) { + // fmt.Printf("Pascal: %s\n", caseit.PascalCase(input)) + // // fmt.Printf("Pascal: %s\n", caseit.DelimiterCase(input, delimiter, "Smart", firstWordLower)) + // } + if subCMD.All || subCMD.Upper { + fmt.Printf(" UPPER: %s\n", caseit.DelimiterCase(input, delimiter, "UPPER", firstWordLower)) + } + fmt.Println() + } +} + +func rangeDotCase(subCMD *DotCMD, inputList []string) { + fmt.Println(" dot.case:") + for _, input := range inputList { + if subCMD.All || subCMD.Lower { + fmt.Printf(" lower: %s\n", caseit.DotLowerCase(input)) + } + if subCMD.All || subCMD.Force { + fmt.Printf(" Force: %s\n", caseit.DotForceCase(input)) + } + if subCMD.All || subCMD.Title { + fmt.Printf(" Title: %s\n", caseit.DotTitleCase(input)) + } + if subCMD.All || subCMD.Coder { + fmt.Printf(" Coder: %s\n", caseit.DotCoderCase(input)) + } + if subCMD.All || subCMD.Smart { + fmt.Printf(" Smart: %s\n", caseit.DotSmartCase(input)) + } + if subCMD.All || subCMD.Upper { + fmt.Printf(" UPPER: %s\n", caseit.DotUpperCase(input)) + } + fmt.Println() + } +} + +func rangeKebabCase(subCMD *KebabCMD, inputList []string) { + fmt.Println(" kebab-case:") + for _, input := range inputList { + if subCMD.All || subCMD.Lower { + fmt.Printf(" lower: %s\n", caseit.KebabCase(input)) + } + if subCMD.All || subCMD.Force { + fmt.Printf(" Force: %s\n", caseit.KebabForceCase(input)) + } + if subCMD.All || subCMD.Title { + fmt.Printf(" Title: %s\n", caseit.KebabTitleCase(input)) + } + if subCMD.All || subCMD.Coder { + fmt.Printf(" Coder: %s\n", caseit.KebabCoderCase(input)) + } + if subCMD.All || subCMD.Smart { + fmt.Printf(" Smart: %s\n", caseit.KebabSmartCase(input)) + } + if subCMD.All || subCMD.Upper { + fmt.Printf(" UPPER: %s\n", caseit.KebabUpperCase(input)) + } + fmt.Println() + } +} + +func rangeSnakeCase(subCMD *SnakeCMD, inputList []string) { + fmt.Println(" snake_case:") + for _, input := range inputList { + if subCMD.All || subCMD.Lower { + fmt.Printf(" lower: %s\n", caseit.SnakeCase(input)) + } + if subCMD.All || subCMD.Force { + fmt.Printf(" Force: %s\n", caseit.SnakeForceCase(input)) + } + if subCMD.All || subCMD.Title { + fmt.Printf(" Title: %s\n", caseit.SnakeTitleCase(input)) + } + if subCMD.All || subCMD.Coder { + fmt.Printf(" Coder: %s\n", caseit.SnakeCoderCase(input)) + } + if subCMD.All || subCMD.Smart { + fmt.Printf(" Smart: %s\n", caseit.SnakeSmartCase(input)) + } + if subCMD.All || subCMD.Upper { + fmt.Printf(" UPPER: %s\n", caseit.SnakeUpperCase(input)) + } + fmt.Println() + } +} + +func rangeSpaceCase(subCMD *SpaceCMD, inputList []string) { + fmt.Println(" Word Case:") + for _, input := range inputList { + if subCMD.All || subCMD.Lower { + fmt.Printf(" lower: %s\n", caseit.SpaceLowerCase(input)) + } + if subCMD.All || subCMD.Force { + fmt.Printf(" Force: %s\n", caseit.SpaceForceCase(input)) + } + if subCMD.All || subCMD.Title { + fmt.Printf(" Title: %s\n", caseit.SpaceTitleCase(input)) + } + if subCMD.All || subCMD.Coder { + fmt.Printf(" Coder: %s\n", caseit.SpaceCoderCase(input)) + } + if subCMD.All || subCMD.Smart { + fmt.Printf(" Smart: %s\n", caseit.SpaceSmartCase(input)) + } + if subCMD.All || subCMD.Upper { + fmt.Printf(" UPPER: %s\n", caseit.SpaceUpperCase(input)) + } + fmt.Println() + } +} + +func showSource(src []string) { + if len(src) > 0 { + fmt.Printf("Source: %q\n", src[0]) + } + for i, input := range src { + if i > 0 { + fmt.Printf(" %q\n", input) + } + } +} + +/* + * THE MAIN ENTRY POINT + */ + +func main() { + args := appArgs{} + p := arg.MustParse(&args) + + if len(os.Args) == 1 { + p.WriteHelp(os.Stdout) + os.Exit(0) + } + + /* + * Handling CLI Argument Defaults + */ + if args.AllCMD != nil { + if args.AllCMD.All == false && args.AllCMD.Force == false && args.AllCMD.Lower == false && + args.AllCMD.Title == false && args.AllCMD.Coder == false && args.AllCMD.Pascal == false && + args.AllCMD.Smart == false && args.AllCMD.Upper == false { + args.AllCMD.All = true + } + } + if args.Camel != nil { + // fmt.Printf("main() | args.Camel.Camel = %#v | truePointer = %#v\n", args.Camel.Camel, truePointer) + // Since args.Camel.Camel is now *bool it will always either be nil or *true + if args.Camel.Camel == nil { + if args.Camel.All == false && args.Camel.Force == false && args.Camel.Lower == false && + args.Camel.Title == false && args.Camel.Coder == false && args.Camel.Pascal == false && + args.Camel.Smart == false && args.Camel.Upper == false { + args.Camel.Camel = truePointer + } else { + args.Camel.Camel = falsePointer + } + } else { + args.Camel.Camel = truePointer + } + // fmt.Printf("main() | args.Camel.Camel = %#v | truePointer = %#v\n", args.Camel.Camel, truePointer) + } + + if args.Char != nil { + if args.Char.All == false && args.Char.Force == false && args.Char.Lower == false && args.Char.Title == false && + args.Char.Coder == false && args.Char.Smart == false && args.Char.Upper == false { + args.Char.Coder = true // NOTE: Maybe this shouldn't be defaulted? + } + } + + if args.Dot != nil { + if args.Dot.All == false && args.Dot.Force == false && args.Dot.Lower == false && args.Dot.Title == false && + args.Dot.Coder == false && args.Dot.Smart == false && args.Dot.Upper == false { + args.Dot.Coder = true // NOTE: Maybe this shouldn't be defaulted? Seems like camelCase is missing and should be the default. + } + } + + if args.Kebab != nil { + if args.Kebab.All == false && args.Kebab.Force == false && args.Kebab.Lower == false && args.Kebab.Title == false && + args.Kebab.Coder == false && args.Kebab.Smart == false && args.Kebab.Upper == false { + args.Kebab.Lower = true + } + } + + if args.Snake != nil { + if args.Snake.All == false && args.Snake.Force == false && args.Snake.Lower == false && args.Snake.Title == false && + args.Snake.Coder == false && args.Snake.Smart == false && args.Snake.Upper == false { + args.Snake.Lower = true + } + } + + if args.Word != nil { + if args.Word.All == false && args.Word.Force == false && args.Word.Lower == false && args.Word.Title == false && + args.Word.Coder == false && args.Word.Smart == false && args.Word.Upper == false { + args.Word.Coder = true // NOTE: Maybe this shouldn't be defaulted? + } + } + + /* + * Handling The CLI Arguments + */ + if args.AllCMD != nil { + // fmt.Printf("main() | subCMD = %#v\n", args.AllCMD) + showSource(args.AllCMD.Input) + } + + if args.AllCMD != nil || args.Camel != nil { + if args.AllCMD == nil { + showSource(args.Camel.Input) + rangeCamelCase(args.Camel, args.Camel.Input) + } else { + fmt.Println(" CamelCase:") + firstWordLower := false + rangeAllCase(args.AllCMD, args.AllCMD.Input, "", firstWordLower) + } + } + + if args.AllCMD != nil || args.Char != nil { + if args.AllCMD == nil { + showSource(args.Char.Input) + firstWordLower := false + rangeDelimitedCase(args.Char, args.Char.Input, args.Char.Delimiter, firstWordLower) + } else { + fmt.Println(" char*case:") + firstWordLower := false + rangeAllCase(args.AllCMD, args.AllCMD.Input, ".", firstWordLower) + } + } + + if args.AllCMD != nil || args.Dot != nil { + if args.AllCMD == nil { + showSource(args.Dot.Input) + rangeDotCase(args.Dot, args.Dot.Input) + } else { + fmt.Println(" dot.case:") + firstWordLower := false + rangeAllCase(args.AllCMD, args.AllCMD.Input, ".", firstWordLower) + } + } + + if args.AllCMD != nil || args.Kebab != nil { + if args.AllCMD == nil { + showSource(args.Kebab.Input) + rangeKebabCase(args.Kebab, args.Kebab.Input) + } else { + fmt.Println(" kebab-case:") + firstWordLower := false + rangeAllCase(args.AllCMD, args.AllCMD.Input, "-", firstWordLower) + } + } + + if args.AllCMD != nil || args.Snake != nil { + if args.AllCMD == nil { + showSource(args.Snake.Input) + rangeSnakeCase(args.Snake, args.Snake.Input) + } else { + fmt.Println(" snake_case:") + firstWordLower := false + rangeAllCase(args.AllCMD, args.AllCMD.Input, "_", firstWordLower) + } + } + + if args.AllCMD != nil || args.Word != nil { + if args.AllCMD == nil { + showSource(args.Word.Input) + rangeSpaceCase(args.Word, args.Word.Input) + } else { + fmt.Println(" Word Case:") + firstWordLower := false + rangeAllCase(args.AllCMD, args.AllCMD.Input, " ", firstWordLower) + } + } +} diff --git a/go.mod b/go.mod index 6b02a4f..2ff8472 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,8 @@ module github.com/runeimp/caseit go 1.13 + +require ( + github.com/alexflint/go-arg v1.2.0 + github.com/runeimp/titlecase v1.0.0 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..a8b9410 --- /dev/null +++ b/go.sum @@ -0,0 +1,12 @@ +github.com/alexflint/go-arg v1.2.0 h1:TOFkN8/Cn1VvbHhsCuYq+P6ol3P5FAmjKIqsk7D2U/Q= +github.com/alexflint/go-arg v1.2.0/go.mod h1:3Rj4baqzWaGGmZA2+bVTV8zQOZEjBQAPBnL5xLT+ftY= +github.com/alexflint/go-scalar v1.0.0 h1:NGupf1XV/Xb04wXskDFzS0KWOLH632W/EO4fAFi+A70= +github.com/alexflint/go-scalar v1.0.0/go.mod h1:GpHzbCOZXEKMEcygYQ5n/aa4Aq84zbxjy3MxYW0gjYw= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/runeimp/titlecase v1.0.0 h1:67I+ThiC5X1+fTFSieMAZopXwPbPHwRK5Vz+/+evNZs= +github.com/runeimp/titlecase v1.0.0/go.mod h1:k1Ubp4rljC27xFRR/9xUqc4Tokt1OfFsoz4lwNv8Uyw= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=