aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/ettle/strcase/split.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/ettle/strcase/split.go')
-rw-r--r--vendor/github.com/ettle/strcase/split.go164
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
+}