pax_global_header00006660000000000000000000000064140623653030014514gustar00rootroot0000000000000052 comment=cc5b89279644a3672ff0fd4c3629b834396cb6d2 flect-0.2.3/000077500000000000000000000000001406236530300126135ustar00rootroot00000000000000flect-0.2.3/.github/000077500000000000000000000000001406236530300141535ustar00rootroot00000000000000flect-0.2.3/.github/FUNDING.yml000066400000000000000000000001221406236530300157630ustar00rootroot00000000000000# These are supported funding model platforms github: markbates patreon: buffalo flect-0.2.3/.github/workflows/000077500000000000000000000000001406236530300162105ustar00rootroot00000000000000flect-0.2.3/.github/workflows/tests.yml000066400000000000000000000007361406236530300201030ustar00rootroot00000000000000name: Tests on: push: branches: - master pull_request: jobs: tests-on: name: ${{matrix.go-version}} ${{matrix.os}} runs-on: ${{ matrix.os }} strategy: matrix: go-version: [1.14.x, 1.15.x] os: [macos-latest, windows-latest, ubuntu-latest] steps: - name: Checkout Code uses: actions/checkout@v1 with: fetch-depth: 1 - name: Test run: | go mod tidy -v go test -race ./... flect-0.2.3/.gitignore000066400000000000000000000003761406236530300146110ustar00rootroot00000000000000*.log .DS_Store doc tmp pkg *.gem *.pid coverage coverage.data build/* *.pbxuser *.mode1v3 .svn profile .console_history .sass-cache/* .rake_tasks~ *.log.lck solr/ .jhw-cache/ jhw.* *.sublime* node_modules/ dist/ generated/ .vendor/ bin/* gin-bin .idea/ flect-0.2.3/.gometalinter.json000066400000000000000000000002221406236530300162520ustar00rootroot00000000000000{ "Enable": ["vet", "golint", "goimports", "deadcode", "gotype", "ineffassign", "misspell", "nakedret", "unconvert", "megacheck", "varcheck"] } flect-0.2.3/LICENSE000066400000000000000000000020651406236530300136230ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2019 Mark Bates 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. flect-0.2.3/Makefile000066400000000000000000000016011406236530300142510ustar00rootroot00000000000000TAGS ?= "" GO_BIN ?= "go" install: $(GO_BIN) install -tags ${TAGS} -v . make tidy tidy: ifeq ($(GO111MODULE),on) $(GO_BIN) mod tidy else echo skipping go mod tidy endif deps: $(GO_BIN) get -tags ${TAGS} -t ./... make tidy build: $(GO_BIN) build -v . make tidy test: $(GO_BIN) test -cover -tags ${TAGS} ./... make tidy ci-deps: $(GO_BIN) get -tags ${TAGS} -t ./... ci-test: $(GO_BIN) test -tags ${TAGS} -race ./... lint: go get github.com/golangci/golangci-lint/cmd/golangci-lint golangci-lint run --enable-all make tidy update: ifeq ($(GO111MODULE),on) rm go.* $(GO_BIN) mod init $(GO_BIN) mod tidy else $(GO_BIN) get -u -tags ${TAGS} endif make test make install make tidy release-test: $(GO_BIN) test -tags ${TAGS} -race ./... make tidy release: $(GO_BIN) get github.com/gobuffalo/release make tidy release -y -f version.go --skip-packr make tidy flect-0.2.3/README.md000066400000000000000000000037671406236530300141070ustar00rootroot00000000000000# Flect

GoDoc CI Go Report Card

This is a new inflection engine to replace [https://github.com/markbates/inflect](https://github.com/markbates/inflect) designed to be more modular, more readable, and easier to fix issues on than the original. ## Installation ```bash $ go get -u -v github.com/gobuffalo/flect ``` ## `github.com/gobuffalo/flect` GoDoc The `github.com/gobuffalo/flect` package contains "basic" inflection tools, like pluralization, singularization, etc... ### The `Ident` Type In addition to helpful methods that take in a `string` and return a `string`, there is an `Ident` type that can be used to create new, custom, inflection rules. The `Ident` type contains two fields. * `Original` - This is the original `string` that was used to create the `Ident` * `Parts` - This is a `[]string` that represents all of the "parts" of the string, that have been split apart, making the segments easier to work with Examples of creating new inflection rules using `Ident` can be found in the `github.com/gobuffalo/flect/name` package. ## `github.com/gobuffalo/flect/name` GoDoc The `github.com/gobuffalo/flect/name` package contains more "business" inflection rules like creating proper names, table names, etc... flect-0.2.3/SHOULDERS.md000066400000000000000000000011131406236530300145010ustar00rootroot00000000000000# github.com/gobuffalo/flect Stands on the Shoulders of Giants github.com/gobuffalo/flect does not try to reinvent the wheel! Instead, it uses the already great wheels developed by the Go community and puts them all together in the best way possible. Without these giants, this project would not be possible. Please make sure to check them out and thank them for all of their hard work. Thank you to the following **GIANTS**: * [github.com/davecgh/go-spew](https://godoc.org/github.com/davecgh/go-spew) * [github.com/stretchr/testify](https://godoc.org/github.com/stretchr/testify) flect-0.2.3/acronyms.go000066400000000000000000000045501406236530300150010ustar00rootroot00000000000000package flect import "sync" var acronymsMoot = &sync.RWMutex{} var baseAcronyms = map[string]bool{ "OK": true, "UTF8": true, "HTML": true, "JSON": true, "JWT": true, "ID": true, "UUID": true, "SQL": true, "ACK": true, "ACL": true, "ADSL": true, "AES": true, "ANSI": true, "API": true, "ARP": true, "ATM": true, "BGP": true, "BSS": true, "CCITT": true, "CHAP": true, "CIDR": true, "CIR": true, "CLI": true, "CPE": true, "CPU": true, "CRC": true, "CRT": true, "CSMA": true, "CMOS": true, "DCE": true, "DEC": true, "DES": true, "DHCP": true, "DNS": true, "DRAM": true, "DSL": true, "DSLAM": true, "DTE": true, "DMI": true, "EHA": true, "EIA": true, "EIGRP": true, "EOF": true, "ESS": true, "FCC": true, "FCS": true, "FDDI": true, "FTP": true, "GBIC": true, "gbps": true, "GEPOF": true, "HDLC": true, "HTTP": true, "HTTPS": true, "IANA": true, "ICMP": true, "IDF": true, "IDS": true, "IEEE": true, "IETF": true, "IMAP": true, "IP": true, "IPS": true, "ISDN": true, "ISP": true, "kbps": true, "LACP": true, "LAN": true, "LAPB": true, "LAPF": true, "LLC": true, "MAC": true, "Mbps": true, "MC": true, "MDF": true, "MIB": true, "MoCA": true, "MPLS": true, "MTU": true, "NAC": true, "NAT": true, "NBMA": true, "NIC": true, "NRZ": true, "NRZI": true, "NVRAM": true, "OSI": true, "OSPF": true, "OUI": true, "PAP": true, "PAT": true, "PC": true, "PIM": true, "PCM": true, "PDU": true, "POP3": true, "POTS": true, "PPP": true, "PPTP": true, "PTT": true, "PVST": true, "RAM": true, "RARP": true, "RFC": true, "RIP": true, "RLL": true, "ROM": true, "RSTP": true, "RTP": true, "RCP": true, "SDLC": true, "SFD": true, "SFP": true, "SLARP": true, "SLIP": true, "SMTP": true, "SNA": true, "SNAP": true, "SNMP": true, "SOF": true, "SRAM": true, "SSH": true, "SSID": true, "STP": true, "SYN": true, "TDM": true, "TFTP": true, "TIA": true, "TOFU": true, "UDP": true, "URL": true, "URI": true, "USB": true, "UTP": true, "VC": true, "VLAN": true, "VLSM": true, "VPN": true, "W3C": true, "WAN": true, "WEP": true, "WiFi": true, "WPA": true, "WWW": true, } flect-0.2.3/camelize.go000066400000000000000000000016231406236530300147350ustar00rootroot00000000000000package flect import ( "strings" "unicode" ) // Camelize returns a camelize version of a string // bob dylan = bobDylan // widget_id = widgetID // WidgetID = widgetID func Camelize(s string) string { return New(s).Camelize().String() } // Camelize returns a camelize version of a string // bob dylan = bobDylan // widget_id = widgetID // WidgetID = widgetID func (i Ident) Camelize() Ident { var out []string for i, part := range i.Parts { var x string var capped bool if strings.ToLower(part) == "id" { out = append(out, "ID") continue } for _, c := range part { if unicode.IsLetter(c) || unicode.IsDigit(c) { if i == 0 { x += string(unicode.ToLower(c)) continue } if !capped { capped = true x += string(unicode.ToUpper(c)) continue } x += string(c) } } if x != "" { out = append(out, x) } } return New(strings.Join(out, "")) } flect-0.2.3/camelize_test.go000066400000000000000000000015751406236530300160020ustar00rootroot00000000000000package flect import ( "testing" "github.com/stretchr/testify/require" ) func Test_Camelize(t *testing.T) { table := []tt{ {"", ""}, {"bob dylan", "bobDylan"}, {"widgetID", "widgetID"}, {"widget_ID", "widgetID"}, {"Widget_ID", "widgetID"}, {"Widget_Id", "widgetID"}, {"Widget_id", "widgetID"}, {"Nice to see you!", "niceToSeeYou"}, {"*hello*", "hello"}, {"i've read a book! have you?", "iveReadABookHaveYou"}, {"This is `code` ok", "thisIsCodeOK"}, {"foo_bar", "fooBar"}, {"admin/widget", "adminWidget"}, {"widget", "widget"}, {"widgets", "widgets"}, {"status", "status"}, {"Statuses", "statuses"}, {"statuses", "statuses"}, {"People", "people"}, {"people", "people"}, } for _, tt := range table { t.Run(tt.act, func(st *testing.T) { r := require.New(st) r.Equal(tt.exp, Camelize(tt.act)) r.Equal(tt.exp, Camelize(tt.exp)) }) } } flect-0.2.3/capitalize.go000066400000000000000000000010021406236530300152600ustar00rootroot00000000000000package flect import "unicode" // Capitalize will cap the first letter of string // user = User // bob dylan = Bob dylan // widget_id = Widget_id func Capitalize(s string) string { return New(s).Capitalize().String() } // Capitalize will cap the first letter of string // user = User // bob dylan = Bob dylan // widget_id = Widget_id func (i Ident) Capitalize() Ident { if len(i.Parts) == 0 { return New("") } runes := []rune(i.Original) runes[0] = unicode.ToTitle(runes[0]) return New(string(runes)) } flect-0.2.3/capitalize_test.go000066400000000000000000000010511406236530300163230ustar00rootroot00000000000000package flect import ( "testing" "github.com/stretchr/testify/require" ) func Test_Capitalize(t *testing.T) { table := []tt{ {"", ""}, {"foo", "Foo"}, {"bob dylan", "Bob dylan"}, {"WidgetID", "WidgetID"}, {"widget_id", "Widget_id"}, {"widget_ID", "Widget_ID"}, {"widget ID", "Widget ID"}, {"гофер", "Гофер"}, // it's "gopher" in Ukrainian } for _, tt := range table { t.Run(tt.act, func(st *testing.T) { r := require.New(st) r.Equal(tt.exp, Capitalize(tt.act)) r.Equal(tt.exp, Capitalize(tt.exp)) }) } } flect-0.2.3/custom_data.go000066400000000000000000000033231406236530300154460ustar00rootroot00000000000000package flect import ( "bytes" "encoding/json" "fmt" "io" "io/ioutil" "os" "path/filepath" ) func init() { loadCustomData("inflections.json", "INFLECT_PATH", "could not read inflection file", LoadInflections) loadCustomData("acronyms.json", "ACRONYMS_PATH", "could not read acronyms file", LoadAcronyms) } //CustomDataParser are functions that parse data like acronyms or //plurals in the shape of a io.Reader it receives. type CustomDataParser func(io.Reader) error func loadCustomData(defaultFile, env, readErrorMessage string, parser CustomDataParser) { pwd, _ := os.Getwd() path, found := os.LookupEnv(env) if !found { path = filepath.Join(pwd, defaultFile) } if _, err := os.Stat(path); err != nil { return } b, err := ioutil.ReadFile(path) if err != nil { fmt.Printf("%s %s (%s)\n", readErrorMessage, path, err) return } if err = parser(bytes.NewReader(b)); err != nil { fmt.Println(err) } } //LoadAcronyms loads rules from io.Reader param func LoadAcronyms(r io.Reader) error { m := []string{} err := json.NewDecoder(r).Decode(&m) if err != nil { return fmt.Errorf("could not decode acronyms JSON from reader: %s", err) } acronymsMoot.Lock() defer acronymsMoot.Unlock() for _, acronym := range m { baseAcronyms[acronym] = true } return nil } //LoadInflections loads rules from io.Reader param func LoadInflections(r io.Reader) error { m := map[string]string{} err := json.NewDecoder(r).Decode(&m) if err != nil { return fmt.Errorf("could not decode inflection JSON from reader: %s", err) } pluralMoot.Lock() defer pluralMoot.Unlock() singularMoot.Lock() defer singularMoot.Unlock() for s, p := range m { singleToPlural[s] = p pluralToSingle[p] = s } return nil } flect-0.2.3/dasherize.go000066400000000000000000000013751406236530300151260ustar00rootroot00000000000000package flect import ( "strings" "unicode" ) // Dasherize returns an alphanumeric, lowercased, dashed string // Donald E. Knuth = donald-e-knuth // Test with + sign = test-with-sign // admin/WidgetID = admin-widget-id func Dasherize(s string) string { return New(s).Dasherize().String() } // Dasherize returns an alphanumeric, lowercased, dashed string // Donald E. Knuth = donald-e-knuth // Test with + sign = test-with-sign // admin/WidgetID = admin-widget-id func (i Ident) Dasherize() Ident { var parts []string for _, part := range i.Parts { var x string for _, c := range part { if unicode.IsLetter(c) || unicode.IsDigit(c) { x += string(c) } } parts = xappend(parts, x) } return New(strings.ToLower(strings.Join(parts, "-"))) } flect-0.2.3/dasherize_test.go000066400000000000000000000013671406236530300161660ustar00rootroot00000000000000package flect import ( "testing" "github.com/stretchr/testify/require" ) func Test_Dasherize(t *testing.T) { table := []tt{ {"", ""}, {"admin/WidgetID", "admin-widget-id"}, {"Donald E. Knuth", "donald-e-knuth"}, {"Random text with *(bad)* characters", "random-text-with-bad-characters"}, {"Trailing bad characters!@#", "trailing-bad-characters"}, {"!@#Leading bad characters", "leading-bad-characters"}, {"Squeeze separators", "squeeze-separators"}, {"Test with + sign", "test-with-sign"}, {"Test with malformed utf8 \251", "test-with-malformed-utf8"}, } for _, tt := range table { t.Run(tt.act, func(st *testing.T) { r := require.New(st) r.Equal(tt.exp, Dasherize(tt.act)) r.Equal(tt.exp, Dasherize(tt.exp)) }) } } flect-0.2.3/flect.go000066400000000000000000000014521406236530300142410ustar00rootroot00000000000000/* Package flect is a new inflection engine to replace [https://github.com/markbates/inflect](https://github.com/markbates/inflect) designed to be more modular, more readable, and easier to fix issues on than the original. */ package flect import ( "strings" "unicode" ) var spaces = []rune{'_', ' ', ':', '-', '/'} func isSpace(c rune) bool { for _, r := range spaces { if r == c { return true } } return unicode.IsSpace(c) } func xappend(a []string, ss ...string) []string { for _, s := range ss { s = strings.TrimSpace(s) for _, x := range spaces { s = strings.Trim(s, string(x)) } if _, ok := baseAcronyms[strings.ToUpper(s)]; ok { s = strings.ToUpper(s) } if s != "" { a = append(a, s) } } return a } func abs(x int) int { if x < 0 { return -x } return x } flect-0.2.3/flect_test.go000066400000000000000000000107041406236530300153000ustar00rootroot00000000000000package flect import ( "bytes" "encoding/json" "testing" "github.com/stretchr/testify/require" ) type tt struct { act string exp string } func Test_LoadInflections(t *testing.T) { r := require.New(t) m := map[string]string{ "beatle": "the beatles", "xyz": "zyx", } b, err := json.Marshal(m) r.NoError(err) r.NoError(LoadInflections(bytes.NewReader(b))) for k, v := range m { r.Equal(v, Pluralize(k)) r.Equal(v, Pluralize(v)) r.Equal(k, Singularize(k)) r.Equal(k, Singularize(v)) } } func Test_LoadAcronyms(t *testing.T) { r := require.New(t) m := []string{ "ACC", "TLC", "LSA", } b, err := json.Marshal(m) r.NoError(err) r.NoError(LoadAcronyms(bytes.NewReader(b))) for _, acronym := range m { r.True(baseAcronyms[acronym]) } } var singlePluralAssertions = []tt{ {"", ""}, {"ability", "abilities"}, {"address", "addresses"}, {"agency", "agencies"}, {"alias", "aliases"}, {"analysis", "analyses"}, {"archive", "archives"}, {"axis", "axes"}, {"basis", "bases"}, {"belief", "beliefs"}, {"blitz", "blitzes"}, {"box", "boxes"}, {"boy", "boys"}, {"buffalo", "buffaloes"}, {"bus", "buses"}, {"cactus", "cacti"}, {"case", "cases"}, {"cat", "cats"}, {"category", "categories"}, {"chef", "chefs"}, {"chief", "chiefs"}, {"child", "children"}, {"circus", "circuses"}, {"city", "cities"}, {"comment", "comments"}, {"crisis", "crises"}, {"criterion", "criteria"}, {"custom_field", "custom_fields"}, {"database", "databases"}, {"datum", "data"}, {"day", "days"}, {"dear", "dears"}, {"deer", "deer"}, {"device", "devices"}, {"diagnosis_a", "diagnosis_as"}, {"diagnosis", "diagnoses"}, {"dwarf", "dwarves"}, {"edge", "edges"}, {"elf", "elves"}, {"ellipsis", "ellipses"}, {"equipment", "equipment"}, {"experience", "experiences"}, {"fez", "fezzes"}, {"field", "fields"}, {"fish", "fish"}, {"fix", "fixes"}, {"focus", "foci"}, {"foobar", "foobars"}, {"foot", "feet"}, {"fox", "foxes"}, {"funky jeans", "funky jeans"}, {"fuse", "fuses"}, {"goose", "geese"}, {"great_person", "great_people"}, {"half", "halves"}, {"halo", "halos"}, {"horse", "horses"}, {"house", "houses"}, {"human", "humans"}, {"index", "indices"}, {"information", "information"}, {"jeans", "jeans"}, {"louse", "lice"}, {"lunch", "lunches"}, {"marsh", "marshes"}, {"matrix", "matrices"}, {"media", "media"}, {"mouse", "mice"}, {"move", "moves"}, {"movie", "movies"}, {"news", "news"}, {"newsletter", "newsletters"}, {"node_child", "node_children"}, {"octopus", "octopi"}, {"ovum", "ova"}, {"ox", "oxen"}, {"payment_information", "payment_information"}, {"person", "people"}, {"perspective", "perspectives"}, {"phenomenon", "phenomena"}, {"photo", "photos"}, {"piano", "pianos"}, {"plus", "pluses"}, {"portfolio", "portfolios"}, {"potato", "potatoes"}, {"prize", "prizes"}, {"process", "processes"}, {"prometheus", "prometheuses"}, {"puppy", "puppies"}, {"query", "queries"}, {"quiz", "quizzes"}, {"ray", "rays"}, {"rice", "rice"}, {"roof", "roofs"}, {"safe", "saves"}, {"salesperson", "salespeople"}, {"search", "searches"}, {"series", "series"}, {"service", "services"}, {"sheep", "sheep"}, {"shoe", "shoes"}, {"species", "species"}, {"spokesman", "spokesmen"}, {"sportsEquipment", "sportsEquipment"}, {"spouse", "spouses"}, {"stack", "stacks"}, {"stadium", "stadia"}, {"status_code", "status_codes"}, {"status", "statuses"}, {"Status", "Statuses"}, {"switch", "switches"}, {"tax", "taxes"}, {"testis", "testes"}, {"tomato", "tomatoes"}, {"tooth", "teeth"}, {"truss", "trusses"}, {"user", "users"}, {"vedalia", "vedalias"}, {"virus", "viri"}, {"wife", "wives"}, {"wish", "wishes"}, {"wolf", "wolves"}, {"woman", "women"}, } var pluralSingularAssertions = []tt{} func init() { for k, v := range singleToPlural { singlePluralAssertions = append(singlePluralAssertions, tt{k, v}) // add some variations // singlePluralAssertions = append(singlePluralAssertions, tt{strings.ToUpper(k), v}) // singlePluralAssertions = append(singlePluralAssertions, tt{strings.ToLower(k), v}) // for i, x := range k { // n := k[:i] + strings.ToLower(string(x)) + k[i+1:] // singlePluralAssertions = append(singlePluralAssertions, tt{n, v}) // // n = k[:i] + strings.ToUpper(string(x)) + k[i+1:] // singlePluralAssertions = append(singlePluralAssertions, tt{n, v}) // } } for _, a := range singlePluralAssertions { pluralSingularAssertions = append(pluralSingularAssertions, tt{act: a.exp, exp: a.act}) } } flect-0.2.3/go.mod000066400000000000000000000001271406236530300137210ustar00rootroot00000000000000module github.com/gobuffalo/flect go 1.13 require github.com/stretchr/testify v1.4.0 flect-0.2.3/go.sum000066400000000000000000000017101406236530300137450ustar00rootroot00000000000000github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= flect-0.2.3/humanize.go000066400000000000000000000013671406236530300147710ustar00rootroot00000000000000package flect import ( "strings" ) // Humanize returns first letter of sentence capitalized. // Common acronyms are capitalized as well. // Other capital letters in string are left as provided. // employee_salary = Employee salary // employee_id = employee ID // employee_mobile_number = Employee mobile number // first_Name = First Name // firstName = First Name func Humanize(s string) string { return New(s).Humanize().String() } // Humanize First letter of sentence capitalized func (i Ident) Humanize() Ident { if len(i.Original) == 0 { return New("") } var parts []string for index, part := range i.Parts { if index == 0 { part = strings.Title(i.Parts[0]) } parts = xappend(parts, part) } return New(strings.Join(parts, " ")) } flect-0.2.3/humanize_test.go000066400000000000000000000011261406236530300160210ustar00rootroot00000000000000package flect import ( "testing" "github.com/stretchr/testify/require" ) func Test_Humanize(t *testing.T) { table := []tt{ {"", ""}, {"IBM", "IBM"}, {"employee_mobile_number", "Employee mobile number"}, {"employee_salary", "Employee salary"}, {"employee_id", "Employee ID"}, {"employee_ID", "Employee ID"}, {"first_name", "First name"}, {"first_Name", "First Name"}, {"firstName", "First Name"}, } for _, tt := range table { t.Run(tt.act, func(st *testing.T) { r := require.New(st) r.Equal(tt.exp, Humanize(tt.act)) r.Equal(tt.exp, Humanize(tt.exp)) }) } } flect-0.2.3/ident.go000066400000000000000000000055731406236530300142570ustar00rootroot00000000000000package flect import ( "encoding" "strings" "unicode" "unicode/utf8" ) // Ident represents the string and it's parts type Ident struct { Original string Parts []string } // String implements fmt.Stringer and returns the original string func (i Ident) String() string { return i.Original } // New creates a new Ident from the string func New(s string) Ident { i := Ident{ Original: s, Parts: toParts(s), } return i } func toParts(s string) []string { parts := []string{} s = strings.TrimSpace(s) if len(s) == 0 { return parts } if _, ok := baseAcronyms[strings.ToUpper(s)]; ok { return []string{strings.ToUpper(s)} } var prev rune var x strings.Builder x.Grow(len(s)) for _, c := range s { // fmt.Println("### cs ->", cs) // fmt.Println("### unicode.IsControl(c) ->", unicode.IsControl(c)) // fmt.Println("### unicode.IsDigit(c) ->", unicode.IsDigit(c)) // fmt.Println("### unicode.IsGraphic(c) ->", unicode.IsGraphic(c)) // fmt.Println("### unicode.IsLetter(c) ->", unicode.IsLetter(c)) // fmt.Println("### unicode.IsLower(c) ->", unicode.IsLower(c)) // fmt.Println("### unicode.IsMark(c) ->", unicode.IsMark(c)) // fmt.Println("### unicode.IsPrint(c) ->", unicode.IsPrint(c)) // fmt.Println("### unicode.IsPunct(c) ->", unicode.IsPunct(c)) // fmt.Println("### unicode.IsSpace(c) ->", unicode.IsSpace(c)) // fmt.Println("### unicode.IsTitle(c) ->", unicode.IsTitle(c)) // fmt.Println("### unicode.IsUpper(c) ->", unicode.IsUpper(c)) if !utf8.ValidRune(c) { continue } if isSpace(c) { parts = xappend(parts, x.String()) x.Reset() x.WriteRune(c) prev = c continue } if unicode.IsUpper(c) && !unicode.IsUpper(prev) { parts = xappend(parts, x.String()) x.Reset() x.WriteRune(c) prev = c continue } if unicode.IsUpper(c) && baseAcronyms[strings.ToUpper(x.String())] { parts = xappend(parts, x.String()) x.Reset() x.WriteRune(c) prev = c continue } if unicode.IsLetter(c) || unicode.IsDigit(c) || unicode.IsPunct(c) || c == '`' { prev = c x.WriteRune(c) continue } parts = xappend(parts, x.String()) x.Reset() prev = c } parts = xappend(parts, x.String()) return parts } var _ encoding.TextUnmarshaler = &Ident{} var _ encoding.TextMarshaler = &Ident{} // LastPart returns the last part/word of the original string func (i *Ident) LastPart() string { if len(i.Parts) == 0 { return "" } return i.Parts[len(i.Parts)-1] } // ReplaceSuffix creates a new Ident with the original suffix replaced by new func (i Ident) ReplaceSuffix(orig, new string) Ident { return New(strings.TrimSuffix(i.Original, orig) + new) } //UnmarshalText unmarshalls byte array into the Ident func (i *Ident) UnmarshalText(data []byte) error { (*i) = New(string(data)) return nil } //MarshalText marshals Ident into byte array func (i Ident) MarshalText() ([]byte, error) { return []byte(i.Original), nil } flect-0.2.3/ident_test.go000066400000000000000000000053031406236530300153050ustar00rootroot00000000000000package flect import ( "testing" "github.com/stretchr/testify/require" ) func Test_New(t *testing.T) { table := []Ident{ {"", []string{}}, {"widget", []string{"widget"}}, {"widget_id", []string{"widget", "ID"}}, {"WidgetID", []string{"Widget", "ID"}}, {"Widget_ID", []string{"Widget", "ID"}}, {"widget_ID", []string{"widget", "ID"}}, {"widget/ID", []string{"widget", "ID"}}, {"widgetID", []string{"widget", "ID"}}, {"widgetName", []string{"widget", "Name"}}, {"JWTName", []string{"JWT", "Name"}}, {"JWTname", []string{"JWTname"}}, {"jwtname", []string{"jwtname"}}, {"sql", []string{"SQL"}}, {"sQl", []string{"SQL"}}, {"id", []string{"ID"}}, {"Id", []string{"ID"}}, {"iD", []string{"ID"}}, {"html", []string{"HTML"}}, {"Html", []string{"HTML"}}, {"HTML", []string{"HTML"}}, {"with `code` inside", []string{"with", "`code`", "inside"}}, {"Donald E. Knuth", []string{"Donald", "E.", "Knuth"}}, {"Random text with *(bad)* characters", []string{"Random", "text", "with", "*(bad)*", "characters"}}, {"Allow_Under_Scores", []string{"Allow", "Under", "Scores"}}, {"Trailing bad characters!@#", []string{"Trailing", "bad", "characters!@#"}}, {"!@#Leading bad characters", []string{"!@#", "Leading", "bad", "characters"}}, {"Squeeze separators", []string{"Squeeze", "separators"}}, {"Test with + sign", []string{"Test", "with", "sign"}}, {"Malmö", []string{"Malmö"}}, {"Garçons", []string{"Garçons"}}, {"Opsů", []string{"Opsů"}}, {"Ærøskøbing", []string{"Ærøskøbing"}}, {"Aßlar", []string{"Aßlar"}}, {"Japanese: 日本語", []string{"Japanese", "日本語"}}, } for _, tt := range table { t.Run(tt.Original, func(st *testing.T) { r := require.New(st) i := New(tt.Original) r.Equal(tt.Original, i.Original) r.Equal(tt.Parts, i.Parts) }) } } func Test_MarshalText(t *testing.T) { r := require.New(t) n := New("mark") b, err := n.MarshalText() r.NoError(err) r.Equal("mark", string(b)) r.NoError((&n).UnmarshalText([]byte("bates"))) r.Equal("bates", n.String()) } func Benchmark_New(b *testing.B) { table := []string{ "", "widget", "widget_id", "WidgetID", "Widget_ID", "widget_ID", "widget/ID", "widgetID", "widgetName", "JWTName", "JWTname", "jwtname", "sql", "sQl", "id", "Id", "iD", "html", "Html", "HTML", "with `code` inside", "Donald E. Knuth", "Random text with *(bad)* characters", "Allow_Under_Scores", "Trailing bad characters!@#", "!@#Leading bad characters", "Squeeze separators", "Test with + sign", "Malmö", "Garçons", "Opsů", "Ærøskøbing", "Aßlar", "Japanese: 日本語", } for n := 0; n < b.N; n++ { for i := range table { New(table[i]) } } } flect-0.2.3/lower_upper.go000066400000000000000000000004461406236530300155110ustar00rootroot00000000000000package flect import "strings" // ToUpper is a convience wrapper for strings.ToUpper func (i Ident) ToUpper() Ident { return New(strings.ToUpper(i.Original)) } // ToLower is a convience wrapper for strings.ToLower func (i Ident) ToLower() Ident { return New(strings.ToLower(i.Original)) } flect-0.2.3/lower_upper_test.go000066400000000000000000000000161406236530300165410ustar00rootroot00000000000000package flect flect-0.2.3/name/000077500000000000000000000000001406236530300135335ustar00rootroot00000000000000flect-0.2.3/name/char.go000066400000000000000000000006541406236530300150040ustar00rootroot00000000000000package name import "unicode" // Char returns the first letter, lowered // "" = "x" // "foo" = "f" // "123d456" = "d" func Char(s string) string { return New(s).Char().String() } // Char returns the first letter, lowered // "" = "x" // "foo" = "f" // "123d456" = "d" func (i Ident) Char() Ident { for _, c := range i.Original { if unicode.IsLetter(c) { return New(string(unicode.ToLower(c))) } } return New("x") } flect-0.2.3/name/char_test.go000066400000000000000000000006121406236530300160350ustar00rootroot00000000000000package name import ( "testing" "github.com/stretchr/testify/require" ) func Test_Char(t *testing.T) { table := []tt{ {"", "x"}, {"foo_bar", "f"}, {"admin/widget", "a"}, {"123d4545", "d"}, {"!@#$%^&*", "x"}, } for _, tt := range table { t.Run(tt.act, func(st *testing.T) { r := require.New(st) r.Equal(tt.exp, Char(tt.act)) r.Equal(tt.exp, Char(tt.exp)) }) } } flect-0.2.3/name/file.go000066400000000000000000000011321406236530300147760ustar00rootroot00000000000000package name import ( "strings" "github.com/gobuffalo/flect" ) // File creates a suitable file name // admin/widget = admin/widget // foo_bar = foo_bar // U$ser = u_ser func File(s string, exts ...string) string { return New(s).File(exts...).String() } // File creates a suitable file name // admin/widget = admin/widget // foo_bar = foo_bar // U$ser = u_ser func (i Ident) File(exts ...string) Ident { var parts []string for _, part := range strings.Split(i.Original, "/") { parts = append(parts, flect.Underscore(part)) } return New(strings.Join(parts, "/") + strings.Join(exts, "")) } flect-0.2.3/name/file_test.go000066400000000000000000000010441406236530300160370ustar00rootroot00000000000000package name import ( "testing" "github.com/stretchr/testify/require" ) func Test_File(t *testing.T) { table := []tt{ {"", ""}, {"foo_bar", "foo_bar"}, {"admin/widget", "admin/widget"}, {"admin/widgets", "admin/widgets"}, {"widget", "widget"}, {"widgets", "widgets"}, {"User", "user"}, {"U$er", "u_er"}, } for _, tt := range table { t.Run(tt.act, func(st *testing.T) { r := require.New(st) r.Equal(tt.exp, File(tt.act)) r.Equal(tt.exp, File(tt.exp)) r.Equal(tt.exp+".a.b", File(tt.act, ".a", ".b")) }) } } flect-0.2.3/name/folder.go000066400000000000000000000014701406236530300153370ustar00rootroot00000000000000package name import ( "regexp" "strings" ) var alphanum = regexp.MustCompile(`[^a-zA-Z0-9_\-\/]+`) // Folder creates a suitable folder name // admin/widget = admin/widget // foo_bar = foo_bar // U$ser = u_ser func Folder(s string, exts ...string) string { return New(s).Folder(exts...).String() } // Folder creates a suitable folder name // admin/widget = admin/widget // foo_bar = foo/bar // U$ser = u/ser func (i Ident) Folder(exts ...string) Ident { var parts []string s := i.Original if i.Pascalize().String() == s { s = i.Underscore().String() s = strings.Replace(s, "_", "/", -1) } for _, part := range strings.Split(s, "/") { part = strings.ToLower(part) part = alphanum.ReplaceAllString(part, "") parts = append(parts, part) } return New(strings.Join(parts, "/") + strings.Join(exts, "")) } flect-0.2.3/name/folder_test.go000066400000000000000000000011121406236530300163670ustar00rootroot00000000000000package name import ( "testing" "github.com/stretchr/testify/require" ) func Test_Folder(t *testing.T) { table := []tt{ {"", ""}, {"foo_bar", "foo_bar"}, {"admin/widget", "admin/widget"}, {"admin/widgets", "admin/widgets"}, {"widget", "widget"}, {"widgets", "widgets"}, {"User", "user"}, {"U$er", "uer"}, {"AdminUser", "admin/user"}, } for _, tt := range table { t.Run(tt.act, func(st *testing.T) { r := require.New(st) r.Equal(tt.exp, Folder(tt.act)) r.Equal(tt.exp, Folder(tt.exp)) r.Equal(tt.exp+".a.b", Folder(tt.act, ".a", ".b")) }) } } flect-0.2.3/name/ident.go000066400000000000000000000003511406236530300151640ustar00rootroot00000000000000package name import "github.com/gobuffalo/flect" // Ident represents the string and it's parts type Ident struct { flect.Ident } // New creates a new Ident from the string func New(s string) Ident { return Ident{flect.New(s)} } flect-0.2.3/name/interface.go000066400000000000000000000007721406236530300160300ustar00rootroot00000000000000package name import ( "fmt" "reflect" ) func Interface(x interface{}) (Ident, error) { switch t := x.(type) { case string: return New(t), nil default: rv := reflect.Indirect(reflect.ValueOf(x)) to := rv.Type() if len(to.Name()) > 0 { return New(to.Name()), nil } k := to.Kind() switch k { case reflect.Slice, reflect.Array: e := to.Elem() n := New(e.Name()) return New(n.Pluralize().String()), nil } } return New(""), fmt.Errorf("could not convert %T to Ident", x) } flect-0.2.3/name/interface_test.go000066400000000000000000000011021406236530300170530ustar00rootroot00000000000000package name import ( "fmt" "testing" "github.com/stretchr/testify/require" ) type car struct{} func Test_Interface(t *testing.T) { table := []struct { in interface{} out string err bool }{ {"foo", "foo", false}, {car{}, "car", false}, {&car{}, "car", false}, {[]car{}, "cars", false}, {false, "bool", false}, } for _, tt := range table { t.Run(fmt.Sprint(tt.in), func(st *testing.T) { r := require.New(st) n, err := Interface(tt.in) if tt.err { r.Error(err) return } r.NoError(err) r.Equal(tt.out, n.String()) }) } } flect-0.2.3/name/join.go000066400000000000000000000006201406236530300150170ustar00rootroot00000000000000package name import "path/filepath" func FilePathJoin(names ...string) string { var ni = make([]Ident, len(names)) for i, n := range names { ni[i] = New(n) } base := New("") return base.FilePathJoin(ni...).String() } func (i Ident) FilePathJoin(ni ...Ident) Ident { var s = make([]string, len(ni)) for i, n := range ni { s[i] = n.OsPath().String() } return New(filepath.Join(s...)) } flect-0.2.3/name/join_test.go000066400000000000000000000011751406236530300160640ustar00rootroot00000000000000package name import ( "runtime" "testing" "github.com/stretchr/testify/require" ) func Test_Ident_FilePathJoin(t *testing.T) { table := map[string]string{ "foo/bar/baz": "foo/bar/baz/boo", "foo\\bar\\baz": "foo/bar/baz/boo", } if runtime.GOOS == "windows" { table = ident_FilePathJoin_Windows_Table() } for in, out := range table { t.Run(in, func(st *testing.T) { r := require.New(st) r.Equal(out, FilePathJoin(in, "boo")) }) } } func ident_FilePathJoin_Windows_Table() map[string]string { return map[string]string{ "foo/bar/baz": "foo\\bar\\baz\\boo", "foo\\bar\\baz": "foo\\bar\\baz\\boo", } } flect-0.2.3/name/key.go000066400000000000000000000003221406236530300146470ustar00rootroot00000000000000package name import ( "strings" ) func Key(s string) string { return New(s).Key().String() } func (i Ident) Key() Ident { s := strings.Replace(i.String(), "\\", "/", -1) return New(strings.ToLower(s)) } flect-0.2.3/name/key_test.go000066400000000000000000000005211406236530300157070ustar00rootroot00000000000000package name import ( "testing" "github.com/stretchr/testify/require" ) func Test_Ident_Key(t *testing.T) { table := map[string]string{ "Foo/bar/baz": "foo/bar/baz", "Foo\\bar\\baz": "foo/bar/baz", } for in, out := range table { t.Run(in, func(st *testing.T) { r := require.New(st) r.Equal(out, Key(in)) }) } } flect-0.2.3/name/name.go000066400000000000000000000025221406236530300150030ustar00rootroot00000000000000package name import ( "encoding" "strings" "github.com/gobuffalo/flect" ) // Proper pascalizes and singularizes the string // person = Person // foo_bar = FooBar // admin/widgets = AdminWidget func Proper(s string) string { return New(s).Proper().String() } // Proper pascalizes and singularizes the string // person = Person // foo_bar = FooBar // admin/widgets = AdminWidget func (i Ident) Proper() Ident { return Ident{i.Singularize().Pascalize()} } // Group pascalizes and pluralizes the string // person = People // foo_bar = FooBars // admin/widget = AdminWidgets func Group(s string) string { return New(s).Group().String() } // Group pascalizes and pluralizes the string // person = People // foo_bar = FooBars // admin/widget = AdminWidgets func (i Ident) Group() Ident { var parts []string if len(i.Original) == 0 { return i } last := i.Parts[len(i.Parts)-1] for _, part := range i.Parts[:len(i.Parts)-1] { parts = append(parts, flect.Pascalize(part)) } last = New(last).Pluralize().Pascalize().String() parts = append(parts, last) return New(strings.Join(parts, "")) } var _ encoding.TextUnmarshaler = &Ident{} var _ encoding.TextMarshaler = &Ident{} func (i *Ident) UnmarshalText(data []byte) error { (*i) = New(string(data)) return nil } func (i Ident) MarshalText() ([]byte, error) { return []byte(i.Original), nil } flect-0.2.3/name/name_test.go000066400000000000000000000033421406236530300160430ustar00rootroot00000000000000package name import ( "testing" "github.com/stretchr/testify/require" ) type tt struct { act string exp string } func Test_Name(t *testing.T) { table := []tt{ {"", ""}, {"bob dylan", "BobDylan"}, {"widgetID", "WidgetID"}, {"widget_ID", "WidgetID"}, {"Widget_ID", "WidgetID"}, {"Widget_Id", "WidgetID"}, {"Widget_id", "WidgetID"}, {"Nice to see you today!", "NiceToSeeYouToday"}, {"*hello*", "Hello"}, {"i've read a book! have you read it?", "IveReadABookHaveYouReadIt"}, {"This is `code` ok", "ThisIsCodeOK"}, {"foo_bar", "FooBar"}, {"admin/widget", "AdminWidget"}, {"admin/widgets", "AdminWidget"}, {"widget", "Widget"}, {"widgets", "Widget"}, {"status", "Status"}, {"Statuses", "Status"}, {"statuses", "Status"}, {"People", "Person"}, {"people", "Person"}, } for _, tt := range table { t.Run(tt.act, func(st *testing.T) { r := require.New(st) r.Equal(tt.exp, Proper(tt.act)) r.Equal(tt.exp, Proper(tt.exp)) }) } } func Test_Group(t *testing.T) { table := []tt{ {"", ""}, {"Person", "People"}, {"foo_bar", "FooBars"}, {"admin/widget", "AdminWidgets"}, {"widget", "Widgets"}, {"widgets", "Widgets"}, {"greatPerson", "GreatPeople"}, {"great/person", "GreatPeople"}, {"status", "Statuses"}, {"Status", "Statuses"}, {"Statuses", "Statuses"}, {"statuses", "Statuses"}, } for _, tt := range table { t.Run(tt.act, func(st *testing.T) { r := require.New(st) r.Equal(tt.exp, Group(tt.act)) r.Equal(tt.exp, Group(tt.exp)) }) } } func Test_MarshalText(t *testing.T) { r := require.New(t) n := New("mark") b, err := n.MarshalText() r.NoError(err) r.Equal("mark", string(b)) r.NoError((&n).UnmarshalText([]byte("bates"))) r.Equal("bates", n.String()) } flect-0.2.3/name/os_path.go000066400000000000000000000005601406236530300155200ustar00rootroot00000000000000package name import ( "path/filepath" "runtime" "strings" ) func OsPath(s string) string { return New(s).OsPath().String() } func (i Ident) OsPath() Ident { s := i.String() if runtime.GOOS == "windows" { s = strings.Replace(s, "/", string(filepath.Separator), -1) } else { s = strings.Replace(s, "\\", string(filepath.Separator), -1) } return New(s) } flect-0.2.3/name/os_path_test.go000066400000000000000000000011141406236530300165530ustar00rootroot00000000000000package name import ( "runtime" "testing" "github.com/stretchr/testify/require" ) func Test_Ident_OsPath(t *testing.T) { table := map[string]string{ "foo/bar/baz": "foo/bar/baz", "foo\\bar\\baz": "foo/bar/baz", } if runtime.GOOS == "windows" { table = ident_OsPath_Windows_Table() } for in, out := range table { t.Run(in, func(st *testing.T) { r := require.New(st) r.Equal(out, OsPath(in)) }) } } func ident_OsPath_Windows_Table() map[string]string { return map[string]string{ "foo/bar/baz": "foo\\bar\\baz", "foo\\bar\\baz": "foo\\bar\\baz", } } flect-0.2.3/name/package.go000066400000000000000000000014721406236530300154610ustar00rootroot00000000000000package name import ( "go/build" "path/filepath" "strings" ) // Package will attempt to return a package version of the name // $GOPATH/src/foo/bar = foo/bar // $GOPATH\src\foo\bar = foo/bar // foo/bar = foo/bar func Package(s string) string { return New(s).Package().String() } // Package will attempt to return a package version of the name // $GOPATH/src/foo/bar = foo/bar // $GOPATH\src\foo\bar = foo/bar // foo/bar = foo/bar func (i Ident) Package() Ident { c := build.Default s := i.Original for _, src := range c.SrcDirs() { s = strings.TrimPrefix(s, src) s = strings.TrimPrefix(s, filepath.Dir(src)) // encase there's no /src prefix } s = strings.TrimPrefix(s, string(filepath.Separator)) s = strings.Replace(s, "\\", "/", -1) s = strings.Replace(s, "_", "", -1) return Ident{New(s).ToLower()} } flect-0.2.3/name/package_test.go000066400000000000000000000015571406236530300165240ustar00rootroot00000000000000package name import ( "go/build" "path/filepath" "testing" "github.com/stretchr/testify/require" ) func Test_Package(t *testing.T) { table := []tt{ {"Foo", "foo"}, {"Foo/Foo", "foo/foo"}, {"Foo_Foo", "foofoo"}, {"create_table", "createtable"}, {"admin/widget", "admin/widget"}, {"admin\\widget", "admin/widget"}, } c := build.Default for _, src := range c.SrcDirs() { adds := []tt{ {filepath.Join(src, "admin/widget"), "admin/widget"}, {filepath.Join(src, "admin\\widget"), "admin/widget"}, {filepath.Join(filepath.Dir(src), "admin/widget"), "admin/widget"}, {filepath.Join(filepath.Dir(src), "admin\\widget"), "admin/widget"}, } table = append(table, adds...) } for _, tt := range table { t.Run(tt.act, func(st *testing.T) { r := require.New(st) r.Equal(tt.exp, Package(tt.act)) r.Equal(tt.exp, Package(tt.exp)) }) } } flect-0.2.3/name/param_id.go000066400000000000000000000010371406236530300156370ustar00rootroot00000000000000package name import "strings" // ParamID returns the string as parameter with _id added // user = user_id // UserID = user_id // admin/widgets = admin_widgets_id func ParamID(s string) string { return New(s).ParamID().String() } // ParamID returns the string as parameter with _id added // user = user_id // UserID = user_id // admin/widgets = admin_widget_id func (i Ident) ParamID() Ident { s := i.Singularize().Underscore().String() s = strings.ToLower(s) if strings.HasSuffix(s, "_id") { return New(s) } return New(s + "_id") } flect-0.2.3/name/param_id_test.go000066400000000000000000000007751406236530300167060ustar00rootroot00000000000000package name import ( "testing" "github.com/stretchr/testify/require" ) func Test_ParamID(t *testing.T) { table := []tt{ {"foo_bar", "foo_bar_id"}, {"admin/widget", "admin_widget_id"}, {"admin/widgets", "admin_widget_id"}, {"widget", "widget_id"}, {"User", "user_id"}, {"user", "user_id"}, {"UserID", "user_id"}, } for _, tt := range table { t.Run(tt.act, func(st *testing.T) { r := require.New(st) r.Equal(tt.exp, ParamID(tt.act)) r.Equal(tt.exp, ParamID(tt.exp)) }) } } flect-0.2.3/name/resource.go000066400000000000000000000006271406236530300157160ustar00rootroot00000000000000package name import ( "strings" ) // Resource version of a name func (n Ident) Resource() Ident { name := n.Underscore().String() x := strings.FieldsFunc(name, func(r rune) bool { return r == '_' || r == '/' }) for i, w := range x { if i == len(x)-1 { x[i] = New(w).Pluralize().Pascalize().String() continue } x[i] = New(w).Pascalize().String() } return New(strings.Join(x, "")) } flect-0.2.3/name/resource_test.go000066400000000000000000000012101406236530300167420ustar00rootroot00000000000000package name import ( "testing" "github.com/stretchr/testify/require" ) func Test_Name_Resource(t *testing.T) { r := require.New(t) table := []struct { V string E string }{ {V: "Person", E: "People"}, {V: "foo_bar", E: "FooBars"}, {V: "admin/widget", E: "AdminWidgets"}, {V: "widget", E: "Widgets"}, {V: "widgets", E: "Widgets"}, {V: "greatPerson", E: "GreatPeople"}, {V: "great/person", E: "GreatPeople"}, {V: "status", E: "Statuses"}, {V: "Status", E: "Statuses"}, {V: "Statuses", E: "Statuses"}, {V: "statuses", E: "Statuses"}, } for _, tt := range table { r.Equal(tt.E, New(tt.V).Resource().String()) } } flect-0.2.3/name/tablize.go000066400000000000000000000006251406236530300155170ustar00rootroot00000000000000package name // Tableize returns an underscore, pluralized string // User = users // Person = persons // Admin/Widget = admin_widgets func Tableize(s string) string { return New(s).Tableize().String() } // Tableize returns an underscore, pluralized string // User = users // Person = persons // Admin/Widget = admin_widgets func (i Ident) Tableize() Ident { return Ident{i.Underscore().Pluralize()} } flect-0.2.3/name/tablize_test.go000066400000000000000000000014751406236530300165620ustar00rootroot00000000000000package name import ( "testing" "github.com/stretchr/testify/require" ) func Test_Tableize(t *testing.T) { table := []tt{ {"", ""}, {"bob dylan", "bob_dylans"}, {"Nice to see you!", "nice_to_see_you"}, {"*hello*", "hellos"}, {"i've read a book! have you?", "ive_read_a_book_have_you"}, {"This is `code` ok", "this_is_code_oks"}, {"foo_bar", "foo_bars"}, {"admin/widget", "admin_widgets"}, {"widget", "widgets"}, {"widgets", "widgets"}, {"status", "statuses"}, {"Statuses", "statuses"}, {"statuses", "statuses"}, {"People", "people"}, {"people", "people"}, {"BigPerson", "big_people"}, {"Wild Ox", "wild_oxen"}, } for _, tt := range table { t.Run(tt.act, func(st *testing.T) { r := require.New(st) r.Equal(tt.exp, Tableize(tt.act)) r.Equal(tt.exp, Tableize(tt.exp)) }) } } flect-0.2.3/name/url.go000066400000000000000000000001211406236530300146560ustar00rootroot00000000000000package name func (n Ident) URL() Ident { return Ident{n.File().Pluralize()} } flect-0.2.3/name/url_test.go000066400000000000000000000010061406236530300157200ustar00rootroot00000000000000package name import ( "testing" "github.com/stretchr/testify/require" ) func Test_URL(t *testing.T) { table := []struct { in string out string }{ {"User", "users"}, {"widget", "widgets"}, {"AdminUser", "admin_users"}, {"Admin/User", "admin/users"}, {"Admin/Users", "admin/users"}, {"/Admin/Users", "/admin/users"}, } for _, tt := range table { t.Run(tt.in, func(st *testing.T) { r := require.New(st) n := New(tt.in) r.Equal(tt.out, n.URL().String(), "URL of %v", tt.in) }) } } flect-0.2.3/name/var_case.go000066400000000000000000000021101406236530300156370ustar00rootroot00000000000000package name // VarCaseSingle version of a name. // foo_bar = fooBar // admin/widget = adminWidget // User = users func VarCaseSingle(s string) string { return New(s).VarCaseSingle().String() } // VarCaseSingle version of a name. // foo_bar = fooBar // admin/widget = adminWidget // User = users func (i Ident) VarCaseSingle() Ident { return Ident{i.Group().Singularize().Camelize()} } // VarCasePlural version of a name. // foo_bar = fooBars // admin/widget = adminWidgets // User = users func VarCasePlural(s string) string { return New(s).VarCasePlural().String() } // VarCasePlural version of a name. // foo_bar = fooBars // admin/widget = adminWidgets // User = users func (i Ident) VarCasePlural() Ident { return Ident{i.Group().Pluralize().Camelize()} } // VarCase version of a name. // foo_bar = fooBar // admin/widget = adminWidget // Users = users func (i Ident) VarCase() Ident { return Ident{i.Camelize()} } // VarCase version of a name. // foo_bar = fooBar // admin/widget = adminWidget // Users = users func VarCase(s string) string { return New(s).VarCase().String() } flect-0.2.3/name/var_case_test.go000066400000000000000000000030751406236530300167110ustar00rootroot00000000000000package name import ( "testing" "github.com/stretchr/testify/require" ) func Test_VarCaseSingle(t *testing.T) { table := []tt{ {"foo_bar", "fooBar"}, {"admin/widget", "adminWidget"}, {"widget", "widget"}, {"widgets", "widget"}, {"User", "user"}, {"FooBar", "fooBar"}, {"status", "status"}, {"statuses", "status"}, {"Status", "status"}, {"Statuses", "status"}, } for _, tt := range table { t.Run(tt.act, func(st *testing.T) { r := require.New(st) r.Equal(tt.exp, VarCaseSingle(tt.act)) r.Equal(tt.exp, VarCaseSingle(tt.exp)) }) } } func Test_VarCasePlural(t *testing.T) { table := []tt{ {"foo_bar", "fooBars"}, {"admin/widget", "adminWidgets"}, {"widget", "widgets"}, {"widgets", "widgets"}, {"User", "users"}, {"FooBar", "fooBars"}, {"status", "statuses"}, {"statuses", "statuses"}, {"Status", "statuses"}, {"Statuses", "statuses"}, } for _, tt := range table { t.Run(tt.act, func(st *testing.T) { r := require.New(st) r.Equal(tt.exp, VarCasePlural(tt.act)) r.Equal(tt.exp, VarCasePlural(tt.exp)) }) } } func Test_VarCase(t *testing.T) { table := []tt{ {"foo_bar", "fooBar"}, {"admin/widget", "adminWidget"}, {"widget", "widget"}, {"widgets", "widgets"}, {"User", "user"}, {"FooBar", "fooBar"}, {"FooBars", "fooBars"}, {"status", "status"}, {"statuses", "statuses"}, {"Status", "status"}, {"Statuses", "statuses"}, } for _, tt := range table { t.Run(tt.act, func(st *testing.T) { r := require.New(st) r.Equal(tt.exp, VarCase(tt.act)) r.Equal(tt.exp, VarCase(tt.exp)) }) } } flect-0.2.3/ordinalize.go000066400000000000000000000013701406236530300153030ustar00rootroot00000000000000package flect import ( "fmt" "strconv" ) // Ordinalize converts a number to an ordinal version // 42 = 42nd // 45 = 45th // 1 = 1st func Ordinalize(s string) string { return New(s).Ordinalize().String() } // Ordinalize converts a number to an ordinal version // 42 = 42nd // 45 = 45th // 1 = 1st func (i Ident) Ordinalize() Ident { number, err := strconv.Atoi(i.Original) if err != nil { return i } var s string switch abs(number) % 100 { case 11, 12, 13: s = fmt.Sprintf("%dth", number) default: switch abs(number) % 10 { case 1: s = fmt.Sprintf("%dst", number) case 2: s = fmt.Sprintf("%dnd", number) case 3: s = fmt.Sprintf("%drd", number) } } if s != "" { return New(s) } return New(fmt.Sprintf("%dth", number)) } flect-0.2.3/ordinalize_test.go000066400000000000000000000027151406236530300163460ustar00rootroot00000000000000package flect import ( "testing" "github.com/stretchr/testify/require" ) func Test_Ordinalize(t *testing.T) { table := []tt{ {"-1", "-1st"}, {"-2", "-2nd"}, {"-3", "-3rd"}, {"-4", "-4th"}, {"-5", "-5th"}, {"-6", "-6th"}, {"-7", "-7th"}, {"-8", "-8th"}, {"-9", "-9th"}, {"-10", "-10th"}, {"-11", "-11th"}, {"-12", "-12th"}, {"-13", "-13th"}, {"-14", "-14th"}, {"-20", "-20th"}, {"-21", "-21st"}, {"-22", "-22nd"}, {"-23", "-23rd"}, {"-24", "-24th"}, {"-100", "-100th"}, {"-101", "-101st"}, {"-102", "-102nd"}, {"-103", "-103rd"}, {"-104", "-104th"}, {"-110", "-110th"}, {"-111", "-111th"}, {"-112", "-112th"}, {"-113", "-113th"}, {"-1000", "-1000th"}, {"-1001", "-1001st"}, {"0", "0th"}, {"1", "1st"}, {"2", "2nd"}, {"3", "3rd"}, {"4", "4th"}, {"5", "5th"}, {"6", "6th"}, {"7", "7th"}, {"8", "8th"}, {"9", "9th"}, {"10", "10th"}, {"11", "11th"}, {"12", "12th"}, {"13", "13th"}, {"14", "14th"}, {"20", "20th"}, {"21", "21st"}, {"22", "22nd"}, {"23", "23rd"}, {"24", "24th"}, {"100", "100th"}, {"101", "101st"}, {"102", "102nd"}, {"103", "103rd"}, {"104", "104th"}, {"110", "110th"}, {"111", "111th"}, {"112", "112th"}, {"113", "113th"}, {"1000", "1000th"}, {"1001", "1001st"}, } for _, tt := range table { t.Run(tt.act, func(st *testing.T) { r := require.New(st) r.Equal(tt.exp, Ordinalize(tt.act)) r.Equal(tt.exp, Ordinalize(tt.exp)) }) } } flect-0.2.3/pascalize.go000066400000000000000000000010211406236530300151070ustar00rootroot00000000000000package flect import ( "unicode" ) // Pascalize returns a string with each segment capitalized // user = User // bob dylan = BobDylan // widget_id = WidgetID func Pascalize(s string) string { return New(s).Pascalize().String() } // Pascalize returns a string with each segment capitalized // user = User // bob dylan = BobDylan // widget_id = WidgetID func (i Ident) Pascalize() Ident { c := i.Camelize() if len(c.String()) == 0 { return c } return New(string(unicode.ToUpper(rune(c.Original[0]))) + c.Original[1:]) } flect-0.2.3/pascalize_test.go000066400000000000000000000011501406236530300161510ustar00rootroot00000000000000package flect import ( "testing" "github.com/stretchr/testify/require" ) func Test_Pascalize(t *testing.T) { table := []tt{ {"", ""}, {"bob dylan", "BobDylan"}, {"widgetID", "WidgetID"}, {"widget_ID", "WidgetID"}, {"Widget_ID", "WidgetID"}, {"Nice to see you!", "NiceToSeeYou"}, {"*hello*", "Hello"}, {"i've read a book! have you?", "IveReadABookHaveYou"}, {"This is `code` ok", "ThisIsCodeOK"}, {"id", "ID"}, } for _, tt := range table { t.Run(tt.act, func(st *testing.T) { r := require.New(st) r.Equal(tt.exp, Pascalize(tt.act)) r.Equal(tt.exp, Pascalize(tt.exp)) }) } } flect-0.2.3/plural_rules.go000066400000000000000000000143131406236530300156550ustar00rootroot00000000000000package flect var pluralRules = []rule{} // AddPlural adds a rule that will replace the given suffix with the replacement suffix. func AddPlural(suffix string, repl string) { pluralMoot.Lock() defer pluralMoot.Unlock() pluralRules = append(pluralRules, rule{ suffix: suffix, fn: func(s string) string { s = s[:len(s)-len(suffix)] return s + repl }, }) pluralRules = append(pluralRules, rule{ suffix: repl, fn: noop, }) } var singleToPlural = map[string]string{ "aircraft": "aircraft", "alias": "aliases", "alumna": "alumnae", "alumnus": "alumni", "analysis": "analyses", "antenna": "antennas", "antithesis": "antitheses", "apex": "apexes", "appendix": "appendices", "axis": "axes", "bacillus": "bacilli", "bacterium": "bacteria", "basis": "bases", "beau": "beaus", "bison": "bison", "bureau": "bureaus", "bus": "buses", "campus": "campuses", "caucus": "caucuses", "child": "children", "château": "châteaux", "circus": "circuses", "codex": "codices", "concerto": "concertos", "corpus": "corpora", "crisis": "crises", "curriculum": "curriculums", "datum": "data", "deer": "deer", "diagnosis": "diagnoses", "die": "dice", "dwarf": "dwarves", "ellipsis": "ellipses", "equipment": "equipment", "erratum": "errata", "faux pas": "faux pas", "fez": "fezzes", "fish": "fish", "focus": "foci", "foo": "foos", "foot": "feet", "formula": "formulas", "fungus": "fungi", "genus": "genera", "goose": "geese", "graffito": "graffiti", "grouse": "grouse", "half": "halves", "halo": "halos", "hoof": "hooves", "human": "humans", "hypothesis": "hypotheses", "index": "indices", "information": "information", "jeans": "jeans", "larva": "larvae", "libretto": "librettos", "loaf": "loaves", "locus": "loci", "louse": "lice", "matrix": "matrices", "minutia": "minutiae", "money": "money", "moose": "moose", "mouse": "mice", "nebula": "nebulae", "news": "news", "nucleus": "nuclei", "oasis": "oases", "octopus": "octopi", "offspring": "offspring", "opus": "opera", "ovum": "ova", "ox": "oxen", "parenthesis": "parentheses", "phenomenon": "phenomena", "photo": "photos", "phylum": "phyla", "piano": "pianos", "plus": "pluses", "police": "police", "prognosis": "prognoses", "prometheus": "prometheuses", "quiz": "quizzes", "quota": "quotas", "radius": "radiuses", "referendum": "referendums", "ress": "resses", "rice": "rice", "salmon": "salmon", "sex": "sexes", "series": "series", "sheep": "sheep", "shoe": "shoes", "shrimp": "shrimp", "species": "species", "stimulus": "stimuli", "stratum": "strata", "swine": "swine", "syllabus": "syllabi", "symposium": "symposiums", "synapse": "synapses", "synopsis": "synopses", "tableau": "tableaus", "testis": "testes", "thesis": "theses", "thief": "thieves", "tooth": "teeth", "trout": "trout", "tuna": "tuna", "vedalia": "vedalias", "vertebra": "vertebrae", "vertix": "vertices", "vita": "vitae", "vortex": "vortices", "wharf": "wharves", "wife": "wives", "woman": "women", "wolf": "wolves", "you": "you", } var pluralToSingle = map[string]string{} func init() { for k, v := range singleToPlural { pluralToSingle[v] = k } } type singularToPluralSuffix struct { singular string plural string } var singularToPluralSuffixList = []singularToPluralSuffix{ {"iterion", "iteria"}, {"campus", "campuses"}, {"genera", "genus"}, {"person", "people"}, {"phylum", "phyla"}, {"randum", "randa"}, {"actus", "acti"}, {"adium", "adia"}, {"basis", "basis"}, {"child", "children"}, {"chive", "chives"}, {"focus", "foci"}, {"hello", "hellos"}, {"jeans", "jeans"}, {"louse", "lice"}, {"media", "media"}, {"mouse", "mice"}, {"movie", "movies"}, {"oasis", "oasis"}, {"atum", "ata"}, {"atus", "atuses"}, {"base", "bases"}, {"cess", "cesses"}, {"dium", "diums"}, {"eses", "esis"}, {"half", "halves"}, {"hive", "hives"}, {"iano", "ianos"}, {"irus", "iri"}, {"isis", "ises"}, {"leus", "li"}, {"mnus", "mni"}, {"move", "moves"}, {"news", "news"}, {"odex", "odice"}, {"oose", "eese"}, {"ouse", "ouses"}, {"ovum", "ova"}, {"rion", "ria"}, {"shoe", "shoes"}, {"stis", "stes"}, {"tive", "tives"}, {"vice", "vices"}, {"wife", "wives"}, {"afe", "aves"}, {"bfe", "bves"}, {"box", "boxes"}, {"cfe", "cves"}, {"dfe", "dves"}, {"dge", "dges"}, {"efe", "eves"}, {"gfe", "gves"}, {"hfe", "hves"}, {"ife", "ives"}, {"itz", "itzes"}, {"ium", "ia"}, {"ize", "izes"}, {"jfe", "jves"}, {"kfe", "kves"}, {"man", "men"}, {"mfe", "mves"}, {"nfe", "nves"}, {"nna", "nnas"}, {"oaf", "oaves"}, {"oci", "ocus"}, {"ode", "odes"}, {"ofe", "oves"}, {"oot", "eet"}, {"pfe", "pves"}, {"pse", "psis"}, {"qfe", "qves"}, {"quy", "quies"}, {"rfe", "rves"}, {"sfe", "sves"}, {"tfe", "tves"}, {"tum", "ta"}, {"tus", "tuses"}, {"ufe", "uves"}, {"ula", "ulae"}, {"ula", "ulas"}, {"uli", "ulus"}, {"use", "uses"}, {"uss", "usses"}, {"vfe", "vves"}, {"wfe", "wves"}, {"xfe", "xves"}, {"yfe", "yves"}, {"you", "you"}, {"zfe", "zves"}, {"by", "bies"}, {"ch", "ches"}, {"cy", "cies"}, {"dy", "dies"}, {"ex", "ices"}, {"fy", "fies"}, {"gy", "gies"}, {"hy", "hies"}, {"io", "ios"}, {"jy", "jies"}, {"ky", "kies"}, {"lf", "lves"}, {"ly", "lies"}, {"my", "mies"}, {"ny", "nies"}, {"py", "pies"}, {"qy", "qies"}, {"rf", "rves"}, {"ry", "ries"}, {"sh", "shes"}, {"ss", "sses"}, {"sy", "sies"}, {"ty", "ties"}, {"tz", "tzes"}, {"va", "vae"}, {"vy", "vies"}, {"wy", "wies"}, {"xy", "xies"}, {"zy", "zies"}, {"zz", "zzes"}, {"o", "oes"}, {"x", "xes"}, } func init() { for _, suffix := range singularToPluralSuffixList { AddPlural(suffix.singular, suffix.plural) AddSingular(suffix.plural, suffix.singular) } } flect-0.2.3/pluralize.go000066400000000000000000000022141406236530300151500ustar00rootroot00000000000000package flect import ( "strings" "sync" ) var pluralMoot = &sync.RWMutex{} // Pluralize returns a plural version of the string // user = users // person = people // datum = data func Pluralize(s string) string { return New(s).Pluralize().String() } // PluralizeWithSize will pluralize a string taking a number number into account. // PluralizeWithSize("user", 1) = user // PluralizeWithSize("user", 2) = users func PluralizeWithSize(s string, i int) string { if i == 1 || i == -1 { return New(s).Singularize().String() } return New(s).Pluralize().String() } // Pluralize returns a plural version of the string // user = users // person = people // datum = data func (i Ident) Pluralize() Ident { s := i.LastPart() if len(s) == 0 { return New("") } pluralMoot.RLock() defer pluralMoot.RUnlock() ls := strings.ToLower(s) if _, ok := pluralToSingle[ls]; ok { return i } if p, ok := singleToPlural[ls]; ok { return i.ReplaceSuffix(s, p) } for _, r := range pluralRules { if strings.HasSuffix(ls, r.suffix) { return i.ReplaceSuffix(s, r.fn(s)) } } if strings.HasSuffix(ls, "s") { return i } return New(i.String() + "s") } flect-0.2.3/pluralize_test.go000066400000000000000000000017031406236530300162110ustar00rootroot00000000000000package flect import ( "testing" "github.com/stretchr/testify/require" ) func Test_Pluralize(t *testing.T) { for _, tt := range singlePluralAssertions { t.Run(tt.act, func(st *testing.T) { r := require.New(st) r.Equal(tt.exp, Pluralize(tt.act)) r.Equal(tt.exp, Pluralize(tt.exp)) }) } } func Test_PluralizeWithSize(t *testing.T) { for _, tt := range singlePluralAssertions { t.Run(tt.act, func(st *testing.T) { r := require.New(st) r.Equal(tt.exp, PluralizeWithSize(tt.act, -2)) r.Equal(tt.exp, PluralizeWithSize(tt.exp, -2)) r.Equal(tt.act, PluralizeWithSize(tt.act, -1)) r.Equal(tt.act, PluralizeWithSize(tt.exp, -1)) r.Equal(tt.exp, PluralizeWithSize(tt.act, 0)) r.Equal(tt.exp, PluralizeWithSize(tt.exp, 0)) r.Equal(tt.act, PluralizeWithSize(tt.act, 1)) r.Equal(tt.act, PluralizeWithSize(tt.exp, 1)) r.Equal(tt.exp, PluralizeWithSize(tt.act, 2)) r.Equal(tt.exp, PluralizeWithSize(tt.exp, 2)) }) } } flect-0.2.3/rule.go000066400000000000000000000002141406236530300141060ustar00rootroot00000000000000package flect type ruleFn func(string) string type rule struct { suffix string fn ruleFn } func noop(s string) string { return s } flect-0.2.3/singular_rules.go000066400000000000000000000007521406236530300162040ustar00rootroot00000000000000package flect var singularRules = []rule{} // AddSingular adds a rule that will replace the given suffix with the replacement suffix. func AddSingular(ext string, repl string) { singularMoot.Lock() defer singularMoot.Unlock() singularRules = append(singularRules, rule{ suffix: ext, fn: func(s string) string { s = s[:len(s)-len(ext)] return s + repl }, }) singularRules = append(singularRules, rule{ suffix: repl, fn: func(s string) string { return s }, }) } flect-0.2.3/singularize.go000066400000000000000000000021741406236530300155020ustar00rootroot00000000000000package flect import ( "strings" "sync" ) var singularMoot = &sync.RWMutex{} // Singularize returns a singular version of the string // users = user // data = datum // people = person func Singularize(s string) string { return New(s).Singularize().String() } // SingularizeWithSize will singular a string taking a number number into account. // SingularizeWithSize("user", 1) = user // SingularizeWithSize("user", 2) = users func SingularizeWithSize(s string, i int) string { if i == 1 || i == -1 { return New(s).Singularize().String() } return New(s).Pluralize().String() } // Singularize returns a singular version of the string // users = user // data = datum // people = person func (i Ident) Singularize() Ident { s := i.Original if len(s) == 0 { return i } singularMoot.RLock() defer singularMoot.RUnlock() ls := strings.ToLower(s) if p, ok := pluralToSingle[ls]; ok { return New(p) } if _, ok := singleToPlural[ls]; ok { return i } for _, r := range singularRules { if strings.HasSuffix(ls, r.suffix) { return New(r.fn(s)) } } if strings.HasSuffix(s, "s") { return New(s[:len(s)-1]) } return i } flect-0.2.3/singularize_test.go000066400000000000000000000017431406236530300165420ustar00rootroot00000000000000package flect import ( "testing" "github.com/stretchr/testify/require" ) func Test_Singularize(t *testing.T) { for _, tt := range pluralSingularAssertions { t.Run(tt.exp, func(st *testing.T) { r := require.New(st) r.Equal(tt.exp, Singularize(tt.act)) r.Equal(tt.exp, Singularize(tt.exp)) }) } } func Test_SingularizeWithSize(t *testing.T) { for _, tt := range pluralSingularAssertions { t.Run(tt.exp, func(st *testing.T) { r := require.New(st) r.Equal(tt.act, SingularizeWithSize(tt.act, -2)) r.Equal(tt.act, SingularizeWithSize(tt.exp, -2)) r.Equal(tt.exp, SingularizeWithSize(tt.act, -1)) r.Equal(tt.exp, SingularizeWithSize(tt.exp, -1)) r.Equal(tt.act, SingularizeWithSize(tt.act, 0)) r.Equal(tt.act, SingularizeWithSize(tt.exp, 0)) r.Equal(tt.exp, SingularizeWithSize(tt.act, 1)) r.Equal(tt.exp, SingularizeWithSize(tt.exp, 1)) r.Equal(tt.act, SingularizeWithSize(tt.act, 2)) r.Equal(tt.act, SingularizeWithSize(tt.exp, 2)) }) } } flect-0.2.3/titleize.go000066400000000000000000000014041406236530300147720ustar00rootroot00000000000000package flect import ( "strings" "unicode" ) // Titleize will capitalize the start of each part // "Nice to see you!" = "Nice To See You!" // "i've read a book! have you?" = "I've Read A Book! Have You?" // "This is `code` ok" = "This Is `code` OK" func Titleize(s string) string { return New(s).Titleize().String() } // Titleize will capitalize the start of each part // "Nice to see you!" = "Nice To See You!" // "i've read a book! have you?" = "I've Read A Book! Have You?" // "This is `code` ok" = "This Is `code` OK" func (i Ident) Titleize() Ident { var parts []string for _, part := range i.Parts { x := string(unicode.ToTitle(rune(part[0]))) if len(part) > 1 { x += part[1:] } parts = append(parts, x) } return New(strings.Join(parts, " ")) } flect-0.2.3/titleize_test.go000066400000000000000000000011511406236530300160300ustar00rootroot00000000000000package flect import ( "testing" "github.com/stretchr/testify/require" ) func Test_Titleize(t *testing.T) { table := []tt{ {"", ""}, {"bob dylan", "Bob Dylan"}, {"Nice to see you!", "Nice To See You!"}, {"*hello*", "*hello*"}, {"i've read a book! have you?", "I've Read A Book! Have You?"}, {"This is `code` ok", "This Is `code` OK"}, {"foo_bar", "Foo Bar"}, {"admin/widget", "Admin Widget"}, {"widget", "Widget"}, } for _, tt := range table { t.Run(tt.act, func(st *testing.T) { r := require.New(st) r.Equal(tt.exp, Titleize(tt.act)) r.Equal(tt.exp, Titleize(tt.exp)) }) } } flect-0.2.3/underscore.go000066400000000000000000000013131406236530300153110ustar00rootroot00000000000000package flect import ( "strings" "unicode" ) // Underscore a string // bob dylan = bob_dylan // Nice to see you! = nice_to_see_you // widgetID = widget_id func Underscore(s string) string { return New(s).Underscore().String() } // Underscore a string // bob dylan = bob_dylan // Nice to see you! = nice_to_see_you // widgetID = widget_id func (i Ident) Underscore() Ident { out := make([]string, 0, len(i.Parts)) for _, part := range i.Parts { var x strings.Builder x.Grow(len(part)) for _, c := range part { if unicode.IsLetter(c) || unicode.IsDigit(c) { x.WriteRune(c) } } if x.Len() > 0 { out = append(out, x.String()) } } return New(strings.ToLower(strings.Join(out, "_"))) } flect-0.2.3/underscore_test.go000066400000000000000000000015401406236530300163520ustar00rootroot00000000000000package flect import ( "testing" "github.com/stretchr/testify/require" ) func Test_Underscore(t *testing.T) { baseAcronyms["TLC"] = true table := []tt{ {"", ""}, {"bob dylan", "bob_dylan"}, {"Nice to see you!", "nice_to_see_you"}, {"*hello*", "hello"}, {"i've read a book! have you?", "ive_read_a_book_have_you"}, {"This is `code` ok", "this_is_code_ok"}, {"TLCForm", "tlc_form"}, } for _, tt := range table { t.Run(tt.act, func(st *testing.T) { r := require.New(st) r.Equal(tt.exp, Underscore(tt.act)) r.Equal(tt.exp, Underscore(tt.exp)) }) } } func Benchmark_Underscore(b *testing.B) { table := []string{ "", "bob dylan", "Nice to see you!", "*hello*", "i've read a book! have you?", "This is `code` ok", "TLCForm", } for n := 0; n < b.N; n++ { for i := range table { Underscore(table[i]) } } } flect-0.2.3/version.go000066400000000000000000000001151406236530300146240ustar00rootroot00000000000000package flect //Version holds Flect version number const Version = "v0.1.6"