pax_global_header 0000666 0000000 0000000 00000000064 14062365303 0014514 g ustar 00root root 0000000 0000000 52 comment=cc5b89279644a3672ff0fd4c3629b834396cb6d2
flect-0.2.3/ 0000775 0000000 0000000 00000000000 14062365303 0012613 5 ustar 00root root 0000000 0000000 flect-0.2.3/.github/ 0000775 0000000 0000000 00000000000 14062365303 0014153 5 ustar 00root root 0000000 0000000 flect-0.2.3/.github/FUNDING.yml 0000664 0000000 0000000 00000000122 14062365303 0015763 0 ustar 00root root 0000000 0000000 # These are supported funding model platforms
github: markbates
patreon: buffalo
flect-0.2.3/.github/workflows/ 0000775 0000000 0000000 00000000000 14062365303 0016210 5 ustar 00root root 0000000 0000000 flect-0.2.3/.github/workflows/tests.yml 0000664 0000000 0000000 00000000736 14062365303 0020103 0 ustar 00root root 0000000 0000000 name: 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/.gitignore 0000664 0000000 0000000 00000000376 14062365303 0014611 0 ustar 00root root 0000000 0000000 *.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.json 0000664 0000000 0000000 00000000222 14062365303 0016252 0 ustar 00root root 0000000 0000000 {
"Enable": ["vet", "golint", "goimports", "deadcode", "gotype", "ineffassign", "misspell", "nakedret", "unconvert", "megacheck", "varcheck"]
}
flect-0.2.3/LICENSE 0000664 0000000 0000000 00000002065 14062365303 0013623 0 ustar 00root root 0000000 0000000 The 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/Makefile 0000664 0000000 0000000 00000001601 14062365303 0014251 0 ustar 00root root 0000000 0000000 TAGS ?= ""
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.md 0000664 0000000 0000000 00000003767 14062365303 0014107 0 ustar 00root root 0000000 0000000 # Flect
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`
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`
The `github.com/gobuffalo/flect/name` package contains more "business" inflection rules like creating proper names, table names, etc...
flect-0.2.3/SHOULDERS.md 0000664 0000000 0000000 00000001113 14062365303 0014501 0 ustar 00root root 0000000 0000000 # 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.go 0000664 0000000 0000000 00000004550 14062365303 0015001 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001623 14062365303 0014735 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001575 14062365303 0016002 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001002 14062365303 0015260 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001051 14062365303 0016323 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000003323 14062365303 0015446 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001375 14062365303 0015126 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001367 14062365303 0016166 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001452 14062365303 0014241 0 ustar 00root root 0000000 0000000 /*
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.go 0000664 0000000 0000000 00000010704 14062365303 0015300 0 ustar 00root root 0000000 0000000 package 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.mod 0000664 0000000 0000000 00000000127 14062365303 0013721 0 ustar 00root root 0000000 0000000 module github.com/gobuffalo/flect
go 1.13
require github.com/stretchr/testify v1.4.0
flect-0.2.3/go.sum 0000664 0000000 0000000 00000001710 14062365303 0013745 0 ustar 00root root 0000000 0000000 github.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.go 0000664 0000000 0000000 00000001367 14062365303 0014771 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001126 14062365303 0016021 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000005573 14062365303 0014257 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000005303 14062365303 0015305 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000446 14062365303 0015511 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000016 14062365303 0016541 0 ustar 00root root 0000000 0000000 package flect
flect-0.2.3/name/ 0000775 0000000 0000000 00000000000 14062365303 0013533 5 ustar 00root root 0000000 0000000 flect-0.2.3/name/char.go 0000664 0000000 0000000 00000000654 14062365303 0015004 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000612 14062365303 0016035 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001132 14062365303 0014776 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001044 14062365303 0016037 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001470 14062365303 0015337 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001112 14062365303 0016367 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000351 14062365303 0015164 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000772 14062365303 0016030 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001102 14062365303 0017053 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000620 14062365303 0015017 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001175 14062365303 0016064 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000322 14062365303 0014647 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000521 14062365303 0015707 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000002522 14062365303 0015003 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000003342 14062365303 0016043 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000560 14062365303 0015520 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001114 14062365303 0016553 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001472 14062365303 0015461 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001557 14062365303 0016524 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001037 14062365303 0015637 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000775 14062365303 0016706 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000627 14062365303 0015716 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001210 14062365303 0016742 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000625 14062365303 0015517 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001475 14062365303 0016562 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000121 14062365303 0014656 0 ustar 00root root 0000000 0000000 package name
func (n Ident) URL() Ident {
return Ident{n.File().Pluralize()}
}
flect-0.2.3/name/url_test.go 0000664 0000000 0000000 00000001006 14062365303 0015720 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000002110 14062365303 0015637 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000003075 14062365303 0016711 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001370 14062365303 0015303 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000002715 14062365303 0016346 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001021 14062365303 0015107 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001150 14062365303 0016151 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000014313 14062365303 0015655 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000002214 14062365303 0015150 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001703 14062365303 0016211 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000214 14062365303 0014106 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000752 14062365303 0016204 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000002174 14062365303 0015502 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001743 14062365303 0016542 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001404 14062365303 0014772 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001151 14062365303 0016030 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001313 14062365303 0015311 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000001540 14062365303 0016352 0 ustar 00root root 0000000 0000000 package 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.go 0000664 0000000 0000000 00000000115 14062365303 0014624 0 ustar 00root root 0000000 0000000 package flect
//Version holds Flect version number
const Version = "v0.1.6"