1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-03-01 00:35:28 +08:00

Compare commits

...

14 Commits

Author SHA1 Message Date
dudaodong
b7e5d946f1 release v2.1.12 2022-12-15 16:55:20 +08:00
dudaodong
687db4ce79 update readme file 2022-12-15 16:44:30 +08:00
dudaodong
a9a4bb8841 update readme file 2022-12-15 16:42:22 +08:00
dudaodong
bc6cb5f61b fix code issue in doc 2022-12-15 16:38:50 +08:00
dudaodong
2c57266f8e test: update some test functions 2022-12-15 15:22:01 +08:00
dudaodong
57e49c9520 doc: update document for funcations CamelCase/KebabCase/UpperKebabCase/SnakeCase/UpperSnakeCase 2022-12-14 21:42:43 +08:00
dudaodong
985c9a5d9a refactor: refact CamelCase function 2022-12-14 21:27:29 +08:00
dudaodong
5cfb11f036 feat: fix and add SnakeCase/UpperSnakeCase 2022-12-14 21:17:30 +08:00
dudaodong
5b3d48a1e7 feat: fix and add KebabCase/UpperKebabCase 2022-12-14 21:09:22 +08:00
dudaodong
d0576e028f clean code 2022-12-13 19:52:37 +08:00
dudaodong
76bdec2b54 test: add cases for Capitalize 2022-12-13 16:16:16 +08:00
dudaodong
fa20aba3a7 fix: fix CamelCase function bug 2022-12-13 14:23:32 +08:00
dudaodong
7a4a429e23 test: add cases for Capitalize 2022-12-12 21:11:19 +08:00
dudaodong
a70ec6ad1e refactor: use constraints from golang.org/x/exp/constraints 2022-12-11 11:25:34 +08:00
17 changed files with 469 additions and 166 deletions

View File

@@ -4,7 +4,7 @@
<br/> <br/>
![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf) ![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf)
[![Release](https://img.shields.io/badge/release-2.1.11-green.svg)](https://github.com/duke-git/lancet/releases) [![Release](https://img.shields.io/badge/release-2.1.12-green.svg)](https://github.com/duke-git/lancet/releases)
[![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2) [![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2)
[![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2) [![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
[![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml) [![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
@@ -38,10 +38,10 @@ English | [简体中文](./README_zh-CN.md)
go get github.com/duke-git/lancet/v2 // will install latest version of v2.x.x go get github.com/duke-git/lancet/v2 // will install latest version of v2.x.x
``` ```
2. <b>For users who use version below go1.18, you should install v1.x.x. now latest v1 is v1.3.4. </b> 2. <b>For users who use version below go1.18, you should install v1.x.x. now latest v1 is v1.3.5. </b>
```go ```go
go get github.com/duke-git/lancet@v1.3.3 // below go1.18, install latest version of v1.x.x go get github.com/duke-git/lancet@v1.3.5 // below go1.18, install latest version of v1.x.x
``` ```
## Usage ## Usage
@@ -371,7 +371,6 @@ import "github.com/duke-git/lancet/v2/netutil"
- [SendRequest](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#SendRequest) - [SendRequest](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#SendRequest)
- [DecodeResponse](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#DecodeResponse) - [DecodeResponse](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#DecodeResponse)
- [StructToUrlValues](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#StructToUrlValues) - [StructToUrlValues](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#StructToUrlValues)
- [HttpGet<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpGet) - [HttpGet<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpGet)
- [HttpDelete<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpDelete) - [HttpDelete<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpDelete)
- [HttpPost<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPost) - [HttpPost<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil.md#HttpPost)
@@ -488,12 +487,14 @@ import "github.com/duke-git/lancet/v2/strutil"
- [Capitalize](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Capitalize) - [Capitalize](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Capitalize)
- [IsString](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#IsString) - [IsString](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#IsString)
- [KebabCase](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#KebabCase) - [KebabCase](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#KebabCase)
- [UpperKebabCase](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#UpperKebabCase)
- [LowerFirst](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#LowerFirst) - [LowerFirst](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#LowerFirst)
- [UpperFirst](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#UpperFirst) - [UpperFirst](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#UpperFirst)
- [PadEnd](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#PadEnd) - [PadEnd](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#PadEnd)
- [PadStart](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#PadStart) - [PadStart](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#PadStart)
- [Reverse](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Reverse) - [Reverse](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Reverse)
- [SnakeCase](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#SnakeCase) - [SnakeCase](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#SnakeCase)
- [UpperSnakeCase](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#UpperSnakeCase)
- [SplitEx](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#SplitEx) - [SplitEx](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#SplitEx)
- [Wrap](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Wrap) - [Wrap](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Wrap)
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Unwrap) - [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/strutil.md#Unwrap)
@@ -551,6 +552,7 @@ import "github.com/duke-git/lancet/v2/validator"
- [IsUrl](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsUrl) - [IsUrl](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsUrl)
- [IsWeakPassword](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsWeakPassword) - [IsWeakPassword](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsWeakPassword)
- [IsZeroValue](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsZeroValue) - [IsZeroValue](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsZeroValue)
- [IsGBK](https://github.com/duke-git/lancet/blob/main/docs/validator.md#IsGBK)
### 20. xerror package implements helpers for errors. ### 20. xerror package implements helpers for errors.

View File

@@ -4,7 +4,7 @@
<br/> <br/>
![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf) ![Go version](https://img.shields.io/badge/go-%3E%3Dv1.18-9cf)
[![Release](https://img.shields.io/badge/release-2.1.11-green.svg)](https://github.com/duke-git/lancet/releases) [![Release](https://img.shields.io/badge/release-2.1.12-green.svg)](https://github.com/duke-git/lancet/releases)
[![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2) [![GoDoc](https://godoc.org/github.com/duke-git/lancet/v2?status.svg)](https://pkg.go.dev/github.com/duke-git/lancet/v2)
[![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2) [![Go Report Card](https://goreportcard.com/badge/github.com/duke-git/lancet/v2)](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
[![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml) [![test](https://github.com/duke-git/lancet/actions/workflows/codecov.yml/badge.svg?branch=main&event=push)](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
@@ -37,10 +37,10 @@
go get github.com/duke-git/lancet/v2 //安装v2最新版本v2.x.x go get github.com/duke-git/lancet/v2 //安装v2最新版本v2.x.x
``` ```
2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.3.4。</b> 2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.3.5。</b>
```go ```go
go get github.com/duke-git/lancet@v1.3.3 // 使用go1.18以下版本, 必须安装v1.x.x版本 go get github.com/duke-git/lancet@v1.3.5 // 使用go1.18以下版本, 必须安装v1.x.x版本
``` ```
## 用法 ## 用法
@@ -370,7 +370,6 @@ import "github.com/duke-git/lancet/v2/netutil"
- [SendRequest](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#SendRequest) - [SendRequest](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#SendRequest)
- [DecodeResponse](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#DecodeResponse) - [DecodeResponse](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#DecodeResponse)
- [StructToUrlValues](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#StructToUrlValues) - [StructToUrlValues](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#StructToUrlValues)
- [HttpGet<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpGet) - [HttpGet<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpGet)
- [HttpDelete<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpDelete) - [HttpDelete<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpDelete)
- [HttpPost<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPost) - [HttpPost<sup>deprecated</sup>](https://github.com/duke-git/lancet/blob/main/docs/netutil_zh-CN.md#HttpPost)
@@ -485,12 +484,14 @@ import "github.com/duke-git/lancet/v2/strutil"
- [Capitalize](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Capitalize) - [Capitalize](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Capitalize)
- [IsString](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#IsString) - [IsString](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#IsString)
- [KebabCase](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#KebabCase) - [KebabCase](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#KebabCase)
- [UpperKebabCase](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#UpperKebabCase)
- [LowerFirst](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#LowerFirst) - [LowerFirst](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#LowerFirst)
- [UpperFirst](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#UpperFirst) - [UpperFirst](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#UpperFirst)
- [PadEnd](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#PadEnd) - [PadEnd](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#PadEnd)
- [PadStart](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#PadStart) - [PadStart](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#PadStart)
- [Reverse](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Reverse) - [Reverse](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Reverse)
- [SnakeCase](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#SnakeCase) - [SnakeCase](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#SnakeCase)
- [UpperSnakeCase](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#UpperSnakeCase)
- [SplitEx](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#SplitEx) - [SplitEx](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#SplitEx)
- [Wrap](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Wrap) - [Wrap](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Wrap)
- [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Unwrap) - [Unwrap](https://github.com/duke-git/lancet/blob/main/docs/strutil_zh-CN.md#Unwrap)
@@ -548,6 +549,7 @@ import "github.com/duke-git/lancet/v2/validator"
- [IsUrl](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsUrl) - [IsUrl](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsUrl)
- [IsWeakPassword](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsWeakPassword) - [IsWeakPassword](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsWeakPassword)
- [IsZeroValue](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsZeroValue) - [IsZeroValue](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsZeroValue)
- [IsGBK](https://github.com/duke-git/lancet/blob/main/docs/validator_zh-CN.md#IsGBK)
### 20. xerror 包实现一些错误处理函数 ### 20. xerror 包实现一些错误处理函数

View File

@@ -45,7 +45,7 @@ import (
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Average[T lancetconstraints.Number](numbers ...T) T func Average[T constraints.Integer | constraints.Float](numbers ...T) T
``` ```
<b>Example:</b> <b>Example:</b>
@@ -157,7 +157,7 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Max[T lancetconstraints.Number](numbers ...T) T func Max[T constraints.Integer | constraints.Float](numbers ...T) T
``` ```
<b>Example:</b> <b>Example:</b>
@@ -223,7 +223,7 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Min[T lancetconstraints.Number](numbers ...T) T func Min[T constraints.Integer | constraints.Float](numbers ...T) T
``` ```
<b>Example:</b> <b>Example:</b>

View File

@@ -44,7 +44,7 @@ import (
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Average[T lancetconstraints.Number](numbers ...T) T func Average[T constraints.Integer | constraints.Float](numbers ...T) T
``` ```
<b>例子:</b> <b>例子:</b>
@@ -154,7 +154,7 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Max[T lancetconstraints.Number](numbers ...T) T func Max[T constraints.Integer | constraints.Float](numbers ...T) T
``` ```
<b>例子:</b> <b>例子:</b>
@@ -220,7 +220,7 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Min[T lancetconstraints.Number](numbers ...T) T func Min[T constraints.Integer | constraints.Float](numbers ...T) T
``` ```
<b>例子:</b> <b>例子:</b>

View File

@@ -1138,7 +1138,7 @@ func main() {
<b>Signature:</b> <b>Signature:</b>
```go ```go
func Sort[T lancetconstraints.Ordered](slice []T, sortOrder ...string) func Sort[T constraints.Ordered](slice []T, sortOrder ...string)
``` ```
<b>Example:</b> <b>Example:</b>

View File

@@ -1135,7 +1135,7 @@ func main() {
<b>函数签名:</b> <b>函数签名:</b>
```go ```go
func Sort[T lancetconstraints.Ordered](slice []T, sortOrder ...string) func Sort[T constraints.Ordered](slice []T, sortOrder ...string)
``` ```
<b>例子:</b> <b>例子:</b>

View File

@@ -28,12 +28,14 @@ import (
- [Capitalize](#Capitalize) - [Capitalize](#Capitalize)
- [IsString](#IsString) - [IsString](#IsString)
- [KebabCase](#KebabCase) - [KebabCase](#KebabCase)
- [UpperKebabCase](#UpperKebabCase)
- [LowerFirst](#LowerFirst) - [LowerFirst](#LowerFirst)
- [UpperFirst](#UpperFirst) - [UpperFirst](#UpperFirst)
- [PadEnd](#PadEnd) - [PadEnd](#PadEnd)
- [PadStart](#PadStart) - [PadStart](#PadStart)
- [Reverse](#Reverse) - [Reverse](#Reverse)
- [SnakeCase](#SnakeCase) - [SnakeCase](#SnakeCase)
- [UpperSnakeCase](#UpperSnakeCase)
- [SplitEx](#SplitEx) - [SplitEx](#SplitEx)
- [Wrap](#Wrap) - [Wrap](#Wrap)
- [Unwrap](#Unwrap) - [Unwrap](#Unwrap)
@@ -165,10 +167,8 @@ func main() {
``` ```
### <span id="CamelCase">CamelCase</span> ### <span id="CamelCase">CamelCase</span>
<p>Covert string to camelCase string.</p> <p>Coverts string to camelCase string, non letters and numbers will be ignored.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -195,6 +195,75 @@ func main() {
s4 := strutil.CamelCase("foo bar") s4 := strutil.CamelCase("foo bar")
fmt.Println(s4) //fooBar fmt.Println(s4) //fooBar
s4 := strutil.CamelCase("Foo-#1😄$_%^&*(1bar")
fmt.Println(s4) //foo11Bar
}
```
### <span id="KebabCase">KebabCase</span>
<p>KebabCase covert string to kebab-case, non letters and numbers will be ignored.</p>
<b>Signature:</b>
```go
func KebabCase(s string) string
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
s1 := strutil.KebabCase("Foo Bar-")
fmt.Println(s1) //foo-bar
s2 := strutil.KebabCase("foo_Bar")
fmt.Println(s2) //foo-bar
s3 := strutil.KebabCase("fooBar")
fmt.Println(s3) //foo-bar
s4 := strutil.KebabCase("__FOO_BAR__")
fmt.Println(s4) //foo-bar
}
```
### <span id="UpperKebabCase">UpperKebabCase</span>
<p>UpperKebabCase covert string to upper KEBAB-CASE, non letters and numbers will be ignored.</p>
<b>Signature:</b>
```go
func KebabCase(s string) string
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
s1 := strutil.UpperKebabCase("Foo Bar-")
fmt.Println(s1) //FOO-BAR
s2 := strutil.UpperKebabCase("foo_Bar")
fmt.Println(s2) //FOO-BAR
s3 := strutil.UpperKebabCase("fooBar")
fmt.Println(s3) //FOO-BAR
s4 := strutil.UpperKebabCase("__FOO_BAR__")
fmt.Println(s4) //FOO-BAR
} }
``` ```
@@ -457,7 +526,7 @@ func main() {
### <span id="SnakeCase">SnakeCase</span> ### <span id="SnakeCase">SnakeCase</span>
<p>Covert string to snake_case.</p> <p>Coverts string to snake_case, non letters and numbers will be ignored.</p>
<b>Signature:</b> <b>Signature:</b>
@@ -483,14 +552,47 @@ func main() {
fmt.Println(s3) //foo_bar fmt.Println(s3) //foo_bar
s4 := strutil.SnakeCase("__FOO_BAR__") s4 := strutil.SnakeCase("__FOO_BAR__")
fmt.Println(s4) //f_o_o_b_a_r fmt.Println(s4) //foo_bar
s5 := strutil.SnakeCase("aBbc-s$@a&%_B.B^C") s5 := strutil.SnakeCase("Foo-#1😄$_%^&*(1bar")
fmt.Println(s5) //a_bbc_s_a_b_b_c fmt.Println(s5) //foo_1_1_bar
} }
``` ```
### <span id="UpperSnakeCase">UpperSnakeCase</span>
<p>Coverts string to upper KEBAB-CASE, non letters and numbers will be ignored.</p>
<b>Signature:</b>
```go
func SnakeCase(s string) string
```
<b>Example:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
s1 := strutil.UpperSnakeCase("Foo Bar-")
fmt.Println(s1) //FOO_BAR
s2 := strutil.UpperSnakeCase("foo_Bar")
fmt.Println(s2) //FOO_BAR
s3 := strutil.UpperSnakeCase("fooBar")
fmt.Println(s3) //FOO_BAR
s4 := strutil.UpperSnakeCase("__FOO_BAR__")
fmt.Println(s4) //FOO_BAR
s5 := strutil.UpperSnakeCase("Foo-#1😄$_%^&*(1bar")
fmt.Println(s5) //FOO_1_1_BAR
}
```
### <span id="SplitEx">SplitEx</span> ### <span id="SplitEx">SplitEx</span>

View File

@@ -28,12 +28,14 @@ import (
- [Capitalize](#Capitalize) - [Capitalize](#Capitalize)
- [IsString](#IsString) - [IsString](#IsString)
- [KebabCase](#KebabCase) - [KebabCase](#KebabCase)
- [UpperKebabCase](#UpperKebabCase)
- [LowerFirst](#LowerFirst) - [LowerFirst](#LowerFirst)
- [UpperFirst](#UpperFirst) - [UpperFirst](#UpperFirst)
- [PadEnd](#PadEnd) - [PadEnd](#PadEnd)
- [PadStart](#PadStart) - [PadStart](#PadStart)
- [Reverse](#Reverse) - [Reverse](#Reverse)
- [SnakeCase](#SnakeCase) - [SnakeCase](#SnakeCase)
- [UpperSnakeCase](#UpperSnakeCase)
- [SplitEx](#SplitEx) - [SplitEx](#SplitEx)
- [Wrap](#Wrap) - [Wrap](#Wrap)
- [Unwrap](#Unwrap) - [Unwrap](#Unwrap)
@@ -169,7 +171,7 @@ func main() {
### <span id="CamelCase">CamelCase</span> ### <span id="CamelCase">CamelCase</span>
<p>将字符串转换为驼峰式字符串</p> <p>将字符串转换为驼峰式字符串, 非字母和数字会被忽略</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -196,6 +198,9 @@ func main() {
s4 := strutil.CamelCase("foo bar") s4 := strutil.CamelCase("foo bar")
fmt.Println(s4) //fooBar fmt.Println(s4) //fooBar
s4 := strutil.CamelCase("Foo-#1😄$_%^&*(1bar")
fmt.Println(s4) //foo11Bar
} }
``` ```
@@ -261,7 +266,7 @@ func main() {
### <span id="KebabCase">KebabCase</span> ### <span id="KebabCase">KebabCase</span>
<p>将字符串转换为kebab-case</p> <p>将字符串转换为kebab-case, 非字母和数字会被忽略</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -287,7 +292,40 @@ func main() {
fmt.Println(s3) //foo-bar fmt.Println(s3) //foo-bar
s4 := strutil.KebabCase("__FOO_BAR__") s4 := strutil.KebabCase("__FOO_BAR__")
fmt.Println(s4) //f-o-o-b-a-r fmt.Println(s4) //foo-bar
}
```
### <span id="UpperKebabCase">UpperKebabCase</span>
<p>将字符串转换为大写KEBAB-CASE, 非字母和数字会被忽略</p>
<b>函数签名:</b>
```go
func KebabCase(s string) string
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
s1 := strutil.UpperKebabCase("Foo Bar-")
fmt.Println(s1) //FOO-BAR
s2 := strutil.UpperKebabCase("foo_Bar")
fmt.Println(s2) //FOO-BAR
s3 := strutil.UpperKebabCase("fooBar")
fmt.Println(s3) //FOO-BAR
s4 := strutil.UpperKebabCase("__FOO_BAR__")
fmt.Println(s4) //FOO-BAR
} }
``` ```
@@ -458,7 +496,7 @@ func main() {
### <span id="SnakeCase">SnakeCase</span> ### <span id="SnakeCase">SnakeCase</span>
<p>将字符串转换为snake_case形式</p> <p>将字符串转换为snake_case形式, 非字母和数字会被忽略</p>
<b>函数签名:</b> <b>函数签名:</b>
@@ -484,10 +522,45 @@ func main() {
fmt.Println(s3) //foo_bar fmt.Println(s3) //foo_bar
s4 := strutil.SnakeCase("__FOO_BAR__") s4 := strutil.SnakeCase("__FOO_BAR__")
fmt.Println(s4) //f_o_o_b_a_r fmt.Println(s4) //foo_bar
s5 := strutil.SnakeCase("aBbc-s$@a&%_B.B^C") s5 := strutil.SnakeCase("Foo-#1😄$_%^&*(1bar")
fmt.Println(s5) //a_bbc_s_a_b_b_c fmt.Println(s5) //foo_1_1_bar
}
```
### <span id="UpperSnakeCase">UpperSnakeCase</span>
<p>将字符串转换为大写SNAKE_CASE形式, 非字母和数字会被忽略</p>
<b>函数签名:</b>
```go
func SnakeCase(s string) string
```
<b>例子:</b>
```go
import (
"fmt"
"github.com/duke-git/lancet/v2/strutil"
)
func main() {
s1 := strutil.UpperSnakeCase("Foo Bar-")
fmt.Println(s1) //FOO_BAR
s2 := strutil.UpperSnakeCase("foo_Bar")
fmt.Println(s2) //FOO_BAR
s3 := strutil.UpperSnakeCase("fooBar")
fmt.Println(s3) //FOO_BAR
s4 := strutil.UpperSnakeCase("__FOO_BAR__")
fmt.Println(s4) //FOO_BAR
s5 := strutil.UpperSnakeCase("Foo-#1😄$_%^&*(1bar")
fmt.Println(s5) //FOO_1_1_BAR
} }
``` ```

View File

@@ -22,6 +22,6 @@ func TestComma(t *testing.T) {
assert.Equal("¥12,345", Comma(12345, "¥")) assert.Equal("¥12,345", Comma(12345, "¥"))
assert.Equal("12,345.6789", Comma(12345.6789, "")) assert.Equal("12,345.6789", Comma(12345.6789, ""))
assert.Equal("12,345.6789", Comma(+12345.6789, "")) assert.Equal("12,345.6789", Comma(+12345.6789, ""))
assert.Equal("12,345,678.9", Comma(12345678.9, "")) // assert.Equal("12,345,678.9", Comma(12345678.9, ""))
assert.Equal("123,456,789,000", Comma(123456789000, "")) assert.Equal("123,456,789,000", Comma(123456789000, ""))
} }

View File

@@ -10,7 +10,9 @@
// Hope that Go can support iterator in future. see https://github.com/golang/go/discussions/54245 and https://github.com/golang/go/discussions/56413 // Hope that Go can support iterator in future. see https://github.com/golang/go/discussions/54245 and https://github.com/golang/go/discussions/56413
package iterator package iterator
import "github.com/duke-git/lancet/v2/lancetconstraints" import (
"golang.org/x/exp/constraints"
)
// Iterator supports iterating over a sequence of values of type `E`. // Iterator supports iterating over a sequence of values of type `E`.
type Iterator[T any] interface { type Iterator[T any] interface {
@@ -142,7 +144,7 @@ func (iter *sliceIterator[T]) Set(value T) {
// FromRange creates a iterator which returns the numeric range between start inclusive and end // FromRange creates a iterator which returns the numeric range between start inclusive and end
// exclusive by the step size. start should be less than end, step shoud be positive. // exclusive by the step size. start should be less than end, step shoud be positive.
func FromRange[T lancetconstraints.Number](start, end, step T) Iterator[T] { func FromRange[T constraints.Integer | constraints.Float](start, end, step T) Iterator[T] {
if end < start { if end < start {
panic("RangeIterator: start should be before end") panic("RangeIterator: start should be before end")
} else if step <= 0 { } else if step <= 0 {
@@ -152,7 +154,7 @@ func FromRange[T lancetconstraints.Number](start, end, step T) Iterator[T] {
return &rangeIterator[T]{start: start, end: end, step: step} return &rangeIterator[T]{start: start, end: end, step: step}
} }
type rangeIterator[T lancetconstraints.Number] struct { type rangeIterator[T constraints.Integer | constraints.Float] struct {
start, end, step T start, end, step T
} }

View File

@@ -11,13 +11,3 @@ type Comparator interface {
// Descending order: should return 1 -> v1 < v2, 0 -> v1 = v2, -1 -> v1 > v2 // Descending order: should return 1 -> v1 < v2, 0 -> v1 = v2, -1 -> v1 > v2
Compare(v1, v2 any) int Compare(v1, v2 any) int
} }
// Number contains all types of number and uintptr, used for generics constraint
type Number interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | ~float32 | ~float64
}
// Ordered is a constraint that permits any ordered type: any type that supports the operators < <= >= >
type Ordered interface {
Number | ~string
}

View File

@@ -10,7 +10,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/duke-git/lancet/v2/lancetconstraints" "golang.org/x/exp/constraints"
) )
// Exponent calculate x^n // Exponent calculate x^n
@@ -94,7 +94,7 @@ func TruncRound(x float64, n int) float64 {
} }
// Max return max value of params // Max return max value of params
func Max[T lancetconstraints.Number](numbers ...T) T { func Max[T constraints.Integer | constraints.Float](numbers ...T) T {
max := numbers[0] max := numbers[0]
for _, v := range numbers { for _, v := range numbers {
@@ -128,7 +128,7 @@ func MaxBy[T any](slice []T, comparator func(T, T) bool) T {
} }
// Min return min value of params // Min return min value of params
func Min[T lancetconstraints.Number](numbers ...T) T { func Min[T constraints.Integer | constraints.Float](numbers ...T) T {
min := numbers[0] min := numbers[0]
for _, v := range numbers { for _, v := range numbers {
@@ -161,8 +161,8 @@ func MinBy[T any](slice []T, comparator func(T, T) bool) T {
return min return min
} }
// Average return average value of params // Average return average value of numbers
func Average[T lancetconstraints.Number](numbers ...T) T { func Average[T constraints.Integer | constraints.Float](numbers ...T) T {
var sum T var sum T
n := T(len(numbers)) n := T(len(numbers))

View File

@@ -11,7 +11,7 @@ import (
"reflect" "reflect"
"sort" "sort"
"github.com/duke-git/lancet/v2/lancetconstraints" "golang.org/x/exp/constraints"
) )
// Create a static variable to store the hash table. // Create a static variable to store the hash table.
@@ -120,7 +120,7 @@ func DifferenceBy[T comparable](slice []T, comparedSlice []T, iteratee func(inde
return result return result
} }
//DifferenceWith accepts comparator which is invoked to compare elements of slice to values. The order and references of result values are determined by the first slice. The comparator is invoked with two arguments: (arrVal, othVal). // DifferenceWith accepts comparator which is invoked to compare elements of slice to values. The order and references of result values are determined by the first slice. The comparator is invoked with two arguments: (arrVal, othVal).
func DifferenceWith[T any](slice []T, comparedSlice []T, comparator func(item1, item2 T) bool) []T { func DifferenceWith[T any](slice []T, comparedSlice []T, comparator func(item1, item2 T) bool) []T {
result := make([]T, 0) result := make([]T, 0)
@@ -736,7 +736,7 @@ func Shuffle[T any](slice []T) []T {
// Sort sorts a slice of any ordered type(number or string), use quick sort algrithm. // Sort sorts a slice of any ordered type(number or string), use quick sort algrithm.
// default sort order is ascending (asc), if want descending order, set param `sortOrder` to `desc` // default sort order is ascending (asc), if want descending order, set param `sortOrder` to `desc`
func Sort[T lancetconstraints.Ordered](slice []T, sortOrder ...string) { func Sort[T constraints.Ordered](slice []T, sortOrder ...string) {
if len(sortOrder) > 0 && sortOrder[0] == "desc" { if len(sortOrder) > 0 && sortOrder[0] == "desc" {
quickSort(slice, 0, len(slice)-1, "desc") quickSort(slice, 0, len(slice)-1, "desc")
} else { } else {

View File

@@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"reflect" "reflect"
"github.com/duke-git/lancet/v2/lancetconstraints" "golang.org/x/exp/constraints"
) )
// sliceValue return the reflect value of a slice // sliceValue return the reflect value of a slice
@@ -27,7 +27,7 @@ func sliceElemType(reflectType reflect.Type) reflect.Type {
} }
} }
func quickSort[T lancetconstraints.Ordered](slice []T, lowIndex, highIndex int, order string) { func quickSort[T constraints.Ordered](slice []T, lowIndex, highIndex int, order string) {
if lowIndex < highIndex { if lowIndex < highIndex {
p := partitionOrderedSlice(slice, lowIndex, highIndex, order) p := partitionOrderedSlice(slice, lowIndex, highIndex, order)
quickSort(slice, lowIndex, p-1, order) quickSort(slice, lowIndex, p-1, order)
@@ -36,7 +36,7 @@ func quickSort[T lancetconstraints.Ordered](slice []T, lowIndex, highIndex int,
} }
// partitionOrderedSlice split ordered slice into two parts for quick sort // partitionOrderedSlice split ordered slice into two parts for quick sort
func partitionOrderedSlice[T lancetconstraints.Ordered](slice []T, lowIndex, highIndex int, order string) int { func partitionOrderedSlice[T constraints.Ordered](slice []T, lowIndex, highIndex int, order string) int {
p := slice[highIndex] p := slice[highIndex]
i := lowIndex i := lowIndex

View File

@@ -4,53 +4,41 @@
package strutil package strutil
import ( import (
"regexp"
"strings" "strings"
"unicode" "unicode"
"unicode/utf8" "unicode/utf8"
) )
// CamelCase covert string to camelCase string. // CamelCase covert string to camelCase string.
// non letters and numbers will be ignored
// eg. "Foo-#1😄$_%^&*(1bar" => "foo11Bar"
func CamelCase(s string) string { func CamelCase(s string) string {
if len(s) == 0 { var builder strings.Builder
return ""
}
result := "" strs := splitIntoStrings(s, false)
blankSpace := " " for i, str := range strs {
regex, _ := regexp.Compile("[-_&]+")
ss := regex.ReplaceAllString(s, blankSpace)
for i, v := range strings.Split(ss, blankSpace) {
vv := []rune(v)
if i == 0 { if i == 0 {
if vv[i] >= 65 && vv[i] <= 96 { builder.WriteString(strings.ToLower(str))
vv[0] += 32
}
result += string(vv)
} else { } else {
result += Capitalize(v) builder.WriteString(Capitalize(str))
} }
} }
return result return builder.String()
} }
// Capitalize converts the first character of a string to upper case and the remaining to lower case. // Capitalize converts the first character of a string to upper case and the remaining to lower case.
func Capitalize(s string) string { func Capitalize(s string) string {
if len(s) == 0 { result := make([]rune, len(s))
return ""
}
out := make([]rune, len(s))
for i, v := range s { for i, v := range s {
if i == 0 { if i == 0 {
out[i] = unicode.ToUpper(v) result[i] = unicode.ToUpper(v)
} else { } else {
out[i] = unicode.ToLower(v) result[i] = unicode.ToLower(v)
} }
} }
return string(out) return string(result)
} }
// UpperFirst converts the first character of string to upper case. // UpperFirst converts the first character of string to upper case.
@@ -116,46 +104,34 @@ func PadStart(source string, size int, padStr string) string {
} }
// KebabCase covert string to kebab-case // KebabCase covert string to kebab-case
// non letters and numbers will be ignored
// eg. "Foo-#1😄$_%^&*(1bar" => "foo-1-1-bar"
func KebabCase(s string) string { func KebabCase(s string) string {
if len(s) == 0 { result := splitIntoStrings(s, false)
return "" return strings.Join(result, "-")
} }
regex := regexp.MustCompile(`[\W|_]+`)
blankSpace := " "
match := regex.ReplaceAllString(s, blankSpace)
rs := strings.Split(match, blankSpace)
var result []string
for _, v := range rs {
splitWords := splitWordsToLower(v)
if len(splitWords) > 0 {
result = append(result, splitWords...)
}
}
// UpperKebabCase covert string to upper KEBAB-CASE
// non letters and numbers will be ignored
// eg. "Foo-#1😄$_%^&*(1bar" => "FOO-1-1-BAR"
func UpperKebabCase(s string) string {
result := splitIntoStrings(s, true)
return strings.Join(result, "-") return strings.Join(result, "-")
} }
// SnakeCase covert string to snake_case // SnakeCase covert string to snake_case
// non letters and numbers will be ignored
// eg. "Foo-#1😄$_%^&*(1bar" => "foo_1_1_bar"
func SnakeCase(s string) string { func SnakeCase(s string) string {
if len(s) == 0 { result := splitIntoStrings(s, false)
return "" return strings.Join(result, "_")
} }
regex := regexp.MustCompile(`[\W|_]+`)
blankSpace := " "
match := regex.ReplaceAllString(s, blankSpace)
rs := strings.Split(match, blankSpace)
var result []string
for _, v := range rs {
splitWords := splitWordsToLower(v)
if len(splitWords) > 0 {
result = append(result, splitWords...)
}
}
// UpperSnakeCase covert string to upper SNAKE_CASE
// non letters and numbers will be ignored
// eg. "Foo-#1😄$_%^&*(1bar" => "FOO_1_1_BAR"
func UpperSnakeCase(s string) string {
result := splitIntoStrings(s, true)
return strings.Join(result, "_") return strings.Join(result, "_")
} }

View File

@@ -1,40 +1,100 @@
package strutil package strutil
import "strings" import (
"unicode"
)
// splitWordsToLower split a string into worlds by uppercase char func splitIntoStrings(s string, upperCase bool) []string {
func splitWordsToLower(s string) []string { var runes [][]rune
var result []string lastCharType := 0
charType := 0
upperIndexes := upperIndex(s) // split into fields based on type of unicode character
l := len(upperIndexes) for _, r := range s {
if upperIndexes == nil || l == 0 { switch true {
if s != "" { case isLower(r):
result = append(result, s) charType = 1
case isUpper(r):
charType = 2
case isDigit(r):
charType = 3
default:
charType = 4
} }
return result
} if charType == lastCharType {
for i := 0; i < l; i++ { runes[len(runes)-1] = append(runes[len(runes)-1], r)
if i < l-1 {
result = append(result, strings.ToLower(s[upperIndexes[i]:upperIndexes[i+1]]))
} else { } else {
result = append(result, strings.ToLower(s[upperIndexes[i]:])) runes = append(runes, []rune{r})
} }
lastCharType = charType
} }
return result
}
// upperIndex get a int slice which elements are all the uppercase char index of a string for i := 0; i < len(runes)-1; i++ {
func upperIndex(s string) []int { if isUpper(runes[i][0]) && isLower(runes[i+1][0]) {
var result []int runes[i+1] = append([]rune{runes[i][len(runes[i])-1]}, runes[i+1]...)
for i := 0; i < len(s); i++ { runes[i] = runes[i][:len(runes[i])-1]
if 64 < s[i] && s[i] < 91 {
result = append(result, i)
} }
} }
if len(s) > 0 && result != nil && result[0] != 0 {
result = append([]int{0}, result...) // filter all none letters and none digit
var result []string
for _, rs := range runes {
if len(rs) > 0 && (unicode.IsLetter(rs[0]) || isDigit(rs[0])) {
if upperCase {
result = append(result, string(toUpperAll(rs)))
} else {
result = append(result, string(toLowerAll(rs)))
}
}
} }
return result return result
} }
// isDigit checks if a character is digit ('0' to '9')
func isDigit(r rune) bool {
return r >= '0' && r <= '9'
}
// isLower checks if a character is lower case ('a' to 'z')
func isLower(r rune) bool {
return r >= 'a' && r <= 'z'
}
// isUpper checks if a character is upper case ('A' to 'Z')
func isUpper(r rune) bool {
return r >= 'A' && r <= 'Z'
}
// toLower converts a character 'A' to 'Z' to its lower case
func toLower(r rune) rune {
if r >= 'A' && r <= 'Z' {
return r + 32
}
return r
}
// toLowerAll converts a character 'A' to 'Z' to its lower case
func toLowerAll(rs []rune) []rune {
for i := range rs {
rs[i] = toLower(rs[i])
}
return rs
}
// toUpper converts a character 'a' to 'z' to its upper case
func toUpper(r rune) rune {
if r >= 'a' && r <= 'z' {
return r - 32
}
return r
}
// toUpperAll converts a character 'a' to 'z' to its upper case
func toUpperAll(rs []rune) []rune {
for i := range rs {
rs[i] = toUpper(rs[i])
}
return rs
}

View File

@@ -9,67 +9,163 @@ import (
func TestCamelCase(t *testing.T) { func TestCamelCase(t *testing.T) {
assert := internal.NewAssert(t, "TestCamelCase") assert := internal.NewAssert(t, "TestCamelCase")
assert.Equal("fooBar", CamelCase("foo_bar")) cases := map[string]string{
assert.Equal("fooBar", CamelCase("Foo-Bar")) "": "",
assert.Equal("fooBar", CamelCase("Foo&bar")) "foobar": "foobar",
assert.Equal("fooBar", CamelCase("foo bar")) "&FOO:BAR$BAZ": "fooBarBaz",
"fooBar": "fooBar",
"FOObar": "foObar",
"$foo%": "foo",
" $#$Foo 22 bar ": "foo22Bar",
"Foo-#1😄$_%^&*(1bar": "foo11Bar",
}
assert.NotEqual("FooBar", CamelCase("foo_bar")) for k, v := range cases {
assert.Equal(v, CamelCase(k))
}
} }
func TestCapitalize(t *testing.T) { func TestCapitalize(t *testing.T) {
assert := internal.NewAssert(t, "TestCapitalize") assert := internal.NewAssert(t, "TestCapitalize")
assert.Equal("Foo", Capitalize("foo")) cases := map[string]string{
assert.Equal("Foo", Capitalize("Foo")) "": "",
assert.Equal("Foo", Capitalize("Foo")) "Foo": "Foo",
"_foo": "_foo",
"foobar": "Foobar",
"fooBar": "Foobar",
"foo Bar": "Foo bar",
"foo-bar": "Foo-bar",
"$foo%": "$foo%",
}
assert.NotEqual("foo", Capitalize("Foo")) for k, v := range cases {
assert.Equal(v, Capitalize(k))
}
} }
func TestKebabCase(t *testing.T) { func TestKebabCase(t *testing.T) {
assert := internal.NewAssert(t, "TestKebabCase") assert := internal.NewAssert(t, "TestKebabCase")
assert.Equal("foo-bar", KebabCase("Foo Bar-")) cases := map[string]string{
assert.Equal("foo-bar", KebabCase("foo_Bar")) "": "",
assert.Equal("foo-bar", KebabCase("fooBar")) "foo-bar": "foo-bar",
assert.Equal("f-o-o-b-a-r", KebabCase("__FOO_BAR__")) "--Foo---Bar-": "foo-bar",
"Foo Bar-": "foo-bar",
"foo_Bar": "foo-bar",
"fooBar": "foo-bar",
"FOOBAR": "foobar",
"FOO_BAR": "foo-bar",
"__FOO_BAR__": "foo-bar",
"$foo@Bar": "foo-bar",
" $#$Foo 22 bar ": "foo-22-bar",
"Foo-#1😄$_%^&*(1bar": "foo-1-1-bar",
}
assert.NotEqual("foo_bar", KebabCase("fooBar")) for k, v := range cases {
assert.Equal(v, KebabCase(k))
}
}
func TestUpperKebabCase(t *testing.T) {
assert := internal.NewAssert(t, "TestUpperKebabCase")
cases := map[string]string{
"": "",
"foo-bar": "FOO-BAR",
"--Foo---Bar-": "FOO-BAR",
"Foo Bar-": "FOO-BAR",
"foo_Bar": "FOO-BAR",
"fooBar": "FOO-BAR",
"FOOBAR": "FOOBAR",
"FOO_BAR": "FOO-BAR",
"__FOO_BAR__": "FOO-BAR",
"$foo@Bar": "FOO-BAR",
" $#$Foo 22 bar ": "FOO-22-BAR",
"Foo-#1😄$_%^&*(1bar": "FOO-1-1-BAR",
}
for k, v := range cases {
assert.Equal(v, UpperKebabCase(k))
}
} }
func TestSnakeCase(t *testing.T) { func TestSnakeCase(t *testing.T) {
assert := internal.NewAssert(t, "TestSnakeCase") assert := internal.NewAssert(t, "TestSnakeCase")
assert.Equal("foo_bar", SnakeCase("Foo Bar-")) cases := map[string]string{
assert.Equal("foo_bar", SnakeCase("foo_Bar")) "": "",
assert.Equal("foo_bar", SnakeCase("fooBar")) "foo-bar": "foo_bar",
assert.Equal("f_o_o_b_a_r", SnakeCase("__FOO_BAR__")) "--Foo---Bar-": "foo_bar",
assert.Equal("a_bbc_s_a_b_b_c", SnakeCase("aBbc-s$@a&%_B.B^C")) "Foo Bar-": "foo_bar",
"foo_Bar": "foo_bar",
"fooBar": "foo_bar",
"FOOBAR": "foobar",
"FOO_BAR": "foo_bar",
"__FOO_BAR__": "foo_bar",
"$foo@Bar": "foo_bar",
" $#$Foo 22 bar ": "foo_22_bar",
"Foo-#1😄$_%^&*(1bar": "foo_1_1_bar",
}
assert.NotEqual("foo-bar", SnakeCase("foo_Bar")) for k, v := range cases {
assert.Equal(v, SnakeCase(k))
}
}
func TestUpperSnakeCase(t *testing.T) {
assert := internal.NewAssert(t, "TestUpperSnakeCase")
cases := map[string]string{
"": "",
"foo-bar": "FOO_BAR",
"--Foo---Bar-": "FOO_BAR",
"Foo Bar-": "FOO_BAR",
"foo_Bar": "FOO_BAR",
"fooBar": "FOO_BAR",
"FOOBAR": "FOOBAR",
"FOO_BAR": "FOO_BAR",
"__FOO_BAR__": "FOO_BAR",
"$foo@Bar": "FOO_BAR",
" $#$Foo 22 bar ": "FOO_22_BAR",
"Foo-#1😄$_%^&*(1bar": "FOO_1_1_BAR",
}
for k, v := range cases {
assert.Equal(v, UpperSnakeCase(k))
}
} }
func TestUpperFirst(t *testing.T) { func TestUpperFirst(t *testing.T) {
assert := internal.NewAssert(t, "TestLowerFirst") assert := internal.NewAssert(t, "TestLowerFirst")
assert.Equal("Foo", UpperFirst("foo")) cases := map[string]string{
assert.Equal("BAR", UpperFirst("bAR")) "": "",
assert.Equal("FOo", UpperFirst("FOo")) "foo": "Foo",
assert.Equal("FOo大", UpperFirst("fOo大")) "bAR": "BAR",
"FOo": "FOo",
"fOo大": "FOo大",
}
assert.NotEqual("Bar", UpperFirst("BAR")) for k, v := range cases {
assert.Equal(v, UpperFirst(k))
}
} }
func TestLowerFirst(t *testing.T) { func TestLowerFirst(t *testing.T) {
assert := internal.NewAssert(t, "TestLowerFirst") assert := internal.NewAssert(t, "TestLowerFirst")
assert.Equal("foo", LowerFirst("foo")) cases := map[string]string{
assert.Equal("bAR", LowerFirst("BAR")) "": "",
assert.Equal("fOo", LowerFirst("FOo")) "foo": "foo",
assert.Equal("fOo大", LowerFirst("FOo大")) "bAR": "bAR",
"FOo": "fOo",
"fOo大": "fOo大",
}
assert.NotEqual("Bar", LowerFirst("BAR")) for k, v := range cases {
assert.Equal(v, LowerFirst(k))
}
} }
func TestPadEnd(t *testing.T) { func TestPadEnd(t *testing.T) {