diff options
Diffstat (limited to 'vendor/github.com/ettle/strcase/split.go')
| -rw-r--r-- | vendor/github.com/ettle/strcase/split.go | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/vendor/github.com/ettle/strcase/split.go b/vendor/github.com/ettle/strcase/split.go new file mode 100644 index 000000000..84381106b --- /dev/null +++ b/vendor/github.com/ettle/strcase/split.go @@ -0,0 +1,164 @@ +package strcase + +import "unicode" + +// SplitFn defines how to split a string into words +type SplitFn func(prev, curr, next rune) SplitAction + +// NewSplitFn returns a SplitFn based on the options provided. +// +// NewSplitFn covers the majority of common options that other strcase +// libraries provide and should allow you to simply create a custom caser. +// For more complicated use cases, feel free to write your own SplitFn +//nolint:gocyclo +func NewSplitFn( + delimiters []rune, + splitOptions ...SplitOption, +) SplitFn { + var splitCase, splitAcronym, splitBeforeNumber, splitAfterNumber, preserveNumberFormatting bool + + for _, option := range splitOptions { + switch option { + case SplitCase: + splitCase = true + case SplitAcronym: + splitAcronym = true + case SplitBeforeNumber: + splitBeforeNumber = true + case SplitAfterNumber: + splitAfterNumber = true + case PreserveNumberFormatting: + preserveNumberFormatting = true + } + } + + return func(prev, curr, next rune) SplitAction { + // The most common case will be that it's just a letter + // There are safe cases to process + if isLower(curr) && !isNumber(prev) { + return Noop + } + if isUpper(prev) && isUpper(curr) && isUpper(next) { + return Noop + } + + if preserveNumberFormatting { + if (curr == '.' || curr == ',') && + isNumber(prev) && isNumber(next) { + return Noop + } + } + + if unicode.IsSpace(curr) { + return SkipSplit + } + for _, d := range delimiters { + if curr == d { + return SkipSplit + } + } + + if splitBeforeNumber { + if isNumber(curr) && !isNumber(prev) { + if preserveNumberFormatting && (prev == '.' || prev == ',') { + return Noop + } + return Split + } + } + + if splitAfterNumber { + if isNumber(prev) && !isNumber(curr) { + return Split + } + } + + if splitCase { + if !isUpper(prev) && isUpper(curr) { + return Split + } + } + + if splitAcronym { + if isUpper(prev) && isUpper(curr) && isLower(next) { + return Split + } + } + + return Noop + } +} + +// SplitOption are options that allow for configuring NewSplitFn +type SplitOption int + +const ( + // SplitCase - FooBar -> Foo_Bar + SplitCase SplitOption = iota + // SplitAcronym - FOOBar -> Foo_Bar + // It won't preserve FOO's case. If you want, you can set the Caser's initialisms so FOO will be in all caps + SplitAcronym + // SplitBeforeNumber - port80 -> port_80 + SplitBeforeNumber + // SplitAfterNumber - 200status -> 200_status + SplitAfterNumber + // PreserveNumberFormatting - a.b.2,000.3.c -> a_b_2,000.3_c + PreserveNumberFormatting +) + +// SplitAction defines if and how to split a string +type SplitAction int + +const ( + // Noop - Continue to next character + Noop SplitAction = iota + // Split - Split between words + // e.g. to split between wordsWithoutDelimiters + Split + // SkipSplit - Split the word and drop the character + // e.g. to split words with delimiters + SkipSplit + // Skip - Remove the character completely + Skip +) + +//nolint:gocyclo +func defaultSplitFn(prev, curr, next rune) SplitAction { + // The most common case will be that it's just a letter so let lowercase letters return early since we know what they should do + if isLower(curr) { + return Noop + } + // Delimiters are _, -, ., and unicode spaces + // Handle . lower down as it needs to happen after number exceptions + if curr == '_' || curr == '-' || isSpace(curr) { + return SkipSplit + } + + if isUpper(curr) { + if isLower(prev) { + // fooBar + return Split + } else if isUpper(prev) && isLower(next) { + // FOOBar + return Split + } + } + + // Do numeric exceptions last to avoid perf penalty + if unicode.IsNumber(prev) { + // v4.3 is not split + if (curr == '.' || curr == ',') && unicode.IsNumber(next) { + return Noop + } + if !unicode.IsNumber(curr) && curr != '.' { + return Split + } + } + // While period is a default delimiter, keep it down here to avoid + // penalty for other delimiters + if curr == '.' { + return SkipSplit + } + + return Noop +} |
