1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-08 22:52:29 +08:00

publish lancet

This commit is contained in:
dudaodong
2021-11-28 21:28:23 +08:00
parent 37edb0fc8f
commit 3254591ab9
38 changed files with 5163 additions and 0 deletions

217
strutil/string.go Normal file
View File

@@ -0,0 +1,217 @@
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
// Use of this source code is governed by MIT license
// Package strutil implements some functions to manipulate string.
package strutil
import (
"regexp"
"strings"
)
// CamelCase covert string to camelCase string.
func CamelCase(s string) string {
if len(s) == 0 {
return ""
}
res := ""
blankSpace := " "
regex, _ := regexp.Compile("[-_&]+")
ss := regex.ReplaceAllString(s, blankSpace)
for i, v := range strings.Split(ss, blankSpace) {
vv := []rune(v)
if i == 0 {
if vv[i] >= 65 && vv[i] <= 96 {
vv[0] += 32
}
res += string(vv)
} else {
res += Capitalize(v)
}
}
return res
}
// Capitalize converts the first character of a string to upper case and the remaining to lower case.
func Capitalize(s string) string {
if len(s) == 0 {
return ""
}
res := ""
for i, v := range []rune(s) {
if i == 0 {
if v >= 97 && v <= 122 {
v -= 32
}
res += string(v)
} else {
res += strings.ToLower(string(v))
}
}
return res
}
// LowerFirst converts the first character of string to lower case.
func LowerFirst(s string) string {
if len(s) == 0 {
return ""
}
res := ""
for i, v := range []rune(s) {
if i == 0 {
if v >= 65 && v <= 96 {
v += 32
res += string(v)
} else {
return s
}
} else {
res += string(v)
}
}
return res
}
// PadEnd pads string on the right side if it's shorter than size.
// Padding characters are truncated if they exceed size.
func PadEnd(source string, size int, padStr string) string {
len1 := len(source)
len2 := len(padStr)
if len1 >= size {
return source
}
fill := ""
if len2 >= size-len1 {
fill = padStr[0 : size-len1]
} else {
fill = strings.Repeat(padStr, size-len1)
}
return source + fill[0:size-len1]
}
// PadStart pads string on the left side if it's shorter than size.
// Padding characters are truncated if they exceed size.
func PadStart(source string, size int, padStr string) string {
len1 := len(source)
len2 := len(padStr)
if len1 >= size {
return source
}
fill := ""
if len2 >= size-len1 {
fill = padStr[0 : size-len1]
} else {
fill = strings.Repeat(padStr, size-len1)
}
return fill[0:size-len1] + source
}
// KebabCase covert string to kebab-case
func KebabCase(s string) string {
if len(s) == 0 {
return ""
}
regex := regexp.MustCompile(`[\W|_]+`)
blankSpace := " "
match := regex.ReplaceAllString(s, blankSpace)
rs := strings.Split(match, blankSpace)
var res []string
for _, v := range rs {
splitWords := splitWordsToLower(v)
if len(splitWords) > 0 {
res = append(res, splitWords...)
}
}
return strings.Join(res, "-")
}
// SnakeCase covert string to snake_case
func SnakeCase(s string) string {
if len(s) == 0 {
return ""
}
regex := regexp.MustCompile(`[\W|_]+`)
blankSpace := " "
match := regex.ReplaceAllString(s, blankSpace)
rs := strings.Split(match, blankSpace)
var res []string
for _, v := range rs {
splitWords := splitWordsToLower(v)
if len(splitWords) > 0 {
res = append(res, splitWords...)
}
}
return strings.Join(res, "_")
}
// Before create substring in source string before position when char first appear
func Before(s, char string) string {
if s == "" || char == "" {
return s
}
i := strings.Index(s, char)
return s[0:i]
}
// BeforeLast create substring in source string before position when char last appear
func BeforeLast(s, char string) string {
if s == "" || char == "" {
return s
}
i := strings.LastIndex(s, char)
return s[0:i]
}
// After create substring in source string after position when char first appear
func After(s, char string) string {
if s == "" || char == "" {
return s
}
i := strings.Index(s, char)
return s[i+len(char):]
}
// AfterLast create substring in source string after position when char last appear
func AfterLast(s, char string) string {
if s == "" || char == "" {
return s
}
i := strings.LastIndex(s, char)
return s[i+len(char):]
}
// IsString check if the value data type is string or not.
func IsString(v interface{}) bool {
if v == nil {
return false
}
switch v.(type) {
case string:
return true
default:
return false
}
}
// ReverseStr return string whose char order is reversed to the given string
func ReverseStr(s string) string {
r := []rune(s)
for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 {
r[i], r[j] = r[j], r[i]
}
return string(r)
}

200
strutil/string_test.go Normal file
View File

@@ -0,0 +1,200 @@
package strutil
import (
"testing"
"github.com/duke-git/lancet/utils"
)
func TestCamelCase(t *testing.T) {
camelCase(t, "foo_bar", "fooBar")
camelCase(t, "Foo-Bar", "fooBar")
camelCase(t, "Foo&bar", "fooBar")
camelCase(t, "foo bar", "fooBar")
}
func camelCase(t *testing.T, test string, expected string) {
res := CamelCase(test)
if res != expected {
utils.LogFailedTestInfo(t, "CamelCase", test, expected, res)
t.FailNow()
}
}
func TestCapitalize(t *testing.T) {
capitalize(t, "foo", "Foo")
capitalize(t, "fOO", "Foo")
capitalize(t, "FOo", "Foo")
}
func capitalize(t *testing.T, test string, expected string) {
res := Capitalize(test)
if res != expected {
utils.LogFailedTestInfo(t, "Capitalize", test, expected, res)
t.FailNow()
}
}
func TestKebabCase(t *testing.T) {
kebabCase(t, "Foo Bar-", "foo-bar")
kebabCase(t, "foo_Bar", "foo-bar")
kebabCase(t, "fooBar", "foo-bar")
kebabCase(t, "__FOO_BAR__", "f-o-o-b-a-r")
}
func kebabCase(t *testing.T, test string, expected string) {
res := KebabCase(test)
if res != expected {
utils.LogFailedTestInfo(t, "KebabCase", test, expected, res)
t.FailNow()
}
}
func TestSnakeCase(t *testing.T) {
snakeCase(t, "Foo Bar-", "foo_bar")
snakeCase(t, "foo_Bar", "foo_bar")
snakeCase(t, "fooBar", "foo_bar")
snakeCase(t, "__FOO_BAR__", "f_o_o_b_a_r")
snakeCase(t, "aBbc-s$@a&%_B.B^C", "a_bbc_s_a_b_b_c")
}
func snakeCase(t *testing.T, test string, expected string) {
res := SnakeCase(test)
if res != expected {
utils.LogFailedTestInfo(t, "SnakeCase", test, expected, res)
t.FailNow()
}
}
func TestLowerFirst(t *testing.T) {
lowerFirst(t, "foo", "foo")
lowerFirst(t, "BAR", "bAR")
lowerFirst(t, "FOo", "fOo")
}
func lowerFirst(t *testing.T, test string, expected string) {
res := LowerFirst(test)
if res != expected {
utils.LogFailedTestInfo(t, "LowerFirst", test, expected, res)
t.FailNow()
}
}
func TestPadEnd(t *testing.T) {
padEnd(t, "a", 1, "b", "a")
padEnd(t, "a", 2, "b", "ab")
padEnd(t, "abcd", 6, "mno", "abcdmn")
padEnd(t, "abcd", 6, "m", "abcdmm")
padEnd(t, "abc", 6, "ab", "abcaba")
}
func padEnd(t *testing.T, source string, size int, fillString string, expected string) {
res := PadEnd(source, size, fillString)
if res != expected {
utils.LogFailedTestInfo(t, "PadEnd", source, expected, res)
t.FailNow()
}
}
func TestPadStart(t *testing.T) {
padStart(t, "a", 1, "b", "a")
padStart(t, "a", 2, "b", "ba")
padStart(t, "abcd", 6, "mno", "mnabcd")
padStart(t, "abcd", 6, "m", "mmabcd")
padStart(t, "abc", 6, "ab", "abaabc")
}
func padStart(t *testing.T, source string, size int, fillString string, expected string) {
res := PadStart(source, size, fillString)
if res != expected {
utils.LogFailedTestInfo(t, "PadEnd", source, expected, res)
t.FailNow()
}
}
func TestBefore(t *testing.T) {
before(t, "lancet", "", "lancet")
before(t, "github.com/test/lancet", "/", "github.com")
before(t, "github.com/test/lancet", "test", "github.com/")
}
func before(t *testing.T, source, char, expected string) {
res := Before(source, char)
if res != expected {
utils.LogFailedTestInfo(t, "Before", source, expected, res)
t.FailNow()
}
}
func TestBeforeLast(t *testing.T) {
beforeLast(t, "lancet", "", "lancet")
beforeLast(t, "github.com/test/lancet", "/", "github.com/test")
beforeLast(t, "github.com/test/test/lancet", "test", "github.com/test/")
}
func beforeLast(t *testing.T, source, char, expected string) {
res := BeforeLast(source, char)
if res != expected {
utils.LogFailedTestInfo(t, "BeforeLast", source, expected, res)
t.FailNow()
}
}
func TestAfter(t *testing.T) {
after(t, "lancet", "", "lancet")
after(t, "github.com/test/lancet", "/", "test/lancet")
after(t, "github.com/test/lancet", "test", "/lancet")
}
func after(t *testing.T, source, char, expected string) {
res := After(source, char)
if res != expected {
utils.LogFailedTestInfo(t, "After", source, expected, res)
t.FailNow()
}
}
func TestAfterLast(t *testing.T) {
afterLast(t, "lancet", "", "lancet")
afterLast(t, "github.com/test/lancet", "/", "lancet")
afterLast(t, "github.com/test/test/lancet", "test", "/lancet")
}
func afterLast(t *testing.T, source, char, expected string) {
res := AfterLast(source, char)
if res != expected {
utils.LogFailedTestInfo(t, "AfterLast", source, expected, res)
t.FailNow()
}
}
func TestIsString(t *testing.T) {
isString(t, "lancet", true)
isString(t, 1, false)
isString(t, true, false)
isString(t, []string{}, false)
}
func isString(t *testing.T, test interface{}, expected bool) {
res := IsString(test)
if res != expected {
utils.LogFailedTestInfo(t, "IsString", test, expected, res)
t.FailNow()
}
}
func TestReverseStr(t *testing.T) {
reverseStr(t, "abc", "cba")
reverseStr(t, "12345", "54321")
//failed
//reverseStr(t, "abc", "abc")
}
func reverseStr(t *testing.T, test string, expected string) {
res := ReverseStr(test)
if res != expected {
utils.LogFailedTestInfo(t, "ReverseStr", test, expected, res)
t.FailNow()
}
}

40
strutil/string_util.go Normal file
View File

@@ -0,0 +1,40 @@
package strutil
import "strings"
// splitWordsToLower split a string into worlds by uppercase char
func splitWordsToLower(s string) []string {
var res []string
upperIndexes := upperIndex(s)
l := len(upperIndexes)
if upperIndexes == nil || l == 0 {
if s != "" {
res = append(res, s)
}
return res
}
for i := 0; i < l; i++ {
if i < l-1 {
res = append(res, strings.ToLower(s[upperIndexes[i]:upperIndexes[i+1]]))
} else {
res = append(res, strings.ToLower(s[upperIndexes[i]:]))
}
}
return res
}
// upperIndex get a int slice which elements are all the uppercase char index of a string
func upperIndex(s string) []int {
var res []int
for i := 0; i < len(s); i++ {
if 64 < s[i] && s[i] < 91 {
res = append(res, i)
}
}
if len(s) > 0 && res != nil && res[0] != 0 {
res = append([]int{0}, res...)
}
return res
}