Skip to content

Commit

Permalink
Merge pull request #22 from dnnrly/feature/strategies
Browse files Browse the repository at this point in the history
Feature/strategies
  • Loading branch information
dnnrly authored Oct 1, 2020
2 parents 7d8453d + 9ee66a1 commit 103c48d
Show file tree
Hide file tree
Showing 14 changed files with 138 additions and 61 deletions.
16 changes: 16 additions & 0 deletions acceptance.bats
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,19 @@
run ./abbreviate separated strategy-limited
[ "${lines[0]}" == "stgltd" ]
}

@test "Errors on unknown strategy" {
run ./abbreviate original --strategy oops strategy-limited
[ "$status" -eq 1 ]
[ "${lines[0]}" = "Error: unknown abbreviation strategy 'oops'. Only allowed lookup, no-abbreviation" ]
}

@test "Use lookup strategy" {
run ./abbreviate original --strategy lookup strategy-limited
[ "${lines[0]}" == "stg-ltd" ]
}

@test "Use no-abbreviation strategy" {
run ./abbreviate original --strategy no-abbreviation strategy-limited
[ "${lines[0]}" == "strategy-limited" ]
}
12 changes: 1 addition & 11 deletions cmd/camel.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ var camelCmd = &cobra.Command{
Long: `Abbreviate a string and convert it to camel case.`,
Args: validateArgPresent,
Run: func(cmd *cobra.Command, args []string) {
abbr := domain.AsPascal(matcher, args[0], optMax, optFrmFront)
abbr := domain.AsPascal(abbreviator, args[0], optMax, optFrmFront)

ch := string(abbr[0])

Expand All @@ -42,14 +42,4 @@ var camelCmd = &cobra.Command{

func init() {
rootCmd.AddCommand(camelCmd)

// Here you will define your flags and configuration settings.

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// camelCmd.PersistentFlags().String("foo", "", "A help for foo")

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// camelCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
2 changes: 1 addition & 1 deletion cmd/kebab.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Where a string is not shortened, it will be converted to kebab case anyway, even
if this means that the string will end up longer.`,
Args: validateArgPresent,
Run: func(cmd *cobra.Command, args []string) {
abbr := domain.AsSeparated(matcher, args[0], optKebabSeperator, optMax, optFrmFront)
abbr := domain.AsSeparated(abbreviator, args[0], optKebabSeperator, optMax, optFrmFront)

fmt.Printf("%s", abbr)
if optNewline {
Expand Down
2 changes: 1 addition & 1 deletion cmd/original.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ var originalCmd = &cobra.Command{
Short: "Abbreviate the string using the original word boundary separators",
Args: validateArgPresent,
Run: func(cmd *cobra.Command, args []string) {
abbr := domain.AsOriginal(matcher, args[0], optMax, optFrmFront)
abbr := domain.AsOriginal(abbreviator, args[0], optMax, optFrmFront)

fmt.Printf("%s", abbr)
if optNewline {
Expand Down
12 changes: 1 addition & 11 deletions cmd/pascal.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ var pascalCmd = &cobra.Command{
Long: `Abbreviate a string and convert it to pascal case.`,
Args: validateArgPresent,
Run: func(cmd *cobra.Command, args []string) {
abbr := domain.AsPascal(matcher, args[0], optMax, optFrmFront)
abbr := domain.AsPascal(abbreviator, args[0], optMax, optFrmFront)

fmt.Printf("%s", abbr)
if optNewline {
Expand All @@ -39,14 +39,4 @@ var pascalCmd = &cobra.Command{

func init() {
rootCmd.AddCommand(pascalCmd)

// Here you will define your flags and configuration settings.

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// pascalCmd.PersistentFlags().String("foo", "", "A help for foo")

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// pascalCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
10 changes: 0 additions & 10 deletions cmd/print.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,4 @@ var printCmd = &cobra.Command{

func init() {
rootCmd.AddCommand(printCmd)

// Here you will define your flags and configuration settings.

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// printCmd.PersistentFlags().String("foo", "", "A help for foo")

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// printCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
56 changes: 39 additions & 17 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"io/ioutil"
"os"
"sort"
"strings"

"github.com/spf13/cobra"

Expand All @@ -35,8 +36,10 @@ var (
optCustom = ""
optMax = 0
optFrmFront = false
optStrategy = "lookup"

matcher *domain.Matcher
matcher *domain.Matcher
abbreviator domain.Abbreviator
)

// rootCmd represents the base command when called without any subcommands
Expand Down Expand Up @@ -74,22 +77,20 @@ request. We're really interested to see more abbreviations added or corrected.`,
os.Exit(0)
}

if optCustom == "" {
matcher = data.Abbreviations[optLanguage][optSet]
} else {
all := ""
buf, err := ioutil.ReadFile(optCustom)
if err != nil {
fmt.Fprintf(
os.Stderr,
"Unable to open custom abbreviations file: %s\n",
err,
)
os.Exit(1)
}

all = string(buf)
matcher = domain.NewMatcherFromString(all)
switch optStrategy {
case "lookup":
matcher = setMatcher()
abbreviator = matcher
case "no-abbreviation":
abbreviator = &domain.NoAbbreviator{}
default:
fmt.Fprintf(
os.Stderr,
`Error: unknown abbreviation strategy '%s'. Only allowed %s
Run 'abbreviate --help' for usage.
`,
optStrategy, strings.Join([]string{"lookup", "no-abbreviation"}, ", "))
os.Exit(1)
}
},
Run: func(cmd *cobra.Command, args []string) {
Expand Down Expand Up @@ -120,6 +121,27 @@ func init() {
rootCmd.PersistentFlags().StringVarP(&optCustom, "custom", "c", optCustom, "Custom abbreviation set")
rootCmd.PersistentFlags().IntVarP(&optMax, "max", "m", optMax, "Maximum length of string, keep on abbreviating while the string is longer than this limit")
rootCmd.PersistentFlags().BoolVarP(&optFrmFront, "from-front", "", optFrmFront, "Shorten from the front")
rootCmd.PersistentFlags().StringVarP(&optStrategy, "strategy", "", optStrategy, "Abbreviation strategy")
}

func setMatcher() *domain.Matcher {
if optCustom == "" {
return data.Abbreviations[optLanguage][optSet]
} else {
all := ""
buf, err := ioutil.ReadFile(optCustom)
if err != nil {
fmt.Fprintf(
os.Stderr,
"Unable to open custom abbreviations file: %s\n",
err,
)
os.Exit(1)
}

all = string(buf)
return domain.NewMatcherFromString(all)
}
}

func validateArgPresent(cmd *cobra.Command, args []string) error {
Expand Down
3 changes: 2 additions & 1 deletion cmd/separated.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
var (
optSeperator = ""
)

// separatedCmd represents the Separated command
var separatedCmd = &cobra.Command{
Use: "separated [string]",
Expand All @@ -34,7 +35,7 @@ Where a string is not shortened, it will be converted to your case anyway, even
if this means that the string will end up longer.`,
Args: validateArgPresent,
Run: func(cmd *cobra.Command, args []string) {
abbr := domain.AsSeparated(matcher, args[0], optSeperator, optMax, optFrmFront)
abbr := domain.AsSeparated(abbreviator, args[0], optSeperator, optMax, optFrmFront)

fmt.Printf("%s", abbr)
if optNewline {
Expand Down
2 changes: 1 addition & 1 deletion cmd/snake.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Where a string is not shortened, it will be converted to snake case anyway, even
if this means that the string will end up longer.`,
Args: validateArgPresent,
Run: func(cmd *cobra.Command, args []string) {
abbr := domain.AsSeparated(matcher, args[0], optSnakeSeperator, optMax, optFrmFront)
abbr := domain.AsSeparated(abbreviator, args[0], optSnakeSeperator, optMax, optFrmFront)

fmt.Printf("%s", abbr)
if optNewline {
Expand Down
20 changes: 20 additions & 0 deletions domain/matcher.go → domain/abbreviate.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@ import (
"strings"
)

// Abbreviator allows you to use different implementations for abbreviating words
type Abbreviator interface {
// Abbreviate attempts to return an abbreviation for the word given. It
// does not guarantee to return a different, shorter string.
Abbreviate(word string) string
}

// NoAbbreviator does not abbreviate anything
type NoAbbreviator struct{}

// Abbreviate just returns the unabbreviated word
func (a *NoAbbreviator) Abbreviate(word string) string {
return word
}

// Matcher finds matches between words and abbreviations
type Matcher struct {
items map[string]string
Expand All @@ -18,6 +33,11 @@ func NewMatcher(items map[string]string) *Matcher {
}
}

// Abbreviate returns an abbreviation looked up from pre-defined mappings
func (matcher *Matcher) Abbreviate(word string) string {
return (*matcher).Match(word)
}

// Match against a list of mappings
func (matcher Matcher) Match(word string) string {
if abbr, found := matcher.items[word]; found {
Expand Down
File renamed without changes.
12 changes: 6 additions & 6 deletions domain/shorteners.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,15 +98,15 @@ type Shortener func(matcher Matcher, original string, max int) string
// AsOriginal discovers words using camel case and non letter characters,
// starting from the back or the front until the string has less than 'max' characters
// or it can't shorten any more.
func AsOriginal(matcher *Matcher, original string, max int, frmFront bool) string {
func AsOriginal(abbr Abbreviator, original string, max int, frmFront bool) string {
if len(original) < max {
return original
}

shortened := NewSequences(original)
shorten(shortened, max, frmFront, func(pos int) {
str := shortened[pos]
abbr := matcher.Match(strings.ToLower(str))
abbr := abbr.Abbreviate(strings.ToLower(str))
if isTitleCase(str) {
abbr = makeTitle(abbr)
}
Expand All @@ -120,7 +120,7 @@ func AsOriginal(matcher *Matcher, original string, max int, frmFront bool) strin
// starting from the back or the front until the string has less than 'max' characters
// or it can't shorten any more. This inserts the specified separator
// where a sequence is not alpha-numeric
func AsSeparated(matcher *Matcher, original, separator string, max int, frmFront bool) string {
func AsSeparated(abbr Abbreviator, original, separator string, max int, frmFront bool) string {
if original == "" {
return ""
}
Expand All @@ -144,7 +144,7 @@ func AsSeparated(matcher *Matcher, original, separator string, max int, frmFront

shorten(shortened, max, frmFront, func(pos int) {
str := shortened[pos]
abbr := matcher.Match(str)
abbr := abbr.Abbreviate(str)
shortened[pos] = abbr
})

Expand All @@ -155,7 +155,7 @@ func AsSeparated(matcher *Matcher, original, separator string, max int, frmFront
// starting from the back or the front until the string has less than 'max' characters
// or it can't shorten any more. Word boundaries are a capital letter at
// the start of each word
func AsPascal(matcher *Matcher, original string, max int, frmFront bool) string {
func AsPascal(abbr Abbreviator, original string, max int, frmFront bool) string {
if original == "" {
return ""
}
Expand All @@ -179,7 +179,7 @@ func AsPascal(matcher *Matcher, original string, max int, frmFront bool) string

shorten(shortened, max, frmFront, func(pos int) {
str := strings.ToLower(shortened[pos])
abbr := matcher.Match(str)
abbr := abbr.Abbreviate(str)
abbr = makeTitle(abbr)
shortened[pos] = abbr
})
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
module github.com/dnnrly/abbreviate

require (
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/gobuffalo/packr/v2 v2.1.0
github.com/pkg/errors v0.8.1
github.com/spf13/cobra v0.0.3
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/testify v1.3.0
)

Expand Down
48 changes: 48 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,13 +1,61 @@
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/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs=
github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk=
github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28=
github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw=
github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360=
github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8=
github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
github.com/gobuffalo/packr/v2 v2.1.0/go.mod h1:n90ZuXIc2KN2vFAOQascnPItp9A2g9QYSvYvS3AjQEM=
github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190404132500-923d25813098/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=

0 comments on commit 103c48d

Please sign in to comment.